Windowハンドルを取得して、ファイル選択ダイアログボックスを操作する
この前、「SendKeysでパソコンのキー操作を自動化する」っていう記事でダイアログボックスを操作する記事を書いたんですが、、、
動作が安定しないんで、面倒ではありますが結局ハンドルを捕まえに行くことになりました。。。
で、そのへんのことを紹介させて頂きます!w
WindowとWindowハンドル
まずは、WindowとWindowハンドルについてです。
ウィンドウズ上で動いているいろんなアプリケーションは、基本的には”Window”と”コントロール”によって構成されています。
Windowは、アイコンクリックしたら、ビヨンって出てくる画面ですね。
コントロールは、その中のボタンとかみたいに理解するといいかもしれません。

それで、上の図のような感じで、各々のパーツが番号で管理されているというわけです。この番号をハンドルといいます。
図で「00000000」とか「99999999」とかの番号(ハンドル)は、Windowが作られた段階で作られるのでその都度変わります。
VBAから、このパーツを操作するためには、そのハンドルをその都度取得して捕まえる必要があるってことです。
操作の方法
WindowsAPI関数
Windowハンドルを捕まえに行くためには、2つのステップがあります。
1つ目は、APIの宣言です。
そして2つ目はそのAPIの関数を使うことです。
これはセットですので覚えておいてください。
APIとは、Application Programming Interface (アプリケーション・プログラミング・インタフェース) の略で
、他の製品やプログラムにアプリケーションにアクセスするために用意されているプログラムです。
Windowは、Windowsの機能になります(別のプログラム)ので、VBAからWindowsのシステムにアクセスするためにはAPIを使う必要があります。
Windowsの機能にアクセスするためには、WindowsAPIというものが用意されています。
VBAから、WindowsAPIを利用するためには、VBAに対して、
「このAPI使うぞ!」
って最初に言っとかないといけないというわけです。
これがAPIの宣言です。
次の図は、Windowハンドルを取得するための”FindWindow関数”を使うための、WindowsAPIの宣言を書いた状態です。




ここで注意してもらいたいのは、APIの宣言は、プロシージャを記述する前の宣言セクションに記述する必要があることです。
図で”FindWindow関数”を使うためのと言いましたが、WindowsAPIは、使用したい関数ごとに宣言セクションに宣言んを記述する必要があります。
めんどくさいですねw
我慢して下さい。
宣言セクションに、宣言が記述出来たら、通常通りプロシージャの中で宣言したWindowsAPI関数が使えるようになります。
ちなみに、Windowハンドルを取得する”FindWindow関数”は以下のような構文になっています。
ウインドウハンドル = FindWindow(“クラス名”, “キャプション名”)
クラス名は、どのウィンドウを取得するのかであらかじめ決まっています。以下に一部紹介しますが、他にもたくさんあります。
アプリケーション名 | ウィンドウクラス名 |
---|---|
Excel | XLMAIN |
Word | OpusApp |
Access | OMain |
PowerPoint | PP10FrameClass |
エクスプローラ | ExploreWClass |
メモ帳 | Notepad |
ペイント | MSPaintApp |
キャプション名は、ウィンドウがポンと出たときに左上に出てくる題名です。
メモ帳だと次のような漢字ですね。




