初めてのIE操作(7)~InternetExplorerオブジェクトが現在表示中のDocumentを返してくれない問題に対応する
InternetExplorerオブジェクトが現在表示中のDocumentを返してくれない問題への対応
前々回の問題点の項でも触れたとおり、VBAからHTML上の要素に対してclick
メソッドを実行してページ移動した場合、親元のInternetExplorer
オブジェクトのDocument
プロパティがちゃんと移動後のHTMLDocument
オブジェクトを返してくれる場合と、移動前のHTMLDocument
オブジェクトを返す場合がある。
素人の私にはなぜこんなわけのわからないことになるのかサッパリ不明だが、とにかく処理の結果が気まぐれというのは実に困る。仕事でIEを自動操縦するというのは、シェフがサラダを作るのとは違うのだ。
強引な対応
原因がわからない以上、素人の私としては対症療法的に対応せざるを得ない。踊るダメ人間が生きて行かざるを得ないように。
そこで、登場するのが、
このときに作成したgetIEByTitle
メソッド。
InternetExplorer
オブジェクトのDocument
プロパティが移動後のHTMLDocument
オブジェクトを返してくれないときでも、画面上にはちゃんと移動後のページが表示されているのである。
ならば、ウインドウに表示されているIEを再び捕まえ直せばよいわけだ。
そこで、前々回のリスト1に、次のようにコードを追加する。
リスト1 標準モジュール
Public Sub test() Dim targetIE As New InternetExplorer With targetIE .Visible = True Call .Navigate("http://akashi-keirin.hatenablog.com/entry/2018/12/16/001606") Do While .Busy Or _ .ReadyState <> READYSTATE_COMPLETE DoEvents Loop End With Dim targetTextBox As Object Set targetTextBox = getElementByTagAndKeyWord(targetIE, "input", "name=""q""") targetTextBox.Value = "ち~んw" Dim targetButton As Object Set targetButton = getElementByTagAndKeyWord(targetIE, "input", "value=""検索""") targetButton.Click '(1)' Dim n As Long n = 1 Do DoEvents Call WindowsAPI.waitFor(1000) '(2)' If n > 2 Then _ Set targetIE = Nothing: _ Set targetIE = getIEByTitle("ち~んw") '(3)' Debug.Print "Wait " & n & " 回目:" & targetIE.Document.Title n = n + 1 '(4)' If n > 5 Then targetIE.Quit: Exit Sub Loop Until isTargetPage(targetIE.Document, "ち~んw") Debug.Print "終了間際:" & targetIE.Document.Title End Sub
追加したのは(1)からの13行(実質11行)。
カウンタ変数「n
」を準備した後のDo
ループ、
Do DoEvents Call WindowsAPI.waitFor(1000) '(2)' If n > 2 Then _ Set targetIE = Nothing: _ Set targetIE = getIEByTitle("ち~んw") '(3)' Debug.Print "Wait " & n & " 回目:" & targetIE.Document.Title n = n + 1 '(4)' If n > 5 Then targetIE.Quit: Exit Sub Loop Until isTargetPage(targetIE.Document, "ち~んw")
では、終了条件判定に、
前回
ご紹介したisTargetPage
というメソッドを用いている。
InternetExplorer
オブジェクトのDocument
プロパティの返り値の返り値を調べ、今回の場合だとtitle
プロパティの返り値に「ち~んw
」が含まれていたら目当てのページが表示されているとみなす。
Do
ループ内部では、カウンタ変数「n」の値が2
を超えていたら、すなわちループ3周目に入ると、今のインスタンスtargetIE
に見切りをつけて、getIEByTitle
メソッドでタイトルに「ち~んw
」が含まれるウインドウを捕まえてInternetExplorer
オブジェクトをtargetIE
にセットし直す。
(3)の
Debug.Print "Wait " & n & " 回目:" & targetIE.Document.Title
は動作確認用。何回目の試行で正しいページが取得できているのか確かめる用。
(4)の
If n > 5 Then targetIE.Quit: Exit Sub
はページが移動できていない時用。
そもそもページが移動できていなければ無限ループになってしまうので、試行5回で見切りをつけてやめてしまうようにする。
実行
イミディエイト・ウインドウの様子をどうぞ。
2回失敗して3回目で無理矢理目的のページを取得したっぽい。
おわりに
決して美しい対応ではないけれど、致し方ないとは思う。
実は、ここまでの過程で当初の目的であった職場に導入されたWebアプリの攻略は終わっているので、このシリーズも今回でおしまい。
再びIE操作を取り上げる日は来るのか!?