
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が実質デフォルトである間は、この方法も一定の存在価値があるということです。
おわりに
考え方としては、まず第一の方法で作ってみる、スピードに満足できないときは第三の方法で試してみる、第三の方法で安定性に欠けるときは第二の方法を試してみる、という手順で考えるのがいいのではないしょうか。
コメントを残す