実施に、図のメモ帳のハンドルを取得してみます。
次のコードです。
’ API宣言
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Sub sample()
Dim hmemo As Long ’変数宣言(ハンドルは番号なのでLong)
hmemo = FindWindow("Notepad", "sample.txt - メモ帳") '実際に取得しているコード
Debug.Print hmemo ’イミディエイトウィンドウに出力
End Sub
※キャプションは、vbNullStringでもいけるっぽい。
番号はその都度変わってしまうので、これとは言えないですが、イミディエイトウィンドウに番号が表示されてばOKです。
ついでに、その捕まえたメモ帳に文字を入力してみましょう!
先ほど捕まえたのは、メモ帳の全体のハンドルなので、
まずは、文字を打ち込む場所のハンドルを捕まえる必要があります。
そして、そのあと文字を打ち込む場所に文字列を送るための機能も必要です。
めんどくさくなってきましたか?
我慢してくださいw
’ API宣言
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
' これ追加(編集部分を取得するために使う)
Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
ByVal hwndParent As LongPtr, _
ByVal hwndChildAfter As LongPtr, _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
' これ追加(編集部分に文字列を送るために使う)
Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As LongPtr
Sub sample()
’メモ帳のハンドルを捕まえる
Dim hmemo As Long
hmemo = FindWindow("Notepad", "sample.txt - メモ帳")
Debug.Print hmemo
'捕まえたハンドル(Hmemo)から、Edit(文字を入れるとこ)のハンドルを捕まえる
Dim hInputBox As Long
hInputBox = FindWindowEx(hmemo, 0, "Edit", "")
Debug.Print hInputBox
'捕まえたハンドル(Edit)に文字を送る
Call SendMessage(hInputBox, &HC, 0, ByVal "さんぷる")
End Sub
まとめると、
- メモ帳のハンドルを捕まえる
- メモ帳のハンドルから編集するところを捕まえる
- 編集するところに文字列を送る
ってことです。
FindWindowsEx関数とSendMessage関数については、ここでは詳しく書きませんが、一個一個API宣言して関数を使うんだな~ということだけ覚えてください(^^♪
他にも、WindowsAPIには色々な関数がありますが、やると長くなりすぎるのでまた別の機会に。。。
パソコンの環境によって微妙に書き方が違ったりするので、これをコピペで動かない場合は、ご自身の環境に合わせていろいろググって探してみてください!(^^♪
ファイル選択ダイアログボックスを操作する
これが本題でしたので、ファイル選択ダイアログボックスの操作について紹介しますw
下の図のようなやつですね。




もうメモ帳でほとんどやったので、さっそくコードです。
’ ①API宣言
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
' これ追加(編集部分を取得するために使う)
Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
ByVal hwndParent As LongPtr, _
ByVal hwndChildAfter As LongPtr, _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
' これ追加(編集部分に文字列を送るために使う)
Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As LongPtr
Sub sample()
’②ファイル選択ダイアログボックスのハンドルを捕まえる
Dim handle As Long
handle = FindWindow("#32770", "開く")
'③捕まえたハンドル(handle)から入力ボックス(ファイル名が入るところ)のハンドルを捕まえる
Dim hInputBox As Long
hInputBox = FindWindowEx(handle, 0&, "ComboBoxEx32", "")
hInputBox = FindWindowEx(hInputBox, 0&, "ComboBox", "")
hInputBox = FindWindowEx(hInputBox, 0&, "Edit", "")
Call SendMessage(hInputBox, &HC, 0, ByVal "***ファイルPATH**")
’④捕まえたハンドル(handle)から”開く”ボタンのハンドルを取得する
Dim hButton As Long
hButton = FindWindowEx(handle, 0&, "Button", "開く(&O)") '開くボタン
Call SendMessage(hButton, &HF5, 0, 0&) 'ボタンをクリックする
End Sub
みたいな感じになります。
①は同じですね。
②は、ファイ選択ダイアログボックスのクラス名は「♯32770」になるので注意してください。
③ファイル名を入れるところに、ファイルPATHを入れる必要がありますが、何階層かになっているので順番に取得していきます。
最後に、SendMessageでファイルPATHを送信です。
④ファイルを確定するには、通常”開く”ボタンを押しますね。
開くボタンを取得して、SendMessage関数を使ってボタン押下の命令を出します。
SeleniumBasicと合わせてWEBアプリを操作
SeleniumBasicでブラウザ操作しながら、ファイルのアップロードなどでダイアログボックスが出てきたらWindowsAPIで操作
みたいな感じで、WEBアプリケーションを操作出来ます!
まとめ
SendKeysでずぼらかまそうとしましたが、やっぱりちゃんとやらんといかんですねw
という勉強になりました(^^♪
安定感抜群で動いてくれますよ。
Seleniumに関する他の記事はこちら
【EXCEL VBA | ノート】Selenium Basicを使うならXPathを覚えよう!要素の指定/上級偏
こんにちは!ひらちんです! WEBブラウザの自動操作でおなじみの”Selenium”について、要素の指定をするときに便利なXPathの基本的な使い方を...
【EXCEL VBA | ノート】Selenium Basicを使うならXPathを覚えよう!要素の指定/中級編
こんにちは!ひらちんです! WEBブラウザの自動操作でおなじみの”Selenium”について、要素の指定をするときに便利なXPathの基本的な使い方を...
【EXCEL VBA | ノート】Selenium Basicを使うならXPathを覚えよう!要素の指定/基本編
こんにちは!ひらちんです! WEBブラウザの自動操作でおなじみの”Selenium”について、要素の指定をするときに便利なXPathの基本的な使い方を...
【EXCEL VBA | ノート】ダウンロードしたマクロ入りファイルが実行出来ないときは、これを試して!
こんにちは!ひらちんです! マイクロソフトさんが、2022年2月7日(現地時間)に明らかにした方針 インターネットから入手したVBA(Visual B...
【Python | Selenium4】”WEBブラウザを操作して、スクレイピングするぞ!(次の1歩のその2)
以下の記事で、「”WEBブラウザを操作して、スクレイピングするぞ!(次の1歩)」の記事を書いたんですが、Selenium4では少しお作法が違うようなの...
【Python | Selenium】”WEBブラウザを操作して、スクレイピングするぞ!(次の1歩)
以前に、初めの1歩として次の”Selenium”の初め方について紹介しました! 今回は、次の1歩として、要素の取得方法やボタンの押し方など基本的な操作...
【Python | Selenium】”WEBブラウザを操作して、スクレイピングするぞ!(初めの1歩)
スポンサーリンク スポンサーリンク Seleniumの使い方 Seleniumは、ブラウザの操作を行う機能を持ったライブラリです。主にはWEBアプリケ...
【EXCEL VBA | Selenium】スクロール出来るモーダルウィンドウ内の要素を表示範囲内に持ってくる
要素を画面内に表示する Seleniumでブラウザを操作していると必ずぶち当たりますが、Seleniumでチャックボックスとかボタンをクリックしたいと...
【EXCEL VBA | ノート】SendKeysでパソコンのキー操作を自動化する
SendKeysでパソコンのキー操作を自動化する SeleniumBasic使って、ブラウザ操作を自動化してるんですが、ファイル選択のダイアログボック...
【EXCEL VBA | ノート】WEBブラウザを自動操作する!Selenium Basicの使い方!その2(Chrome編)
SeleniumBasicの始め方 SeleniumBasicって何?って言う方は、まずはこちらの記事をどうぞ。 始め方を説明しています! ※Sele...
コメント
[…] 【EXCEL VBA | ノート】Windowハンドルを取得して、ファイル選択ダイアログボックスを操作する 投稿日: 2022年3月17日2022年3月17日作成者 y-uechiカテゴリー VBA関連 […]
[…] 【EXCEL VBA | ノート】Windowハンドルを取得して、ファイル選択ダイアログボックスを操作する 投稿日: 2022年3月17日作成者 y-uechiカテゴリー 未分類 […]
(ファイル選択ダイアログボックスを操作する)でファイルパスを変数にしたいのですが、どうすれば良いか教えてください。
@たろさん
コメントありがとうございます!
Sub sample()
’②ファイル選択ダイアログボックスのハンドルを捕まえる
Dim handle As Long
handle = FindWindow("#32770", "開く")
'③捕まえたハンドル(handle)から入力ボックス(ファイル名が入るところ)のハンドルを捕まえる
Dim hInputBox As Long
hInputBox = FindWindowEx(handle, 0&, "ComboBoxEx32", "")
hInputBox = FindWindowEx(hInputBox, 0&, "ComboBox", "")
hInputBox = FindWindowEx(hInputBox, 0&, "Edit", "")
Call SendMessage(hInputBox, &HC, 0, ByVal "*ファイルPATH")
’④捕まえたハンドル(handle)から”開く”ボタンのハンドルを取得する
Dim hButton As Long
hButton = FindWindowEx(handle, 0&, "Button", "開く(&O)") '開くボタン
Call SendMessage(hButton, &HF5, 0, 0&) 'ボタンをクリックする
End Sub
これの
Call SendMessage(hInputBox, &HC, 0, ByVal "*ファイルPATH")
の部分でしょうか?
Dim path As String: path = "*ファイルPATH"
Call SendMessage(hInputBox, &HC, 0, ByVal path)
にしてはいかがでしょう?