人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

VBAによるIE操作についてご存知の方にお尋ねします。以下のコードを試しているのですが、フォームを指定したらタグが抜き出せるのに、指定しなければタグが抜き出せません。ドキュメント中のエレメントが多すぎるからでしょうか?

1:Debug.Print objIE.Document.forms("hoge").all.tags("b").Length →5と出力
2:Debug.Print objIE.Document.all.Length →2500と出力
3:Debug.Print objIE.Document.all.tags("b").length →エラーを起こす

よろしくお願いします。

●質問者: ReoReo7
●カテゴリ:インターネット ウェブ制作
✍キーワード:ALL hoge IE print VBA
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● doxas
●20ポイント

ソースコードが一部しか記載されていないですし、情報が少なすぎます。

もう少し細かく開示していただければ、解決のお手伝いができるかもしれません。

まずエラーが起きるということですが、どのような内容のエラーが起きるのでしょうか。

また、データ取得の対象となるHTMLソースには、どのくらいの<b>要素があるのでしょう。

全体が2500だからそれ以下だとは思いますが、もう少し情報をいただけませんか。

普通に考えると ReoReo7 さんが示してくれたコードでうまくいくはずですね。

現状ではそれ以上のことが言えません。

◎質問者からの返答

ありがとうございます。

その "b" の要素を一つ一つ取り出そうとしたのですが、うまくいきませんでした。

数えてみたら100くらいだと思います。

「普通に考えると ReoReo7 さんが示してくれたコードでうまくいくはずですね。」

↑コードの誤りそのものでは無いということですね。ありがとうございます。

多分全体の数が大きすぎるのかな?

あと、エラーの捕捉の方法が分かりません。

objIEはIEオブジェクトを格納しており、これはある会員制サイトのページを表示しています。

On Error GoTo myFail

Debug.Print objIE.Document.forms("hoge").all.tags("b").Length '←1

Debug.Print objIE.Document.all.Length '←2

Debug.Print objIE.Document.all.tags("b").Length '←3

Debug.Print " "

myFailコロン

で、F8を押しながら一つ一つ実行していくと、←3の時点でmyFailへ移動します。


2 ● a-kuma3
●20ポイント

エラーの内容をさらすと、答えがつきやすいんじゃないかな。

とりあえず、length の頭が L になってないのを、候補に挙げておこう。

◎質問者からの返答

エラーの内容の捕捉ができたら補足します!Lは単純に質問時のミスでした。


3 ● doxas
●20ポイント

こんばんは。回答者1です。

On Error GoTo? の記述がありますので、これだとエラーメッセージは表示されずに、指定されている myFail へ処理が移ってしまいますね。エラーの内容を得る方法はいくつかありますが、この On Error GoTo? の一行を無効化しておけばエラーメッセージが出るはずです。

F8を押しながらステップ実行しているのであれば、オブジェクト(IEやそれに付随するオブジェクト)が破棄されてしまっているなどの、参照系のエラーではないと思いますが、なんでしょうね……想像がつきません。

もし、可能であればローカルウィンドウを活用して、オブジェクトの中身を参照してみると原因がわかるかもしれません。手元にExcelがないので記憶に頼るかたちになりますが、VBEの表示メニューのなかに、ローカルウィンドウというのがあるはずですので、それを表示しておき、同様にF8でステップ実行してみてください。ローカルウィンドウのなかにオブジェクトの詳細な情報が表示されるはずです。

他に有効なデバッグ手段としては、オブジェクト変数をもうひとつ用意して、そちらにまずデータを取得してみる方法が考えられます。

Dim objTAG_B As Object 'オブジェクト変数をひとつ新しく宣言

'------------------------
'中略
'------------------------

Set objTAG_B = objIE.Document.all.tags("b") 'オブジェクト変数にエレメントコレクションを取得

上記のようにオブジェクト変数に一度データを取得することができると、ローカルウィンドウから目的の情報を探しやすくなるでしょう。

ただし、一度オブジェクト変数を経由しているとは言え、<b>タグのエレメントコレクションを取得しようとしている処理自体は ReoReo7 さんが先に掲示してくれたコードと同じです。つまり先ほどのエラーの原因がわからないと(解決しないと)、オブジェクト変数(objTAG_B)にオブジェクトを得ることができないはずです。

とにかくエラーの内容、これがわからないことにはどうにも難しいです。

