【VBA】UIAutomationで業務改善2

目次

ハンドル

きゃーの☆きゃーの☆こんにちはですの☆jimですなのは☆

はい!今回は、『【VBA】UIAutomationで業務改善1』の続きです。

ハンドル使わなくて『UIAutomation』のみで自動化できそうですが、ハンドル操作を絡めてRPAをやっつけましょう!

自動化の流れ(おさらい)

1、まずハンドルを取得👈ここ

2、そのハンドルのエレメントをUIAutomationで取得して実行

3、エレメントorハンドルを取得するまで無限ループ(待機)

とりあえず、ハンドルの取得から。

そもそも、ハンドルとは?簡単に説明すると。。

ファイルやエクスプローラー、アプリケーションなど。それらに割り当てられる識別番号のことハンドルと言います。

ちなみ、ハンドルには子がいたりします。ボタンとかテキストボックスとか。

今回は下のダイアログを使って、テキストボックスにファイル名を入れて、保存を押下するまで説明します。

子の中に子がいたりするから面倒。孫か。

ピッコロは、「そん!」って言うけども。。。

 

ハンドルの取得

親のハンドル取得には『FindWindowA』、子のハンドル取得には『FindWindowEx』ってAPI使います。

APIをモジュールの一番上に宣言します。

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(クラス名, ウィンドウ名)

Sub a()
Dim Hwnd As Long
    Hwnd = FindWindowA("#32770", "名前を付けて保存")
End Sub

クラス名やウィンドウ名は『vbNullString』で省略可能です。

↓んで、ちょっと面倒なのは子ね😓

・FindWindowEx(親のハンドル, 子のハンドル, クラス名, ウィンドウ名)

Sub a()
Dim Hwnd As Long
Dim ButtonHwnd As Long
    Hwnd = FindWindowA("#32770", "名前を付けて保存")
    ButtonHwnd = FindWindowEx(Hwnd, 0&, vbNullString, "保存(&S)")
End Sub

↓もっと面倒なのは子の子😅

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をモジュールの一番上に宣言します。

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(送信先のハンドル, メッセージの種類, パラメータ, パラメータ)

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使ったりとか、、、

工夫しないと使えないんですけどね。

 

今回はここまで。またなのですは☆

 

next:【VBA】UIAutomationで業務改善3