VBAでIEを操る(処理・読み込みを待機する)
今回はIEの操作を行った後に発生する処理および読み込みを待って、次の操作を行うといったことに焦点を当てて話を進めていきたいと思います。
前回も書きましたが、読み込み完了を待たずに次の操作を行っても空振りする場合があるので、何らかの形で処理を待機させる必要があります。
処理を待機するには次の2通りが考えられると思います。
- IEの状態を監視する
- 時間的なウエイトを挿入する
IEの状態を監視する、については、書籍やネットでよく紹介されるのは下記のようなものです。
Do While ie.Busy Or ie.readyState < READYSTATE_COMPLETE
DoEvents
Loop
ie.Busy は、名前の通り ieのBusy状態を取得するプロパティです。Busy(処理中)であれば Trueを、それ以外には Falseを返します。
ie.readyStateは、ドキュメントの読み込み状態を取得するプロパティです。読み込みの段階によって、0~4の数値が返されます(4で完了)。READYSTATE_COMPLETE は、4 を表す定数です。
この2つを組み合わせて、「Busy状態」または「読み込み段階が4未満」であれば待機する、というのが上記コードの内容です。
しかし・・・・・・世界に存在するあまたのWebページは千差万別であり、必ずしも上記コードで待機できる保障はありません_| ̄|○
そういう時は、時間的なウエイトを挿入するで解決します。Win64/32 API関数の Sleep を使って、単純に指定時間、処理を待機させます。
3秒待機するなら、下記のようにします。引数はミリ秒で指定します。(下記は、Win32 API での例)
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sleep 3000
太字の箇所は、使用するWin32 API関数のありかをVBAに教えるためのもので、モジュールの先頭(宣言エリア)記述します。
Privateで宣言された関数はモジュール内でのみ使用可能で、Publicまたは省略で宣言された関数は他のモジュールでも使用可能になります。(この辺はまた別の機会に・・・・・・)
ただし、時間的なウエイトで待つというのは不確定要素なので、回線が込み合っていたり・サーバーが重くなっていたり・自身のPCのが重くなっていても確実に待機させるのなら、たっぷり時間を指定する必要があります。
IEの状態を監視するのと、時間的なウエイトを挿入するのを組み合わせるのももちろんアリです。
どうしても、プログラムに最短で処理をさせたいのであれば、ページ毎に最適な待機方法をあみだす・・・・・・という手もあるのですが、IEの時代も終わりが見えてきているのに、それに時間をかけるのは私はナンセンスだと思います。
私はたっぷりと Sleepを入れて、プログラムが終わるまでは割り切って、コーヒーブレイクにするか、PC以外の仕事をするようにしてます。
一律 Sleepを思考停止ととらえるか、時間的コストダウンととらえるかは、人それぞれだと思います(@_@;)
前回紹介したコードに、Sleepをかませてループさせるものはこちら
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub test()
Dim ie As Object
Dim sh As Object
Dim win As Object
Dim i As Integer
Set sh = CreateObject("Shell.Application")
For Each win In sh.Windows
If win.Name = "Internet Explorer" Then
Set ie = win
Exit For
End If
Next
For i = 1 To 5
ie.document.getElementsByClassName("hatena-star-add-button")(0).Click
Sleep 1000
Next i
End Sub