どうも、マサヤです!
この記事は、VBAでのIE操作が初めて or 慣れていない方向けに『Webサイト・システムの情報を取得・設定する方法』をお伝えしていく連載記事となってます!
前回はリストボックスのJavaScriptを発動させる方法を紹介しました!
今回は「Webサイト上にある「ファイルを選択」のクリック、ファイルを選択する方法」をお伝えします!
「ファイルを選択」をクリックするだけならClickメソッドで可能ですが・・・・・・実は落とし穴があります。
これを解説していきますよ!
ファイル選択のサンプルページ
今回も例にもれずサンプルページを用意しました。
ぜひ理解度を上げるためにも、記事を読む前にサンプルページを触ってみてください。
「ファイルを選択」ボタンのHTMLコード
サンプルのファイル選択のHTMLは下記となります。
<input id="add-file" type="file">
idが付与されているので、VBAではgetElementByIdを使って操作していきます。
失敗:Clickメソッドだけでは失敗する
では、Clickメソッドだけで実行した例をみていきましょう。
動画で失敗例を見る
では、Clickメソッドだけで実行した動画をご覧ください。
失敗するVBAコード
下記が失敗するコードになります。
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr) Sub ie_AddFile() 'IEオブジェクトを作成 Dim ie As InternetExplorer Set ie = CreateObject("InternetExplorer.Application") 'HTMLコレクションを取得 独自関数化 Call IeGetObj(ie, "https://mmm-program.com/vba-ie-sumple-file/") 'ファイルを選択をクリック ie.document.getElementById("add-file").Click 'クリップボードにコピー Dim CB As New DataObject Dim buf As String 'ファイルのパス設定 buf = "C:\Users\masay\Downloads\テスト.png" With CB .SetText buf '変数のデータをDataObjectに格納する .PutInClipboard 'DataObjectのデータをクリップボードに格納する End With Sleep 2000 'キー操作 Ctrl+V を実行 SendKeys "^v" Sleep 1000 'キー操作 Altl+o を実行 SendKeys "%o" 'オブジェクトを閉じる ie.Quit 'メモリからオブジェクトを破棄 Set ie = Nothing End Sub '指定URLのオブジェクトを取得する独自関数 Sub IeGetObj(obj, url, Optional vFlg As Boolean = True) 'IEを表示(見えるようにする) obj.Visible = vFlg '指定したURLをIEで開く obj.navigate url 'サイトの読み込みが完了するまで待つ Do While obj.Busy = True Or obj.readyState <> READYSTATE_COMPLETE DoEvents Loop End Sub
なぜ、Clickメソッドでは失敗するのか?
前途のコードは一見すると問題なさそうですが、どこが問題なんでしょうか?
本来であれば、ファイル選択画面が表示されたら次のプログラムを実行してほしいわけですが、下記コード実行すると、IE処理からWindowsのファイル選択画面となり、プログラムとしてはIE処理が途中と認識して、ファイル選択の画面を閉じられるまで次の行にあるプログラム処理へ移行できません。
ie.document.getElementById("add-file").Click
成功:ファイルを選択を成功させた動画
では、成功させるコードをみていきましょう。
まずは動画で動きを確認してから、VBAコードを見ていきましょう。
VBAコードでJavaScriptが発動した動画
↑の動画を見ると、ファイル選択後の画面でもプログラムは止まらず、ファイル名を入力⇒開くと操作が続いてることが確認できます。
何が違うのか?
コードを見ていきましょう。
このVBAコードでファイル選択が成功!
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr) Sub ie_AddFile() 'IEオブジェクトを作成 Dim ie As InternetExplorer Set ie = CreateObject("InternetExplorer.Application") 'HTMLコレクションを取得 独自関数化 Call IeGetObj(ie, "https://mmm-program.com/vba-ie-sumple-file/") '「ファイルを選択する」をクリックする ie.document.parentWindow.execScript "window.setTimeout(""document.getElementById('add-file').click()"",100);" 'クリップボードにコピー Dim CB As New DataObject Dim buf As String 'ファイルのパス設定 buf = "C:\Users\masay\Downloads\テスト.png" With CB .SetText buf '変数のデータをDataObjectに格納する .PutInClipboard 'DataObjectのデータをクリップボードに格納する End With Sleep 2000 'キー操作 Ctrl+V を実行 SendKeys "^v" Sleep 1000 'キー操作 Altl+o を実行 SendKeys "%o" 'オブジェクトを閉じる ie.Quit 'メモリからオブジェクトを破棄 Set ie = Nothing End Sub
コードを見るとClickメソッドではなく、何が長いコードを使っているのが解ります。
parentWindow.execScriptがポイント
Clickメソッドの代わりに下記のコードを利用しています。
ie.document.parentWindow.execScript "window.setTimeout(""document.getElementById('add-file').click()"",100);"
これは「100ミリ秒後にid属性add-file(ファイルを選択ボタン)をクリックしろ」といったコードになってます。
parentWindow.exeScriptは、IE側にスクリプト処理を依頼することができるメソッドになります。
ただ、IE側にスクリプト処理が完了するまで、次のプログラムに進めません。
これを回避するために、JavaScriptのsetTimeoutメソッドで対処しています。
setTimeoutは「何秒後に●●処理しなさい」と命令した段階で処理完了扱いとなり次のプログラムを処理することができるようになります。
お気づきの方がいるかもしれませんが、VBSを作成・実行することでVBAとVBSでの疑似マルチスレッドで同じことが可能ですが、少し面倒なので簡単に済むsetTimeoutメソッドを使ってます。
注意!スクリプトの書き方
parentWindow.execScriptの””(ダブルクォーテーション)の中に書くスクリプトは、JavaScriptで正しく書きましょう。
大文字・小文字や使用するカッコなどを間違えると、エラー or エラーは出ないが想定処理がされない
例えば、Clickメソッドを下記のように書いてもダメです。
VBAでは正解ですが、JavaScriptではclick()が正しいため正しく処理されません。
詳しく言うと、エラーは発生しませんがクリック処理がされません。
また、要素番号をしているときに利用するカッコは、()ではなく[]なので注意しましょう。
まとめ
Webサイトでのファイル選択(添付)の方法をお伝えしました。
さて、今回でIE操作編は最後となります。
ここまでお読みいただいてありがとうございました!
1回目から実践しながら追っていれば、IE操作処理に困ることはほぼなくなっているでしょう。
まさに自由自在にWeb操作できるようになっていると思います。
もし、あなたが単調なデータ収集や入力操作で時間を使っているなら、ぜひ学んだことを生かして自動化してみてくださいね。
さて、IE操作編は連載としては終了しましたが、ピンポイントで操作方法や補足知識などを不定期でお届けする予定です。
コメント