初めてのIE操作(7)~InternetExplorerオブジェクトが現在表示中のDocumentを返してくれない問題に対応する

InternetExplorerオブジェクトが現在表示中のDocumentを返してくれない問題への対応

前々回の問題点の項でも触れたとおり、VBAからHTML上の要素に対してclickメソッドを実行してページ移動した場合、親元のInternetExplorerオブジェクトのDocumentプロパティがちゃんと移動後のHTMLDocumentオブジェクトを返してくれる場合と、移動前のHTMLDocumentオブジェクトを返す場合がある。

素人の私にはなぜこんなわけのわからないことになるのかサッパリ不明だが、とにかく処理の結果が気まぐれというのは実に困る。仕事でIEを自動操縦するというのは、シェフがサラダを作るのとは違うのだ。

強引な対応

原因がわからない以上、素人の私としては対症療法的に対応せざるを得ない。踊るダメ人間が生きて行かざるを得ないように。

そこで、登場するのが、

akashi-keirin.hatenablog.com

このときに作成した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")

では、終了条件判定に、

前回

akashi-keirin.hatenablog.com

ご紹介した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回で見切りをつけてやめてしまうようにする。

実行

イミディエイト・ウインドウの様子をどうぞ。

f:id:akashi_keirin:20181229182111g:plain

2回失敗して3回目で無理矢理目的のページを取得したっぽい。

おわりに

決して美しい対応ではないけれど、致し方ないとは思う。

実は、ここまでの過程で当初の目的であった職場に導入されたWebアプリの攻略は終わっているので、このシリーズも今回でおしまい。

再びIE操作を取り上げる日は来るのか!?

参考

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com