DOMを変数で渡してinnerTextを得る方法

最近の書き込み件数: 今日 0件、昨日 0件
未読分:16件

最新20件 最新50件 最新100件 最新200件 200件以前
昨日以降(0) 2日前以降(0) 3日前以降(0) 4日前以降(0) 5日前以降(0)


Excel VBAでIEを思いのままに操作できるプログラミング術 Excel 2013/2010/2007/2003対応

近田 伸矢, 植木 悠二, 上田 寛

IEのデータ収集&自動操作のプログラミング本はこの1冊だけ!IEの起動やポップアップウィンドウ、表示を制御する基本的なコードはもちろん、テキストボックスやラジオボタン、表、ハイパーリンクなどのHTML部品を制御する方法など、自動操作に欠かせないノウハウを丁寧に解説。

Message#16 2015年7月18日(土)01時55分
From: 管理人
返事 削除 変更
> のIf InStr(objDoc.outerHTML, keywords) > 0 Thenの中のobjDoc.outerHTMLは、オブジェクト名が変わっているので、正しくは
> If InStr(myDoc.outerHTML, keywords) > 0
> になります。
> こちらでしたら、正常に取得できますね。
> 管理人様へメール報告しておきました。

VBAマスター様

ご連絡ありがとうございました。
ご指摘どおり記述が間違っておりました。
修正しましたので、ご報告させていただきます。