◎質問者からの返答

ありがとうございます。

エラーコード取得はまだできていませんが、先にローカルウィンドウでのオブジェクトの展開を試してみました。

オブジェクトの構造は、objIE-Document-allの下にItem(*)があるのですが、これがItem(256)までしか表示されていません。つまり、エレメントの下のコマンドが使えるのは256個以下の数字のみということになりそうです。

つまり、Debug.Print objIE.Document.all.Lengthは2500個あっても出力できるが、その下位エレメントであるobjIE.Document.all.tags("b")というのは、allの数が256を超えた時点でtags()コマンドが使用不可になるらしいのです。

ありがとうございました。必要に応じてもう少し掘り下げてみます。

追記(10月9日):

Dim objTAG_B as Object

Set objTAG_B = objAppIE.Document.all.tags("b")

debug.print objAppIE.Document.all.tags("b").Length

を、4の回答者Silvanusさんの示すプログラムのURLの値を所望のアドレスに変えてobjAppIEを取得後、試しましたが、コメント欄に示すエラーが出ます。また、URLをwww.google.co.jpで試したところ、

Debug.Print objAppIE.document.all.Length '106を出力

Set objButton = objAppIE.document.all.tags("b") '実行可能

Debug.Print objAppIE.document.all.tags("b").Length '2を出力

となり、大丈夫でした。このエラーの原因は分かりませんが、ページのDocument.All.Lengthで示されるエレメント数が256を超えていることと何か関係あるのでしょうか。


4 ● Silvanus
●40ポイント ベストアンサー

doxasさんがご指摘の様に、On Error GoToの行の先頭にアポストロフィ(')を挿入し、

エラー処理を無効化してから実行して、エラーメッセージを報告していただかないと

なかなか問題の本質を把握できません。

また、以下のコードを実行して、そのページの内部の構造が

きちんと列挙されるかどうか確認されてみては?

Option Explicit

Sub Enumerate_objAppIE_Document_All()

Dim iCount1 As Integer

Dim objAppIE As Object

Set objAppIE = CreateObject("InternetExplorer.application")

objAppIE.Visible = True

objAppIE.Navigate "http://XXX.YYY/"

While objAppIE.ReadyState <> 4

While objAppIE.Busy = True

DoEvents

Wend

Wend

Sheets.Add

ActiveSheet.Name = "Report" & Format(Rnd() * 10000, "0")

Cells(1, 1).Value = "Num"

Cells(1, 2).Value = "Type"

Cells(1, 3).Value = "Tag"

Cells(1, 4).Value = "OuterHTML"

Columns(1).ColumnWidth = 10

Columns(2).ColumnWidth = 20

Columns(3).ColumnWidth = 10

Columns(4).ColumnWidth = 100

For iCount1 = 0 To objAppIE.Document.All.Length - 1

Cells(iCount1 + 2, 1) = iCount1

Cells(iCount1 + 2, 2) = "'" & TypeName(objAppIE.Document.All(iCount1))

Cells(iCount1 + 2, 3) = "'" & objAppIE.Document.All(iCount1).TagName

Cells(iCount1 + 2, 4) = "'" & Left(objAppIE.Document.All(iCount1).OuterHTML, 100)

Next

End Sub

◎質問者からの返答

ありがとうございます。プログラムを実行してみたところ、できました!

実行には2分ほどかかりました。NUM=2331程度でした。

内部の構造の取得には問題ないようですね・・・。


複数ある"B"タグの中から、所望の"B"タグの中身(innerText)を取り出したかったのですが、まず"B"要素を取り出したくてもできなくて困っていました。

そこで、違う回避策を見つけました。このほうが実行も早そうです。

objIE.Document.all.tags("b").length

ではなくて、所望の"B"タグの直前(タグ数で10個以内)にある、「DIV ID="hoge"」や「SCRIPT NAME="hoge2"」のように、ユニークなIDまたは名前のついている要素を

Dim i as Long

i = objIE.Document.all.Item("hoge").sourceindex

のように取得して、

Dim j as Long

For j = i to i + 10

If objIE.Document.all.Item(j).nodeName = "B" then

msgbox "望みの'B'タグの中身は" & objIE.Document.all.Item(j).innerText & "です。"

End If

Next

として取得することで解決している状態です。

まだ、そもそも何でエラーしたのかは分かっていませんが。。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