Excel VBAでIEを操作 iframe(インナーフレーム)を操作する
2018/11/04
フレームページは随分と減少しましたが、まだまだ現役のiframe(インナーフレーム)をExcelマクロから操作する方法を今回は紹介します。
前準備
- Visual Basic Editor の画面から「ツール」→「参照設定」を選択します。
- 「Microsoft Internet Controls」と「Microsoft HTML Object Library」にチェックを入れて、OKを押す
iframeを操作する
ヒトがieのiframeの処理をする場合は以下の操作をします。
- IEを立ち上げる
- URLを入力する
- サイトが表示されるのを待つ
- フレームページが表示されるのを待つ
- インナーフレームの中身を操作する
上記をVBAで表現すると以下のようになります。
実際のコード
Option Explicit Dim i As Integer Dim objIE As InternetExplorer Dim objFrames As FramesCollection Dim ieDoc As HTMLDocument Dim iframeDoc As HTMLDocument Sub html_get() For Each objIE In CreateObject("Shell.Application").Windows If LCase(objIE.FullName) Like "*iexplore.exe" Then While objIE.Busy Or objIE.readyState <> READYSTATE_COMPLETE DoEvents Wend Set ieDoc = objIE.document If ieDoc.frames.Length > 0 Then For i = 0 To ieDoc.frames.Length - 1 On Error Resume Next Set iframeDoc = ieDoc.frames(i).document On Error GoTo 0 If Not iframeDoc Is Nothing Then While iframeDoc.readyState <> "complete" DoEvents Wend End If Next End If ieDoc.frames(0).document.getElementsByTagName("a")(0).Click End If Next End Sub
実際にインナーフレームページの内容が画面遷移されていませんか?
では、ソースの解説です。
変数を宣言
Option Explicit Dim i As Integer Dim objIE As InternetExplorer Dim objFrames As FramesCollection Dim ieDoc As HTMLDocument Dim iframeDoc As HTMLDocument
使用する変数を宣言しています。
一応フレームページのため、「FramesCollection」用の変数をしていますが、今回は使用していません。
URL指定してサイトが表示されるのを待つ
Sub IE_open() 'Internet Exploreを立ち上げる Set objIE = CreateObject("InternetExplorer.Application") objIE.Visible = True 'URLを指定する objIE.Navigate "https://www.yahoo.co.jp/" '該当のWebサイトが表示されるのを待つ While objIE.Busy Or objIE.readyState <> READYSTATE_COMPLETE DoEvents Wend 'ドキュメントをオブジェクトに入れる Set ieDoc = objIE.document ・・・・ End Sub
ここまではいつもな感じです。
初めて見る方は、以下のサイトでここまでをもう少し詳しく解説していますので、よろしければご覧ください。
フレームの数を数える
ieDoc.frames.Length
ドキュメントにフレーム数をカウントしています。
数は「Length」プロパティにセットされます。
「iframe」もしくは「frame」の数が収録されます。
フレームがあった場合、処理をする
If ieDoc.frames.Length > 0 Then ・・・・ End if
フレームがあった場合、「・・・・」の処理をします。
フレーム内のサイトが表示されるのを待つ
For i = 0 To ieDoc.frames.Length - 1 On Error Resume Next Set iframeDoc = ieDoc.frames(i).document On Error GoTo 0 If Not iframeDoc Is Nothing Then While iframeDoc.readyState <> "complete" DoEvents Wend End If Next
親ページの「busy」や「ReadyState」だけではフレーム側のページが表示されているかを厳密には判断できません。
そのため、フレームページ側の処理が終了されていることも確認します。
まずフレームページは「0」から始まる配列に収録されてますので、フレームページの数だけ、フレームページ側の「readyState」を確認する必要があります。
注意したいのは、
- フレーム側のドキュメントをオブジェクトに入れることができないことがあります。
(Youtubeなどで確認してみてください)
そのためにオブジェクトにセットできずにエラーとなってもいいように「On Error」を入れています。
「readyState」の確認方法も以下の通り異なります。
- フレームページ側の「readyState」は「document」に収録されていること
- 変数は「4」ではなく「complete」で返却されること
フレーム内を操作する(クリック)
ieDoc.frames(0).document.getElementsByTagName("a")(0).Click
上記の通り、一番目のフレームに対して最初のアンカータグをクリックするような操作は、他のページと操作方法は大きく変わりません。
通常は「ieDoc」に対して、「操作対象タグを探し」て「操作する」やり方でしたが、iframe(インナーフレームページ)の場合は
「ieDoc.frames(フレーム番号).document」に対して「操作」することとなります。