【VBA】UIAutomationで業務改善2
目次
ハンドル
きゃーの☆きゃーの☆こんにちはですの☆jimですなのは☆
はい!今回は、『【VBA】UIAutomationで業務改善1』の続きです。
ハンドル使わなくて『UIAutomation』のみで自動化できそうですが、ハンドル操作を絡めてRPAをやっつけましょう!
1、まずハンドルを取得👈ここ
2、そのハンドルのエレメントをUIAutomationで取得して実行
3、エレメントorハンドルを取得するまで無限ループ(待機)
とりあえず、ハンドルの取得から。
そもそも、ハンドルとは?簡単に説明すると。。
ファイルやエクスプローラー、アプリケーションなど。それらに割り当てられる識別番号のことハンドルと言います。
ちなみ、ハンドルには子がいたりします。ボタンとかテキストボックスとか。
今回は下のダイアログを使って、テキストボックスにファイル名を入れて、保存を押下するまで説明します。
子の中に子がいたりするから面倒。孫か。
ピッコロは、「そん!」って言うけども。。。
ハンドルの取得
親のハンドル取得には『FindWindowA』、子のハンドル取得には『FindWindowEx』ってAPI使います。
APIをモジュールの一番上に宣言します。
1 2 3 4 5 |
Private Declare Function FindWindowA Lib "USER32" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "User32.dll" Alias "FindWindowExA" _ (ByVal hWndParent As Long, ByVal hwndChildAfter As Long, _ ByVal lpszClass As String, ByVal lpszWindow As String) As Long |
↓親は簡単に取得できるんだよねぇ。
・FindWindowA(クラス名, ウィンドウ名)
1 2 3 4 |
Sub a() Dim Hwnd As Long Hwnd = FindWindowA("#32770", "名前を付けて保存") End Sub |
クラス名やウィンドウ名は『vbNullString』で省略可能です。
↓んで、ちょっと面倒なのは子ね😓
・FindWindowEx(親のハンドル, 子のハンドル, クラス名, ウィンドウ名)
1 2 3 4 5 6 |
Sub a() Dim Hwnd As Long Dim ButtonHwnd As Long Hwnd = FindWindowA("#32770", "名前を付けて保存") ButtonHwnd = FindWindowEx(Hwnd, 0&, vbNullString, "保存(&S)") End Sub |
↓もっと面倒なのは子の子😅
1 2 3 4 5 6 7 8 9 10 11 |
Dim Hwnd As Long Dim InputHwnd As Long Dim ButtonHwnd As Long Hwnd = FindWindowA("#32770", "名前を付けて保存") ButtonHwnd = FindWindowEx(Hwnd, 0&, vbNullString, "保存(&S)") InputHwnd = FindWindowEx(Hwnd, 0&, "DUIViewWndClassName", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "DirectUIHWND", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "FloatNotifySink", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "ComboBox", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "Edit", vbNullString) End Sub |
深い。深すぎる。。。
ハンドルに送信
取得したハンドルに、『SendMessage』や『PostMessage』といったAPIで、文字列の送信・アクティブ・クリックなどが可能です。
今回は『SendMessage』を使います。
APIをモジュールの一番上に宣言します。
1 2 |
Declare Function SendMessage Lib "User32.dll" Alias "SendMessageA" _ (ByVal Hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long |
・SendMessage(送信先のハンドル, メッセージの種類, パラメータ, パラメータ)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Option Explicit Declare Function SendMessage Lib "User32.dll" Alias "SendMessageA" _ (ByVal Hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long Private Declare Function FindWindowA Lib "USER32" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function FindWindowEx Lib "User32.dll" Alias "FindWindowExA" _ (ByVal hWndParent As Long, ByVal hwndChildAfter As Long, _ ByVal lpszClass As String, ByVal lpszWindow As String) As Long Sub a() Dim Hwnd As Long Dim InputHwnd As Long Dim ButtonHwnd As Long Hwnd = FindWindowA("#32770", "名前を付けて保存") ButtonHwnd = FindWindowEx(Hwnd, 0&, vbNullString, "保存(&S)") InputHwnd = FindWindowEx(Hwnd, 0&, "DUIViewWndClassName", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "DirectUIHWND", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "FloatNotifySink", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "ComboBox", vbNullString) InputHwnd = FindWindowEx(InputHwnd, 0&, "Edit", vbNullString) Call SendMessage(InputHwnd, &HC, 0, "C:\テストだよ.txt") Call SendMessage(ButtonHwnd, &HF5, 0, 0&) End Sub |
最後に
如何だったでしょうか?自分は派遣先で、ダイアログ操作をハンドルとUIAutomationを使って操作しています。
今回みたいな感じで(ちょっと違うけど)、システム類からファイルをダウンロードするときや、アップロードも自動化可能です。
まあ、確実にハンドルを取得するように、ハンドル番号を取得するまで抜けないDo~Loopを使ったりとかSleep使ったりとか、、、
工夫しないと使えないんですけどね。
今回はここまで。またなのですは☆
ディスカッション
コメント一覧
まだ、コメントがありません