The third way to get web page from the web by Excel VBA
第一の方法とは
次のソースコードを見てください。
#If VBA7 Then
Private Declare PtrSafe Function GetInputState Lib "user32" () As LongPtr
#Else
Private Declare Function GetInputState Lib "user32" () As Long
#End If
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
#End If
Private Function F_GetHTMLDoc(ByVal IE As InternetExplorer, _
ByVal URL As String, _
ByVal mySecond As Long, Optional _
ByVal Flag As Boolean = False) _
As HTMLDocument
IE.Navigate URL
IE.Visible = Flag
Dim myTime As Date: myTime = Now + TimeSerial(0, 0, mySecond)
Do While IE.Busy = True Or IE.ReadyState <> READYSTATE_COMPLETE
If GetInputState() = True Then DoEvents
Sleep 1
If Now > myTime Then
IE.Refresh
myTime = Now + TimeSerial(0, 0, mySecond)
End If
Loop
myTime = Now + TimeSerial(0, 0, mySecond)
Do While IE.Document.ReadyState <> "complete"
If GetInputState() = True Then DoEvents
Sleep 1
If Now > myTime Then
IE.Refresh
myTime = Now + TimeSerial(0, 0, mySecond)
End If
Loop
Set F_GetHTMLDoc = IE.Document
End Function
第一の方法は、「Microsoft Internet Controls」と「Microsoft HTML Object Library」を参照して、InternetExplorerオブジェクトを利用して、NavigateメソッドでURLを読み込み、DocumentプロパティでHTMLDocumentオブジェクトを取得します。
InternetExplorerオブジェクトとHTMLDocumentオブジェクトの両方を使うので、確実ですが、遅い方法です。
第二の方法とは
#If VBA7 Then
Private Declare PtrSafe Function GetInputState Lib "user32" () As LongPtr
#Else
Private Declare Function GetInputState Lib "user32" () As Long
#End If
#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
#End If
Private Function F_GetHTMLDoc2(ByVal URL As String) As HTMLDocument
Dim HTML As MSHTML.HTMLDocument
Set HTML = New MSHTML.HTMLDocument
Dim myDocument As MSHTML.HTMLDocument
Set myDocument = HTML.createDocumentFromUrl(URL, vbNullString)
Do While HTML.ReadyState <> "complete"
If GetInputState() = True Then DoEvents
Sleep 1
Loop
Set F_GetHTMLDoc2 = myDocument
Set HTML = Nothing
Set myDocument = Nothing
End Function
第二の方法は、「Microsoft HTML Object Library」のみを参照して、InternetExplorerオブジェクトは利用せずに、直接HTMLDocumentオブジェクトを取得します。
InternetExplorerオブジェクトを使わないので、第一の方法よりは速い方法です。
まずは親となるHTMLDocumentオブジェクトを変数「HTML」で用意します。
「createDocumentFromUrl」メソッドでURLにアクセスし、HTMLDocumentオブジェクト取得し、変数「myDocument」に格納します。
第三の方法とは
Private Function F_GetHTMLDoc3(ByVal URL As String) As HTMLDocument
Dim HTTP As Object
Set HTTP = CreateObject("MSXML2.XMLHTTP")
HTTP.Open "GET", URL, False
HTTP.send (Null)
Dim myHTMLDocument As IHTMLDocument
Set myHTMLDocument = New IHTMLDocument
myHTMLDocument.Write HTTP.responseText
Set F_GetHTMLDoc3 = myHTMLDocument
Set myHTMLDocument = Nothing
Set HTTP = Nothing
End Function
第三の方法は、「Microsoft XML. v3.0」、「Microsoft HTML Object Library」を参照します。参照結果は、変数「F_GetHTMLDoc3」にHTMLDocumentオブジェクトとして格納されます。
この方法では、スピードは最速なのですが、第一・第二の方法と違い、HTMLDocumentオブジェクトではなく、文字列型データを戻り値とすることに注意が必要です。
つまり、「HTTP.responseText」の戻り値はHTMLDocumentオブジェクトではないので、取得データに対して「getElementsByClassName」メソッドなどのHTMLDocumentオブジェクトの機能(メソッド・プロパティ)が使えないのです。
ですから、自前でHTMLDocumentオブジェクトを作成します。
変数「myHTMLDocument」を用意して、「Write」メソッドで「HTTP.responseText」の文字列データを書き込みます。
一つ、注意点としては、変数「myHTMLDocument」のデータ型は、「HTMLDocument」型や、「IHTMLDocument2」型ではダメで、「IHTMLDocument」型である必要があります。
たしかに「Write」メソッドを規定しているのは「IHTMLDocument2」インターフェイスですが、実は、「IHTMLDocument」のインターフェイスには「IHTMLDocument interface」から「ihtmldocument8 interface」の8つがあります。したがって、「Write」メソッドを使うには、これらを代表して「IHTMLDocument」型を使う必要があるのではないか、と考えています。
ということで、第二の方法よりもスピードが速いときに限って、この方法を使うメリットがあります。
もう一つのメリットとしては、IEを使わないということです。今後、Edgeが企業でのデフォルト・ブラウザになるような状況が実現すれば、あるいは現状のようにGoogle Chromeが実質デフォルトである間は、この方法も一定の存在価値があるということです。
おわりに
考え方としては、まず第一の方法で作ってみる、スピードに満足できないときは第三の方法で試してみる、第三の方法で安定性に欠けるときは第二の方法を試してみる、という手順で考えるのがいいのではないしょうか。


コメントを残す