【エクセルVBAでIE操作】ブラウザの読み込み待ちをしないとダメなのです


待つ犬

みなさん、こんにちは!
テンポよくブログ更新していますタカハシ(@ntakahashi0505)です。

初心者向けエクセルVBAでIEを操作するシリーズの第3回目です。

前回はこちらの記事で

【エクセルVBAでIE操作】HTMLタグと要素そしてドキュメントの取得
初心者向けエクセルVBAでIEを操作するシリーズの第2回目です。今回はHTMLタグと要素について簡単に説明をしつつIEで開いたページのHTMLドキュメントを取得する方法についてお伝えします。

HTMLタグと要素についての説明とHTMLドキュメントの取得についてのお話をしました。

ですが、実際に動かしてみたらエラーが出た…という明らかに中途半端なところで終わらしてしまってごめんなさい。

今回はIEの読み込み待ちの処理を入れることで、そのエラーをバッチリ解決していきますよ。

この処理はVBAでIEを扱う限りはほとんどの場合で必要となる処理ですので、ぜひ覚えて頂ければと思います。

前回のおさらい

前回のプログラムはこちらでした。

HTMLドキュメントを格納するhtmlDocというオブジェクト変数を用意して、IEで開いたページのHTMLドキュメントをセット。

そして取得したHTMLドキュメントのTitleつまりWEBページのタイトルをイミディエイトウィンドウに表示する、という内容でした。

しかし、実行してみると

オートメーションエラー

こんなエラー画面が出てしまいました。

特定できません、って…

でも安心して下さい。原因はわかっています。

HTMLドキュメントの取得の際に発生するエラーの原因

このエラーの原因を解明していきます。

まずこの命令でIEが指定したURLのページを読み込んでくるのですが、どんなに通信環境がよいところでも少し読み込むまでに時間がかかりますよね?

IEは一生懸命読み込みをしているのですが、VBAはお構いなしに次の命令を実行しに行ってしまいます。

先ほどのエラー画面で「デバッグ」をクリックしてみると

エラーの発生箇所

この黄色の箇所でエラーになっていることがわかります。

ここですね。

何が問題かと言いますとIEがページを読み込み切っていないところで、そのHTMLドキュメントを取得しにいっているのでエラーになっているのです。

要は「存在していないHTMLドキュメントをセットしろ」という命令をしてしまっているということなんです。

無いものはセットできないよ~、てなわけです。

これを避けるために、IEが読み込みが完了したことを確認してから次の処理に移るようにするという対策をとります。

IEブラウザの読み込み待ちの処理

IEのページ読み込みが完了することを待つ処理はこのように書きます。

条件が2つありまして、このどちらかの条件が満たされている間はDoEventsをして、という処理です。

それぞれ説明をしていきますね。

BusyプロパティでIEが忙しいかどうかを判断

まず、InternetExplorerオブジェクトのBusyプロパティです。

InternetExplorerオブジェクト.Busy

BusyプロパティはIEが忙しければTrue、そうでなければFalseを返します。

忙しいですか?と聞いて、忙しいよと回答されている間はDoEventsすることになります。一生懸命読み込みをしている間は当然Busyになっているということですね。

readyStateプロパティでIEが準備完了かどうかを判断

次に、readyStateプロパティです。

InternetExplorerオブジェクト.readyState

readyStateプロパティはIEの準備状態を数値で返します。

準備完了を表す数値は4で、準備が完了していない間は4未満の数値が返ります。

一方で、「READYSTATE_COMPLETE」はなんだか難しく見えますが、ただの定数で4を表しています。

ですから、IEの準備状態が完了つまり4になるまでDoEventsをするということになります。

DoEvents関数でOSに処理を渡す

DoEventsはOSに処理を渡す命令です。

は?って感じですが、少し説明をしますね。

VBAはループ処理をしている間は、OSにすら処理を渡さずに一生懸命ループをします。つまり他のアプリケーションなどがループが終わるまで全て待ち状態になります。

DoEvents

この命令があるタイミングでVBAは一旦OSに対して「待ってる処理ある?」とお伺いを立てにいき、OSの処理を優先してあげるという行動を取ります。

これがないとブラウザでページが表示されるまでの間、画面が固まったような状態になってしまいますので、このDoEventsを入れているということです。

この説明をさらに詳しく知りたい場合はこちらの記事もご覧頂ければと思います。

