IEのサポートがWindows11で完全終了してしまいましたね。(2021/10/05冒頭に追記)
そんな感じで下記の質問が来たので対応策の参考になれば
下記いただいた質問
>ExcelVBAでデータを集め、競輪予想を作っています。
・
・
・
>さて最近、IEのサポート終了が告知されていますが
>WEBからのデータ取得はどのような対処がベターなのでしょうか?ご意見をお聞かせください。
ベター、ベスト、イロイロな考え方がありますが、
1.MSXML2.XMLHTTP などでHTMLを取得して、CreateObject("htmlfile") を使う
下記の例題動画、なんだか私の解説はイマイチだった・・・やはり、素直にSelenium VBAなのかなぁ。
と思いつつ、冒頭で Set objHTML = CreateObject("MSXML2.XMLHTTP")
でHTMLを取得して、使ったサンプルを紹介してみたり
IEサポート終了後の世界 MSXML2.XMLHTTPとCreateObject("htmlfile")を使用してJRAオッズ取得 ワイドのオッズ取得に挑戦してみた
目次
10:08 2.ワイドのオッズを押す
11:55 2.1 strレースを探し、頭出し?
18:47 3.オッズのテーブルを判断して、Excelにワイドオッズを取得
21:37 3.1 tableのcaptionで判断
28:30 4.ワイドの一番人気を探す
31:17 元に戻って、2.4 2回目以降は、レースを選択
他の動画を見る(YouTubeで再生リストを見る)
↑も参考になれば・・無事に移行できるといいですね。 三流プログラマー Ken3
※ソースコードは[MSXML2.XMLHTTPとCreateObject("htmlfile")を使用してJRAオッズ取得]を見てアレンジしてください。
はじめは[WebBrowserを参照設定]から入り [VBAでIE操作解説]やってます。 よく使う.Document:の解説から [.Forms]で入力処理 [.Links]でリンク情報取得 [.Images]で画像の情報 [.Frames]でフレーム処理 [.Script]でスクリプト処理 ...など、まだまだ抜けてますが、 |
手探りで[ヘルプ IEのオブジェクトを探る] IE,WebBrowser: [IE プロパティ(各種設定)] [IE メソッド(イロイロな動作)] [IE イベント(発生後処理)] |
[VBAでIE操作(TOP)] 小さな[IE操作のサンプル]でTEST 次に[少し大きなIEを使ったサンプル] にチャレンジしたり [IE関係記事一覧] [VBA(TOP)] [三流君(TOP)] |
全ての質問には、答えられませんが、リクエストや質問があったら、[作者(三流君)に質問する] から 気軽に送ってください
挨拶:VBAで(ExcelやAccessなどから)InternetExplorer WebBrowserを操作してみたいと思います。
サンプルで私がよく使う好きな方法は、Set objIE = CreateObject("InternetExplorer.application")なのですが、Vista IE7の保護モードだと.Navigateで失敗したり・・うまくIE制御ができません。[三流君 Vista IE7の修正でハマる(小細工で逃げる)] ← VistaでIE7を制御予定の人はこちらも見てください。
改版履歴 更新情報:過去の解説はこちら↓(IE6+XP 時代の記事です)
2008-05-01:[過去の解説 vba_ie_20080501.asp]
2007-08-31:[過去の解説 vba_ie_20070831.asp]
2007-05-20:[過去の解説 vba_ie20070520.asp]
もあわせてみてください。
(↑もしかして書き直さない過去の解説の方がよかったかも?(笑))
過去記事のリンク→[過去のメルマガ] も参考にしてください
Ken3の連絡先:[連絡先@メールアドレス]です。何か相談事があれば気軽に連絡してね(頼りないけど)
Blog紹介:どさくさ紛れにをBlog紹介 [サンプルCODEのゴミ箱]
/ [IE系の解説blog]
/ [更新されない作業日記]です
ページ内が無駄に長いので、ページ内の目次を作りました
ページ内 分類と目次
大分類 | 詳細 |
|
|
|
|
|
|
私がIE操作、プロパティやメソッドを探る方法 を ネタばらしすると(はやいよ)、MSDNで探したりプログラムを途中で止めて オブジェクトの中身を直接見たりしています。
[三流君 が MSDN で InternetExplorer の 資料を探す]
↑上級者はここを先に見た方が良かったり?(ヘンテコな説明や動画を見るよりも こちらの方が近道かも)
と書きつつ、いきなり大切な読者様へ嘘つきました、最近はGoogleの検索を主に使っていたりします。検索のキーワードがなかなか思いつかないと思うので私のお気に入りのキーワードを紹介します。(読者の声:だったら先に書けよ↓)
[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]
↑MSDNの目次(頭)から探すのが大変なので、検索すると良いサンプルや数少ない解説ページに巡り逢えるかも、なんて自信をなくしつつも三流製 手前味噌のサンプルをどさくさに紛れて紹介します 過去記事のリンク→[過去のメルマガ] ← IE6時代のサンプルですが何かの役に立つと願いつつ・・・
※時の流れはハヤク、あと少ししたら(まだまだ先だけどオオゲサに書いてみました)IE8がリリースされるのに、実はVista IE7に苦戦しています。(IE7を攻略する前にIE8になり、取り残されたりして・・・)
さて、IEを操作 Documentの森・WebBrowserの山を頼りないガイドの三流君と一緒にさまよってみましょうか!!!
このページ 三流プログラマー的解説がIE操作方法(プロパティやメソッド)の入り口として何かの参考・お役に立てれば幸いです。
下記↓、私のASP解説のテストページなのですが、ここの表からデータを抜いてみたいと思います
[http://www.ken3.org/cgi-bin/test/test028-2.asp]
↑test028-2.asp 感想データをORDER BY ID DESC で IDの降順で表示↓
ID | F_TITLE | F_MEMO | WriteTime |
---|---|---|---|
6026 | 説明が下手 | 理解が難しい・・・ | 2008/05/04 4:57:50 |
6025 | 解らん | 使えないサイトだな | 2008/05/03 5:23:24 |
5968 | ok | test | 2008/03/02 13:30:49 |
5696 | a | a | 2007/09/19 19:04:19 |
5675 | IE操作 | UWSC使用が正解 変な記事書き続けるなボケ | 2007/09/09 23:31:41 |
5505 | てすと | できるかな? | 2007/05/30 18:02:13 |
処理の流れ・仕様は
1.IEを起動する CreateObject("InternetExplorer.application")
2.目的のURL(test28-2.asp)を開く .Navigate
3.テーブルからデータを抜く(Excelのシートにセットする)
なんて感じの3行おまかせ仕様で(笑)
OS XP で IE6(IE7)の起動 CreateObject で 起動させるのは意外と簡単で
CreateObject("InternetExplorer.application")
で、IEを起動しています。まずは、ここからかな。
読者の心の声:イマイチ何?言ってんだか?わからないのですが・・・
三流君の説明聞くより、コード見たほうがハヤイって?
CreateObjectで起動する方法(XPやIE6の場合)は簡単で、
Sub ie_test()
Dim objIE As Object 'IEオブジェクト参照用
Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
objIE.Visible = True '見えるようにする(お約束)
End Sub
↑とにかくコレを貼り付けて実行してみてください。※サンプルで私がよく使う好きな方法は、Set objIE = CreateObject("InternetExplorer.application")なのですが、Vista IE7の保護モードだと.Navigateで失敗したり・・[三流君 Vista IE7の修正でハマる(小細工で逃げる)] ← Vista IE7の人はこちらも見てください。
CreateObject("InternetExplorer.application")なんて感じで、無事にIEのオブジェクトを作成できたら、次は指定したURL(目的のサイト)を開きたいですよね。
まぁ、文章でもなんでもたいていは開く処理が必要ですよね。
Workbooks.Open Filename みたいに.Open?
それとも、.URLOpen?
ハヤク、IEでURLを開くメソッドを教えろコラ!!
アナタ、先走りますねぇ、想像力豊かでガマン汁出てるよ(オイオイ)じゃなくって、メソッドの名前を勝手に.URLOpenとか創造するなんて先走り過ぎ。※まぁ、予測・予想する能力もプログラマーとしてはとても大切で必要なんですが・・・([愚痴系 No.181 TimeAddって関数を予想する力? ]を暇な時にでも読んでみてください)
感覚は文章やブックを開く感覚でURLを開くOpenなのですが、URLを開く命令は.Navigateです。
今回作成して代入したオブジェクトがobjIEなので、
objIE.Navigate "http://〜(URLを文字列で)" って感じです。
データ表示のURL[http://www.ken3.org/cgi-bin/test/test028-2.asp]を開く(飛ばす)には、
下記のような命令を1行書きます(.Navigateメソッドを実行します)。
Sub ie_test_Navigate()
Dim objIE As Object 'IEオブジェクト参照用
Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
objIE.Visible = True '見えるようにする(お約束)
'.Navigate で 指定した文字列のURLを開く
objIE.Navigate "http://www.ken3.org/cgi-bin/test/test028-2.asp"
End Sub
ねっ、簡単に目的のURLを開くことができたでしょ。無事にページを開くことができたので、データを抜き出したいと思います。
イロイロな方法があるので(わざと回り道をしますが)自分に合った方法で取り出してみてください。
.Navigateメソッドで"http://www.ken3.org/cgi-bin/test/test028-2.asp"の文章を開くことができました。文章じゃねぇだろ?といったアナタへ
test028-2.aspへアクセスするとIIS WebServer が HTML から 始まる タグで囲われた文章(Document)を返してくれるので、まぁ広い意味でタグ付きの文章を開くって感じなんですよ。
タグ付きの文章?HTMLの文法に詳しくないのですが
<html><head> <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=x-sjis"> <META NAME="keyword" content="三流君,三流プログラマー,IE操作,objIE"> <title>三流君VBAでIE操作 InternetExplorer.Applicationを操作する</title> </head> <body bgcolor=#ffffff text=#000000><A NAME="TOP"></A> <h1>三流君VBAでIE操作 InternetExplorer.Applicationを操作する</h1> <p>文章など・・・</p> <h2>データはDocumentの山からイロイロな方法で抜く</h2> <p>文章など・・・</p> <h3>テーブルは・・・</h3> <TABLE Border='1'> <TR><TH>ID</TH><TH>F_TITLE</TH><TH>F_MEMO</TH><TH>WriteTime</TH></TR> <TR><TD>6026</TD><TD>説明が下手</TD><TD>理解が難しい・・・</TD><TD>2008/05/04 4:57:50</TD></TR> <TR><TD>6025</TD><TD>解らん</TD><TD>使えないサイトだな</TD><TD>2008/05/03 5:23:24</TD></TR> <TR><TD>5968</TD><TD>ok</TD><TD>test</TD><TD>2008/03/02 13:30:49</TD></TR><TR> <TR><TD>5505</TD><TD>てすと</TD><TD>できるかな?</TD><TD>2007/05/30 18:02:13</TD></TR> </TABLE> ・ ・ ・ </body></html>など <html>〜</html>を受け取って IE(ブラウザ)さんが解析して表示をしてくれる。そんなイメージです。
先走らないでここで深呼吸、一呼吸おいて、
VBAでExcelのブック・シート・セルへデータをセットする場合、下記のように
シート--範囲
Sheets("Sheet2").Range("B3").Value = "値 B列3行目です"
や
シート--セル(y,x)
Sheets("Sheet3").Cells(5, 4).Value = 1234
Sheets(シート名).Rangeや.Cellsでオブジェクトへアクセスして、.Valueなどプロパティに値をセットしていると思います。
HTMLの文章データを取り出す場合、オブジェクトの構造が
IEアプリの下 -- .Document(文章/ドキュメント) -- .all(n番目 or 項目名)
と.All.プロパティ で たどり着くことができるので(ほかにも表現方法はあるのですが今回はこれで)
objIE.Document.All(0).イロイロなプロパティ で 値を取り出してみます
(htmlドキュメント の ALL(0番目)頭 を 探って見たいと思います)
実際に文章 Documentオブジェクトに.InnerTEXTプロパティ と .InnerHTMLプロパティを使ってアクセスしてみたいと思います。
アクセス方法は簡単で、
objIE.Document.All(0).InnerTEXT
objIE.Document.All(0).InnerHTML
.InnerHTMLプロパティや.InnerTextプロパティから値を取り出して使用することができます。(テストで画面に表示してみたいと思います。)
※MsgboxでDocument.All(0).InnerHTML と Document.All(0).InnerTextを表示させて違いを確認しました。
Sub ie_test_Document_All_innerTEXT()
Dim objIE As Object 'IEオブジェクト参照用
Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
objIE.Visible = True '見えるようにする(お約束)
'.Navigate で 指定した文字列のURLを開く
objIE.Navigate "http://www.ken3.org/cgi-bin/test/test028-2.asp"
'手抜きで2秒待つ(オブジェクトの展開時間を待つ)
Application.Wait Time:=Now + TimeValue("00:00:02") '2秒間 ボーっとする
'文章をMsgboxで表示する
MsgBox objIE.Document.All(0).InnerTEXT
MsgBox objIE.Document.All(0).InnerHTML
End Sub
.InnerTEXT プロパティでテキスト文章が.InnerHTMLプロパティで<タグ></タグ>付きのデータが表示されたと思います。手抜きで2秒待つ(オブジェクトの展開時間を待つ)
↑何だコレ、手抜きって?、そもそも、なぜ2秒?
なぜ、待つかと言うと、いきなりさわるとビックリするでしょ?(オイオイ、何言ってんだおっさん)
表示待ちを入れないで いきなりオブジェクトに触りに行くと(ドキュメントなどのオブジェクトにアクセスすると) 相手の心の準備ができていないみたいで(オブジェクトの展開処理が間に合わないみたいで)、どこ見てんのよ(古)と怒られるじゃなかった、 実行時エラー Document メソッドは失敗しました ・・・など、エラーで怒られるんですよ。
エラーの画像→[http://ken3-info.blog.ocn.ne.jp/screen/2007/05/ie__debe.html]
なので、objIE.Navigate 後に相手の準備ができるが確認します。
手抜きの2秒はじゃなくてもっとチャントシタ行儀作法があるので後ほど。
えっ、今説明しないの?はい、アトで・・・気になる人は先に→[.ReadyStateと.Busyで待つ]を見てください
今度は始めの0番目を表示だけじゃなくて、データを新しいシートに書き出してみます。
バカの一つ覚えのExcelとの比較を一つ、ブック内のシート名を表示するテストプログラムを書きます。
Sub TEST_SHEET_NAME()
'シートの名前をテストで表示する
Dim i As Integer 'カウンター、添え字
For i = 1 To ActiveWorkbook.Sheets.Count
MsgBox i & " シートの名前 " & ActiveWorkbook.Sheets(i).Name
Next i
End Sub
読者の声:だから何?、ドキュメント内のオブジェクト数は、objIE.Document.All.Countと言いたいの?感覚的にExcel VBAに慣れた人は.Countを使うと決め付けたいの??でも、要素の数は.Lengthなんでしょ?
あまり怒らないでくださいよ、タグ(Item)の数(要素の数)は.Countじゃなくて.Lengthです、配列も0から始まるので、
For i = 0 To objIE.Document.All.Length - 1
XXXX = "'" & objIE.Document.All(i).InnerTEXT
XXXX = "'" & objIE.Document.All(i).InnerHTML
Next i
と、i=0から初めて、.Length - 1までのループとしてます
Sub ie_test_Document_All_Length()
Dim i As Integer 'カウンター
Dim objIE As Object 'IEオブジェクト参照用
Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
objIE.Visible = True '見えるようにする(お約束)
'.Navigate で 指定した文字列のURLを開く
objIE.Navigate "http://www.ken3.org/cgi-bin/test/test028-2.asp"
'手抜きで2秒待つ(オブジェクトの展開時間を待つ)
Application.Wait Time:=Now + TimeValue("00:00:02") '2秒間 ボーっとする
'新規のブックを追加して、.InnerTEXTと.InnerHTMLを吐き出す
Workbooks.Add '新規ブックを追加
Range("A1") = "NO.i番目" '見出しのセット
Range("B1") = "TypeName関数の結果"
Range("C1") = ".TagName タグの名前"
Range("D1") = ".OuterHTML 外側含むHTML"
Range("E1") = ".InnerText 内側のTEXT"
Range("F1") = ".InnerHTML 内側のHTML"
Columns("A:G").ColumnWidth = 20 '列幅を20に変更
'ループさせDocumentを書き出す
For i = 0 To objIE.Document.All.Length - 1
'データをセルへセットする
Cells(i + 2, "A") = i 'i番目
Cells(i + 2, "B") = "'" & TypeName(objIE.Document.All(i)) 'TypeNameでオブジェクトのタイプを表示
Cells(i + 2, "C") = "'" & objIE.Document.All(i).TagName 'タグの名前
Cells(i + 2, "D") = "'" & Left(objIE.Document.All(i).OuterHTML, 256) '頭から256文字だけセット
Cells(i + 2, "E") = "'" & Left(objIE.Document.All(i).InnerText, 256)
Cells(i + 2, "F") = "'" & Left(objIE.Document.All(i).InnerHTML, 256)
Next i
'IEを閉じる
objIE.Quit
Set objIE = Nothing
End Sub
TypeName関数 を 使うと変数の中身のタイプを知ることができます。知ってどうする?の?
たとえば、HTMLTable や HTMLTableRow , HTMLTableCell を検索して例題を探すとか
.OuterHTMLは自分自身、外側を表示してくれるので解析時はこっちを使うと良かったり。
<TR><TD>DATA</TD><TD>DATA2</TD></TR>
↑オブジェクトにTRのデータが入っている時、
.OuterHTMLはそのまま <TR><TD>DATA</TD><TD>DATA2</TD></TR> を返し
.InnerHTMLは内側の <TD>DATA</TD><TD>DATA2</TD> を返します。
用途に応じて使い分けてください。
.TagName は そのままタグの名前を返すので、<TR>はTR <TD>はTDが返ってきます。泥臭い処理の時によく使うのかなぁ。
.Quit は 処理が終わり IEを閉じたいときに使います。 デバッグ中などはコメントアウトして そのままIEが開きっぱなしの方が確認しやすかったりしますが・・・
以上、簡単な説明でした。ぇっ、もう終わりカヨ・・・
※.Length - 1までのループでエラーが発生する場合、指定したURLで広告などを表示していると(私のページも広告あるので)、途中で動的に要素の数が変わってしまい Document.All(i)にアクセスしに行くとエラーになったりします注意してね
よし、簡単なオブジェクトの説明終了、、、ここまで長かった。酔っぱらいの独り言に付き合っていただきどうもです。朝までにもう一軒飲み屋じゃなかった、オブジェクトをハシゴするぞと行きたい所ですが、あと一杯、少しだけお時間をとらせてください。
読者の声:だから、余計な会話はいいから、はやくシロ。(※←この読者の心の声もかなりの蛇足なんですが(笑)説明に必要ないでしょと思いつつ)
書き方に好みの問題もあるのですが、
objIE.Document.All(i)
と、配列(i番目)でまわす方法のほかに、
For Each 変数 In オブジェクト
なんて書き方もあります
読者の声:何言ってんだか、よくわからん。いつもの例 サンプルだせよ
えっ、いつもの蛇足の例を出して いいんですか?。では、お言葉に甘えてExcelのシートを例にして、
Sub TEST_SHEET_NAME_FOR_EACH()
Dim objSHEET As Worksheet 'シートのオブジェクト受け取り用
For Each objSHEET In ActiveWorkbook.Sheets
MsgBox " シートの名前 " & objSHEET.Name
Next
End Sub
この書き方が Document.All でも 当然使えます。だってオブジェクト単位のループだしね。
For Each objTAG In objIE.Document.allで順番にobjTAGに入るので、
objTAG.OuterHTML や objTAG.InnerTEXT と書けるのでスッキリするのかなぁ。
処理によって使い分けてください。
Sub ie_test_Document_All_For_Each()
Dim i As Integer 'カウンター
Dim objIE As Object 'IEオブジェクト参照用
Dim objTAG As Object '1つ1つ タグのオブジェクトを入れる
Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
objIE.Visible = True '見えるようにする(お約束)
'.Navigate で 指定した文字列のURLを開く
objIE.Navigate "http://www.ken3.org/cgi-bin/test/test028-2.asp"
'手抜きで2秒待つ(オブジェクトの展開時間を待つ)
Application.Wait Time:=Now + TimeValue("00:00:02") '2秒間 ボーっとする
'新規のブックを追加して、.InnerTEXTと.InnerHTMLを吐き出す
Workbooks.Add '新規ブックを追加
Range("A1") = "NO.i番目" '見出しのセット
Range("B1") = "TypeName関数の結果"
Range("C1") = ".TagName タグの名前"
Range("D1") = ".OuterHTML 外側含むHTML"
Range("E1") = ".InnerText 内側のTEXT"
Range("F1") = ".InnerHTML 内側のHTML"
Columns("A:G").ColumnWidth = 20 '列幅を20に変更
'ループさせDocumentを書き出す
i = 0
For Each objTAG In objIE.Document.all
'データをセルへセットする
Cells(i + 2, "A") = i 'i番目 結局iは使うのかよ(笑)
Cells(i + 2, "B") = "'" & TypeName(objTAG) 'TypeNameでオブジェクトのタイプを表示
Cells(i + 2, "C") = "'" & objTAG.TagName 'タグの名前
Cells(i + 2, "D") = "'" & Left(objTAG.OuterHTML, 256) '頭から256文字だけセット
Cells(i + 2, "E") = "'" & Left(objTAG.InnerText, 256)
Cells(i + 2, "F") = "'" & Left(objTAG.InnerHTML, 256)
i = i + 1 'インクリメント
Next
'IEを閉じる
objIE.Quit
Set objIE = Nothing
End Sub
話を戻して、文章の表からデータを抜きたいんですよね、やりたいことは。 忘れてたよ
HTMLの表は、基本のパターンを書くと、
<TABLE> (テーブル開始) <TR> (行開始)※1行目 <TH>見出し1</TH> <TH>見出し2</TH> <TH>見出し3</TH> </TR> (行終了) <TR> (行開始)※2行目 <TD>DATA A</TD> <TD>DATA B</TD> <TD>DATA 3333</TD> </TR> (行終了) <TR> (行開始)※3行目 <TD>XXXXXX</TD> <TD>YYYYYY</TD> <TD>ZZZZZZ</TD> </TR> (行終了) </TABLE>(テーブル終わり)と、
ループで1つ1つの要素が取り出せるので、.TagName <TR>で改行 <TD>でデータセットしてみます
1.IEを起動させ 目的のサイト test028-2.asp を開きます
2.データセット用のBookを追加します
3. .TagName = <TR> で 行カウンタを+1 列カウンタを1に初期化
4. .TagName = <TD> or <TH> で .InnerText をセルにセット 列を+1 次へ
こんな感じの口答仕様書で作ってみます(4行で仕様書?当然、穴があるんだけど・・・)
|
ポイントは、特になく(オイオイ)、
For Each objTAG In objIE.Document.all で、文章から1つ1つタグを取り出し
strTNAME = objTAG.TagName でタグの名前を変数へ保存して、
単純にIf文で、TRの行のタグならyを増やし、
TH,TDならobjTAG.InnerTextでテキストを代入
そんな感じです。
実行してみると、データがセットされ完成・・と思いきや、後ろにゴミデータが入っているよ(笑)。
不具合には原因があります。
テストURL[http://www.ken3.org/cgi-bin/test/test028-2.asp]をよく見ると
データの表の下にソースコードの表(TABLE)と広告の表(TABLE)があります。
なるほどねぇ、目的のTABLE以外のTH,TDに反応してデータを書き出していたのかぁ。
1番目のTABLEだけ、なんとか処理したいなぁ。
.TagName で /TABLEがあると便利なんだけど、無いんですよね。
泥縄式に仕様を追加してみます(朝令暮改 的な指示を出す上司・先輩はイヤですね)
1.IEを起動させ 目的のサイト test028-2.asp を開きます
2.データセット用のBookを追加します
3. .Document.all(n) はじめのTABLEがくるまでタグ(DATA)を読み飛ばします
4. .TagName = <TR> で 行カウンタを+1 列カウンタを1に初期化
5. .TagName = <TD> or <TH> で .InnerText をセルにセット 列を+1
6. .TagName = <TABLE> 次のTABLEが来たらループを抜ける
こんな処理に変更してみたいと思います
|
ポイントは、まず初めのTABLEまでデータを飛ばしたいので
変数nを使ったループを作り、
For n = 0 To objIE.Document.all.Length - 1
If objIE.Document.all(n).tagname = "TABLE" Then Exit For
Next n
Document.all(n).tagname が "TABLE" になった時点で強制的にループを抜けます。
次に、n+1番目からデータセットのループに入ります。
For i = n + 1 To objIE.Document.all.Length - 1
で、追加したのが、
If strTNAME = "TABLE" Then 'TABLEなら(次のテーブルが現れたら)
Exit For 'ループを強制的に抜けます
End If
i番目がTABLEだったら(次のテーブルが現れたら)ループを抜けて終了、こんな感じです。
実行結果 と 修正ポイントの解説動画
Document.all から .tagname で判断して自分でセットする、そんな原始的 イヤ三流的な方法でした。嘘つきがもっとスマートな方法があるだろオイ・・と、上級読者様は突っ込まれたと思いますが、泥臭いループの練習、反面教師的ソースの例ってことでご勘弁を。
自分で1つ1つタグを見て?代入 そんな泥臭い方法よりも、まとめてコピペできないの?と普通の操作者は考えるよね
まぁ手作業だったら条件反射で(無意識に)
Ctrl+A全て選択 Ctrl+Cコピー Ctrl+V貼り付け
そんな操作を行うと思います。まずはIEの動作 メソッドを探って見たいと思います。
プロパティやメソッドを調べるなら、Excelのマクロ記録を使ってみたら?とよく聞きますよね、手順は→[プロパティ、メソッドの探り方 マクロ記録とF1のHelpを使う]← こんな感じです
ってことで、実際の操作を行い、マクロを記録してみます。
記録スタート
1. IEを立ち上げる
2. http://www.ken3.org/cgi-bin/test/test028-2.asp を URLに入力
3. ページが表示されたら、IE上で 編集・全て選択 編集・コピー
4. Excelに切り替えて貼り付け
記録終了(上記操作をマクロ記録してみます)
実際に記録したコードを見てみると、ダメだ記録されてない。。。
|
マクロ記録に載らなかったことをいつまでも気にしていても先に進まないので、
MSDNのIEオブジェクトのメソッドを探ってみます
[InternetExplorer Object (MSDN)]
↑ここのMethods を探ってみます。
するとコマンドを発行する.ExecWB メソッド↓が見つかります。
[.ExecWB メソッド http://msdn.microsoft.com/en-us/library/aa752087.aspx]
使い方は、
object.ExecWB( _ cmdID As OLECMDID, _ cmdexecopt As OLECMDEXECOPT, _ [pvaIn As Variant,] _ [pvaOut As Variant])object.ExecWB(cmdID(コマンドID)と , cmdexecoptを指定)するみたいですね。
typedef enum { OLECMDEXECOPT_DODEFAULT = 0, OLECMDEXECOPT_PROMPTUSER = 1, OLECMDEXECOPT_DONTPROMPTUSER = 2, OLECMDEXECOPT_SHOWHELP = 3 } OLECMDEXECOPT;となっており、まぁ、DO DEFAULT の 0でいいのかなぁ。
test028-2.aspのページを表示後、全て選択(OLECMDID_SELECTALL = 17)発行後、コピー(OLECMDID_COPY = 12)を連続発行してから、Excelに貼り付けてみます。
シートを追加しながら、3パターンの貼り付けを実行してみます
|
テーブルを選択 selectしたくてMSDNを探す
と
select Method (TextRange, controlRange)
http://msdn.microsoft.com/en-us/library/ms536735.aspx
が見つかります。
ここに、サンプルコードが2つあって、そのうちの一つが、
>function ControlRangeSelect() {
> var r = document.body.createControlRange();
> r.add(document.all.aaa);
> r.select();
>}
が、ありました。みるからにコントロールをセレクト、選択している?
この、document.all.aaa を 変更して、r.Add objIE.document.all(n) こんな感じで、.allから見つけたn番目(テーブル位置を指定)にしてみたいと思います。
|
↑なんとか、テーブルのみを選択して貼り付けできました。まぁ、貼り付けの形式はHTML以外は使いにくいかなぁ。※罫線や文字飾りのない生データが貼り付いてくれたらうれしかったけど・・・
余談:後日(少し経ってから)興味があったので、createControlRange を さらに探すと、
プログラムでクリップボードに IMG 要素をコピーする方法
http://support.microsoft.com/kb/293125/ja
を見ると、
>この資料は、プログラムでクリップボードに( IMG Element の)
>Web ページでのイメージをコピーする方法を示します
ここにもサンプルソースがあって、
> function copyImage(sImgID)
> {
> var ctrlRange = document.body.createControlRange();
> ctrlRange.add(document.all(sImgID));
> ctrlRange.execCommand("Copy");
> }
んっ、.execCommand("Copy") これでコピーできるのかな?
ってことで、下記のようにプログラムを修正しました。
|
.execCommand "Copy" でコピーする方法、惜しかったなぁ・・・カッコつけ損ねました(笑)ってことで、表のコピーはなんかカッコ悪いけど、テーブル選択後.ExecWB 12, 0とコピーのコマンドを発行してください。
document.all(n)で.tagnameが指定したタグになるまで空読みとかいかにも泥臭いよね・・・
実はもっとスマートな読者様に好かれる方法があって、(読者の声:だったら先に書けよ)
.all コレクション の 中に、.tags メソッドなんて便利なメソッドがあって、
実行すると指定したタグのオブジェクトを返してくれるそんなイメージです。
※[.document .all .tags http://msdn.microsoft.com/en-us/library/ms536776.aspx]にMSDNのサンプルvar coll = document.all.tags("p");があります。
これ("p")をtableに変更してテストしてみます。
|
ポイントは、
Set objTABLE = objIE.document.all.tags("TABLE")
で.tags("TABLE")を指定して抜いたオブジェクトをobjTABLEにセットします。
セットされたobjTABLEを使い、objTABLE(0)が1番目のテーブルなので、
Set objRANGE = objIE.document.body.createControlRange '範囲のオブジェクトを新規で作り
objRANGE.Add objTABLE(0) '(0)でテーブルを追加(指定する) 1番目は0からなので
objRANGE.Select '範囲のオブジェクトを セレクト 選択する
objIE.ExecWB 12, 0 'コマンド発行 OLECMDID_COPY = 12 コピー
と、して、テーブルをコピーして、HTML形式で貼り付けた、そんな感じです。
objTABLE(0)としてプログラムを組んでいると知りたいのが、配列の数ですよね、これも.Lengthで簡単に知ることができます。
Dim objTABLE As Object 'テーブルオブジェクトの格納用
Set objTABLE = objIE.document.all.tags("TABLE") 'TABLEを指定して抜く
For n = 0 To objTABLE.Length - 1 '.Lengthがテーブル数なので-1する
'テスト用シートを追加し名前をTABLE?とする
Sheets.Add 'のシートを新規追加する
ActiveSheet.Name = "TABLE" & n 'TABLE0,1,2...シートに名前を付ける
'テーブルを範囲指定後、コピーする
Set objRANGE = objIE.document.body.createControlRange '範囲のオブジェクトを新規で作り
objRANGE.Add objTABLE(n) '(n)で1つ1つテーブルを追加(指定する)
objRANGE.Select '範囲のオブジェクトを セレクト 選択する
objIE.ExecWB 12, 0 'コマンド発行 OLECMDID_COPY = 12 コピー
'TABLEデータをシートに貼り付ける
Range("C3").Select '先頭A1じゃ面白くないので C3をテストで選択
ActiveSheet.PasteSpecial Format:="HTML" 'HTML形式を選択して貼り付け
Next n
↑こんな感じで、.Lengthを使い、全てのテーブルを処理することもできます。
ループで全て回すなら、For Each を使えよ・・・と、読者様の声が聞こえたので、テストプログラムを書いてみます。
|
↑ここまでのXP+IE6,IE7で動くサンプルです→[Documentの山からテーブルデータを抜くサンプル 20080513_IE_TEST.zip]←Excel2003の.xlsファイルです、解凍後実行しながら、修正したりして遊んでみてください。
いつもの私が好きな Set objIE = CreateObject("InternetExplorer.application") だと、Vista + IE7で失敗したり(オイオイ、いきなり失敗談かよ)
なので、これから新規に始める人は、素直にUserFormにIEを貼ると . を押すとプロパティやメソッドが出てくるので、そちらのほうがお勧めかなぁ。始めは手間だけど、Excel持ってれば、こっちから入るのがいいかも。ってことで 4種類の動画解説を作りました。周りに人が居ないときに見てください(オイオイ)
OS:XP Excel2003 と IE6,7で動作したIE操作のVBAサンプル Set objIE = CreateObject("InternetExplorer.application") をそのままVista IE7 Excel2007で走らせたら 接続中でループしているIE と 動いているが新規のIEが立ち上がっていて objIE経由でコントロールできなかった、動かなかった・・・そんな悲しいお話です。 Vista Excel2007でサンプルをダウンロードして実行してコケた失敗動画です。→ で、考えた対策は下↓の3つです。 | |
原因がVista IE7の保護モードなので、お勧めできないのですが、コントロールしたいサイトを手動で(オイオイ手動かよ)信頼済みのサイトにしてテストしてみたそんな実験結果です。→ IE7への移行で困ってサイトに来た読者様へ : すでにXP+IE6で作成したシステムが稼働・運用中で、新規のVista PC端末に移行・機能追加しないとダメ、IE7でテストしたらCreateObject("InternetExplorer.application")でコケタ急いで修正しないと・・・そんな急ぎの時は、とてもお勧めできないけど一番手軽なのが↓ [Vista IE7 信頼済みのサイトにしてVBAからコントロールしてみた] ↑操作対象のURLが固定のサイトだからって、セキュリティを変更するとマズイし気分が悪いよね(本格的な対策のつなぎで) ※いくら急ぎだからって、手を抜くと後で倍になって返ってきたりします(経験談?) 次に考えたセコイ方法が↓ | |
IEのコントロールをExcelのUserFormに貼り、 UserForm1.Show vbModeless と、モードレスで立ち上げます、 次に、 Set objIE = UserForm1.WebBrowser1 で、フォームのWebBrowserを変数に代入します。 あとはobjIEに対して既存のプログラムを変更無しで動くのでは? そんなテストを実行してみました。 ※三流的な小細工ですが・・・→ ↓実際に過去の資産(作成済みのプログラム)を有効に?細工したサンプルです。IE6とFormにIEを貼った違いです[IE起動とデータセットのサンプル 20080527_IE_Form.zip]←Excel VBAです objIE = UserForm1.WebBrowser1のセコイ方法を実際に動かしたりソースをみてください。 | |
既存のプログラムを生かす、、、↑ と 過去の資産にこだわってました、 が、 これから新規にIE操作プログラムを組む人は、 Excel UserForm に コントロールを貼ったら、 素直に Me.WebBrowser1.Navigate など、 フォームにモジュールを書いた方がいいのでは? そんな、過去に引きずられない方法です。→ |
上にUserFormにIEを貼る操作の動画を入れたんだけど、クレームの連絡をいただく。。。(オイオイまたか)
・音声付きの動画だと 会社で観ると恥ずかしい
・YouTube は フィルタリングされていて会社から観ることができない
・PCの音量切ってます or スピーカーはハズしています・・・
など。
たしかに ソフト会社のPC。音源ボード入っていてもスピーカーつないでいなかったり、
勤務中にYouTube動画を見るのをルーター側で禁止している会社があっても不思議じゃないですね。
意外と動画解説って不評だったり(笑)
おっと、失敗話はこれくらいにして、そんな読者様のために静止画を貼ります(初めから画面のハードコピーにしとけよ)
UserFormを作り、IEのコントロールを貼りたいと思います
フォームを1つ作り IEのオブジェクトを貼る
まぁ、ユーザーフォームを選択すると、下記のようにUserForm1が作成されます。
次に、ツールボックスで空白エリアを選択後、右クリックを押してその他を選択します。
利用可能なコントロールがたくさん表示されるので迷いますが、
下の方にスクロールさせ、Microsoft Web Browser を選択します。
すると、コントロールに丸い世界のアイコンが表示されます。※地球をイメージ?
これを選択してフォームに貼り付けます。
貼り付けると こんな感じ↓(オブジェクト名 WebBrowser1 で貼り付けられると思います)
忘れずに保存します。これで、下準備ができました。
UserForm に 無事貼ることができたら、あとは、
Me.WebBrowser1.Navigate や Me.WebBrowser1.Document.〜
など、頭が違うだけで同じように使えます(気がついてみれば当たり前のことなんだけど・・・)
同じようで違うことがあって、UserFormに貼って便利になったのが、
プログラムを打ち込んでいると気がつくが、ドットを押してメソッドやプロパティが出るので大変便利なんですよ。
↑もっとはやく 教えろよ ボケ・・・と 読者様の声が聞こえてくるような・・・・
新規に作成する場合でExcelやAccessが使える場合はUserFormに貼ってみては?
また既存のシステムでは、
Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
をコメントにして、
Set objIE = Me.WebBrowser1 'フォームのIEを代入する
と起動部分を置き換える こんな感じで既存の動いているプログラムの起動部分 1行を修正して対応してみました。対応したサンプルです→[Documentの山からテーブルデータを抜くサンプル 20080513_IE_TEST.zip]←Excel2003の.xlsファイルです、解凍後実行しながら、修正したりして遊んでみてください。
まだまだ、書かないといけないDocument操作 プロパティやメソッドなどの組み合わせがあるのですが、このあたりで逃げるように失礼します(オイオイ)。更新が遅いけど温かく見守ってください 更新中 まだまだ書きかけ
いろいろな表現があって、かえって迷ってしまうかもしれませんが、数をこなすと見えてくるので、私のサンプルだけじゃなく、いろいろなサンプルを探して見てください。[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]にお勧めのキーワード検索方法を載せてます
はじめに(あいさつ?):インターネットエクスプローラーの操作と一口に言ってもイロイロな操作があると思います。
そのうちの一つが、あるホームページ(URL)を表示して、入力フォームにデータをセットして登録ボタンを押す、この一連の流れをVBA上から行いたい・・・と日本語で書くのは簡単なんだけど、この流れをプログラムで記述してみたいと思います
初めの一歩・とっかかりとして、隣のメルマガ([ASPで遊ぶ])の宣伝を兼ねて(オイオイ) ASPとMDBで作ったデータ入力フォームにデータをセットしてみたいと思います。
VBAから、IEの入力フォームを操作する・・・と簡単に書いてますが、どこから手を付けるか、、、ですよねぇ。
まずは敵(ターゲット)を知る 事前準備からかな。
深呼吸して心を落ちつかせます(別にもともと落ち着いてるって?)
自動化の前に手動で、操作したいホームページを自分で(手作業で)操作して、処理のイメージをつかみます。
今回のターゲット → [http://www.ken3.org/cgi-bin/test/test029-2.asp]を開いて、手動でデータを入力したり、ボタンを押して、動きをチェックします
手動で操作のイメージを軽く頭に入れたら、
次に、文章(htmlなど)のソースを表示して<form>の中身を確認します。
いきなり、中身とかソースとか言われてもなぁ・・・頭の中?だらけだよ。
あっ、すいません、自分だけわかってて相手のこと考えて無くて。
目的の入力フォームの構造が知りたいので、
目的のページを表示後、
表示--ソースとするとhtmlやcgiの中身を手作業ですが確認できます。
[ソースの確認画面イメージ] ← 単純にIEのメニューから表示させているだけですが
※↑フレームやJavaScriptで細工されたページ、文字コードが違って化け文字になっている・・・など簡単に表示できない場合もありますが
繰り返すと、
・手作業で自動化したい操作を行ってみる。
・ソースを表示して、入力フォームや構造のチェックに使う準備をする
まずは、この2点です。
今回は、よくあるデータ登録で、テキストボックスにデータを入力して、データ送信(Submitボタン)処理を行ってみます。
Formのデータ登録サンプル:[IE起動とデータセットのサンプル 20080527_IE_Form.zip]←Excel VBAです
↑保存後、実行しながら下記の解説を読んでみてください。
今回のターゲット(操作場所)は [http://www.ken3.org/cgi-bin/test/test029-2.asp] です。下記のような単純な入力フォームです。
データを入力して下さい。 感想を書き込んでください。 ↑実際に入力したり、まずは手動で動かしてみてください。 |
←のソース↓下記、ターゲットの文章(test029-2.asp)から抜き出した<form>の中身(ソース)です。
↑みたいな感じで、入力用のFORMが作られています。 |
最近の若者は仕様書くれとうるさいので(オイオイ)
手作業の操作をただ箇条書きにした流れを書いて渡してあげた(架空の話です、現実では通用しないのでくれぐれもマネなどせぬように...)
手動で操作した時の操作を今一度思い出してください。
まず、コンピュータの電源を入れて、ログインする(ここからやるの?)
・インターネットエクスプローラーを起動して、
・URLを入力 目的の文章・ページを表示させる(ショートカットやお気に入りの人も居るかなぁ)
・入力フォーム(画面の表示)を目で確認
・マウスやキーボードを使って入力エリアへデータをセットする。(データの入力)
・書 込(送信ボタン) を 押す
だいたいこんな感じかな。
そんなの言われなくてもわかってんだよ、しつこいなぁ、ハヤク コードの解説始めろよ※クドクてシツコイ男は嫌われるぞ
最近流行の 高級料亭でも行っている料理の使い回し じゃないけど、解説の使い回しで、
[IEの起動] : CreateObject("InternetExplorer.application")でブラウザを起動させました
[.Navigateで開く] : 次に目的のページを開くために.Navigateメソッドでページを移動しました
上記を参考に(って言っても、URLが変わっただけですが)
|
次は、
・入力フォーム(画面の表示)を目で確認
です。コンピューターに目は付いていないので、IE Document.プロパティの値(状態変化)で判断します。
なぜ、表示完了を待つかと言うと、いきなり入れるとイタイでしょ?(オイオイ、何言ってんだおっさん)
表示待ちを入れないで いきなりオブジェクトに触りに行くと(フォームなどのオブジェクトにアクセスすると) 相手の心の準備ができていないみたいで(オブジェクトの展開処理が間に合わないみたいで)、どこ触ってんだよと怒られるじゃなかった、 実行時エラー Document メソッドは失敗しました ・・・など、エラーで怒られるんですよ。
エラーの画像→[http://ken3-info.blog.ocn.ne.jp/screen/2007/05/ie__debe.html]
なので、objIE.Navigate 後に相手の準備ができるが確認します。
いろいろな調理方法(待ち方)があるのですが、ここも私の好きな調理方法を紹介します(三流的手法を押しつけます)。
読者の声:Application.Wait Time:=Now + TimeValue("00:00:05") '5秒間待つとか秒数を増やす手抜きなんだろ?
ギク、、今回は少しまともな方法を使います、判断によさそうなプロパティが2つあるので、.Busy と .ReadyState の状態を見て読み込み完了を判断してみます。
1つ目の判断材料が.ReadyStateです。
MSDNの[.ReadyState http://msdn2.microsoft.com/en-us/library/aa752066.aspx]←を見ると、
Enum READYSTATE READYSTATE_UNINITIALIZED = 0 READYSTATE_LOADING = 1 READYSTATE_LOADED = 2 READYSTATE_INTERACTIVE = 3 READYSTATE_COMPLETE = 4 End Enum
2つ目の判断材料が.Busyです
MSDNで.Busy プロパティ→[.Busy http://msdn2.microsoft.com/en-us/library/aa752050.aspx]を見ると
True or False なので、
Busy(忙しい?) True→忙しい、動いてる False→ヒマ、止まっている
単純に、objIE.Busy = Trueの間、ループで待ってみますか。
材料がそろったので、調理してみたいと思います。
|
次の工程は、
・マウスやキーボードを使って入力エリアへデータをセットする。(データの入力)
です
※指定したURLを開き、相手の受け入れ準備も確認できたので、次はWeb上の入力フォームにデータを挿入してみたいと思います。
入力したいinputエリアは、
<INPUT TYPE="TEXT" NAME="MEMO" SIZE=20><br>
の部分です。
name=XXXX(NAME="MEMO")と定義されてます。
このnameを利用してオブジェクトを表現するには、どうするのだろう?
先走らないでここで深呼吸、一呼吸おいて(何事もあせっちゃダメよ落ち着いてね!!)
見慣れたExcelの例だと ブック・シート・セルへデータをセットする場合、下記のように
シート--範囲
Sheets("Sheet2").Range("B3") = "B列3行目です"
や
シート--セル(y,x)
Sheets("Sheet3").Cells(5, 4) = "y,x 5行目の4列です"
Sheets(シート名).Rangeや.Cellsでオブジェクトへアクセスしていると思います。
Htmlの入力フォームの場合、オブジェクトの階層構造が
IEアプリ--ドキュメント--フォーム--アイテム(項目)
で表すことができるので(ほかにも表現方法はあるのですが今回はこれで)
objIE.Document.Forms(0).Item("MEMO").Value = 値
htmlドキュメント フォーム(0番目) アイテム(名称:MEMO)に転記(代入)する。って感じです。
※今回Formに名前Name=が付いてるので、objIE.Document.Forms("inputTEST").Item("MEMO").Value = 値 のほうが.Forms(0)で0番目のフォームよりもカッコいいんだけど・・・(Formに名前がない場合が多いので、.Forms(0)を先にやらせてください)
下記のような感じでデータをFormのMEMOにセットすることができます
|
次の工程は
・書 込(送信ボタン) を 押す
です
挿入(データをフォームにセット)できたら、次は、送信ボタン(書込や投稿)を押したいですよね・・・
実は、単純に該当フォームを.Submitなんてメソッドで できちゃったりするんですよ。
※オブジェクト.動作(メソッド) ってイメージかなぁ。
objIE.Document.Forms(0).Submit
こんな1行で、送信処理(書込や投稿)ができてしまいます。
データセット後にobjIE.Document.Forms(0).Submitを実行してみます。
|
読者の声:だからさっきから質問してるでしょ、.Submit ? Form ? F1押して表示されるExcel VBAのヘルプにそんなの一言も載ってないよ、データセットの件、なんとなくわかってきたけど、自分でも調べてみたいし、どこで調べるんだよ??
あっ、これですか・・
英語だけどMSDNの下記の項目を見るとオブジェクトの階層構造がわかりやすいと思います。
Reference for Visual Basic Developers [http://msdn.microsoft.com/en-us/library/aa752043.aspx] が 一覧で、その 下に、
document Object [http://msdn.microsoft.com/en-us/library/ms531073.aspx] をクリック 後に、
Collections を探っていくと、
forms Collection [http://msdn.microsoft.com/en-us/library/ms537457.aspx] オブジェクトがあります。
やっとFormまでたどり着けたので、
次に FORM Element | form Object [http://msdn.microsoft.com/en-us/library/ms535249.aspx]
のメソッドの中に
submit [http://msdn.microsoft.com/en-us/library/ms536771.aspx] があります。
※なかなか、探るのが大変ですが私も[三流君 が MSDN で InternetExplorer の 資料を探す]←みたいな非効率的な探し方をしたり、効率的に同じ処理を探すために検索に頼って[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]←みたいにして探ってます
次は、ラジオボタン(INPUT TYPE="RADIO")を選択してみたいと思います。ラジオボタン選択後、テキストボックスにデータを入力して、書込ボタンを押す、そんな処理を行ってみます。
今回も前回同様(操作場所)は [http://www.ken3.org/cgi-bin/test/test029-2.asp] です。下記のような単純な入力フォームで メルマガ区分の4種類ラジオボタンを選択してみます。
データを入力して下さい。 感想を書き込んでください。 ↑実際に入力したり、まずは手動で動かしてみてください。 |
←のソース↓下記、ターゲットの文章(test029-2.asp)から抜き出した<form>の中身(ソース)です。
↑みたいな感じで、入力用のFORMが作られています。 |
最近の若者は仕様書くれとうるさいので(マダ言ってるよいい加減にしろよ)
手作業の操作をただ箇条書きにした流れを書いて渡してあげた(架空の話です、現実では通用しないのでくれぐれもマネなどせぬように...)
※読者からのクレーム(神の声):だったらマネできる仕様書の書き方を教えろ・公開しろって感じなんだけど。(三流作者:クレームは神の声です、検討します(←よく聞く検討しますの逃げ言葉・・・))
手動で操作した時の操作を今一度思い出してください。
・インターネットエクスプローラーを起動して、[IEの起動]
・URLを入力 目的の文章・ページを表示させる(ショートカットやお気に入りの人も居るかなぁ)[.Navigateで開く]
・入力フォーム(画面の表示)を目で確認[.ReadyStateと.Busyで待つ]
・ラジオボタンを選択する。(目的の区分を選択する)※今回の目的
・マウスやキーボードを使って入力エリアへデータをセットする。(データの入力)[Input TEXTにデータをセット]
・書 込(送信ボタン) を 押す[.Submitで送信処理]
だいたいこんな感じかな。
そんなの言われなくてもわかってんだよ、しつこいなぁ、ハヤク コードの解説始めろよ※クドクてシツコイ男は嫌われるぞ
IEの起動 と ページの表示ができたら、ラジオボタンの選択を行いたいと思います。
ソースを見ると、<INPUT TYPE="RADIO"で名前もNAME="KUBUN"で一緒、VALUE=と値だけが違います。
HTML タグなどで表現された文章、タグが階層構造になっているとか言ってました。FORMも文章の一部で、その中(<FORM>〜</FORM>まで)のイロイロなタグによって構成されています。
だから何?
えっと、Formの構成要素を1つ1つ取り出してみます。
For Each objTAG In objIE.Document.Forms(0)で1つ1つ要素をobjTAGに入れて、.Value , .Name を表示させてみました。
|
オブジェクトをどうにか特定できそうなので、実際にチェックしてみたいと思います。
名前(.NAME) が KUBUN
で
値(.Value) が VBA
のオブジェクトの.CheckedプロパティをTrueにしてみます。
For Each objTAG In objIE.Document.Forms(0) で回して、単純にIF文で .Name=KUBUN .Value=VBAを判断後、.Checked=Trueにしてみました。
|
プログラミングの面白さって、同じ結果を得るのにイロイロな書き方があるって所ですよね。まぁ、回答が1つじゃないので個性が出たり、書き方の好き嫌いでもめたりするんだけどね。。。(読者の声:そんな無駄話はいいから、簡単な近道があるなら寄り道しないで教えろよ)
えっと、ラジオボタンの.CheckedプロパティにTrueをセットして選択したのですが、別の方法があって、オブジェクトに対してクリックする、.Clickメソッドを発行する、そんな方法もあります。
簡略仕様書(いつもの使えない箇条書き仕様書)
1.InputBoxで上司・先輩への愚痴を文字列で受け取ります
2.次にIEを起動してWebページを開き
3.フォームの名前がinputTESTのHTML Formに対して以下の処理を行え
ア..Name(名前)=KUBUN,.Value(値)=GUCHIのオブジェクトを.Click(クリック)
イ..Name(名前)=MEMOのオブジェクトに入力文字列をセット
ウ. .Name(名前)=btnSUBMITのオブジェクトを.Click(クリック)
|
関連項目:[HTML入力フォーム外側のボタンを押す .Click]
(過去のメルマガ)[No.148 IE ラジオボタン(RADIO)の.Checkedと.Clickの違い]
今回は、データの選択方法でよく見かける SELECT OPTION の選択処理を行ってみます。
リストから1つのOPTIONを選択する場合▼の ドロップダウン パターン
と
リストからCtrlキーを押して複数選択可能な[SELECT 複数OPTIONの選択] パターン リストボックスのイメージかな?
の2つがあると思います。
まずは、OPTIONを単独で選択する場合を攻略したいと思います。今回のターゲット(操作場所)は [http://www.ken3.org/cgi-bin/test/test092-2.asp] です。下記のような選択(SELECT OPTION)です。
↑実際に入力したり、まずは手動で動かしてみてください。 |
←のソース↓下記、ターゲットの文章(test092-2.asp)から抜き出した<form>の中身(ソース)です。
↑みたいな感じで、入力用のFORM 選択(SELECT OPTION)が作られています。 |
手間だけど、Form下のオブジェクトを表示させて探ってみますか。
下記、単純にページを表示させ、手抜きでForm(0)の下、オブジェクトをシートに書き出してみました。
|
For Each objTAG In objIE.Document.Forms(0) だと、<Option>へ たどり着けなかったので、For Each objTAG In objIE.Document.Forms(0).Allと.Allを付けて探ってみました。
Sub ie_Forms_Input_Select_002() 'Form(0).Allの下、構成要素を1つ1つ取り出す '調査するURLをInput Boxでもらう Dim strURL As String '調査したいURL strURL = InputBox("調べたいURL", "URL", "http://www.ken3.org/cgi-bin/test/test092-2.asp") Dim objIE As Object 'IEオブジェクト参照用 'IEを起動する Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る objIE.Visible = True '見えるようにする(お約束) '.Navigate で 指定したURLを開く objIE.Navigate Trim(strURL) '念のため左右の空白を取ってから、.Navigateに渡す 'ページが表示される 完了を待つ While objIE.ReadyState <> 4 'READYSTATE_COMPLETE = 4 While objIE.Busy = True DoEvents '特に何もしないで.Busyの状態が変わるまで待つ Wend Wend '※FORM(0).Allの下 オブジェクトを1つ1つ表示してみた Dim i As Integer 'カウンター Dim objTAG As Object 'タグのオブジェクト格納用 Workbooks.Add 'テスト用の新規ブックを追加 Range("A1") = "NO.i番目" '見出しのセット Range("B1") = "TypeName関数の結果" Range("C1") = ".TagName タグの名前" Range("D1") = ".OuterHTML 外側含むHTML" Range("E1") = ".Value 値" Range("F1") = ".Name 項目に付けた名前" Columns("A:G").ColumnWidth = 20 '列幅を20に変更 'Form(0).AllのオブジェクトをFor Each で書き出す i = 0 For Each objTAG In objIE.Document.Forms(0).All 'データをセルへセットする Cells(i + 2, "A") = i 'i番目 結局iは使うのかよ(笑) Cells(i + 2, "B") = "'" & TypeName(objTAG) 'TypeNameでオブジェクトのタイプを表示 Cells(i + 2, "C") = objTAG.TagName 'タグの名前 Cells(i + 2, "D") = "'" & Left(objTAG.OuterHTML, 512) 'HTML 頭から512文字だけ書く '※タグの名前がSELECTかOPTIONの時だけ値を書く(FONTタグなど値や名前を持たないタグがあるので) If objTAG.TagName = "SELECT" Or objTAG.TagName = "OPTION" Or objTAG.TagName = "INPUT" Then Cells(i + 2, "E") = objTAG.Value '値 End If '※タグの名前がSELECTかINPUTの時だけ名前を書く(FONTタグなど名前を持たないタグがあるので) If objTAG.TagName = "SELECT" Or objTAG.TagName = "INPUT" Then Cells(i + 2, "F") = objTAG.Name '名前 End If i = i + 1 'インクリメント Next End Sub |
For Each objTAG In objIE.Document.Forms(0).All のループで、OPTIONを取り出せたので、値(.Value)がVBAのオブジェクトを選択(.Selected=True)してみます。
|
んっ、↑で、Document.Forms(0).All のループで回してとか言ってたけど、その前に<OPTION>は<SELECT>〜</SELECT>の中だからか?なんて言ってたよね。
はい、言ってたよ。それが何か?
何かじゃねぇダロ、選択させる値が<SELECT>〜</SELECT>の中なら初めから、<SELECT>のタグに、.Valueに値をセットしてみたら?<OPTION>を探して.Selected=Trueなんてやってられるか
、、ってことで実際にやってみました。
|
関連項目:値を直接セットできるなら、(過去のメルマガ)→ [No.154 IE SELECTタグの選択 .SelectedIndex=nで選択] も、必要なかったか・・・次に説明しようとしたのに。。。
じゃなくて屁理屈をこねると、値を変えただけだとJavaScriptのイベントが発生しないので、(過去のメルマガ)→[No.155 IE SELECT後 .fireEventでJavaScriptのイベントを起動]みたいなことが必要だし、<OPTION>を探して.Selected=Trueの応用で、探した<OPTION>を.ClickすればJavaScriptも起動する(過去のメルマガ 例はラジオボタンの.Checkedだけど)→ [No.148 IE ラジオボタン(RADIO)の.Checkedと.Clickの違い ] ってことで、<OPTION>タグを1から探す方法も無駄じゃない・・と、かなりの行数をかけて力説してみました。(読者の声:※素直にあやまればいいのに、屁理屈言って粘る 謝らないプログラマーっているよね。実力が三流のクセにプライドだけは一流ぶってるヤツ、えっ私Ken3のこと?(笑))
上で単独のOPTION選択を行ったので、次は、SELECT Size=nで複数表示されたリストボックスから、Ctrl+クリックで複数のOPTIONデータを選択する方法を探ってみたいと思います。
今回のターゲット(操作場所)は [http://www.ken3.org/cgi-bin/test/test093-5.asp] です。下記のようなリストボックスで複数選択可能なSELECTタグとOPTIONタグです。
FORM リストボックスの複数選択(selectタグ multiple で VALUE=を個別に作成) ↑実際に入力したり、まずは手動で動かしてみてください。 |
←のソース↓下記、ターゲットの文章(test093-5.asp)から抜き出した<form>の中身(ソース)です。
↑みたいな感じで、入力用のFORM 選択(SELECT OPTION)が作られています。 |
複数でも単独と同様、OPTIONの選択は.Selected = Trueかな。
単独のOPTION選択の時、[Option .Selected]で単純に For Each objTAG In objIE.Document.Forms(0).Allでループして.TagNameでOptionタグを探しOptionタグ.Selected = Trueをセットしました。
今回、同じだとつまらないので、少し変えてみます。.Allで指定したタグを抜くことが可能な、[.tags("タグの名称")]を使って、
For Each objTAG In objIE.Document.Forms(0).All.tags("OPTION")でFormからOPTIONのみを抜き、
値をチェック .Value="VBA" なら.Selected = True
と
表示文章(TEXT)の値 .InnerTEXT="愚痴系(GUCHI)" なら同じく.Selected = True
値とテキストをみて判断してみます。(※↑.InnerTEXTで見えているリストの文章を選択するのもアリかなぁ。)
|
できれば、複数選択も値の代入だけですましたかったんだけど・・・これもいつもの調査中で逃げてるって感じですね。(時間を作って、壁に立ち向かわないとダメですね)
フォームのチェックボックス INPUT TYPE="CHECKBOX"を操作します。
おおまかなタイプは2つあって、NAME="オブジェクト名"が個々に違う場合と、NAME="オブジェクト名"が同じでValue="識別する値"で区別しているパターンです。
読者の声:何言ってるのかわからない、意味不明、日本語でお願いします。。。
日本語かぁ・・・自信がないので下記にHTML言語を書きます(HTML言語で話します)
INPUT TYPE="CHECKBOX"の2パターン
NAME="xxxx"が個々に違う | NAME="xxxx"が同じでValue="zzzz"が違う |
Formの場所[test093-2.asp]↓入力イメージ ↑のHTMLソース↓ <FORM ACTION="test093-2.asp" METHOD="POST"> <font color="blue">CHECKBOX NAME=を個別に作成 Where句を作成するTEST</font><br> 表示したい・区分をチェックしてから検索ボタンを押してください<br> <INPUT TYPE="CHECKBOX" NAME="ASP">ASP<br> <INPUT TYPE="CHECKBOX" NAME="VBA">VBA<br> <INPUT TYPE="CHECKBOX" NAME="24H">コンビニ系<br> <INPUT TYPE="CHECKBOX" NAME="GUCHI">愚痴系<br> <INPUT TYPE="submit" VALUE="検索する"> </FORM> NAME="XXXX"が違うパターンです |
Formの場所[test093-4.asp] チェックボックス↓入力フォーム ↑のHTMLソース↓ <FORM ACTION="test093-4.asp" METHOD="POST"> <font color="blue">FORM CHECKBOX VALUE=を個別に作成 Where句を作成するTEST</font><br> 表示したい・区分をチェックしてから検索ボタンを押してください<br> <INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="ASP">ASP<br> <INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="VBA">VBA<br> <INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="24H">コンビニ系<br> <INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="GUCHI">愚痴系<br> <INPUT TYPE="submit" VALUE="検索する"> </FORM> NAME="XXXX"が同じでVALUE="ZZZZ"が違うパターンです |
Name="XXXX"が個別に違う場合は、素直に名前で目的のオブジェクトへアクセスできるので、
オブジェクト.Checked = Trueでチェックボックスにチェックを入れてみます
Name="VBA"とName="24H"にチェックを入れてみます。
|
次に、CHECKBOXのName="XXXX"が同じでValue="ZZZZ"が違う入力フォーム
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="ASP">ASP<br>
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="VBA">VBA<br>
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="24H">コンビニ系<br>
<INPUT TYPE="CHECKBOX" NAME="KUBUN" VALUE="GUCHI">愚痴系<br>
の場合、フォームのオブジェクトを1つ1つみて、.NameがKUBUNで.Valueが目的の値で判断してから、.CheckedをTrueにしてみます。
KUBUN が ASP,VBA,24Hの3つにチェックを入れる
|
上のチェックボックスの判断で、名前(.Name)と値(.Value)を判断したかったので、
For Each objTAG In objIE.Document.Forms(0) で ループを作り、
If objTAG.Name = "KUBUN" Then で 名前が KUBUN かみて
さらに If objTAG.Value = "ASP" Then で値を判断しました。
動いているので、これはこれで正解なのですが(動いているソースをイジルなってプログラマーの格言?もあるんだけど)、指定した名前を取り出す方法があったりします。
文章から指定したタグのオブジェクトを抜く時に、document.all.tags("タグの名前")で指定したタグを抜き出せました→[.tags("タグの名称")]
これに近い命令があって、
document.getElementsByName("名前(Nameの値)")
なんて感じで意外と簡単に取り出せたり。
てっことで、実際に.getElementsByNameを使ってみます
|
次は、<INPUT type="button" 〜 onclick="Javaで作った関数('パラメータ')"> で作られたボタンを.Clickで押し JavaScriptを起動してみたいとおもいます。Formに属さない無いボタンを押す、そんな処理を行ってみます。
テスト場所(操作場所)は [http://ken3-info.blog.ocn.ne.jp/test/2007/09/post_d21d.html] です。下記のように<FORM>〜</FORM> が 無く、ボタンのonclickイベントでJavaScriptを起動しています。 ↓htmlソース
<SCRIPT language="javaScript">
function IE_JUMP(s){
location.href=location.href='http://'+s;
}
</SCRIPT>
<p>フォームの外のボタンを押すテスト</p>
<hr>
<INPUT type="button" name="btop" value="三流君Topへ" onclick="IE_JUMP('www.ken3.org')"><br>
<INPUT type="button" id="idvba" value="VBA解説" onclick="IE_JUMP('www.ken3.org/vba/')"><br>
<INPUT type="button" value="ASP解説" onclick="IE_JUMP('www.ken3.org/asp/')"><br>
<INPUT type="button" value="IE操作解説" onclick="IE_JUMP('www.ken3.org/cgi-bin/group/vba_ie.asp')"><br>
<hr>
いままでの例だと 名前が付いていれば objIE.Document.Forms("フォームの名前").Item("ボタンの名前").Click や 名前が無くても番号で objIE.Document.Forms(0).Item(6).Click などFormオブジェクトの下を操作してました。
が、今回の文章(Document)には、<Form>がありません・・・
Formの下にINPUTのボタンが無いからってあわてないでよ。(読者の声:別にあわててないよ、疑問を聞いてるだけ)
<INPUT type="button" name="btop" value="三流君Topへ" onclick="IE_JUMP('www.ken3.org')"><br>
のボタンを押したい場合、名前がname="btop"と付いているので、
Document.all("btop").Click
↑こんな感じで、.all("名前")で目的のオブジェクトを指定することができます。
※余談:いつものFormアリ 属したボタン objIE.Document.Forms("フォームの名前").Item("ボタンの名前").Click 操作 を objIE.Document.All("ボタンの名前").Click と書くことも名前が重複していなければできたりします。全体allから名前でオブジェクトを特定することもできます。
話を戻して、Document.all("btop").Clickでクリックできるか、テストしてみます。
|
ボタンにName=で名前が付いてればいいけど、
<INPUT type="button" value="ASP解説" onclick="IE_JUMP('www.ken3.org/asp/')"><br>
<INPUT type="button" value="IE操作解説" onclick="IE_JUMP('www.ken3.org/cgi-bin/group/vba_ie.asp')"><br>
上記INPUTのボタンは、ボタンにName=名前が付いてないよ。お手上げでしょ?
名前がなければ素直にあきらめるのかい?名前が付いていなくても あのお店・店員の中で地下の食品売り場の背が高くて痩せ型の男性やいつも元気で笑顔がステキな女性など、特定方法はいくらでもあるダロ(読者の声:また違う方向に話が進んでるよ、まじめに解説しろ)
文章から表・テーブルデータを抜くときに、document.all.tags("タグの名前")で指定したタグを抜き出してたよね→[.tags("タグの名称")]
これ(.tags)を利用して、.tags("Input")で、INPUTを抜き、<INPUT type="button" value="IE操作解説" onclick="IE_JUMP('www.ken3.org/cgi-bin/group/vba_ie.asp')"><br>
取り出したINPUTの.Valueがvalue="IE操作解説"か判断してみます
ボタンの名称が(.Valueが) IE操作解説のボタンを押すサンプル
For Each objINPUT In objIE.Document.all.tags("INPUT")でINPUTを抜き出して、ボタンの名称をobjINPUT.Value = "IE操作解説"で判断して、見つかったらそのオブジェクトをobjINPUT.Clickしました。
|
余談:間違っても客先や派遣先で名前がわからないからって、胸の大きいな女性に説明しましたとか、とんでもない発言を客先担当者(納品先の課長)に言っちゃイケマセンよ(あの頃は若かったなぁ それで次の仕事が来なかったのか って、誰の失敗談だよ) じゃなくて、少々パターン違いの 逆にName=砂糖さん と名前が同じ場合もあったり、過去のメルマガ → [No.176 VBAからIE操作 NAMEが同じフォームの項目へデータをセットする] も参考にしてください。※逆の立場で自分が派遣で来ているデブ プログラマーとか社員さん達に言われたらと思うとかなり反省(オイオイ)
まだまだ、書かないといけないForm操作 プロパティやメソッドなどの組み合わせがあるのですが、このあたりで逃げるように失礼します(オイオイ)。更新が遅いけど温かく見守ってください 更新中 まだまだ書きかけ
いろいろな表現があって、かえって迷ってしまうかもしれませんが、数をこなすと見えてくるので、私のサンプルだけじゃなく、いろいろなサンプルを探して見てください。[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]にお勧めのキーワード検索方法を載せてます
ここまでのサンプル Formのデータ登録サンプル:[IE起動とデータセットのサンプル 20080527_IE_Form.zip]←Excel VBAです
保存後、解凍して、テストしてみてください。
はじめに(あいさつ?):インターネットエクスプローラーの操作と一口に言ってもイロイロな操作があると思います。
そのうちの一つが、あるホームページ(URL)を表示して、リンク先の情報を取り出したい、、、そんな要望があると思います。※リンクの先を探りたいなど、この一連の流れをVBA上から行いたい・・・と日本語で書くのは簡単なんだけど、この流れをプログラムで記述してみたいと思います
ここからのリンク先の取り出しサンプル[IE起動とリンクの取り出し サンプル 20080605_IE_Link.zip]←Excel VBAです
ダウンロードして遊んでみてください。
読者の声:.Document.Links ? アンタまたわけわかんないオブジェクトをイキナリくちばしるね?自分だけわかってて、相手のこと考えたことあるの??説明の順番は、考えたことあるの?もっと違う方向性・説明の順番があると思うけどなぁ。。。読者Bそうだそうだ、基本もいいけどもっと実用的なことやれよ
まぁまぁ、そんなこと言わないで、今回の1 .Lengthの話 2. For Eachの話、3. InnerHTMLやInnerTEXTと.OuterHTMLや.OuterTEXTの違いだけでも、この3点だけでも聞いてくださいね。
と、いつもの小芝居は置いといて、表示したHP(ドキュメント)のリンク先が.Linksオブジェクトに保存されています。この.Document.Linksを操作して、IEドキュメント操作の感覚をつかんでもらう、それが狙いなのでよろしくお願いします。
今回操作したいリンクはAタグなので、MSDNで調べるならココ、
アクセス可能な HTML 要素 [http://www.microsoft.com/japan/msdn/workshop/author/access/accessibility.aspx#acc_elements] をクリック 後に、
Aタグ を探っていくと、
A Element | a Object [http://msdn2.microsoft.com/en-us/library/ms535173.aspx] が見つかります。
ここにイロイロと使えそうなプロパティやメソッドがありそうです。ワクワクしませんか?
読者の声:あっそ、でも英語でしょ?日本語の解説無いの?
冷めてるなぁ、、、でも、いっぱいあって何を使えばいいのか・・・いきなりこんなの見せられたら挫折しますね。
なので、私が使っている(知っている)プロパティを使って、テストプログラムを書いてみました。
読者の声:はじめから知ってるコマンドだけ解説します・残りは自分でMSDNやネットから探してくださいと言えよ?全て丁寧に解説してくれるものだと期待するでしょ
スミマセン、、、と、落ち込みつつ、リンクを取り出すサンプルを作成します
初めは、どんなことをやるか、仕様(仕様書)を書かないといけないんだっけ、
では、いつもの通用しない箇条書き仕様を軽く書きます。
1.調査したいURLをInputBoxで受け取ります(かなり手抜き・・・)
2.IEを起動させ、目的のページを表示させます。
3.目的のページからリンク先を取り出し、セルに書き出します。
こんな感じかな。※オイオイ、おおまか過ぎでしょ・・・
次章からこの3つに対応したコードを載せます。
もしかして、解説不要?だと思いつつ、標準関数のInputBoxを使ってURLを受け取る(入力してもらう)には、
strURL = InputBox("調査するURLは?", "URL入力", "http://www.ken3.org/backno/backno_vba_mokuji.html")
こんな感じかな?
標準関数なので、よく見かけると思います。
IEの起動とページ表示です。最近流行の 高級料亭でも行っている料理の使い回し じゃないけど、解説の使い回しで、
ア.初めは[IEの起動] CreateObject("InternetExplorer.application")でブラウザを起動させます
イ.次に[.Navigateで開く] 目的のページを開くために.Navigateメソッドでページを移動させます。
ウ.最後に[.Busyと.ReadyState]で表示の完了(ページの読み込み)を待ちます。
上記を参考に(って言ってもほぼそのまま、URLが変数に変わっただけですが)
|
調査対象のページが無事に表示されたら、新しいブックを追加後
Document.Links.Lengthでリンクの数がわかるので、
For i = 0 To objIE.Document.Links.Length - 1とループを作り
objIE.Document.Links(i).Href
objIE.Document.Links(i).OuterText .OuterHTML
objIE.Document.Links(i).InnerText .InnerHTML
objIE.Document.Links(i).Target
をセルに書き込みます。
解説の前に 先出しで下記、テストで作ったリンク書き出しのプログラムです。
|
ループで回す時、最大値・要素の数を知りたいので、そんな時は、Document.Links.Lengthで知ることができます。
バカの一つ覚えのExcelとの比較を一つ、ブック内のシート名を表示するテストプログラムを書きます。
Sub TEST_SHEET_NAME()
'シートの名前をテストで表示する
Dim i As Integer 'カウンター、添え字
For i = 1 To ActiveWorkbook.Sheets.Count
MsgBox i & " シートの名前 " & ActiveWorkbook.Sheets(i).Name
Next i
End Sub
ドキュメント内 リンクのオブジェクト に
objIE.Document.Links(i番目)
で、アクセスできた(できる)ので、次はプロパティ・値を取りたいと思います。
objIE.Document.Links(i).Hrefでリンク先などを取り出すことができます
私が使ったことがあるプロパティをセルに書き出してみました。↓単純に縦に羅列しただけですが
Cells(yLINE, "A") = "'" & objIE.Document.Links(i).Href
Cells(yLINE, "B") = "'" & objIE.Document.Links(i).OuterText
Cells(yLINE, "C") = "'" & objIE.Document.Links(i).OuterHTML
Cells(yLINE, "D") = "'" & objIE.Document.Links(i).InnerText
Cells(yLINE, "E") = "'" & objIE.Document.Links(i).InnerHTML
Cells(yLINE, "F") = "'" & objIE.Document.Links(i).Target
実行結果を見ていただけると、各プロパティの違いがわかると思います
読者の声:わかるわけねぇだろコラ。また、自分だけ気持ち良くなってんじゃねぇよ。。。InnerとOuterやHTMLとTEXT どこが違うんだよ。
スミマセン、手抜きの解説で、少々いつものようにくどく書くと下記のリンクのAタグがあります
<A href="http://www.ken3.org/" target=_blank><Big><STRONG>三流</STRONG>プログラマー</Big></A>
↑のデータを例にすると、
.Hrefは リンク先URL http://www.ken3.org が値として取り出せます。
.Targetは _blank (見たまんまか)
.OuterTextと.InnerTextは タグの付いてないテキスト文字列 三流プログラマー を値として取り出せます
.OuterHTMLは、外側のタグを含むHTML <A href="http://www.ken3.org/" target=_blank><Big><STRONG>三流</STRONG>プログラマー</Big></A> です。あっ、そのまま全てか(笑)
.InnerHTMLで タグの内側 <Big><STRONG>三流</STRONG>プログラマー</Big> 外側を1つはずした感じかな の データを受け取れます。
.OuterText .OuterHTML .InnerText .InnerHTMLは、他のタグでも使うことが多いので、なんとなくでもいいので頭のスミにでも覚えておいてください。
よし、リンクオブジェクトの説明終了、、、朝までにもう一軒飲み屋じゃなかった、オブジェクトをハシゴするぞと行きたい所ですが、あと一杯、少しだけお時間をとらせてください。
読者の声:だから、余計な会話はいいから、はやくシロ。(※←この読者の心の声もかなりの蛇足なんですが(笑)説明に必要ないでしょと思いつつ)
書き方に好みの問題もあるのですが、
objIE.Document.Links(i)
と、配列(i番目)でまわす方法のほかに、
For Each 変数 In オブジェクト
なんて書き方もあります
読者の声:何言ってんだか、よくわからん。いつもの例だせよ
えっ、いいんですか?いつもの蛇足の例を出して。では、お言葉に甘えてExcelのシートを例にして、
Sub TEST_SHEET_NAME_FOR_EACH()
Dim objSHEET As Worksheet 'シートのオブジェクト受け取り用
For Each objSHEET In ActiveWorkbook.Sheets
MsgBox " シートの名前 " & objSHEET.Name
Next
End Sub
話を戻して、下記 For Each INを使用したサンプルに書き換えました。
Sub ie_Link_For_Each_test() 'For Each 変数 In objIE.Document.Links のテスト '1.調査したいURLをInputBoxで受け取ります(かなり手抜き・・・) Dim strURL As String '入力値を受け取る変数 'INPUTBOXでURLをもらう strURL = InputBox("調査するURLは?", "URL入力", "http://www.ken3.org/backno/backno_vba_mokuji.html") If strURL = "" Then MsgBox "調査したいURLを指定してください" Exit Sub '途中で抜ける End If '2.IEを起動させ、目的のページを表示させます。 Dim objIE As Object 'IEオブジェクト参照用 'IEを起動する Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る objIE.Visible = True '見えるようにする(お約束) '.Navigate で 指定したURLを開く objIE.Navigate strURL '表示完了を待つ While objIE.ReadyState <> 4 While objIE.Busy = True DoEvents '特に何もしないで.Busyの状態が変わるまで待つ Wend Wend '3.目的のページからリンク先を取り出し、セルに書き出します。 Dim yLINE As Integer '行カウンタ、Y行目 Dim objLINK As Object 'リンクのオブジェクト受け取り用 'html ドキュメント リンク オブジェクトからデータをセルへ転記(代入)する。 Workbooks.Add '新規ブックを追加 データ転送用に新規のブックを追加する Range("A1") = "調査したURLは " & strURL & " です" 'A1にURLを記述(セット) Range("D1") = "リンクの数は " & objIE.Document.Links.Length & "です" 'D1にリンクの数をセット Range("A2") = ".Href(リンク先)" 'A2〜F2 2行目に見出しをセットする Range("B2") = ".OuterText" Range("C2") = ".OuterHTML" Range("D2") = ".InnerText" Range("E2") = ".InnerHTML" Range("F2") = ".Target" Columns("A:F").ColumnWidth = 22 '列幅を22に変更 yLINE = 3 'セット開始の行を代入する For Each objLINK In objIE.Document.Links 'リンクを1つ1つ取り出しobjLINKへ 'データをセルへセットする 'を付けて文字列にする(セルにセットしたいので) Cells(yLINE, "A") = "'" & objLINK.Href 'リンク先 Cells(yLINE, "B") = "'" & objLINK.OuterText '自分を含む テキスト(Innerと変わりない?) Cells(yLINE, "C") = "'" & objLINK.OuterHTML '自分を含む HTML Cells(yLINE, "D") = "'" & objLINK.InnerText '内側のテキスト Cells(yLINE, "E") = "'" & objLINK.InnerHTML '内側のHTML Cells(yLINE, "F") = "'" & objLINK.Target '_Blank や 表示先フレームの名前など yLINE = yLINE + 1 'セット位置(行)を+1する Next 'IEの終了を聞く If MsgBox("IEを閉じますか?", vbYesNo, "終了確認") = vbYes Then objIE.Quit '.Quitで閉じる End If Set objIE = Nothing End Sub |
今回のリンク抜き出し処理にはあまり関係ないのですが、
objIE.Quit
.Quitで、Set objIE = CreateObject("InternetExplorer.application") で作成した IEを終了、閉じることができます。
開発中やデバッグ中はIEをそのまま残しておいたほうが何かと便利なのですが、処理が終わったら.Quitでサヨナラをすることもできます。
はじめに(あいさつ?):日々の操作を自動化したい、楽したい。そんな理由でシステム化・プログラムで自動化、寝てても勝手にコンピューターが働いてくれる・・・と夢を見るんだろうなぁ。
そんな迷える読者様から、たまに依頼が来たりする。。。
さてと、依頼内容を理解して、仕様を起こしますか。
今回の依頼内容は:Amazonのホームページから、本日発売の雑誌リンクを取り出したいと簡単な依頼を受けました。
いつも思うけど、日本語1行で書かれると広いよね。
えっ、だから仕様をつめて(依頼主とやりとりをして)、落としていくんだろうって?
ここで手を抜くと痛い目に遭うよね。やりたいことを聞き出し仕様を起こすのって意外と大変なんですよ。。。
現在の処理を見せてもらう(見物を確認する)
文章で依頼書を書いてもらうのがアトアト面倒にならないでいいんだけど、なかなか書いてくれないので、最低限の現物確認から今回も仕様を泥縄式に決めていきます。
現在の操作手順 ・Amazon.co.jp TOPページを表示する。 ・雑誌を選択する ・スクロールさせm/d発売の雑誌を確認する。 ※↑この確認した本日発売の雑誌をシートに取り込みたい。 |
動画解説:[事前準備 amazonの雑誌を調査する] |
あまり変わらないんだけど、↑の情報からいつもの箇条書きの仕様書を書きます
1.IEを起動します。
2.Amazon.co.jp TOPページを表示する。表示完了を待つ。
3.雑誌のリンクをクリックする
4.雑誌のページが表示されるのを待つ
5.表示された文章から 本日発売の雑誌 を探す
6.その下の 雑誌名とリンク先をシートに書き出す
7.IEを閉じる
と、まぁ、こんな感じかなぁ。(穴だらけの仕様書↑これを受け取った作業者は苦労するんだけど)
仕様書もアバウトなので、プログラムを書きながら詰めていきますか。
読者の声:たまたまテストに毛の生えた小さな作成依頼だからいいけど、詳細設計しないで作り始めるなんてサスガ三流プログラマーだね。
三流君:ほめられたので調子に乗ってプログラムを書いちゃうか(オイオイ褒められてないだろ、違うって)
いつものように箇条書きをコメントで関数内に書き込みます
Sub Amazon_Today_Link_test() '1.IEを起動します。 '2.Amazon.co.jp TOPページを表示する。表示完了を待つ。 '3.雑誌のリンクをクリックする '4.雑誌のページが表示されるのを待つ '5.表示された文章から 本日発売の雑誌 を探す '6.その下の 雑誌名とリンク先をシートに書き出す '7.IEを閉じる End Sub |
IEを起動、Amazon.co.jp TOPページを表示する、表示完了を待つ。
は、解説の使い回しで
ア.初めは[IEの起動] CreateObject("InternetExplorer.application")でブラウザを起動させます
イ.次に[.Navigateで開く] 目的のページを開くために.Navigateメソッドでページを移動させます。
ウ.最後に[.Busyと.ReadyState]で表示の完了(ページの読み込み)を待ちます。
↓こんな感じで、書いてみました。
|
トップページから、雑誌のページに移動したいので
[For Each 変数 In objIE.Document.Links] や [Document.Links の .Href .OuterText .OuterHTML .InnerText .InnerHTML]を参考にしながら、
Document.Linksから雑誌の文字を探し(.InnerTextを見て)、クリック.Clickしてみます。
雑誌のリンクを探したかったので、For Each objLINK In objIE.Document.Links を使い文章のリンク全体をループで回して、中身のテキストをobjLINK.InnerTEXT = "雑誌"で判断後、見つけたオブジェクトに対して、objLINK.Clickでクリックメソッドを実行しました。
|
動画解説:[こんな感じ?] ↑リンクのオブジェクトから雑誌を探してクリックしました |
リンクは、.Document.Links にまとまっているので、全てを取り扱うときは便利なのですが、今回みたいに一部を抜き出したい場合は、.Document.Allから探った方が楽な場合があります(私が楽と言っているだけで、実際は違う方法があるかもしれませんが・・・)
今回やりたい処理は、6/10発売の雑誌 のパターン m/d発売の雑誌を探しその下のリンク(Aタグ a href=)を取り出し、セルに書き込む処理です。
文字を探したいので、
[.Allで文章にアクセス]と[All.Length]を使います。
泥臭く カウンターnを用意して、
For n = 0 To objIE.Document.All.Length - 1で頭からのループを作り
Document.All(n).InnerTEXT = m/d発売の雑誌 で テキストを探してn番目を保持します
n番目の頭出し(読み飛ばし)ができたら、次は、そこから下のAタグa href=を取り出し、セルに書き込みます。
プログラムが無駄に長くなってますが、こんな感じです。
|
動画解説:[m/d発売の文字を探しその下のリンクを書き出す] |
まだまだ、書かないといけないIE操作 プロパティやメソッドなどの組み合わせがあるのですが、このあたりで逃げるように失礼します(オイオイ)。更新が遅いけど温かく見守ってください 更新中 まだまだ書きかけ
いろいろな表現があって、かえって迷ってしまうかもしれませんが、数をこなすと見えてくるので、私のサンプルだけじゃなく、いろいろなサンプルを探して見てください。[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]にお勧めのキーワード検索方法を載せてます
過去のメールマガジンのリンクが長かったので、下記に移動しました。
[IE操作 メルマガ 一覧]
よろしくお願いします。
改版履歴 更新情報:過去のIE操作の解説はこちら↓(IE6+XP,IE7+XPの古い記事もアリ)
2009-12-01:[過去の解説 vba_ie_20091201.asp]
2009-06-01:[過去の解説 vba_ie_20090601.asp]
2009-02-01:[過去の解説 vba_ie_20090201.asp]
2008-05-01:[過去の解説 vba_ie_20080501.asp]
2007-08-31:[過去の解説 vba_ie_20070831.asp]
2007-05-20:[過去の解説 vba_ie20070520.asp]
2012-03-19:[過去の解説 vba_ie_20120319.html]
もあわせてみてください。
(↑もしかして書き直さない過去の解説の方がよかったかも?(笑))
せっかくホームページに来ていただいたのに、検索の紹介 ぉぃぉぃ
サイト指定や期間の指定を組み合わせて実行してみてください。
ここまで、読んでいただきどうもです。ここから下は、三流君宛のメッセージ送信や 三流君のホームページの紹介・案内です
目的の情報が見つかったか?少々心配しつつ、、、
感想や質問・要望・苦情など 三流君へメッセージを送る。
下記のフォームからメッセージを送ることができます。
[三流君(TOPへ)] / [VBAで楽しく] / [記事一覧] |
カスタム検索
|