VBAからIE9のタブ機能を操作する方法

このQ&Aのポイント
  • VBAからIE9のタブ機能を操作する方法について調査しました。
  • IAccessibleインタフェースのaccStateプロパティを使用すると、タブがアクティブになっているかどうか判別できます。
  • AccessibleオブジェクトとIEオブジェクトを行き来する方法がわからず、タブの状態を正しく反映することができません。
回答を見る
  • ベストアンサー

Accessible ObjからIE Obj

VBAからIE9のタブ機能を操作しようと悪戦苦闘しております。 詳しく申し上げると、最前面に表示されているIEの アクティブなタブを確実につかんだうえで、 そのページのDOMを操作したいです。 色々調べていったところ、IAccessibleインタフェースの 中にあるaccStateプロパティを見れば、タブがアクティブになっているかどうか 判別できるところまでたどり着きました。 以下のページを参考にしました。 http://mt-soft.sakura.ne.jp/kyozai/excel_apps/tab-ctrl/index-jump.html?pg_02.html ※C#を多少かじったので、クラス等の知識は微量ですがあります。 上記のサイトを参考に実際にコードを組んでいたのですが、 AccessibleオブジェクトとIEオブジェクトを行き来する方法が わからず、せっかくタブの状態がわかっても それをメインのコードに反映することができません。 Accessibleオブジェクトの階層を上のほうまで辿って行けば、 IEオブジェクト(Shell Windowオブジェクト?)にたどり着く? ということも考えたのですが、辿り方がわからず頓挫しております。 最前面のIEはFindWindow関数でハンドルを取得し、 それをAccessibleインターフェイスに渡す方法で accStateを取得しています。 Sub ie_find() Dim IE As Object Dim hWnd As Double hWnd = FindWindow("IEFrame", vbNullString) 'タブのリスト Dim TabList() 'タブリスト作成 MakeTabList hWnd, TabList For i = 0 To UBound(TabList) If TabList(i).accState(CHILDID_SELF) = 2097154 Then Next i ’ここにいれる処理がわかりません。 ’IEオブジェクト⇔Accessibleオブジェクトの ’方法があれば処理できると思います。 End Sub Private Sub MakeTabList(hWnd As Double, ByRef TabList()) ' ' タブ一覧生成 ' Dim hWndChild As Long Dim Cnt As Long, i As Long Dim ClassName As String Call Class_Initialize 'AccessibleオブジェクトのUUID設定 hWndChild = GetDirectUIHWND(hWnd, "CommandBarClass") 'IE9以前 If hWndChild = 0 Then hWndChild = GetDirectUIHWND(hWnd, "WorkerW") 'IE10以降 If hWndChild = 0 Then Exit Sub Dim objAcc As IAccessible, v AccessibleObjectFromWindow hWndChild, OBJID_CLIENT, IID_IAccessible, objAcc If Not (objAcc Is Nothing) Then Dim Children() As Variant Dim Count1 As Long, Count2 As Long Dim retCount As Long Count1 = objAcc.accChildCount ReDim Children(Count1 - 1) Call AccessibleChildren(objAcc, 0, Count1, Children(0), retCount) '子オブジェクト For i = 0 To objAcc.accChildCount - 1 If TypeOf Children(i) Is IAccessible Then If Children(i).accRole(CHILDID_SELF) = ROLE_SYSTEM_PAGETABLIST Then 'タブ行? Count2 = Children(i).accChildCount ReDim TabList(Count2 - 1) 'タブの一覧を生成 「タブ」と「新しいタブ」のボタン Call AccessibleChildren(Children(i), 0&, ByVal Count2, TabList(0), retCount) Exit For End If End If Next i End If End Sub Private Function GetDirectUIHWND(hWnd As Double, ClassName As String) As Long ' ' DirectUIHWND のウィンドウハンドルを取得 ' Dim hWndChild As Long hWndChild = FindWindowEx(hWnd, 0, ClassName, vbNullString) If hWndChild <> 0 Then hWndChild = FindWindowEx(hWndChild, 0, "ReBarWindow32", vbNullString) If hWndChild <> 0 Then hWndChild = FindWindowEx(hWndChild, 0, "TabBandClass", vbNullString) If hWndChild <> 0 Then hWndChild = FindWindowEx(hWndChild, 0, "DirectUIHWND", vbNullString) GetDirectUIHWND = hWndChild End Function Private Sub Class_Initialize() 'AccessibleオブジェクトのUUID設定 With IID_IAccessible .Data1 = &H618736E0 .Data2 = &H3C3D .Data3 = &H11CF .Data4(0) = &H81 .Data4(1) = &HC .Data4(2) = &H0 .Data4(3) = &HAA .Data4(4) = &H0 .Data4(5) = &H38 .Data4(6) = &H9B .Data4(7) = &H71 End With End Sub どうかこの辺詳しい方、ご教示よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • kumatti1
  • ベストアンサー率60% (73/121)
