Navigateメソッドを利用して指定したURLをIEで起動させる
<< エクセルVBAでIE制御の基本操作 :前の記事
こちらでは、指定したURLをIE(InternetExplorer)で起動させる制御方法について解説しています。IE起動にはInternetExplorerオブジェクトの「Navigateメソッド」を利用していきます。
Navigateメソッドは指定したURLのWebページを表示させる処理になりますが、Webページが完全に読み込まれる待機処理とは別の処理になりますので、こちらについても詳しく解説していきます。
目次
- 指定したURLをIE(InternetExplorer)で起動させる処理の流れ
- 利用するVBA関数・メソッド・プロパティについて
- 指定したURLをIE(InternetExplorer)で起動させるサンプルコード
- 改良版サンプルコード
- まとめ
指定したURLをIE(InternetExplorer)で起動させる処理の流れ
本サイトでは、まずどのような処理を行っていくのかについて最初に説明していきます。個人的には、どのような処理を行っていくのかという全体像を把握した上で具体的なプログラムの書き方を学んだほうがより理解力が深まると考えているからです。
以下が今回の処理の流れになります。
- ①変数宣言
- ②IEオブジェクトを生成
※IEオブジェクトのメソッド・プロパティを利用できる状態にします。 - ③IEオブジェクトを表示
※ブラウザを視覚的に表示します。 - ④指定したURLを表示
- ⑤Webページが完全に読み込まれるまで処理を待機
※Webページの表示と読込み完了処理は別の処理になります。
利用するVBA関数・メソッド・プロパティについて
今回利用するVBA関数・メソッド・プロパティは以下になります。
- CreateObject関数
- DoEvents関数
- Now関数
- TimeSerial関数
- Navigateメソッド
- Visibleプロパティ
- Busyプロパティ
- InternetExplorerオオブジェクトのReadyStateプロパティ
- DocumentオブジェクトのReadyStateプロパティ
- Refreshメソッド
CreateObject関数とは
CreateObject関数はオートメーション機能を利用して一時的なオブジェクトを作成する関数です。この関数を利用すると、外部アプリケーションをオブジェクトとして操作することが可能となります。
Set オブジェクト変数名 = CreateObject("アプリケーション名・オブジェクトの種類")
DoEvents関数とは
DoEvents関数は、処理の途中にオペレーティングシステムに制御を移すための関数です。時間のかかる処理やループ処理の場合、処理が完了するまでOS(オペレーティングシステム)は制御を行うことができません。(ループ処理中は、OSやExcelそのものにも再描画をさせる暇さえ与えません。)
そこで、DoEvents関数を利用することで一時的にOS(オペレーティングシステム)に制御を移して、処理を行うことができます。長期のループ処理や無限ループ処理に陥った場合に利用されることが多いですが、使いすぎると処理は安定するものの処理時間が長くなってしまうこともあるので注意しましょう。
DoEvents
Now関数とは
Now関数は、利用しているコンピュータシステムの日付と時刻の設定に基づいて、現在の日付と時刻を表すバリアント型の値を返す関数です。今回は、無限ループ対策で利用されます。
Now
TimeSerial関数とは
TimeSerial関数は、引数で指定した時、分、秒に対応する時刻を含むバリアント型の値を返す関数です。こちらも無限ループ対策で利用されます。
TimeSerial(0, 0, 20)
Navigateメソッドとは
InternetExplorerオブジェクトのNavigateメソッドは指定したURLをIE(InternetExplorer)で表示させます。5つの引数が用意されていますが、こちらでは必須項目であるURLだけを利用していきます。
objIE.Navigate ("IEに表示させるWebページのURL")
Visibleプロパティとは
InternetExplorerオブジェクトのVisibleプロパティはInternetExplorerオブジェクトを表示するか非表示にするかを設定できます。非表示にしたとしても視覚的に見えなくなるだけですので、そのままInternetExplorerオブジェクトを操作することができます。
objIE.Visible = True/False
Busyプロパティとは
InternetExplorerオブジェクトのBusyプロパティはWebページが読み込み中かどうかを示します。Trueは読み込み中でFalseは読み込み完了を表しますが、実際の処理ではTrue→False→True→Falseを繰り返すことがあります。
例えばframeタグやiframeタグを利用しているサイトの場合、最初のフレームの読み込みが完了すると一旦Falseを返しますが、次のフレームの読み込みを開始するとTrueに戻ります。
他にもJavaScriptなどのスクリプト処理でも同様のことが起こる場合がありますので、BusyプロパティだけではWebページの読み込み完了待機処理を補えないことを理解してください。
objIE.Busy = True/False
InternetExplorerオブジェクトのReadyStateプロパティとは
InternetExplorerオブジェクトのReadyStateプロパティはInternetExplorerオブジェクトのドキュメントの読み込み状態を示します。読み込み状態は0~4までの5段階で、Busyプロパティでは不完全だったフレームの読み込みも完全に読み込んでから完了状態を示します。ちなみにWebページの完全読み込み待機処理では、Busyプロパティと併せて利用するのが一般的な方法となります。
objIE.readyState = 0~4
DocumentオブジェクトのReadyStateプロパティとは
DocumentオブジェクトのReadyStateプロパティはDocumentオブジェクトのドキュメントの読み込み状態を示します。読み込み状態は4段階で、文字列で返す点にご注意ください。こちらもWebページの完全読み込み待機処理で利用します。
objIE.document.readyState = "uninitialized"/"loading"/
"interactive"/"complete"
Refreshメソッドとは
InternetExplorerオブジェクトのRefreshメソッドはWebブラウザに表示されているWebページの再読み込み(リフレッシュ)を行うメソッドです。Webブラウザ自体が読み込み失敗している場合などで有効な処理となります。
objIE.Refresh
指定したURLをIE(InternetExplorer)で起動させるサンプルコード
今回のVBAコードは「VBAのIE制御」サイトのトップページを表示させるマクロになります。IE制御では必ず利用する処理になりますのでしっかり覚えましょう。
Sub sample()
Dim objIE As InternetExplorer
'IE(InternetExplorer)のオブジェクトを作成する
Set objIE = CreateObject("InternetExplorer.Application")
'IE(InternetExplorer)を表示する
objIE.Visible = True
'指定したURLのページを表示する
objIE.Navigate "http://www.vba-ie.net/"
'完全にページが表示されるまで待機する
Do While objIE.Busy = True Or objIE.ReadyState <> 4
DoEvents
Loop
End Sub
実行結果
「VBAのIE制御」サイトのトップページが表示されます。
解説
それでは、VBAコードを1つずつ説明していきます。
Sub sample()
Dim objIE As InternetExplorer
こちらはSubステートメントに引数の設定がないsampleプロシージャになります。まずは、変数宣言でメモリ領域を割り当てるDimステートメントを利用してオブジェクト変数objIEにInternetExplorer型を変数宣言しています。
これによりInternetExplorerオブジェクトを作成した際にプロパティやメソッドを利用できるようになりました。
'IE(InternetExplorer)のオブジェクトを作成する
Set objIE = CreateObject("InternetExplorer.Application")
次にオブジェクトを参照するSetステートメントとオブジェクトを作成するCreateObject関数を利用してInternetExplorerのオブジェクトを作成します。
'IE(InternetExplorer)を表示する
objIE.Visible = True
こちらでは、InternetExplorerオブジェクトのVisibleプロパティに「True」が設定されています。VisibleプロパティはIE(InternetExplorer)の表示・非表示の設定になりますので、「True」を設定するとIE(InternetExplorer)が表示されます。
デフォルトでは「False」が設定されており非表示の状態ですが、表示がされないだけでInternetExplorerオブジェクトの操作は可能ですので覚えておきましょう。
'指定したURLのページを表示する
objIE.Navigate "http://www.vba-ie.net/"
指定したURLをIE(InternetExplorer)で表示するInternetExplorerオブジェクトのNavigateメソッドの設定です。第一引数は表示させるWebページのURLの設定になりますので「http://www.vba-ie.net/」を設定すると「VBAのIE制御」サイトのトップページが表示されます。
'完全にページが表示されるまで待機する
Do While objIE.Busy = True Or objIE.ReadyState <> 4
DoEvents
Loop
こちらのコードは他のサイトでも見たことがある方も多いかと思います。Navigateメソッドは指定したWebページを表示させますが、Webブラウザがページを完全に表示するまで処理を待機してくれません。
完全に表示されていない状態で次の処理に進むとエラーが発生したり、思ったとおりの処理を行ってくれない可能性が高くなります。そこで、Webブラウザがページを完全に表示するまで待機する処理を行う必要があります。(Basic認証処理の場合は除く)
待機処理には読み込みの状態を示すInternetExplorerオブジェクトのBusyプロパティとReadyStateプロパティで判断します。Busyプロパティの「True」は読み込み中をReadyStateプロパティの「4」は読み込み完了状態を示します。
以下はReadyStateプロパティの戻り値一覧ですが、4以外の値が読み込み中を示していますので、待機処理の内容は「Busyプロパティの値がTrueまたはReadyStateプロパティ値が4以外の場合はループ処理を繰り返す」処理になります。
定数 | 戻り値 | 説明 |
---|---|---|
READYSTATE_UNINITIALIZED | 0 | デフォルト値。未完了状態。 |
READYSTATE_LOADING | 1 | IEオブジェクトのロード中状態。 |
READYSTATE_LOADED | 2 | IEオブジェクトのロード完了状態。ただし操作不可能状態。 |
READYSTATE_INTERACTIVE | 3 | IEオブジェクトの操作可能状態。 |
READYSTATE_COMPLETE | 4 | IEオブジェクトの全データ読み込み完了状態。 |
ループ処理には条件が満たされる(条件式が真の場合)限り繰り返し処理を行うDo While~Loopステートメントを利用していますので、Busyプロパティが「True」またはReadyStateプロパティが「4でない」間、ループを繰り返します。
余談ですが、ReadyStateプロパティの戻り値には組み込み定数が設定されていますので、「4」を「READYSTATE_COMPLETE」に変更しても同じ内容になります。他サイトでこちらの記述があった場合は、READYSTATE_COMPLETE=4であることを理解しましょう。
'完全にページが表示されるまで待機する
Do While objIE.Busy = True Or objIE.ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
また、ループ内の処理でDoEvents関数を記述しています。通常ループ処理の間は操作を行うことができませんが、処理中にOS(オペレーティングシステム)へ制御を移すDoEvents関数を利用することで、ループ処理中であっても操作が可能となります。ただし、極端にパフォーマンスが低下してしまうなど敬遠されるVBA関数でもあります。
DoEvents関数を記述するかどうかについて個人的な見解としては、Webページを巡回してデータ収集のみを目的とした処理かつパソコン操作をしない場合であれば特に記述する必要はないかと思います。制御ができなかったとしてEscキーで処理を一旦停止させることはできますので他のユーザーが利用しないなど個人的な使用であれば必要性はないと感じます。
さて、ここまで2つのプロパティを使用してWebページの読み込み完了待機処理を行いましたが、稀にWebブラウザが読込を完了せず永遠と読込中になる場合があります。俗にいう「固まった」という状態です。Webブラウザがそのような状態になってしまうと完全に読み込まれるまでループを繰り返しますので、無限ループに陥ってしまいます。
そちらを回避する対策の1つとして、一定時間経過した場合にWebブラウザの再読込処理(リフレッシュ)を加えることでWebページの更新を行い無限ループを回避させます。 当方の場合は、以下のコードでよく制御します。
Dim timeOut As Date
'現在の時間から20秒後の時間
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.Busy = True Or objIE.ReadyState <> 4
DoEvents
Sleep 1
If Now > timeOut Then
'ページの再読み込み(リフレッシュ)
objIE.Refresh
timeOut = Now + TimeSerial(0, 0, 20)
End If
Loop
'現在の時間から20秒後の時間
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.document.ReadyState <> "complete"
DoEvents
Sleep 1
If Now > timeOut Then
'ページの再読み込み(リフレッシュ)
objIE.Refresh
timeOut = Now + TimeSerial(0, 0, 20)
End If
Loop
まず、Dimステートメントを利用して変数timeOutを日付型(Date)で宣言します。そして、現在の時刻を返すNow関数と指定した日付・時刻に対応した数値をDate型へ変換するTimeSerial関数を利用して、変数timeOutに処理時間+20秒を加算した時間を代入します。例をあげると処理時間10:15:20の場合、変数timeOutの値は+20秒の10:15:40になります。
Do While objIE.Busy = True Or objIE.ReadyState <> 4
DoEvents
Sleep 1
(省略)
Loop
こちらは先ほど説明した内容でDo While~Loopステートメントを利用して読み込みが完全に完了するまでループ処理を行っています。ループ内の処理にはDoEvents関数とWindows APIのSleep関数を記述しています。
先ほども説明したようにDoEvents関数は処理の内容によって利用するかどうか判断してください。Windows APIのSleep関数については、ループ処理を行うとCPUを占有してしまいます。
そこで、指定した時間だけ処理を停止させるWindows APIのSleep関数を設定することで処理が停止されCPUの使用率を抑えることができます。こちらでは「Sleep 1」で設定していますが、引数はミリ秒単位ですので「0.001秒」停止する処理になります。
ただデメリットもあり、こちらを処理した回数だけマクロの実行速度が遅くなってしまいます。こちらも処理の内容と環境に合わせて利用するようにしましょう。
If Now > timeOut Then
'ページの再読み込み(リフレッシュ)
objIE.Refresh
timeOut = Now + TimeSerial(0, 0, 20)
End If
続いての処理ですがこちらは、条件分岐ができるIf~Then~Elseステートメントを利用して変数timeOutに格納している時間を過ぎたら、InternetExplorerオブジェクトのRefreshメソッドで一旦ページの再読み込み処理(リフレッシュ)を行い無限ループを回避しています。
再読み込み処理(リフレッシュ)後は、変数timeOutに処理時間+20秒を加算した時間を再度代入します。これでブラウザが固まったとしても再読み込みを行い無限ループを回避できましたが、こちらも完璧というわけではなくスペックの小さいパソコンや容量の大きいWebページを開く場合、通常より読み込みに時間がかかってしまうこともあります。
その読み込み時間が20秒を超えると、逆に「ページ再読み込み(リフレッシュ)」の無限ループに陥ってしまいますので、処理をする内容によって待機時間の変更を行いましょう。
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.document.ReadyState <> "complete"
DoEvents
Sleep 1
If Now > timeOut Then
'ページの再読み込み(リフレッシュ)
objIE.Refresh
timeOut = Now + TimeSerial(0, 0, 20)
End If
Loop
次にこちらの処理について、先ほどまではInternetExplorerオブジェクトの状態を対象にチェックしましたが、こちらはDocumentオブジェクトの状態を対象にチェックを行います。
DocumentオブジェクトはHTMLドキュメントそのものですので、データの抽出やクリック操作などHTMLドキュメントを扱う場合は、より確実に処理できるよう「HTMLドキュメントの読込が完了しているかのチェック」も行った方がより安全です。
ここで注意しなければいけないのは、オブジェクトによってReadyStateプロパティの戻り値が異なる点です。InternetExplorerオブジェクトのReadyStateプロパティは読み込み完了時に整数値の「4」を返しましたが、DocumentオブジェクトのReadyStateプロパティは文字列の「"complete"」を返します。
以下はDocumentオブジェクトのReadyStateプロパティの戻り値一覧になりますが、InternetExplorerオブジェクトのReadyStateプロパティの戻り値と異なっているのがわかるかと思います。
戻り値 | 説明 |
---|---|
"uninitialized" | デフォルト値。読み込み開始前。 |
"loading" | documentオブジェクトの読み込み中。 |
"interactive" | documentオブジェクトの読み込み中で操作可能。 |
"complete" | documentオブジェクトの読み込み完了。 |
このように同じプロパティやメソッドであってもオブジェクトによって戻り値や設定内容が異なるため、本サイトでは必ずどのオブジェクトに対してのプロパティやメソッドなのかを記述しています。その点を意識して読み進めるとより理解しやすいかと思います。
また、オブジェクト・コレクション・メソッド・プロパティなどVBAの基礎を理解できていない方は「VBA初心者入門」を学習してからIE制御に挑戦すると理解力が深まるかと思いますので一読ください。
さて話を戻すと、Documentオブジェクトの読み込みチェックの処理内容はReadyStateプロパティの設定値が異なるだけで他はまったく同じ処理になります。こちらも読み込みが完了するまでループする処理になっていますので、こちらのループを抜けたとき初めてすべての読み込みが完了したことを表します。
今回は、InternetExplorerオブジェクトのRefreshメソッドで読み込み完了処理の無限ループを回避する方法を紹介しましたが、読み込みが完全でなくても処理を確実に終了させたい場合もあります。
そのような場合は、Refreshメソッドではなく以下のように処理をジャンプさせるGoToステートメントを利用して20秒経過したらループを抜け出す処理にするのも1つの手です。こちらでしたら、時間経過後に確実に次の処理へ進みますので、処理を強制的に進めることができます。
Dim timeOut As Date
'現在の時間から20秒後の時間
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.Busy = True Or objIE.readyState <> 4
DoEvents
Sleep 1
If Now > timeOut Then
'label01へ移動
GoTo label01
End If
Loop
label01:
'現在の時間から20秒後の時間
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.document.ReadyState <> "complete"
DoEvents
Sleep 1
If Now > timeOut Then
'label02へ移動
GoTo label02
End If
Loop
label02:
改良版サンプルコード
こちらはWebページの読み込みが完了するまでの待機処理を考慮したVBAコードです。今回、Windows APIのSleep関数について割愛しましたが、そちらも考慮しています。Windows APIについては改めて解説しますので、こちらでは処理の内容をしっかり理解しましょう。
#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
Sub sample()
Dim objIE As InternetExplorer
Dim timeOut As Date
'IE(InternetExplorer)のオブジェクトを作成する
Set objIE = CreateObject("InternetExplorer.Application")
'IE(InternetExplorer)を表示する
objIE.Visible = True
'指定したURLのページをIEで起動する
objIE.navigate "http://www.vba-ie.net/"
'完全にページが表示されるまで待機する
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.Busy = True Or objIE.readyState <> 4
DoEvents
Sleep 1
If Now > timeOut Then
objIE.Refresh
timeOut = Now + TimeSerial(0, 0, 20)
End If
Loop
timeOut = Now + TimeSerial(0, 0, 20)
Do While objIE.document.ReadyState <> "complete"
DoEvents
Sleep 1
If Now > timeOut Then
objIE.Refresh
timeOut = Now + TimeSerial(0, 0, 20)
End If
Loop
End Sub
まとめ
今回は、Webページを表示させるまでに注意しなければならない点も含めて説明してきました。処理の内容を1つ1つ理解していけばそんなに難しいことはありません。こちらは基本中の基本ですので、しっかり内容を理解しましょう。
次回はプログラムのサブルーチン化についての解説していきます。
次の記事: プログラムのサブルーチン化について >>
近田 伸矢, 植木 悠二, 上田 寛
IEのデータ収集&自動操作のプログラミング本はこの1冊だけ!IEの起動やポップアップウィンドウ、表示を制御する基本的なコードはもちろん、テキストボックスやラジオボタン、表、ハイパーリンクなどのHTML部品を制御する方法など、自動操作に欠かせないノウハウを丁寧に解説。