ゼロからはじめるVBA - その他の関数編 (1) システムで待っている処理を行うため
今回説明する組み込み関数は数値関数、文字列関数、日付関数以外でよく使用される関数です。ループ処理中にシステムで待っている処理を行うための関数(DoEvents)、いままでの例題でよく使用していたデータ表示関数(MsgBox)、セル操作で使用される関数をVBAで使用する方法などについて説明したいと思います。

IEの読み込み待ち処理を入れて実行

以上、IEの読み込み待ち処理について説明をしてきましたが、これを応用してあれこれやることはあまりないと思いますので、このDo~Loopに関してはnavigateでURLでページを開く処理の次に定型で入れたらよいです。

読み込み待ちを入れたプログラムはこちらです。

これを実行すると、イミディエイトウィンドウには

HTMLドキュメントのタイトルを表示

と表示されます。

バッチリですね!

まとめ

このようにエクセルVBAでIEを操作する際には、IEがちゃんと読み込み完了からHTMLドキュメントを取得する必要があります。

これはほとんどの場合で必要になりますので、定型文的にいつも入れるようにするのが良いです。

さて、次回以降いよいよ本格的に取得したHTMLドキュメントから色々な情報を抽出していく方法についてお伝えしていきますね。

まず手始めに、こちらの記事でページ内のリンク先URLをゴソっと取得する方法です。

【エクセルVBAでIE操作】ページ内のリンク先URLを全部取得する
初心者向けエクセルVBAでIEを操作するシリーズの第4回目です。今回はLinksとFor Each~Nextという繰り返し処理を用いてページ内のリンク先URLを全て取得する方法についてお伝えします。

合わせてご覧くださいね!

連載目次:エクセルVBAでIEを操作してWEBスクレイピング

IEを操作してWEBページのデータを取得して、エクセルのデータとして取り込む、つまりWEBスクレイピングをエクセルVBAで実現します。各種WEBページを課題として様々なデータの取得の仕方を解説していきたいと思います。

  1. 【エクセルVBAでIE操作】10分で終わるセッティングとWEBページの閲覧確認
  2. 【エクセルVBAでIE操作】HTMLタグと要素そしてドキュメントの取得
  3. 【エクセルVBAでIE操作】ブラウザの読み込み待ちをしないとダメなのです
  4. 【エクセルVBAでIE操作】ページ内のリンク先URLを全部取得する
  5. 【エクセルVBAでIE操作】ディスクリプションなどの要素をname属性でGetする
  6. 【エクセルVBAでIE操作】hタグなどの要素をタグ名でGetする
  7. 【エクセルVBAでIE操作】WEBページのテーブル要素を自動で取得する方法
  8. 【エクセルVBAでIE操作】WEBページのテーブル要素からセルのデータを取り出す方法
  9. 【エクセルVBAでIE操作】IEで検索窓にキーワードを入力して送信する方法
  10. 【エクセルVBAでIE操作】検索結果一覧から記事タイトルを取得する方法
  11. 【エクセルVBAでIE操作】ブログの記事一覧ページから公開日とカテゴリを取得する
  12. 【エクセルVBAでIE操作】ページャーをめくって複数ページからデータを取得する
  13. 【エクセルVBAでIE操作】ユーザー名とパスワードを入力してログインをする
  14. 【エクセルVBAでIE操作】name属性を利用して画像ボタンをクリックする
  15. 【エクセルVBAでIE操作】alt属性・src属性を利用して画像ボタンをクリックする

コメント

  1. ryo より:

    実務でEXCELVBAからIEを操作する開発をやっている者です。私は当初IEの読み込みをいかに完全に待つことができるのか、方法を見つけ出すのに本当に苦労しました。いろんなサイトで紹介されている方法でもうまくいかず、もういくつか追加する必要があることに気づきました。

    まずは、objIE.Documentの読み込みが完了しているか、そしてさらにobjIE内の全要素数が数秒後の要素数と同じになるのか、までチェックしないと私の経験上では順調に次の処理に進むことができませんでした。

    しかしこれでも常時正常に動くかは不安です。API Sleepも使いつつなんとか動かすことができている状況です。

    以上、情報共有でした。

    • ryoさん

      コメントありがとうございます!
      参考になります!

      objIE内の全要素数が数秒後の要素数と同じになるのか

      なるほどですね…うまく動作しないときには、この方法も有効ですね。活用させていただきますね!

タイトルとURLをコピーしました