Message#15 2015年7月17日(金)18時40分
From: pyonko
返事 削除 変更
ジャッカルのメッセージ(#14)への返事

ありがとうございました。

> 確かに、myDocに変更するとうまくいくね。
> IEバージョンの問題ではないか?
> 違うバージョンを試してみるとか。

IE.8(基幹業務のため)では、先程報告したエラーが出ましたが、
別のPC(IE.11)で実行したところ、myDocに変更することで、
3か所のMsgBoxが全て正常に表示されました。

環境さえ合致すれば利用が可能であることが判りましたので、
大変スッキリしました。

いろいろご指導いただきまして、ありがとうございました。

Message#14 2015年7月17日(金)15時33分
From: ジャッカル
返事 削除 変更
> のIf InStr(objDoc.outerHTML, keywords) > 0 Thenの中のobjDoc.outerHTMLは、オブジェクト名が変わっているので、正しくは
> If InStr(myDoc.outerHTML, keywords) > 0
> になります。

確かに、myDocに変更するとうまくいくね。
IEバージョンの問題ではないか?
違うバージョンを試してみるとか。
もしくは64bitを利用しているとか。
64bit版はエラーがおきやすいらしい。

Message#13 2015年7月17日(金)10時12分
From: pyonko
返事 削除 変更
VBAマスターのメッセージ(#12)への返事

> のIf InStr(objDoc.outerHTML, keywords) > 0 Thenの中のobjDoc.outerHTMLは、オブジェクト名が変わっているので、正しくは
>
>
> If InStr(myDoc.outerHTML, keywords) > 0
>
> になります。

ご指摘ありがとうございました。
このとおりにした上で、再度実行しました。
結果は、2015年7月16日(木)15時53分に投稿した時と同じことになりました。
・一つ目のMsgBoxは表示されましたが、空白
・二つ目表示の直前で実行時エラー438。
Case "class"
Set objDoc = objIE.Document.getElementsByClassName(elementName)
のSet objDoc.......で停止します。elementNameには「classtest3」は入っていますが、
onjDocは「Nothing」です。

参照設定は、Microsoft Internet Controlesの他に必要なものがあったりしますでしょうか?

ご面倒おかけしますが、よろしくお願いします。

【追記】
Microsoft HTML Object Libraly を追加設定して実行しましたが、状況に変化はありませんでした。

Message#12 2015年7月17日(金)08時45分
From: VBAマスター
返事 削除 変更
サブルーチンが間違っていますね。

For Each myDoc In objDoc

With myDoc

If InStr(objDoc.outerHTML, keywords) > 0 Then

Select Case valueType

Case "innerHTML"

tagValue = .innerHTML

Case "innerText"

tagValue = .innerText

Case "outerHTML"

tagValue = .outerHTML

Case "outerText"

tagValue = .outerText

End Select

Exit For


のIf InStr(objDoc.outerHTML, keywords) > 0 Thenの中のobjDoc.outerHTMLは、オブジェクト名が変わっているので、正しくは


If InStr(myDoc.outerHTML, keywords) > 0

になります。

こちらでしたら、正常に取得できますね。

管理人様へメール報告しておきました。

Message#11 2015年7月17日(金)00時12分
From: pyonko
返事 削除 変更
ジャッカルのメッセージ(#10)への返事
> 設定したコードを張らないことには答えようがないはず。
> 多分、エラーからみてドキュメントが取得できずエラーが起きているんだろう。
> オブジェクトの取得もね。
失礼しました。前回投稿したのと違うPCからですが、コードを付けます。http://www.vba-ie.net/element/tagvalue.html
のサンプルをそのまま使ったもので、一切変更しておりません。

Sub sample()

Dim objIE As InternetExplorer

'IE(InternetExplorer)でテストページを起動する
Call ieView(objIE, "http://www.vba-ie.net/code/all.html")

'getElementsByNameメソッドで文書ドキュメントを抽出する
MsgBox tagValue(objIE, "name", "nametest3", "円(税込)", "innerText")

'getElementsByClassNameメソッドで文書ドキュメントを抽出する
MsgBox tagValue(objIE, "class", "classtest3", "円(税込)", "innerText")

'getElementsByTagNameメソッドで文書ドキュメントを抽出する
MsgBox tagValue(objIE, "tag", "td", "円(税込)", "innerText")

End Sub

Function tagValue(objIE As InternetExplorer, _
methodType As String, _
elementName As String, _
keywords As String, _
valueType As String) As String

Dim objDoc As Object, myDoc As Object

Select Case methodType

Case "id"

Set objDoc = objIE.Document.getElementById(elementName)

Case "name"

Set objDoc = objIE.Document.getElementsByName(elementName)

Case "class"

Set objDoc = objIE.Document.getElementsByClassName(elementName)

Case "tag"

Set objDoc = objIE.Document.getElementsByTagName(elementName)

End Select


For Each myDoc In objDoc

With myDoc

If InStr(objDoc.outerHTML, keywords) > 0 Then

Select Case valueType

Case "innerHTML"

tagValue = .innerHTML

Case "innerText"

tagValue = .innerText

Case "outerHTML"

tagValue = .outerHTML

Case "outerText"

tagValue = .outerText

End Select

Exit For

End If

End With

Next

End Function

今sample()を実行させますと、一つ目のMsgBoxが表示される前にストップします。エラー内容は変わりませんでした。
今回は、elementNameには"nametest3"が入っています。
(前回投稿時は、一つ目のMsgBoxは表示され(ただし内容は"")、二つ目の手前で止まったので、elementNameが"classtest3"になったんだと思います。)

Message#10 2015年7月16日(木)23時07分
From: ジャッカル
返事 削除 変更
> 1回目が""ということは、
> MsgBox tagValue(objIE, "name", "nametest3", "円(税込)", "innerText")
> の結果が""、
> 2回目では、黄色くなったコードの「elementName」の上にマウスをかざすと、
> ツールチップで「classtest3」が入っていますが、「objDoc」の上では、
> 「Nothing」になります。

classtest3? nametest3の間違いということか?
これだけじゃ何が悪いのかなんて分からないぞ。

設定したコードを張らないことには答えようがないはず。
多分、エラーからみてドキュメントが取得できずエラーが起きているんだろう。
オブジェクトの取得もね。

Message#9 2015年7月16日(木)15時53分
From: pyonko
返事 削除 変更
VBAマスターのメッセージ(#8)への返事

いろいろやっています。
今回は、tagValue用に掲示されているサンプルコードを変更なしで実行してみました。
その結果、最初のMsgBoxでは中身は"",
そして2回目のMsgBoxは表示されず、次のコードの背景が黄色くなり、
Set objDoc = objIE.Document.getElementsByClassName(elementName)
でストップし、
「実行時エラー438
オブジェクトは、このプロパティまたはメソッドをサポートしていません。」
となります。

1回目が""ということは、
MsgBox tagValue(objIE, "name", "nametest3", "円(税込)", "innerText")
の結果が""、
2回目では、黄色くなったコードの「elementName」の上にマウスをかざすと、
ツールチップで「classtest3」が入っていますが、「objDoc」の上では、
「Nothing」になります。

どこに原因があるのかわからずにいます。よろしくお願いします。

Message#8 2015年7月15日(水)22時56分
From: VBAマスター
返事 削除 変更
> 「tagValue」を利用して特定の文書ドキュメントを抽出するサンプルコードを使い、
> 'getElementsByNameメソッドで文書ドキュメントを抽出する
> Debug.Print tagValue(objIE, "id", "temp_contents", "", "innerText")
> を実行させると、サブルーチンの
> Set objDoc = objIE.Document.getElementById(elementName)
> で止まり、objDocは「Nothing」となりました。(実行時エラー424,オブジェクトが必要です)
>

tagValue(objIE, "id", "temp_contents", "", "innerText")

は第四引数のキーワードが設定されていないので、Nothingがでてるんでしょう。
キーワードはouterHTMLでチェックしてるので、そのままid名でもキーワードとして利用すればいけると思いますよ。

Message#7 2015年7月15日(水)21時39分
From: pyonko
返事 削除 変更
VBAマスターのメッセージ(#6)への返事
VBAマスター様

早速ですが、methodTypeを「id」でやる場合です。
<div id=temp_contents">
<h1>見出し</h1>
<ul>
<li>テキスト</li>
<li>テキスト</li>
<li>テキスト</li>
<li>テキスト</li>
</ul>
</div>
この場合、
「tagValue」を利用して特定の文書ドキュメントを抽出するサンプルコードを使い、
'getElementsByNameメソッドで文書ドキュメントを抽出する
Debug.Print tagValue(objIE, "id", "temp_contents", "", "innerText")
を実行させると、サブルーチンの
Set objDoc = objIE.Document.getElementById(elementName)
で止まり、objDocは「Nothing」となりました。(実行時エラー424,オブジェクトが必要です)

ul内のテキストがほしいのですが、この中にキーワードとなりうる単語がないのです。
かと言ってh1のテキストを使用するわけにもいかず。。。

どこを勘違いしているのでしょうか?

Message#6 2015年7月15日(水)12時27分
From: VBAマスター
返事 削除 変更

> あ!こんな便利な関数を作ってくださっていたのですね!

いえ、作ってくれたのはこのサイトの管理人様ですw

> idでやれそうなサイトにはidで、idがなくてもclassがあれば、さらにclassが同じのがいくつかあれば何か違っている所をみつけてキーワード、
> という感じでやっていけばいいのですね?


そんな感じであっています。



> 今夜、早速取り組んでみます。また、お聞きしなくてはならないことがあるかもしれません。出来たら報告させていただきます。
> まずは、どうもありがとうございました。引き続きがんばってみます。

がんばってみてください。

Message#5 2015年7月15日(水)06時31分
From: pyonko
返事 削除 変更
VBAマスターのメッセージ(#4)への返事

VBAマスター様
ありがとうございます。
> 極論で言えば100行あったら100ケース記述する必要があると思いますが、ちょっとこれはどうかなと思います・・・
>

おしゃるとおりです!(汗)
> 理想としては、tagValueサブルーチンを利用するのがスマートに記述できる方法だと思います。

あ!こんな便利な関数を作ってくださっていたのですね!
idでやれそうなサイトにはidで、idがなくてもclassがあれば、さらにclassが同じのがいくつかあれば何か違っている所をみつけてキーワード、
という感じでやっていけばいいのですね?

> おそらくここの「一意のキーワード」を見つけれないがために断念したと思いますが、どこかしら違うところがあるはずなので、それを見つけたほうが早いかと思います。
>
> どうしても分からない場合は、以下のように個別の条件を追記すれば対応できるかと思います。
>
> For i = 2 To sh2.Cells(Rows.Count, 1).End(xlUp).Row
>
> With sh2
>
> sh1.Cells(i, 2) = tagValue(objIE, .Cells(i, "B"), .Cells(i, "C"), .Cells(i, "D"), "innerText")
>
> If sh1.cells(i,2) = "" then
> ※個別条件のマクロを記述
> End if
>
> End With
>
> Next
今夜、早速取り組んでみます。また、お聞きしなくてはならないことがあるかもしれません。出来たら報告させていただきます。
まずは、どうもありがとうございました。引き続きがんばってみます。

Message#4 2015年7月15日(水)00時36分
From: VBAマスター
返事 削除 変更
> スマートではないですが、とりあえずは現在動いている
> Select Case構文で進めることとにします。

For i = 2 To sh2.Cells(Rows.Count, 1).End(xlUp).Row Step 1
   '第一列目(A列)にURLリストがあるとします

Select Case i
Case 1
sh1.Cells(i, 2) = objIE.Document.body.all.tags("ul")(3).innerText
Case 2
sh1.Cells(i, 2) = objIE.Document.body.all.tags("table")(3).all(61).innerText
Case 3
sh1.Cells(i, 2) = objIE.Document.body.all.tags("div")(10).innerText
End Select

Next

For Next構文ですが、上記の変数iは行番号ですよね?
この変数iをSelect Case構文の条件としているということは、

1行目の場合は、objIE.Document.body.all.tags("ul")(3).innerText
2行目の場合は、objIE.Document.body.all.tags("table")(3).all(61).innerText
3行目の場合は、objIE.Document.body.all.tags("div")(10).innerText

のデータを抽出しているということであってますか?

極論で言えば100行あったら100ケース記述する必要があると思いますが、ちょっとこれはどうかなと思います・・・

あと、

tags("ul")(3)
tags("table")(3).all(61)
tags("div")(10)

も指定した要素に対して何番目の要素を抽出するかということですが、html文が変わると取得範囲も変わるのでオススメではないですね。
特に2番目の(61)はよく数えていったなと思います。



> getElementById(sh2.Cells(i, 3))はオールマイティではないことが判りました。
> classも同じclass名を持つ要素がサイトによって違っていたり、ということで
> 結局諦めてしまったわけなのです。

ということですが、サイトによって違う部分を変数扱いすることで大抵は解決します。

理想としては、tagValueサブルーチンを利用するのがスマートに記述できる方法だと思います。

sh2シート
A列 |B列      |C列 |D列        |
URL |メソッドタイプ |タグ |一意のキーワード  |


For i = 2 To sh2.Cells(Rows.Count, 1).End(xlUp).Row

With sh2

sh1.Cells(i, 2) = tagValue(objIE, .Cells(i, "B"), .Cells(i, "C"), .Cells(i, "D"), "innerText")

End With

Next

おそらくここの「一意のキーワード」を見つけれないがために断念したと思いますが、どこかしら違うところがあるはずなので、それを見つけたほうが早いかと思います。

どうしても分からない場合は、以下のように個別の条件を追記すれば対応できるかと思います。



For i = 2 To sh2.Cells(Rows.Count, 1).End(xlUp).Row

With sh2

sh1.Cells(i, 2) = tagValue(objIE, .Cells(i, "B"), .Cells(i, "C"), .Cells(i, "D"), "innerText")

If sh1.cells(i,2) = "" then
※個別条件のマクロを記述
End if

End With

Next

Message#3 2015年7月14日(火)21時13分
From: pyonko
返事 削除 変更
VBAマスターのメッセージ(#2)への返事

> よく分からない部分もあったのですが
>
> objIE.sh2.Cells(i, 2)
>
> の部分がエラーがでて動作しないということでしょうか?
>
> sh2.Cells(i, 2)に記述されたobjIE.Document.body.all.tags("ul")(3).innerTextを利用しているということですが、こちらを当てはめたら、objIE.objIE.Document.body.all.tags("ul")(3).innerTextでobjIEオブジェクトが2つ続きます。

まずは訂正させてください。objIE.objIEとならないように、
sh1.Cells(i, 2) = sh2.Cells(i, 3)
としています。この結果はエラーにはなりませんが、(当然ですが)文字列で、
objIE.Document.body.all.tags("ul")(3).innerText
と出力されます。
>
> 試していませんが、セルをオブジェクトに代入してもエラーが起きるだけではないでしょうか?
>
> サイトによって値が異なるのであれば、処理をサイト毎にわけるか、統一したデータを取得する方法を利用するほうが一般的だと思いますよ。
>
> 値の取得については、以下ページが参考になりますので、こちらを見てみてはいかがですか?
>
>
> http://www.vba-ie.net/element/tagvalue.html

はい、
http://www.vba-ie.net/element/idvalue.html
を参考にしていますいが、id属性は引数になるので目的に叶うのですが、
大半のWEBページにおいて、絞り込んだエリアに適当なid属性がなく、
getElementById(sh2.Cells(i, 3))はオールマイティではないことが判りました。
classも同じclass名を持つ要素がサイトによって違っていたり、ということで
結局諦めてしまったわけなのです。

> あと、セル値をオブジェクトとしてセットしてみるとうまくいくかもしれません。イメージとしては以下のような感じです。
> 試したわけではないので、参考まで。
>
>
> Dim objDoc As Object
>
> Set objDoc = osh2.Cells(i, 2)
>
> sh1.Cells(i, 2) = objDoc

ありがとうございます。これを早速試しましたが、
sh1.Cells(i, 2) = sh2.Cells(i, 3)
と同じ結果になりました。オブジェクトにならない
みたいです。
javascriptでいう、eval()関数のようなものでどうかと思い、
sh1.Cells(i, 2) = Application.Evaluate(sh2.Cells(i, 3))
とやってみましたが、この行で「オブジェクトが必要です」
エラーとなりました。

Dim objDoc As IHTMLDOMNode
Set objDoc = sh2.Cells(i, 3)
sh1.Cells(i, 2) = objDoc
を試してみようとしましたが、
「こんぱいるえらー:ユーザー定義型は定義されていません」
となりました。参照設定が足りないと思われますが、
何を参照したらよいか解らなくて。。。。

スマートではないですが、とりあえずは現在動いている
Select Case構文で進めることとにします。

Message#2 2015年7月14日(火)16時30分
From: VBAマスター
返事 削除 変更
よく分からない部分もあったのですが

objIE.sh2.Cells(i, 2)

の部分がエラーがでて動作しないということでしょうか?

sh2.Cells(i, 2)に記述されたobjIE.Document.body.all.tags("ul")(3).innerTextを利用しているということですが、こちらを当てはめたら、objIE.objIE.Document.body.all.tags("ul")(3).innerTextでobjIEオブジェクトが2つ続きます。

試していませんが、セルをオブジェクトに代入してもエラーが起きるだけではないでしょうか?

サイトによって値が異なるのであれば、処理をサイト毎にわけるか、統一したデータを取得する方法を利用するほうが一般的だと思いますよ。

値の取得については、以下ページが参考になりますので、こちらを見てみてはいかがですか?


http://www.vba-ie.net/element/tagvalue.html


あと、セル値をオブジェクトとしてセットしてみるとうまくいくかもしれません。イメージとしては以下のような感じです。
試したわけではないので、参考まで。


Dim objDoc As Object

Set objDoc = osh2.Cells(i, 2)

sh1.Cells(i, 2) = objDoc

Message#1 2015年7月13日(月)19時37分
From: pyonko
返事 削除 変更
Excelに記述したURLリストに従って、WEBページの更新有無
を定期的にチェックするVBAを作成中です。

ページごとに、着目している情報が掲載されているDOM要素
を次のような感じで予め特定しました。

Aサイト:objIE.Document.body.all.tags("ul")(3).innerText
Bサイト:objIE.Document.body.all.tags("table")(3).all(61).innerText
Cサイト:objIE.Document.body.all.tags("div")(10).innerText

これらも、URLリストの隣の列に記述しております。
(sh2:URL,DOMを記述したSheet2とします)

サイトが沢山ある場合、ループで回し、例えば

For i = 2 To sh2.Cells(Rows.Count, 1).End(xlUp).Row Step 1
   '第一列目(A列)にURLリストがあるとします

Select Case i
Case 1
sh1.Cells(i, 2) = objIE.Document.body.all.tags("ul")(3).innerText
Case 2
sh1.Cells(i, 2) = objIE.Document.body.all.tags("table")(3).all(61).innerText
Case 3
sh1.Cells(i, 2) = objIE.Document.body.all.tags("div")(10).innerText
End Select

Next

などとしていますが、このように右辺に直接個々の i 毎にDOMの連なりを記述する
のではループの意味がなくなってしまうので、シートのsh2.Cells(i, 2)に記述されたobjIE.Document.body.all.tags("ul")(3).innerTextを使って
sh1.Cells(i, 2) = objIE.sh2.Cells(i, 2)
のように記述できないでしょうか?
DOM要素でなく、id属性をリストに入れているのであれば、
sh1.Cells(i, 2) = objIE.Document.body.getElementById("id名")
が使えるので、
sh1.Cells(i, 2) = objIE.Document.body.getElementById(sh2.Cells(i, 2))
と、( )内に変数を渡すことが可能と思われます。「.」でつなげていく方法では、
変数にできなくて困っています。

アイデアがあれば、ぜひ教えて下さい。

最新20件 最新50件 最新100件 最新200件 200件以前
昨日以降 2日前以降 3日前以降 4日前以降 5日前以降

VBAのIE制御についてのQ&A掲示板

↑エクセルVBAのIE(InternetExplorer)操作で分からない事があればこちらの掲示板よりご質問ください^^

ExcelのVBA初心者入門

↑こちらはExcelのVBAをマスターできるよう初心者向けのエクセルVBA入門コンテンツになります^^

VBAのIE制御入門RSS

RSSフィードを登録すると最新記事を受け取ることができます。

VBAIE操作のスカイプレッスン

VBAでIE(InternetExplorer)制御の準備

エクセルVBAでIE制御の応用編

こちらでは、エクセルVBAで実際に作成したIE(InternetExplorer)制御ツールをまとめています。自動ログインや情報収集など具体的に解説しています。IE(InternetExplorer)制御をされる方は参考にしてください。

【ダウンロード】IE操作に便利なツール

こちらでは、これまでに紹介したIE(InternetExplorer)操作で便利な機能をツール化しています。無償でダウンロードできますので、目的に合わせたご利用ください。

IEオブジェクトのメソッド・プロパティ

こちらでは、IE(InternetExplorer)オブジェクトのメソッド・プロパティをまとめています。

IE操作に利用されているVBA関数

こちらでは、エクセルVBAのIE(InternetExplorer)操作で利用されたVBA関数をまとめています。

IE操作に利用されているステートメント

こちらでは、エクセルVBAのIE(InternetExplorer)操作で利用されたステートメントをまとめています。ExcelのVBAで基本的な部分になりますので、しっかり理解しましょう。

IE(InternetExplorer)制御のVBAコード

こちらでは、これまでに作成したIE(InternetExplorer)操作で役立つサブルーチンをまとめています。
全てをコピーする必要はありませんが、目的に合わせたサブルーチンをご利用ください。

ExcelのVBAで作成した役立つVBAコード

こちらでは、IE(InternetExplorer)制御の利用だけでなく、Excel全般で利用できるVBAコードです。エクセルVBAで役に立つものばかりですので、ご利用ください。

dmb.cgi Ver. 1.068
Copyright(C) 1997-2014, hidekik.com