HTMLのオブジェクトの位置を取得してカーソルを合わせるExcelVBAコード

スポンサーリンク

HTMLオブジェクトを取得できても操作できないケースの対応方法を調べた結果をご紹介

直近で私が作業の自動化を行ったウェブサイトでは、HTMLの構造を取得して文字を入力しても受付されないものがありました。

ログイン画面にIDとパスワードを入力して個別ページに移動する際、不正ログインを防止するためなのか、単純に無効なIDとパスワードを検出するためなのか不明ですが、テキストボックスに入力したIDとパスワードをうまく読み込んでいない現象がありました。

今回はウェブサイト側に認識される形でテキストボックスにIDとパスワードを入力する方法について私が調べて作ったExcelコードを紹介します。

HTMLオブジェクトを取得できても操作できないケースと対処法

HTML情報から対象となるオブジェクトを取得できても操作できないケースでこれまで私が遭遇したものとしては、JavaScriptなどのプログラムが含まれている場合があります。

一例として、取得したオブジェクトをクリックした際にある場所に入力されている内容をサーバーに送信したりするプログラムが実行されるものがあったりすると操作がうまく進まないケースがあります。

簡単なプログラムであれば内容を見てそのプログラム自体を一つずつ手作業で入力した時と同じ順序で実行していく方法が考えられます。
プログラムの実行方法はこちらのページで紹介しています。

今回の操作対象では実行されるプログラム処理内容の詳細は見えなかったので上記のプログラムを実行する方法が使えませんでした。

ただ、今回のケースではIDとパスワードを入力してログインするフローの中で、IDとパスワードを入力するにあたって、カーソルを移動させるタイミングで入力された値をチェックするプログラムが働いていることが挙動を見ていてわかりました。

そのため、オブジェクトの位置を認識してマウスを移動させてカーソルを合わせてクリックしてやれば問題が解決するのではないかと推測し、対応方法を調べました。

スポンサーリンク

IEのオブジェクトの画面での位置を取得するAPI関数

IEのオブジェクト位置を取得するAPI関数は「IUnknown_QueryService」というものです。

あまり私自身詳しく把握していないのですが、4つの引数のうち最初の引数にオブジェクトを指定すると4つ目の引数に位置情報を含むデータが出力されるという使い方ができるようです。

(本来は使い方が違うのかなと思いますので詳細わかりましたら追記いたします。)

宣言部分の記載方法は下記の通りです。

Public Declare PtrSafe Function IUnknown_QueryService Lib “shlwapi.dll” _
(ByVal punk As IUnknown, guidService As GUID, riid As GUID, ppvOut As IAccessible) As Long

Public Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type

第二・第三引数で使用するGUIDの構造体の宣言も必要となります。
ややこしいので意味わからなくてもおまじないと思って宣言部分に記載すれば大丈夫です。

例えばGoogleのページを表示した後、検索文字を入力するテキストボックスの位置を取得し、左クリックを押してカーソルを合わせるVBAコードは下記の通りです。

位置を取得したあと、カーソルを合わせる、クリックするなど後の処理があるのでSetCursorPosやmouse_eventなどのAPIも同時に使用します。
これらの使い方についてはこちらの記事をご参照ください。

’オブジェクトの位置取得用API関数
Public Declare PtrSafe Function IUnknown_QueryService Lib “shlwapi.dll” _
(ByVal punk As IUnknown, guidService As GUID, riid As GUID, ppvOut As IAccessible) As Long

’オブジェクトの位置取得用構造体の宣言
Public Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type

’Sleep(待機用)
Public Declare PtrSafe Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)

’マウスカーソル位置を変更する関数
Public Declare Function SetCursorPos Lib “user32” (ByVal x As Long, ByVal y As Long) As Long

’マウスをクリックするAPI
Public Declare Sub mouse_event Lib “user32” ( _
ByVal dwFlags As Long, _
Optional ByVal dx As Long, _
Optional ByVal dy As Long, _
Optional ByVal dwDate As Long, _
Optional ByVal dwExtraInfo As Long)

’マウスクリック用定数
Public Const MOUSE_LEFTDOWN = &H2
Public Const MOUSE_LEFTUP = &H4

Public Const MOUSE_RIGHTDOWN = &H8
Public Const MOUSE_RIGHTUP = &H10

Sub Googleの検索文字入力部分にカーソルを合わせて左クリック()

’第二・第三引数を使用するための部分
Dim IID_IAccessible As GUID
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

Dim IE As Object
Set IE = CreateObject(“InternetExplorer.Application”)
IE.Visible = True

IE.navigate (“https://www.google.co.jp/”)

Do While IE.Busy Or IE.readyState < READYSTATE_COMPLETE
DoEvents
Sleep 1
Loop

Dim e As Object
Set e = IE.document.getElementsByName(“q”)(0)

Dim hr As Long
Dim acc As IAccessible
hr = IUnknown_QueryService(e, IID_IAccessible, IID_IAccessible, acc)

Dim a As Long, b As Long, c As Long, d As Long
acc.accLocation a, b, c, d ’a:左位置 b:上位置 c:横幅 d:高さ

Sleep 1000

SetCursorPos a + c / 2, b + d / 2 ’テキストボックスの真ん中をクリック
mouse_event MOUSE_LEFTDOWN, 0, 0, 0, 0 ’左クリックを押す
mouse_event MOUSE_LEFTUP, 0, 0, 0, 0 ’左クリックを離す

End Sub

コメント