回答No.1

「About Active Accessibility Support (Windows)」 https://msdn.microsoft.com/en-us/library/ie/gg701963%28v=vs.85%29.aspx このページから察するに(少なくとも)ウィンドウクラス名「Internet Explorer_Server」と 対応してるIAccessibleオブジェクトの子孫要素まで辿らないといけなそうです。 で、IServiceProvider::QueryServiceでIHTMLWindow2を得て、IHTMLDocument2を得ればいいのではと。 (ラッパー関数はIUnknown_QueryService) https://msdn.microsoft.com/en-us/library/windows/desktop/bb759858%28v=vs.85%29.aspx

momomo100
質問者

お礼

本当にありがとうございました!! 数ヶ月悩んでいたことがついに解決しました! 感謝です!

関連するQ&A

  • タグ名取得でエラー

    エクセル2003VBAで以下のコードを実行するとBrowser1がエラーとなります。 どなたか解決法がわからないでしょうか。 よろしくお願いします。 \'IEのウィンドウハンドルを取得 Dim hwnd As Long hwnd = FindWindow(\"IEFrame\", vbNullString) \'ウィンドウを前面に表示する If hwnd = 0 Then MsgBox \"IEが起動していません\" Exit Sub End If SetForegroundWindow hwnd Dim Browser1 As Object Dim elm As Object Dim i As Integer Const READYSTATE_COMPLETE As Long = 4 \'次の画面が表示されるまで待機 While Browser1.ReadyState <> READYSTATE_COMPLETE While Browser1.Busy = True DoEvents Wend Wend Set elm = Browser1.document.getElementsByTagName(\"INPUT\") For i = 0 To elm.Length - 1 If (elm(i).Name = \"q\") Then elm(i).Focus: Exit For Next i

  • Web上のチェックボックスにフォーカスをあてたいのですが

    エクセル2003のVBAで困っています。 IE6のグーグルで検索したWebページ上のチェックボックスにカーソルをあてたいのですが、以下のコードではチェックボックスを取得できません。 別のページで動かしてみたのですが、 ちゃんと動くページもありました。 確実にWebページ上のチェックボックスをひろいたいのですが、 良い方法はないでしょうか。 どなたかご存知の方、アドバイスをよろしくお願いします。 ------------------------------------------------------ 'SetForegroundWindowの定義 Public Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long 'FindWindow関数の定義 Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long '************************************************************ 'IEのウィンドウハンドルを取得 '************************************************************ Dim hwnd As Long hwnd = FindWindow("IEFrame", vbNullString) '見つからなければ戻り値0 '************************************************************ 'ウィンドウを前面に表示する '************************************************************ If hwnd = 0 Then MsgBox "IEが起動していません" Exit Sub End If SetForegroundWindow hwnd '============================================= 'チェックボックス検索開始 '============================================= Dim i as Integer Dim Browser1 As Object Dim elm As Object Dim objShell As Object Dim ShWins As Object Dim IE As Object Const READYSTATE_COMPLETE As Long = 4 'IEオブジェクト状態(4=読み込み完了) Set objShell = CreateObject("Shell.Application") Set ShWins = objShell.Windows() For Each IE In ShWins Set Browser1 = IE Exit For Next '次の画面が表示されるまで待機 While Browser1.ReadyState <> READYSTATE_COMPLETE While Browser1.Busy = True DoEvents Wend Wend Set elm = Browser1.document.getElementsByTagName("INPUT") For i = 0 To elm.Length - 1 'If (elm(i).Name = "q") Then elm(i).Focus: Exit For MsgBox elm(i).Type Next i ------------------------------------------------------

  • 素数を求めるマクロを

    走らすと暴走したようになり、素数=151で止まります。 どこが悪いのでしょうか。正常に終わるようにしたいです。 ====================== Sub 素数を求める()   Dim i As Long   Dim j As Long   Dim m As Long   Dim p As Long   Dim flg As Boolean   i = 1   j = 1   p = 2   Do     flg = False     For m = 2 To Int(Sqr(p))       If p Mod m = 0 Then         flg = True         Exit For       End If     Next     If flg = False Then       Cells(i, j) = p       i = i + 1       If i > Rows.Count Then         i = 1         j = j + 1       End If     End If     p = p + 1   Loop End Sub ======================

  • windows7のエクスプローラをVBAで操作-3

    アドバイスをお願いします。 Excel-VBAで起動しているエクスプローラに対してハンドルを取得してクリックしたり、テキストボックスに文字をセットするプログラムを作って動かしています。 WindowsXPのときはできていたのですが、Windows7になったらエクスプローラが変わったため正しく動作しなくなりました。 やりたいのはエクスプローラに検索文字列(添付ファイル参照)をセットして検索をさせたいのです。 「windows7のエクスプローラをVBAで操作-1」「windows7のエクスプローラをVBAで操作-2」のタイトルで質問させていただき、下のコードを考えましたが、★のところでハンドルが返らず0でした。InspectObjectsで見ると「読み込み専用」と。これが原因ですか?どうしたらいいのだろう・・・。 またこのハンドルを取得して、AccessibleObjectFromWindowでIAccessible を取り出して、accDoDefaultActionしたいのですが、UUIDの値が分かりません。OLEViewで見たのですがExplorer関連がいくつかあり(添付ファイル参照)どれを使っていいものやら。ボタンクリックの後に文字列セットがあるのですが、まだたどり着けず。 IAccessible初心者です。 質問ばかりで済みませんがコーディングのアドバイスお願いします。 Option Explicit Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _ ByVal hwndParent As Long, _ ByVal hwndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private Declare Function AccessibleObjectFromWindow Lib "oleacc" _ (ByVal hWnd As Long, _ ByVal dwObjectID As Long, _ ByRef riid As Any, _ ByRef ppvObject As Any) As Long Const WM_SETTEXT = &HC '文字列送信 Const BM_CLICK = &HF5 'クリック Const OBJID_CLIENT As Integer = &HFFFFFFFC Private Type UUID Data1 As Long Data2 As Integer Data3 As Integer Data4(7) As Byte End Type Private IID_IAccessible As UUID Private oShell Private ie Private hWnd As Long Private SearchBoxハンドル As Long Private Search_Folder As String Private RC As Long 'Private objAcc As IAccessible Private objAcc As UUID Private varChild As Variant Private cnt Private fullnames As String Sub 検索指定のインプット() Search_Folder = "c:\xxx" Set oShell = CreateObject("Shell.Application") For cnt = oShell.Windows().Count - 1 To 0 Step -1 ' On Error Resume Next Set ie = oShell.Windows().Item(cnt) fullnames = ie.FullName ' On Error GoTo 0 If fullnames = "C:\Windows\Explorer.EXE" Then ie.Navigate (Search_Folder) hWnd = FindWindow("CabinetWClass", vbNullString) hWnd = FindWindowEx(hWnd, 0, "WorkerW", vbNullString) hWnd = FindWindowEx(hWnd, 0, "ReBarWindow32", vbNullString) hWnd = FindWindowEx(hWnd, 0, "UniversalSearchBand", vbNullString) hWnd = FindWindowEx(hWnd, 0, "Search Box", vbNullString) hWnd = FindWindowEx(hWnd, 0, "SearchEditBoxWrapperClass", vbNullString) hWnd = FindWindowEx(hWnd, 0, "SearchBox", vbNullString) ' ★--> 0 return SearchBoxハンドル = hWnd hWnd = FindWindowEx(SearchBoxハンドル, 0, "Button", "検索") hWnd = FindWindowEx(SearchBoxハンドル, 0, "SearchEditBox", vbNullString) ' "SearchEditBox" に検索文字列入力の予定だった With IID_IAccessible .Data1 = &H68284FAA .Data2 = &H6A48 .Data3 = &H11D0 .Data4(0) = &H8C .Data4(1) = &H78 .Data4(2) = &H0 .Data4(3) = &HC0 .Data4(4) = &H4F .Data4(5) = &HD9 .Data4(6) = &H18 .Data4(7) = &HB4 End With RC = AccessibleObjectFromWindow(hWnd, OBJID_CLIENT, IID_IAccessible, objAcc) ' 80004005が返る varChild = 2 ' Class="Button", Name="検索"のコントロールをクリックしたいが・・・ ' RC = objAcc.accDoDefaultAction(varChild) ' 書き方が違うみたい・・・ ' Class="SearchEditBox" に検索する文字列を入れたいが・・・ Exit Sub End If Set ie = Nothing Next End Sub

  • IE10の通知バーの保存ボタンをVBAで制御したい

    IE10でダウンロードの際に表示される通知バーの保存ボタンをAccess2010VBAで制御したいと考えており、 http://okwave.jp/qa/q8121989.html を参考にさせていただきました。 この際、下記コードのように Const url As String = "ttp://www.xxx.com"と、 urlを定数にするとVBAでIE通知バーのボタンを制御できますが、 Dim url As String url = "ttp://www.xxx.com"と urlを変数にして、リンク先を記述するとIEのウィンドウを認識してくれません。 なぜ変数にすると認識されないのか理解できず、質問させていただきました。 また、urlを動的に変化させたいのですが、なにかいい方法はないでしょうか。 どなたかご教示のほど、よろしくお願いいたします。 OS Windows7 32bit Access2010です。 以下、コードです。 Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long Sub hoge2() Const url As String = "ttp://www.xxx.com" Dim IE As Object Set IE = CreateObject("Shell.Application").Windows.FindWindowSW(url, Empty, 1, 0, 1) If IE Is Nothing Then msgbox "IEがありません" Exit Sub End If Dim o As IUIAutomation Dim e As IUIAutomationElement Set o = New CUIAutomation Dim h As LongPtr h = IE.hwnd h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString) If h = 0 Then Exit Sub Set e = o.ElementFromHandle(ByVal h) Dim iCnd As IUIAutomationCondition Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "保存") Dim Button As IUIAutomationElement Set Button = e.FindFirst(TreeScope_Subtree, iCnd) Dim InvokePattern As IUIAutomationInvokePattern Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId) InvokePattern.Invoke DoEvents Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "通知バーのテキスト") Dim iElemFound As IUIAutomationElement Set iElemFound = e.FindFirst(TreeScope_Subtree, iCnd) Dim iValuePattern As IUIAutomationValuePattern Set iValuePattern = iElemFound.GetCurrentPattern(UIA_ValuePatternId) Do DoEvents If iValuePattern.CurrentValue Like "*のダウンロードが完了しました。*" Then Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "閉じる") Set iElemFound = e.FindFirst(TreeScope_Subtree, iCnd) Set InvokePattern = iElemFound.GetCurrentPattern(UIA_InvokePatternId) InvokePattern.Invoke Exit Do End If Loop End Sub

  • 作成方法についての質問です。

    下記のマクロで実行すると添付画像[現状]のようになってしまいます。 私としては[こうなってほしい]の形にしたいのですが、どこに何を組み込めばよいかわかりません。 誰か教えてください。 Dim Matches As Object Dim Match As Object Dim i As Long, j As Long Dim a As Variant With CreateObject("VBScript.RegExp") Set rng = Range("A1", Cells(Rows.Count, 1).End(xlUp)) Application.ScreenUpdating = False For i = 1 To rng.Rows.Count If InStr(1, rng.Cells(i, 1).Value, "(", 1) > 0 Then .Pattern = "\(([A-z\d,]+)" Else .Pattern = "([A-z\d,]+)" End If .Global = True Set Matches = .Execute(StrConv(rng.Cells(i, 1).Value, vbNarrow)) If Matches.Count > 0 Then a = Matches(0).SubMatches(0) a = Split(a, ",") Cells(i, 2).Resize(, UBound(a) + 1).Value = a End If j = 0 Next End With Application.ScreenUpdating = True Set rng = Nothing End Sub

  • IEブラウザよりmsgboxを手前に表示したい

    当方 IE9+2007です。 Sub yahoo() Dim objIE As Object Dim i As Long Set objIE = CreateObject("InternetExplorer.Application") objIE.Visible = True objIE.Navigate "http://www.yahoo.co.jp/" Do Until objIE.Busy = False And objIE.ReadyState = 4: Loop If objIE.Document.Body.innerHTML Like "*こんにちは、*さん*" Then i = MsgBox("別のIDでログインしています!続けますか?", vbYesNo + vbApplicationModal) If i = 7 Then End End If End Sub このような事がやりたいのですが、 IEブラウザを立ち上げてメッセージボックスをvbApplicationModalで表示させても ブラウザより裏側で表示されてしまいます。 If objIE.Document.Body.innerHTML Like "*こんにちは、*さん*" Then i = MsgBox("別のIDでログインしています!続けますか?", vbYesNo + vbApplicationModal) If i = 7 Then End End If objIE.Visible = True という順番にすればよいのですが、他のコードの関係もあってメッセージボックスより先にブラウザを表示させたいのです。 そんな事は可能でしょうか? ご回答よろしくお願いします。

  • VBA どこでもセル選択

    教えて頂いたVBAなのですがもう一つ Sub Macro1() Dim Ws01 As Worksheet Dim Counter As Long, i As Long, j As Long Dim INP As String Set wS = Worksheets("Sheet4") wS.Cells.ClearContents For i = 3 To ActiveSheet.UsedRange.Rows.Count INP = "" For j = Selection(1).Column To Selection(Selection.Count).Column If Cells(i, j) = 1 Then INP = INP & Cells(2, j) & "," End If Next j Counter = Counter + 1 If INP <> "" Then wS.Cells(Counter, "A") = Left(INP, Len(INP) - 1) End If Next i End Sub -------------------------------------------------------------- For i = 3 のところを3としないでどのセル(行)にも対応させたいのですが どうすればいいでしょうか?

  • VBAで起動しているIEの操作

    IEでOKWAVEを開いていたら イミディエイトウィンドウに タイトルを表示するのに 次の 記述をしましたが エラーになりました。 実行時エラー '-2147467259 (80004005)': 'Document' メソッドは失敗しました: 'IWebBrowser2' オブジェクト なぜでしょうか? IEは11です。 エクセルは2013 OSは windows7 ホームプレミアム vbsは次の通り Sub okwave() Dim colSh As Object Dim win As Object Dim strTemp As String Dim objIE As Object Set colSh = CreateObject("Shell.Application") For Each win In colSh.Windows If TypeName(win.document) = "HTMLDocument" Then If InStr(win.document.Title, "okwave") > 0 Then Set objIE = win Exit For End If End If Next Debug.Print objIE.document.Title End Sub

  • IE9のダウンロード通知バーで名前を付けて保存

    IE9のダウンロード通知バーをVBAから制御する方法について、下記のQ&Aでkumatti1さんの解にあるコードでは「保存」をさせる動作となっています。これを「名前に付けて保存」させることはできないでしょうか。よろしくお願いします。 http://okwave.jp/qa/q8121989.html -------------------------------------------------------------------------------- Option Explicit '参照設定 UIAutomationClient 'C:\Windows\System32\UIAutomationCore.dll Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr Sub hoge2() Const url As String = "" Dim ie As Object Set ie = CreateObject("Shell.Application").Windows.findwindowSW(url, Empty, 1, 0, 1) If ie Is Nothing Then Exit Sub Dim o As IUIAutomation2 Dim e As IUIAutomationElement Set o = New CUIAutomation8 Dim h As LongPtr h = ie.Hwnd h = FindWindowEx(h, 0, "Frame Notification Bar", vbNullString) If h = 0 Then Exit Sub Set e = o.ElementFromHandle(ByVal h) Dim iCnd As IUIAutomationCondition Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "保存") Dim Button As IUIAutomationElement Set Button = e.FindFirst(TreeScope_Subtree, iCnd) Dim InvokePattern As IUIAutomationInvokePattern Set InvokePattern = Button.GetCurrentPattern(UIA_InvokePatternId) InvokePattern.Invoke DoEvents Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "通知バーのテキスト") Dim iElemFound As IUIAutomationElement Set iElemFound = e.FindFirst(TreeScope_Subtree, iCnd) Dim iValuePattern As IUIAutomationValuePattern Set iValuePattern = iElemFound.GetCurrentPattern(UIA_ValuePatternId) Do DoEvents If iValuePattern.CurrentValue Like "*のダウンロードが完了しました。*" Then Set iCnd = o.CreatePropertyCondition(UIA_NamePropertyId, "閉じる") Set iElemFound = e.FindFirst(TreeScope_Subtree, iCnd) Set InvokePattern = iElemFound.GetCurrentPattern(UIA_InvokePatternId) InvokePattern.Invoke Exit Do End If Loop End Sub --------------------------------------------------------------------------------

専門家に質問してみよう