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でIE操作 2009-02-01 履歴として残す

2009/02/01 までに書いた IE関係の記事です。あと少ししたらIE8になるのに?IE6+XPがメインの記事です・・・(IE7を攻略する前にIE8になっちゃったりして・・・)
現在の最新解説は、
http://www.ken3.org/cgi-bin/group/vba_ie.asp
↑を見てください。

2009/02/01に書いていた記事

挨拶: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] / [更新されない作業日記]です

メニュー おしながき 目次

ページ内が無駄に長いので、ページ内の目次を作りました
ページ内 分類と目次
大分類詳細
[Document.Allをさわる]
Webに記載(表示)されているデータを取り出したいのでDocument.allオブジェクトにイロイロな方法でアプローチ、アクセスしてデータを取得したIE操作の解説です
  • [IEの起動] : CreateObject("InternetExplorer.application")でブラウザを起動させました
  • [.Navigateで開く] : 次に目的のページを開くために.Navigateメソッドでページを移動しました
  • [.Allで文章にアクセス] : ページが無事表示されたらテストでDocument.all(番号) で 文章にアクセス .Document.All(0).InnerTEXTなどのテストを行いました
  • [All.Length] : Document.All.Length で タグ(要素)の数がわかるので 0から.Length-1までループさせ、.TagName タグの名称 や .OuterHTML .InnerText .InnerHTML を シートに書き出してみました
  • [For Each IN でループ] : For Each objTAG In objIE.Document.all で ループを作りデータを処理してみました。
  • [表(TABLE)からデータを抜く] : 表示されたページのTABLE(表)からデータを抜きたいと思います※イロイロな方法があって迷いますが
  • [.TagName] : .TagNameでタグの名前が取得できるので、名称が<TR>で改行、<TD,TH>で次の列、そんなDocument.all から .tagname で判断して自分でセットする泥臭い方法でデータを抜いてみました
  • [.ExecWBメソッド] : .ExecWBメソッドを使って 全て選択,コピー の コマンドを発行してデータをExcelシートに貼り付けましたてみました
  • [createControlRange] : ↑上記の全体コピーは使いにくかったので、document.body.createControlRange を使い、指定したテーブルをシートに貼り付けてみました。
  • [.tags("タグの名称")] : document.all(n)で.tagnameが指定したタグなら・・・そんな処理で便利な方法があって Set objTABLE = objIE.document.all.tags("TABLE")でTABLEのみを抜く(指定したタグを抜く)ことができました
[Document.Formsをさわる]
Web上の入力フォームにデータをセットしたいので、Document.FormsオブジェクトにイロイロなアプローチでアクセスしてデータをセットしたIE操作の解説です
[Document.Formsを操作する]
  • [事前準備] : 操作したい入力フォームを手作業でいじってみたり、FORMのソースを表示したり、事前準備を行います
  • テキスト入力と送信 [.Submitで送信] : .Busy.ReadyStateを見て表示の完了を待ってから.Document.Forms(0).Item("MEMO").Value = 値でデータをセット後、.Submitメソッドでデータを送信しました。

  • ラジオボタンの選択 [INPUT RADIO(ラジオボタン)] : 次は、ラジオボタン INPUT TYPE="RADIO"を操作してみました。
  • [.Nameと.Value] : テストで Forms(0) を For Eachで探り、.Name.Valueを表示しました。
  • [.Checked] : 目的のオブジェクトが見つかったら.Checked = Trueとして、ラジオボタンを選択状態にしました。
  • [.Click] : 単純にオブジェクトが見つけて.Clickメソッドでオブジェクトをクリックして押してみました。

  • ドロップダウン▼の選択 [SELECT OPTION 選択] : FORM SELECT OPTION の攻略(選択)サンプル
  • [Option .Selected] : 選択なので単純に Optionタグを探しOptionタグ.Selected = Trueをセットしました。
  • [Select .Value] : もっと素直になって 選択したい値がわかっているのでSELECTタグ.Value = 選択したい値でセットしました。

  • リストボックス複数選択 [SELECT 複数OPTIONの選択] : SELECT Size=nで複数表示されたリストボックスから、Ctrl+クリックで複数のOPTIONデータを選択する方法
  • [.tags("OPTION")で探す] : 該当するOPTIONのデータを探したかったので、For Each objOPTION In objIE.Document.tags("OPTION")で選択データを探しobjOPTION.Selected = Trueを複数セットしました。

  • [□レ チェックボックス] : まず、実際のINPUT TYPE="CHECKBOX"のパターン2つ(HTML FORM)を抜き出しました。
  • [.Checkedを付ける] : Name="XXXX"が個々に違う場合(CHECKBOXに1つ1つ別の名前が付いている場合)、入力フォームを表示してから、素直に Document.Forms(0).Item("名前")でオブジェクトが特定できるので、あとは.Checked = Trueで選択状態にしました。objIE.Document.Forms(0).Item("VBA").Checked = Trueみたいな感じで意外と簡単でした。
  • [.Valueで探す] : 次に、CHECKBOXのName="XXXX"が同じでValue="ZZZZ"が違う入力フォームの場合、.Valueで判断してから、.CheckedをTrueにしました
  • [Document.getElementsByNameで探す] : Name="XXXX"がわかっているなら、便利な取得方法があって、Document.getElementsByName("名前")で指定した名前(.Name)のオブジェクトを取り出せます。

  • 名前付きのボタンを押す [Form外のボタンを押す(.Click)] : <Form>が無く<INPUT type="button" onclick="Javaで作った関数"> だけで作られたボタンを.Clickで押し JavaScriptを起動しました
  • [名無しのボタンを押す(.Click)] : INPUT type="button" に name="名前"> と名前が付いていない場合、.Valueなど他の値を利用してオブジェクトを特定しで.Click操作したお話です

[Document.Linksをさわる]
ネットはリンクでつながってます、そんなリンク情報を扱いたかったので、Document.Linksオブジェクトにイロイロなアプローチでアクセスしてリンク情報を取得したIE操作の解説です
[Document.Linksを操作する]
  • [リンク先を取り出すテスト] : 表示したページのリンク先の情報をセルに書き出すテストプログラムを作ってみます。(URLを受け取り、ページを表示させ、リンク先をセルに書き出します。)
  • [Links.Length] : Document.Links.Lengthでリンクの数がわかるので、Document.Links(i)とi番目にアクセス可能です
  • [.Href] : .Hrefでリンク先と他のタグでも使うことの多い.OuterText .OuterHTML .InnerText .InnerHTMLなど知っているプロパティを説明しました。
  • [For Each 変数 In objIE.Document.Links] : いつもよく使っている For i = 0 To objIE.Document.Links.Length - 1のループをFor Each objLINK In objIE.Document.Linksのループに書き換えてテストしてみました。お好みでどうぞ。
  • [.QuitでIEの終了] : objIE.Quitで、Set objIE = CreateObject("InternetExplorer.application") で作成した IEを終了、閉じることができます。開発中やデバッグ中はIEをそのまま残しておいたほうが何かと便利なのですが、処理が終わったら.QuitでIEを閉じることができます。

  • [Amazon雑誌から本日発売のリンクを抜く] : より実戦的に全体から目的のリンクを抜いてみました(雑誌のページから本日発売の雑誌を抜き出してみました)
  • [.Click] : トップページを表示後、Document.Linksから雑誌の文字を探し(.InnerTextを見て)、クリック.Clickして雑誌のページへ移動します。
  • 雑誌のページに移動したら [A タグからリンク情報を取り出す] : 文章内をDocument.All(n).InnerTEXT = m/d発売の雑誌 で テキストを探してn番目を保持してから、そこから下のAタグ .All(n).TagName = "A"で判断して、セルに.InnerText(タイトル)と.href(飛び先)を書き込みました
↑動作イメージがつかめたらたたき台とて改良したり遊んでみてください

私がIE操作、プロパティやメソッドを探る方法 を ネタばらしすると(はやいよ)、MSDNで探したりプログラムを途中で止めて オブジェクトの中身を直接見たりしています。
[三流君 が MSDN で InternetExplorer の 資料を探す]
↑上級者はここを先に見た方が良かったり?(ヘンテコな説明や動画を見るよりも こちらの方が近道かも)
と書きつつ、いきなり大切な読者様へ嘘つきました、最近はGoogleの検索を主に使っていたりします。検索のキーワードがなかなか思いつかないと思うので私のお気に入りのキーワードを紹介します。(読者の声:だったら先に書けよ↓)
[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]
↑MSDNの目次(頭)から探すのが大変なので、検索すると良いサンプルや数少ない解説ページに巡り逢えるかも、なんて自信をなくしつつも三流製 手前味噌のサンプルをどさくさに紛れて紹介します 過去記事のリンク→[過去のメルマガ] ← IE6時代のサンプルですが何かの役に立つと願いつつ・・・
※時の流れはハヤク、あと少ししたら(まだまだ先だけどオオゲサに書いてみました)IE8がリリースされるのに、実はVista IE7に苦戦しています。(IE7を攻略する前にIE8になり、取り残されたりして・・・)

さて、IEを操作 Documentの森・WebBrowserの山を頼りないガイドの三流君と一緒にさまよってみましょうか!!!
このページ 三流プログラマー的解説がIE操作方法(プロパティやメソッド)の入り口として何かの参考・お役に立てれば幸いです。


[#Document][ページ内のTOPへ戻る]

Documentオブジェクトの山からデータをイロイロな方法で抜く

下記↓、私のASP解説のテストページなのですが、ここの表からデータを抜いてみたいと思います
[http://www.ken3.org/cgi-bin/test/test028-2.asp]
↑test028-2.asp 感想データをORDER BY ID DESC で IDの降順で表示↓
IDF_TITLEF_MEMOWriteTime
6026説明が下手理解が難しい・・・2008/05/04 4:57:50
6025解らん使えないサイトだな2008/05/03 5:23:24
5968oktest2008/03/02 13:30:49
5696aa2007/09/19 19:04:19
5675IE操作UWSC使用が正解 変な記事書き続けるなボケ2007/09/09 23:31:41
5505てすとできるかな?2007/05/30 18:02:13
こんな感じのテーブルからデータを抜いてみます
動くサンプル:[Documentの山からテーブルデータを抜くサンプル 20080513_IE_TEST.zip]←Excel2003の.xlsファイルです。解凍後実行しながら下記の解説を見てみてください

処理の流れ・仕様は
1.IEを起動する CreateObject("InternetExplorer.application")
2.目的のURL(test28-2.asp)を開く .Navigate
3.テーブルからデータを抜く(Excelのシートにセットする)
なんて感じの3行おまかせ仕様で(笑)


[#Create_IE][ページ内のTOPへ戻る]

1.CreateObject("InternetExplorer.application")

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
↑とにかくコレを貼り付けて実行してみてください。
CreateObject("InternetExplorer.application")でIEを起動させobjIEの変数に代入して、objIE.Visible = True 他のVBAでもおなじみの.VisibleプロパティをTrueにしてます。
読者の声:一言で言えよ、起動して可視(見えるように)しただけだろ。

※サンプルで私がよく使う好きな方法は、Set objIE = CreateObject("InternetExplorer.application")なのですが、Vista IE7の保護モードだと.Navigateで失敗したり・・[三流君 Vista IE7の修正でハマる(小細工で逃げる)] ← Vista IE7の人はこちらも見てください。


[#Document_Navigate][ページ内のTOPへ戻る]

2.URLを開く(.open)じゃなくって、.Navigateなんですよ

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 URL文字列 でOKだろ。説明が無駄に長いんだよ。


[#Document_All][ページ内のTOPへ戻る]

3.開いた文章 Document に アクセスする

無事にページを開くことができたので、データを抜き出したいと思います。
イロイロな方法があるので(わざと回り道をしますが)自分に合った方法で取り出してみてください。

.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(ブラウザ)さんが解析して表示をしてくれる。そんなイメージです。

Document.all(番号) で 文章にアクセスする

先走らないでここで深呼吸、一呼吸おいて、
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番目)頭 を 探って見たいと思います)

.InnerTEXT プロパティ と .InnerHTML プロパティを使ってみた

実際に文章 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秒待つ(オブジェクトの展開時間を待つ)
↑何だコレ、手抜きって?、そもそも、なぜ2秒?
なぜ、待つかと言うと、いきなりさわるとビックリするでしょ?(オイオイ、何言ってんだおっさん)
表示待ちを入れないで いきなりオブジェクトに触りに行くと(ドキュメントなどのオブジェクトにアクセスすると) 相手の心の準備ができていないみたいで(オブジェクトの展開処理が間に合わないみたいで)、どこ見てんのよ(古)と怒られるじゃなかった、 実行時エラー Document メソッドは失敗しました ・・・など、エラーで怒られるんですよ。
エラーの画像→[http://ken3-info.blog.ocn.ne.jp/screen/2007/05/ie__debe.html]
なので、objIE.Navigate 後に相手の準備ができるが確認します。
手抜きの2秒はじゃなくてもっとチャントシタ行儀作法があるので後ほど。
えっ、今説明しないの?はい、アトで・・・気になる人は先に→[.ReadyStateと.Busyで待つ]を見てください


[#Document_All_Length][ページ内のTOPへ戻る]
Document.Allのオブジェクトにアクセスする .Length と For Eachでまわす方法

今度は始めの0番目を表示だけじゃなくて、データを新しいシートに書き出してみます。

Document.All.Lengthでデータ数 添え字 All(i) でアクセス

バカの一つ覚えの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

ActiveWorkbook.Sheets.Count
で、ブックのシート数が取れるので、ループで1からシート数分まわし、
ActiveWorkbook.Sheets(i).Name
で、i番目のシートの名前(.Name)を表示してます。

読者の声:だから何?、ドキュメント内のオブジェクト数は、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

他のIEオブジェクト操作でも 配列の要素数は、パターン的に.Lengthが多いので覚えておいてください・・それが言いたかっただけなんですが、Excelを例にしてた蛇足の解説でしたね(少々反省)

読者の声:蛇足でも何でもいいから、ハヤク、次行けよ
の前にさりげなく説明無しに使っている .OuterHTML 外側含むHTML とか TypeName関数 とか .TagName タグ や .Quit?

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)にアクセスしに行くとエラーになったりします注意してね


[#Document_All_For_Each][ページ内のTOPへ戻る]
要素数を気にすんなよ (i)で参照 から For Each で回せば

よし、簡単なオブジェクトの説明終了、、、ここまで長かった。酔っぱらいの独り言に付き合っていただきどうもです。朝までにもう一軒飲み屋じゃなかった、オブジェクトをハシゴするぞと行きたい所ですが、あと一杯、少しだけお時間をとらせてください。

読者の声:だから、余計な会話はいいから、はやくシロ。(※←この読者の心の声もかなりの蛇足なんですが(笑)説明に必要ないでしょと思いつつ)

書き方に好みの問題もあるのですが、
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

みたいに、Dim objSHEET As Worksheetと受け取り用の変数を1つ定義して、
For Each objSHEET In ActiveWorkbook.Sheets
と記述すると、ActiveWorkbook.Sheets分だけ1つ1つ次のオブジェクトを取り出しながらループさせ、objSHEET.Nameみたいに(i)とか添え字や.Countなどの要素数を使わないで処理することができます。
頭から全てのデータをループさせる場合、このほうがスッキリとした記述かなぁ。
※三流君的には、.Length - 1のループでDocument.All(i)とか(n)、の書き方が好きだけど。

この書き方が 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

[#TABLE_TAG][ページ内のTOPへ戻る]
イロイロなTABLEタグの操作・処理

話を戻して、文章の表からデータを抜きたいんですよね、やりたいことは。 忘れてたよ

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>(テーブル終わり)
と、
<TABLE>テーブルのタグから始まり、
<TR>行の開始
<TD>列のデータ(<TH>の見出しをTDで書いているページもありです)

おおざっぱに書くと3つの組み合わせと順番です。


[#TagName][ページ内のTOPへ戻る]
.TagName <TR>で改行 <TD>でデータセットしてみる

ループで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行で仕様書?当然、穴があるんだけど・・・)


'TABLE データ取り出し、TRで改行、TDの中身をセットする
Sub ie_test_Document_All_TagName_TR_TD()

    Dim x As Integer, y As Integer  '列と行カウンター
    
    Dim objIE    As Object  'IEオブジェクト参照用
    Dim objTAG   As Object  '1つ1つ タグのオブジェクトを入れる
    Dim strTNAME As String 'タグの名前を保存する
    
    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を吐き出す
    Workbooks.Add  '新規ブックを追加
    
    y = 0  '行カウンターを初期化(はじめの改行で+1するので0から)
    x = 0  '列カウンターを初期化(TR 改行時に初期化するのでいらないんだけど)
    
    'Documentから.TagNameでTR TD THを判断して テキスト(.InnerText)を書き出す
    For Each objTAG In objIE.Document.all
        
        strTNAME = objTAG.TagName 'タグの名前を変数へ保存
        
        If strTNAME = "TR" Then   'TR行の開始なら
            y = y + 1   '行開始なので 行カウンターを+1
            x = 0       '列を0(頭)初期化
        End If
            
        If strTNAME = "TH" Or strTNAME = "TD" Then 'TH見出し TDデータ
            x = x + 1   '列カウンターを+1
            Cells(y, x) = "'" & objTAG.InnerText '.InnerTextをセットする
        End If
        
    Next

    '抜き出し処理が終わったので、普通はIEを.Quitで閉じる
    'objIE.Quit    'コメントにして処理しない(残しておいた方がテスト時は楽です)
    'Set objIE = Nothing

End Sub

ポイントは、特になく(オイオイ)、
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に反応してデータを書き出していたのかぁ。


↑プログラムの説明 と テスト結果 (動画です、再生を押すかダブルクリックしてください)
TABLEタグまで読み飛ばし、次のテーブルで抜ける

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 データ取り出し、TRで改行、TDの中身をセットする
'初めのテーブルまで空読み  次のテーブルが来たら処理を抜ける
Sub ie_test_Document_All_TagName_TABLE_TR_TD()

    Dim x As Integer, y As Integer  '列と行カウンター
    Dim n As Integer, i As Integer
    Dim objIE    As Object  'IEオブジェクト参照用
    Dim objTAG   As Object  '1つ1つ タグのオブジェクトを入れる
    Dim strTNAME As String 'タグの名前を保存する
    
    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  '新規ブックを追加
    
    'はじめのTABLEまでから読みする
    For n = 0 To objIE.Document.all.Length - 1
        If objIE.Document.all(n).tagname = "TABLE" Then Exit For
    Next n
    
    y = 0  '行カウンターを初期化(はじめの改行で+1するので0から)
    x = 0  '列カウンターを初期化(TR 改行時に初期化するのでいらないんだけど)
    
    'Documentから.TagNameでTR TD THを判断して テキスト(.InnerText)を書き出す
    For i = n + 1 To objIE.Document.all.Length - 1
        
        strTNAME = objIE.Document.all(i).tagname 'タグの名前を変数へ保存
        
        If strTNAME = "TR" Then   'TR行の開始なら
            y = y + 1   '行開始なので 行カウンターを+1
            x = 0       '列を0(頭)初期化
        End If
            
        If strTNAME = "TH" Or strTNAME = "TD" Then 'TH見出し TDデータ
            x = x + 1   '列カウンターを+1
            Cells(y, x) = "'" & objIE.Document.all(i).InnerText '.InnerTextをセットする
        End If
        
        If strTNAME = "TABLE" Then   'TABLEなら(次のテーブルが現れたら)
            Exit For    'ループを強制的に抜けます
        End If
        
    Next i

    '抜き出し処理が終わったので、普通はIEを.Quitで閉じる
    'objIE.Quit    'コメントにして処理しない(残しておいた方がテスト時は楽です)
    'Set objIE = Nothing

End Sub

ポイントは、まず初めの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 で判断して自分でセットする、そんな原始的 イヤ三流的な方法でした。嘘つきがもっとスマートな方法があるだろオイ・・と、上級読者様は突っ込まれたと思いますが、泥臭いループの練習、反面教師的ソースの例ってことでご勘弁を。


[#ExecWB][ページ内のTOPへ戻る]
コピー、貼り付けしてみたら?(.ExecWBでコマンド発行)

自分で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に切り替えて貼り付け
記録終了(上記操作をマクロ記録してみます)

実際に記録したコードを見てみると、ダメだ記録されてない。。。
Sub Macro1()
    Sheets("Sheet2").Select
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="HTML", Link:=False, DisplayAsIcon:= _
        False
    ActiveWindow.SmallScroll Down:=-18
    Sheets("Sheet3").Select
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="テキスト", Link:=False, DisplayAsIcon:= _
        False
    Range("A5").Select
    ActiveWindow.SmallScroll Down:=-9
End Sub
残念ながら IEの起動や IE上での全てを選択・コピーのコードが記録されていません・・・

マクロ記録に載らなかったことをいつまでも気にしていても先に進まないので、
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を指定)するみたいですね。
どんなコマンドがあるか、
[OLECMDID http://msdn.microsoft.com/en-us/library/ms691264.aspx]をみると
12と17番の OLECMDID_COPY = 12 コピー, OLECMDID_SELECTALL = 17 セレクトオール が使えそうです。※その他、いろいろなコマンドがあるので見てください。
もう一つのパラメーター [OLECMDEXECOPT http://msdn.microsoft.com/en-us/library/ms683930.aspx]をみると
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パターンの貼り付けを実行してみます
'IEコマンド発行のテスト  全てを選択・コピーしてから、シートに貼り付けてみる
Sub ie_test_ExecWB()

    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秒間 ボーっとする

    'テスト用に新規のブックを追加する
    Workbooks.Add  '新規ブックを追加
    
    '形式を選択して貼り付け HTML貼り付けのテスト
    objIE.ExecWB 17, 0  'OLECMDID_SELECTALL = 17 全てを選択
    objIE.ExecWB 12, 0  'OLECMDID_COPY = 12 コピー
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "FormatHTML"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="HTML"
    
    '形式を選択して貼り付け Unicode テキスト貼り付けのテスト
    objIE.ExecWB 17, 0  'OLECMDID_SELECTALL = 17 全てを選択
    objIE.ExecWB 12, 0  'OLECMDID_COPY = 12 コピー
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "FormatUnicode テキスト"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="Unicode テキスト"

    '形式を選択して貼り付け テキスト貼り付けのテスト
    objIE.ExecWB 17, 0  'OLECMDID_SELECTALL = 17 全てを選択
    objIE.ExecWB 12, 0  'OLECMDID_COPY = 12 コピー
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "Formatテキスト"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="テキスト"

End Sub
↓実行結果

う〜ん、使えそうな、使えなさそうな・・・全てじゃなくて、テーブルを指定して(範囲指定でドラックして)コピーできるといいんだけどなぁ。


[#createControlRange][ページ内のTOPへ戻る]
document.body.createControlRange を使い、テーブルを指定する

テーブルを選択 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番目(テーブル位置を指定)にしてみたいと思います。


'TABLEのオブジェクトをコピーして シートに貼り付けてみる
Sub ie_test_document_body_createControlRange()

    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秒間 ボーっとする

    'はじめのTABLEまで空読みする
    Dim n As Integer
    For n = 0 To objIE.document.all.Length - 1
        If objIE.document.all(n).tagname = "TABLE" Then Exit For
    Next n

    Dim r As Object
    Set r = objIE.document.body.createControlRange
    r.Add objIE.document.all(n) '上で見つけたテーブルを指定する。
    r.Select                    'セレクト 選択
    objIE.ExecWB 12, 0          'コマンド発行 OLECMDID_COPY = 12 コピー

    'テスト用に新規のブックを追加する
    Workbooks.Add  '新規ブックを追加
    
    '形式を選択して貼り付け HTML貼り付けのテスト
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "HTML形式で貼り付け"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="HTML"
    
    '形式を選択して貼り付け Unicode テキスト貼り付けのテスト
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "FormatUnicode テキスト"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="Unicode テキスト"

    '形式を選択して貼り付け テキスト貼り付けのテスト
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "Formatテキスト"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="テキスト"

End Sub

↑なんとか、テーブルのみを選択して貼り付けできました。まぁ、貼り付けの形式は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") これでコピーできるのかな?
ってことで、下記のようにプログラムを修正しました。
Sub ie_test_document_body_createControlRange22()

    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秒間 ボーっとする

    'はじめのTABLEまで空読みする
    Dim n As Integer
    For n = 0 To objIE.document.all.Length - 1
        If objIE.document.all(n).tagname = "TABLE" Then Exit For
    Next n

    Dim r As Object
    Set r = objIE.document.body.createControlRange
    r.Add objIE.document.all(n)   '上で見つけたテーブルを指定する。
    r.Select                      'セレクト 選択(選択しなくてもコピー可能かなぁ)
    r.execCommand "Copy"          'コピーのコマンドを発行?

    'テスト用に新規のブックを追加する
    Workbooks.Add  '新規ブックを追加
    
    '形式を選択して貼り付け HTML貼り付けのテスト
    Sheets.Add          'テスト用のシートを新規追加する
    ActiveSheet.Name = "HTML形式で貼り付け"  'シートに名前を付ける
    Range("A1").Select
    ActiveSheet.PasteSpecial Format:="HTML"

End Sub
ところが、コピーの確認ダイアログが出ますね・・・
セキュリティのレベルが上がって自動実行にはツライ環境?になりましたね。う〜ん・・・
20080520001

.execCommand "Copy" でコピーする方法、惜しかったなぁ・・・カッコつけ損ねました(笑)ってことで、表のコピーはなんかカッコ悪いけど、テーブル選択後.ExecWB 12, 0とコピーのコマンドを発行してください。


[#Document_all_tags][ページ内のTOPへ戻る]
オブジェクトを指定したタグで抜くには .tags("タグ名")を使う

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に変更してテストしてみます。


'文章 document 全体 all から指定したタグを抜き出す.tagsのテスト
Sub ie_test_document_all_tags()

    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秒間 ボーっとする

    '.tags("TABLE") で テーブルオブジェクトを文章 document 全体 all から抜く
    Dim objTABLE As Object 'テーブルオブジェクトの格納用
    Set objTABLE = objIE.document.all.tags("TABLE")  'TABLEを指定して抜く
    
    'テーブル(0)初めのテーブルを範囲指定後、コピーする
    Dim objRANGE As Object  '範囲 ControlRange
    Set objRANGE = objIE.document.body.createControlRange  '範囲のオブジェクトを新規で作り
    objRANGE.Add objTABLE(0)    '(0)でテーブルを追加(指定する) 1番目は0からなので
    objRANGE.Select             '範囲のオブジェクトを セレクト 選択する
    objIE.ExecWB 12, 0          'コマンド発行 OLECMDID_COPY = 12 コピー
    
    'テスト用に新規のブックを追加する
    Workbooks.Add  '新規ブックを追加
    Sheets.Add     'シートを新規追加する
    ActiveSheet.Name = "test028のテーブル"  'シートに名前を付ける
    
    'TABLEデータをシートに貼り付ける
    Range("C3").Select    '先頭A1じゃ面白くないので C3をテストで選択
    ActiveSheet.PasteSpecial Format:="HTML" 'HTML形式を選択して貼り付け
    Columns("A:Z").EntireColumn.AutoFit   '手抜きでA-Zの列は時をオートで調整

    '後始末(使った食器はキレイにしてから戸棚に戻そうね)
    Set objRANGE = Nothing
    Set objTABLE = Nothing
    'objIE.Quit    '今回はコメントにして処理しない(残しておいた方がテスト時は楽です)
    'Set objIE = Nothing
    
End Sub

ポイントは、
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 を使えよ・・・と、読者様の声が聞こえたので、テストプログラムを書いてみます。
Sub ie_test_document_all_tags_for_each_in()

    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秒間 ボーっとする

    'テスト用に新規のブックを追加する
    Workbooks.Add  '新規ブックを追加

    '.tags("TABLE") で テーブルオブジェクトを文章 document 全体 all から抜く
    Dim objTABLE As Object 'テーブルオブジェクトの格納用
    Dim objRANGE As Object  '範囲 ControlRange
    
    'objTABLE に.tags("TABLE")で取り出したオブジェクトを入れながらループ
    For Each objTABLE In objIE.document.all.tags("TABLE")  '.tags("TABLE")でテーブルタグのみ取り出す
        Sheets.Add  'テストのシートを新規追加する
    
        'テーブルを範囲指定後、コピーする
        Set objRANGE = objIE.document.body.createControlRange  '範囲のオブジェクトを新規で作り
        objRANGE.Add objTABLE    'テーブルを追加(指定する)
        objRANGE.Select          '範囲のオブジェクトを セレクト 選択する
        objIE.ExecWB 12, 0       'コマンド発行 OLECMDID_COPY = 12 コピー
    
        'TABLEデータをシートに貼り付ける
        Range("C3").Select    '先頭A1じゃ面白くないので C3をテストで選択
        ActiveSheet.PasteSpecial Format:="HTML" 'HTML形式を選択して貼り付け
    Next
    
    '後始末(使った食器はキレイにしてから戸棚に戻そうね)
    Set objRANGE = Nothing
    Set objTABLE = Nothing
    objIE.Quit    'IEを閉じる(テストでさんざん使ったから残しとかなくてもいいかな)
    Set objIE = Nothing
    
End Sub

ポイントは、
For Each objTABLE In objIE.document.all.tags("TABLE") '.tags("TABLE")でテーブルタグのみ取り出す
みたいに、For Each オブジェクト変数 In .document.all.tags("タグの名前")で1つ1つ指定したタグのオブジェクトを取り出して処理しています。
For n = 0 To objTABLE.Length - 1でループさせ
objTABLE(n)で使う方法と使い分けてイロイロと遊び、楽しんでください。

↑ここまでのXP+IE6,IE7で動くサンプルです→[Documentの山からテーブルデータを抜くサンプル 20080513_IE_TEST.zip]←Excel2003の.xlsファイルです、解凍後実行しながら、修正したりして遊んでみてください。


[#VistaIE7NG][ページ内のTOPへ戻る]

やっとVista IE7対応に入る(ExcelのUserFormにIEコントロールを貼る)

いつもの私が好きな 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を貼る方法

上にUserFormにIEを貼る操作の動画を入れたんだけど、クレームの連絡をいただく。。。(オイオイまたか)
・音声付きの動画だと 会社で観ると恥ずかしい
・YouTube は フィルタリングされていて会社から観ることができない
・PCの音量切ってます or スピーカーはハズしています・・・
など。
たしかに ソフト会社のPC。音源ボード入っていてもスピーカーつないでいなかったり、
勤務中にYouTube動画を見るのをルーター側で禁止している会社があっても不思議じゃないですね。
意外と動画解説って不評だったり(笑)
おっと、失敗話はこれくらいにして、そんな読者様のために静止画を貼ります(初めから画面のハードコピーにしとけよ)

UserFormを作り、IEのコントロールを貼りたいと思います
フォームを1つ作り  IEのオブジェクトを貼る
まぁ、ユーザーフォームを選択すると、下記のようにUserForm1が作成されます。


次に、ツールボックスで空白エリアを選択後、右クリックを押してその他を選択します。


利用可能なコントロールがたくさん表示されるので迷いますが、
下の方にスクロールさせ、Microsoft Web Browser を選択します。



すると、コントロールに丸い世界のアイコンが表示されます。※地球をイメージ?
これを選択してフォームに貼り付けます。


貼り付けると こんな感じ↓(オブジェクト名 WebBrowser1 で貼り付けられると思います)

忘れずに保存します。これで、下準備ができました。

Object.メソッド や object.プロパティ などあとは同じ

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からデータを抜く 終わりの挨拶

まだまだ、書かないといけないDocument操作 プロパティやメソッドなどの組み合わせがあるのですが、このあたりで逃げるように失礼します(オイオイ)。更新が遅いけど温かく見守ってください 更新中 まだまだ書きかけ

いろいろな表現があって、かえって迷ってしまうかもしれませんが、数をこなすと見えてくるので、私のサンプルだけじゃなく、いろいろなサンプルを探して見てください。[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]にお勧めのキーワード検索方法を載せてます


[#Document_Froms][ページ内のTOPへ戻る]

HTML入力フォームをさわる(FORMオブジェクトにアクセス)

はじめに(あいさつ?):インターネットエクスプローラーの操作と一口に言ってもイロイロな操作があると思います。
そのうちの一つが、あるホームページ(URL)を表示して、入力フォームにデータをセットして登録ボタンを押す、この一連の流れをVBA上から行いたい・・・と日本語で書くのは簡単なんだけど、この流れをプログラムで記述してみたいと思います

初めの一歩・とっかかりとして、隣のメルマガ([ASPで遊ぶ])の宣伝を兼ねて(オイオイ) ASPとMDBで作ったデータ入力フォームにデータをセットしてみたいと思います。


[#Look_Form_SRC][ページ内のTOPへ戻る]

事前準備

VBAから、IEの入力フォームを操作する・・・と簡単に書いてますが、どこから手を付けるか、、、ですよねぇ。
まずは敵(ターゲット)を知る 事前準備からかな。
深呼吸して心を落ちつかせます(別にもともと落ち着いてるって?)
自動化の前に手動で、操作したいホームページを自分で(手作業で)操作して、処理のイメージをつかみます。
今回のターゲット → [http://www.ken3.org/cgi-bin/test/test029-2.asp]を開いて、手動でデータを入力したり、ボタンを押して、動きをチェックします

手動で操作のイメージを軽く頭に入れたら、
次に、文章(htmlなど)のソースを表示して<form>の中身を確認します。
いきなり、中身とかソースとか言われてもなぁ・・・頭の中?だらけだよ。
あっ、すいません、自分だけわかってて相手のこと考えて無くて。
目的の入力フォームの構造が知りたいので、
目的のページを表示後、
表示--ソースとするとhtmlやcgiの中身を手作業ですが確認できます。
[ソースの確認画面イメージ] ← 単純にIEのメニューから表示させているだけですが
※↑フレームやJavaScriptで細工されたページ、文字コードが違って化け文字になっている・・・など簡単に表示できない場合もありますが

繰り返すと、
・手作業で自動化したい操作を行ってみる。
・ソースを表示して、入力フォームや構造のチェックに使う準備をする
まずは、この2点です。


[#Document_Forms_Submit][ページ内のTOPへ戻る]

データセットとデータ送信(Submitボタン)のサンプル

今回は、よくあるデータ登録で、テキストボックスにデータを入力して、データ送信(Submitボタン)処理を行ってみます。

Formのデータ登録サンプル:[IE起動とデータセットのサンプル 20080527_IE_Form.zip]←Excel VBAです
↑保存後、実行しながら下記の解説を読んでみてください。

今回のターゲット(操作場所)は [http://www.ken3.org/cgi-bin/test/test029-2.asp] です。下記のような単純な入力フォームです。
データを入力して下さい。
感想を書き込んでください。
メルマガ区分選択:
ASPで遊ぶ、失敗する
VBAで楽しく
愚痴系メルマガ
コンビニのオモテとウラ
感想:


↑実際に入力したり、まずは手動で動かしてみてください。
←のソース↓下記、ターゲットの文章(test029-2.asp)から抜き出した<form>の中身(ソース)です。
  <FORM ACTION="test029-2.asp" METHOD="POST" NAME="inputTEST" id="test029">
  <INPUT TYPE="HIDDEN" NAME="NO" VALUE="0">
  <b>メルマガ区分選択:</b><br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="ASP" CHECKED>ASPで遊ぶ、失敗する<br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="VBA" >VBAで楽しく<br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="GUCHI" >愚痴系メルマガ<br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="24H" >コンビニのオモテとウラ<br>
  <b>感想:</b>
  
  <INPUT TYPE="TEXT" NAME="MEMO" SIZE=60 VALUE="VBA IE TEST"><br>
  <br>
  <INPUT TYPE="SUBMIT" NAME="btnSUBMIT" VALUE="書 込">
  <INPUT TYPE="RESET" NAME="btnRESET" VALUE="クリア">
  </FORM>

↑みたいな感じで、入力用のFORMが作られています。
この入力フォームに対して、操作(データをセット)してみたいと思います。

箇条書きの仕様書 流れを書く

最近の若者は仕様書くれとうるさいので(オイオイ)
手作業の操作をただ箇条書きにした流れを書いて渡してあげた(架空の話です、現実では通用しないのでくれぐれもマネなどせぬように...)

手動で操作した時の操作を今一度思い出してください。
まず、コンピュータの電源を入れて、ログインする(ここからやるの?)
・インターネットエクスプローラーを起動して、
・URLを入力 目的の文章・ページを表示させる(ショートカットやお気に入りの人も居るかなぁ)
・入力フォーム(画面の表示)を目で確認
・マウスやキーボードを使って入力エリアへデータをセットする。(データの入力)
・書 込(送信ボタン) を 押す
だいたいこんな感じかな。
そんなの言われなくてもわかってんだよ、しつこいなぁ、ハヤク コードの解説始めろよ※クドクてシツコイ男は嫌われるぞ

IEの起動 と ページの表示

最近流行の 高級料亭でも行っている料理の使い回し じゃないけど、解説の使い回しで、
[IEの起動] : CreateObject("InternetExplorer.application")でブラウザを起動させました
[.Navigateで開く] : 次に目的のページを開くために.Navigateメソッドでページを移動しました
上記を参考に(って言っても、URLが変わっただけですが)
Sub ie_test029_open()  'test029-2.aspを開くテスト

    Dim objIE      As Object  'IEオブジェクト参照用
    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test029-2.asp"

End Sub
上記プログラムで、
・インターネットエクスプローラーを起動して、
・URLを入力 目的の文章・ページを表示させる(ショートカットやお気に入りの人も居るかなぁ)
ここまでの操作ができました。


[#Document_ReadyState_Busy][ページ内のTOPへ戻る]

.Busy と .ReadyState を見て 表示の完了を待つ

次は、
・入力フォーム(画面の表示)を目で確認
です。コンピューターに目は付いていないので、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

と、定義されています。このプロパティがREADYSTATE_COMPLETE = 4になるまで待てばいいのかな。objIE.ReadyState <> 4と直接値の4を書いて使っています。(参照設定して objIE.ReadyState <> READYSTATE_COMPLETEと書くときれいですよ)

2つ目の判断材料が.Busyです
MSDNで.Busy プロパティ→[.Busy http://msdn2.microsoft.com/en-us/library/aa752050.aspx]を見ると
True or False なので、
Busy(忙しい?) True→忙しい、動いてる False→ヒマ、止まっている
単純に、objIE.Busy = Trueの間、ループで待ってみますか。

材料がそろったので、調理してみたいと思います。
Sub ie_ReadyState_Busy_TEST()  '表示待ちのテスト

    Dim objIE      As Object  'IEオブジェクト参照用
    
    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test029-2.asp"

    '表示完了を待つ
    While objIE.ReadyState <> 4
        Debug.Print ".ReadyState = " & objIE.ReadyState
        Debug.Print ".Busy = " & objIE.Busy  'デバッグで文字を書く
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    Debug.Print ".ReadyState = " & objIE.ReadyState
    Debug.Print ".Busy = " & objIE.Busy  'デバッグで文字を書く
    
    MsgBox objIE.Document.Forms(0).OuterHTML 'テストでForm(0)のHTMLを表示
    
End Sub
単純に、
While objIE.ReadyState <> 4で4の完了以外を回し(4になるまで回し)
もう一つ内側のループで、While objIE.Busy = True (忙しいあいだ回る?)
で、表示を待ってみました。


[#Input_Text][ページ内のTOPへ戻る]

IEのdocumentオブジェクト formを使ってhtml入力フォームにアクセスする

次の工程は、
・マウスやキーボードを使って入力エリアへデータをセットする。(データの入力)
です
※指定した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にセットすることができます
Sub ie_Forms_DataSET()  'データセットのテスト

    Dim objIE      As Object  'IEオブジェクト参照用
    
    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test029-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend

    'データをセットする
    'htmlドキュメント フォーム(0番目) アイテム(MEMO)に転記(代入)する
    objIE.Document.Forms(0).Item("MEMO").Value = "こんな感じでデータセット可能"

End Sub
ポイントは、
Excelなら、アプリ -- ブック(Book) -- シート(Sheet) -- セル(Cells)
のオブジェクト階層が、
アプリ -- html(Document) -- フォーム(Form) -- 入力エリア(A INPUT)
objIE.Document.Forms(0).Item("MEMO").Value
みたいな感じです。


[#Input_Submit][ページ内のTOPへ戻る]

.Submit メソッドを使って フォームの送信動作

次の工程は
・書 込(送信ボタン) を 押す
です
挿入(データをフォームにセット)できたら、次は、送信ボタン(書込や投稿)を押したいですよね・・・
実は、単純に該当フォームを.Submitなんてメソッドで できちゃったりするんですよ。
※オブジェクト.動作(メソッド) ってイメージかなぁ。

objIE.Document.Forms(0).Submit
こんな1行で、送信処理(書込や投稿)ができてしまいます。

データセット後にobjIE.Document.Forms(0).Submitを実行してみます。
Sub ie_Forms_Submit()  'データセット後 Submitボタンを押す

    Dim objIE      As Object  'IEオブジェクト参照用
    Dim strCOMMENT As String  'コメントの入力
    
    '固定文字だとつまらないので、INPUTBOXで感想をもらう
    strCOMMENT = InputBox("何か一言コメントを入れてください")
    If strCOMMENT = "" Then
        MsgBox "何か文字を入れてくださいね"
        Exit Sub  '途中で抜ける
    End If
    Application.WindowState = xlMinimized  '入力後Excelを最小化、下に下げる

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "'http://www.ken3.org/cgi-bin/test/test029-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    'データをセットする
    'htmlドキュメント フォーム(0番目) アイテム(MEMO)に転記(代入)する
    objIE.Document.Forms(0).Item("MEMO").Value = strCOMMENT
    
    'フォーム(0番目)を .Submit(送信・投稿) する
    objIE.Document.Forms(0).Submit  '送信処理

End Sub
↑strCOMMENT = InputBox で入力させ、objIE.Document.Forms(0).Item("MEMO").Value = strCOMMENTで代入後に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にして検索]←みたいにして探ってます


[#Document_Forms_Radio][ページ内のTOPへ戻る]

ラジオボタン(INPUT TYPE="RADIO")を選択するサンプル

次は、ラジオボタン(INPUT TYPE="RADIO")を選択してみたいと思います。ラジオボタン選択後、テキストボックスにデータを入力して、書込ボタンを押す、そんな処理を行ってみます。

今回も前回同様(操作場所)は [http://www.ken3.org/cgi-bin/test/test029-2.asp] です。下記のような単純な入力フォームで メルマガ区分の4種類ラジオボタンを選択してみます。
データを入力して下さい。
感想を書き込んでください。
メルマガ区分選択:
ASPで遊ぶ、失敗する
VBAで楽しく
愚痴系メルマガ
コンビニのオモテとウラ
感想:


↑実際に入力したり、まずは手動で動かしてみてください。
←のソース↓下記、ターゲットの文章(test029-2.asp)から抜き出した<form>の中身(ソース)です。
  <FORM ACTION="test029-2.asp" METHOD="POST" NAME="inputTEST" id="test029">
  <INPUT TYPE="HIDDEN" NAME="NO" VALUE="0">
  <b>メルマガ区分選択:</b><br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="ASP" CHECKED>ASPで遊ぶ、失敗する<br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="VBA" >VBAで楽しく<br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="GUCHI" >愚痴系メルマガ<br>
  <INPUT TYPE="RADIO" NAME="KUBUN" VALUE="24H" >コンビニのオモテとウラ<br>
  <b>感想:</b>
  
  <INPUT TYPE="TEXT" NAME="MEMO" SIZE=60 VALUE="VBA IE TEST"><br>
  <br>
  <INPUT TYPE="SUBMIT" NAME="btnSUBMIT" VALUE="書 込">
  <INPUT TYPE="RESET" NAME="btnRESET" VALUE="クリア">
  </FORM>

↑みたいな感じで、入力用のFORMが作られています。
この入力フォームに対して、操作(データをセット)してみたいと思います。

箇条書きの仕様書 流れを書く

最近の若者は仕様書くれとうるさいので(マダ言ってるよいい加減にしろよ)
手作業の操作をただ箇条書きにした流れを書いて渡してあげた(架空の話です、現実では通用しないのでくれぐれもマネなどせぬように...)
※読者からのクレーム(神の声):だったらマネできる仕様書の書き方を教えろ・公開しろって感じなんだけど。(三流作者:クレームは神の声です、検討します(←よく聞く検討しますの逃げ言葉・・・))

手動で操作した時の操作を今一度思い出してください。
・インターネットエクスプローラーを起動して、[IEの起動]
・URLを入力 目的の文章・ページを表示させる(ショートカットやお気に入りの人も居るかなぁ)[.Navigateで開く]
・入力フォーム(画面の表示)を目で確認[.ReadyStateと.Busyで待つ]
・ラジオボタンを選択する。(目的の区分を選択する)※今回の目的
・マウスやキーボードを使って入力エリアへデータをセットする。(データの入力)[Input TEXTにデータをセット]
・書 込(送信ボタン) を 押す[.Submitで送信処理]
だいたいこんな感じかな。
そんなの言われなくてもわかってんだよ、しつこいなぁ、ハヤク コードの解説始めろよ※クドクてシツコイ男は嫌われるぞ


[#Input_Radio][ページ内のTOPへ戻る]

ラジオボタンの攻略方法を紹介する

IEの起動 と ページの表示ができたら、ラジオボタンの選択を行いたいと思います。

ソースを見ると、<INPUT TYPE="RADIO"で名前もNAME="KUBUN"で一緒、VALUE=と値だけが違います。


<INPUT TYPE="RADIO" NAME="KUBUN" VALUE="ASP" CHECKED>ASPで遊ぶ、失敗する<br>
<INPUT TYPE="RADIO" NAME="KUBUN" VALUE="VBA" >VBAで楽しく<br>
<INPUT TYPE="RADIO" NAME="KUBUN" VALUE="GUCHI" >愚痴系メルマガ<br>
<INPUT TYPE="RADIO" NAME="KUBUN" VALUE="24H" >コンビニのオモテとウラ<br>

このINPUT RADIO群をいろいろとさわって、選択状態 Checkedにしてみたいと思います。

準備と確認 FORMの構成要素をFor Eachで1つ1つ取り出してみた

HTML タグなどで表現された文章、タグが階層構造になっているとか言ってました。FORMも文章の一部で、その中(<FORM>〜</FORM>まで)のイロイロなタグによって構成されています。
だから何?
えっと、Formの構成要素を1つ1つ取り出してみます。

For Each objTAG In objIE.Document.Forms(0)で1つ1つ要素をobjTAGに入れて、.Value , .Name を表示させてみました。
Sub ie_Forms_Input_Radio_001()  'Form(0)の下、構成要素を1つ1つ取り出す

    Dim objIE      As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test029-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    'データをセットする
    'htmlドキュメント フォーム(0番目) アイテム(MEMO)に転記(代入)する
    objIE.Document.Forms(0).Item("MEMO").Value = "テスト中"
    
    '※FORM(0)の下 オブジェクトを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)のオブジェクトをFor Each で書き出す
    i = 0
    For Each objTAG In objIE.Document.Forms(0)
        'データをセルへセットする
        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) 'HTML 頭から256文字
        Cells(i + 2, "E") = objTAG.Value  '値
        Cells(i + 2, "F") = objTAG.Name   '名前
        
        i = i + 1   'インクリメント
    Next

End Sub
↑の実行結果↓

.Value と .NAMEが使えそうです。


[#Input_Radio_Checked][ページ内のTOPへ戻る]
ラジオボタン オブジェクトの.Checked = True

オブジェクトをどうにか特定できそうなので、実際にチェックしてみたいと思います。
名前(.NAME) が KUBUN

値(.Value) が VBA
のオブジェクトの.CheckedプロパティをTrueにしてみます。

For Each objTAG In objIE.Document.Forms(0) で回して、単純にIF文で .Name=KUBUN .Value=VBAを判断後、.Checked=Trueにしてみました。
Sub ie_Forms_Input_Radio_Checked()  '見つけたボタンのCheckedにTrueをセット

    Dim objIE      As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test029-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    'HTML Formにデータをセットする
    'htmlドキュメント フォーム(0番目) アイテム(MEMO)に転記(代入)する
    objIE.Document.Forms(0).Item("MEMO").Value = "VBAをCHKする"

    '目的のラジオボタンを探す
    'Form(0)のオブジェクトをFor Each で探る
    Dim objTAG As Object  'タグのオブジェクト格納用
    For Each objTAG In objIE.Document.Forms(0) '構成要素を1つ1つ取り出す
        '名前がKUBUN で 値がVBAのデータを探す
        If objTAG.Name = "KUBUN" And objTAG.Value = "VBA" Then '見つかったか?
            objTAG.Checked = True  '.Checked = True で チェックを付ける
            Exit For               '探し終わったのでループを抜ける
        End If
    Next
    
End Sub
For Each objTAG In objIE.Document.Forms(0)でループを作り、
If objTAG.Name = "KUBUN" And objTAG.Value = "VBA" Thenで該当オブジェクトを特定して、
見つけたオブジェクトの.CheckedプロパティにTrueをセットしただけです。(わかってしまえば意外と簡単?だった)


[#Input_Radio_Click][ページ内のTOPへ戻る]
ラジオボタン オブジェクトを.Clickしてみた

プログラミングの面白さって、同じ結果を得るのにイロイロな書き方があるって所ですよね。まぁ、回答が1つじゃないので個性が出たり、書き方の好き嫌いでもめたりするんだけどね。。。(読者の声:そんな無駄話はいいから、簡単な近道があるなら寄り道しないで教えろよ)

えっと、ラジオボタンの.CheckedプロパティにTrueをセットして選択したのですが、別の方法があって、オブジェクトに対してクリックする、.Clickメソッドを発行する、そんな方法もあります。

簡略仕様書(いつもの使えない箇条書き仕様書)
1.InputBoxで上司・先輩への愚痴を文字列で受け取ります
2.次にIEを起動してWebページを開き
3.フォームの名前がinputTESTのHTML Formに対して以下の処理を行え
 ア..Name(名前)=KUBUN,.Value(値)=GUCHIのオブジェクトを.Click(クリック)
 イ..Name(名前)=MEMOのオブジェクトに入力文字列をセット
 ウ. .Name(名前)=btnSUBMITのオブジェクトを.Click(クリック)
Sub ie_Forms_Input_Radio_Click()  '見つけたオブジェクトをClick

    '1.InputBoxで上司・先輩への愚痴を文字列で受け取ります
    Dim strCOMMENT As String  'コメントの入力
    
    '固定文字だとつまらないので、INPUTBOXで感想をもらう
    strCOMMENT = InputBox("上司や先輩への愚痴は?", "遠慮無く愚痴って", "まともな仕様書書け")
    If strCOMMENT = "" Then
        MsgBox "何か文字を入れてくださいね"
        Exit Sub  '途中で抜ける
    End If

    '2.次にIEを起動してWebページを開く
    Dim objIE      As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test029-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    '3.フォームの名前がinputTESTのHTML Formに対して以下の処理を行え
    ' ア..Name(名前)=KUBUN,.Value(値)=GUCHIのオブジェクトを.Click(クリック)
    ' イ..Name(名前)=MEMOのオブジェクトに入力文字列をセット
    ' ウ. .Name(名前)=btnSUBMITのオブジェクトを.Click(クリック)
    
    Dim objTAG As Object  'タグのオブジェクト格納用
    
    'Form("inputTEST")のオブジェクトをFor Each で探る
    For Each objTAG In objIE.Document.Forms("inputTEST") '構成要素を1つ1つ取り出す
        '名前で分岐
        Select Case objTAG.Name
            Case "KUBUN": 'ア..Name(名前)=KUBUN
                If objTAG.Value = "GUCHI" Then '.Value(値)=GUCHIのオブジェクト?
                    objTAG.Click               '.Value(値)=GUCHIのオブジェクトを.Click(クリック)
                End If
            Case "MEMO"   'イ..Name(名前)=MEMOのオブジェクトに入力文字列をセット
                objTAG.Value = strCOMMENT  '値をセットする
            Case "btnSUBMIT" 'ウ. .Name(名前)=btnSUBMITのオブジェクトを.Click(クリック)
                objTAG.Click
                Exit For   'ボタンを押したので強制的にループを抜ける。
        End Select
    Next
   
End Sub
↑通常は、こんな書き方見かけないと思いますが・・・まぁ、いろいろな表現方法があるってことで、、、
いつもDocument.Forms("0")と0番目とか手抜きでやってましたが、
<FORM ACTION="test029-2.asp" METHOD="POST" NAME="inputTEST" id="test029">
みたいにFORMに名前が付いているなら、Document.Forms("inputTEST")と名前で表すこともできます、こちらの方がみなさんの好みかな。
当然 objIE.Document.Forms(0).Item("MEMO").ValueもobjIE.Document.Forms("inputTEST").Item("MEMO").Valueと書けます。
Form .Submitメソッドでデータを送信できるのですが、ボタンを押す、.Clickメソッド クリック動作でデータを登録することもできます。(ボタンにJavaScriptが貼ってある場合.Clickが有効な場合が多いです)
今回、ループの中でbtnSUBMITボタンを探しましたが objIE.Document.Forms("inputTEST").Item("btnSUBMIT").Clickなんて書き方もOKです。※ボタンの位置がたまたま一番下だったので、ループの中でクリックしてもOKだったけど、ボタンが上にあったらデータセット前に送信ボタンを押してしまいうまくいきませんよ。できたらデータセットとボタンを押すプログラムはわけたほうがいいです。

関連項目:[HTML入力フォーム外側のボタンを押す .Click]
(過去のメルマガ)[No.148 IE ラジオボタン(RADIO)の.Checkedと.Clickの違い]


[#Document_Forms_Select][ページ内のTOPへ戻る]

FORM SELECT OPTION の攻略(選択)サンプル

今回は、データの選択方法でよく見かける SELECT OPTION の選択処理を行ってみます。
リストから1つのOPTIONを選択する場合▼の ドロップダウン パターン

リストからCtrlキーを押して複数選択可能な[SELECT 複数OPTIONの選択] パターン リストボックスのイメージかな?
の2つがあると思います。

まずは、OPTIONを単独で選択する場合を攻略したいと思います。今回のターゲット(操作場所)は [http://www.ken3.org/cgi-bin/test/test092-2.asp] です。下記のような選択(SELECT OPTION)です。
SELECT OPTION の 入力(選択) TEST
表示したい・区分を選択して検索ボタンを押してください

↑実際に入力したり、まずは手動で動かしてみてください。
←のソース↓下記、ターゲットの文章(test092-2.asp)から抜き出した<form>の中身(ソース)です。
<FORM ACTION="test092-2.asp" METHOD="POST">
<font color="blue">SELECT OPTION の 入力(選択) TEST</font><br>
表示したい・区分を選択して検索ボタンを押してください<br>
<SELECT name="KUBUN">
   <option value="">全てのデータ</option>
   <option value="ASP">ASPのデータ</option>
   <option value="VBA">VBAのコメント</option>
   <option value="GUCHI">愚痴系</option>
   <option value="24H">24Hコンビニ</option>
</SELECT>
<INPUT TYPE="submit" VALUE="検索する">
</FORM>

↑みたいな感じで、入力用のFORM 選択(SELECT OPTION)が作られています。
この入力フォームに対して、操作(データをセット)してみたいと思います。


[#Select_Option_Selected][ページ内のTOPへ戻る]

選択なので、素直にオブジェクト .Selected = True にする

手間だけど、Form下のオブジェクトを表示させて探ってみますか。
下記、単純にページを表示させ、手抜きでForm(0)の下、オブジェクトをシートに書き出してみました。
Sub ie_Forms_Input_Select_001()  'Form(0)の下、構成要素を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)の下 オブジェクトを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)のオブジェクトをFor Each で書き出す
    i = 0
    For Each objTAG In objIE.Document.Forms(0)
        'データをセルへセットする
        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文字だけ書く
        Cells(i + 2, "E") = objTAG.Value  '値
        Cells(i + 2, "F") = objTAG.Name   '名前
        
        i = i + 1   'インクリメント
    Next
    
End Sub
↑を実行すると↓の結果が表示されました。

↑あれれ、Optionが見つからないよ。<SELECT>〜</SELECT>の中だからか?

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
※FONTやBRなど名前・値を持たないオブジェクトがあるので注意
↑を実行すると↓の結果が表示されました。

↑For Each objTAG In objIE.Document.Forms(0).All のループだと、OPTIONが取れます※余計な FONT や BR も 付いてくるけど、まぁ、よしとしますか。

For Each objTAG In objIE.Document.Forms(0).All のループで、OPTIONを取り出せたので、値(.Value)がVBAのオブジェクトを選択(.Selected=True)してみます。
Sub ie_Forms_Input_Select_003()  'Form(0).Allの下、.TagName = "OPTION" .Value="VBA" を探し.Select=Trueにする

    Dim objIE    As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test092-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    '※FORM(0).Allの下 オブジェクトを1つ1つ探す
    Dim objTAG As Object  'タグのオブジェクト格納用

    'Form(0).AllのオブジェクトをFor Each で取り出す
    For Each objTAG In objIE.Document.Forms(0).All
        'タグの名前がOPTIONで値がVBAのオブジェクトを探す
        If objTAG.TagName = "OPTION" Then   '初めにOPTIONタグを探す
            If objTAG.Value = "VBA" Then    '次に値がVBAを探す
                objTAG.Selected = True   '.Selected = Trueで選択状態にする
                Exit For                 '見つかったのでループを抜ける
            End If
        End If
    Next

End Sub
↑こんな感じで、タグがOPTION 値がVBAのデータを選択(.Selected=True)できました。


[#Select_Value][ページ内のTOPへ戻る]

もっと素直に<SELECT>タグ .Value に 値をそのままセット

んっ、↑で、Document.Forms(0).All のループで回してとか言ってたけど、その前に<OPTION>は<SELECT>〜</SELECT>の中だからか?なんて言ってたよね。
はい、言ってたよ。それが何か?
何かじゃねぇダロ、選択させる値が<SELECT>〜</SELECT>の中なら初めから、<SELECT>のタグに、.Valueに値をセットしてみたら?<OPTION>を探して.Selected=Trueなんてやってられるか
、、ってことで実際にやってみました。
Sub ie_Forms_Input_Select_004()  'Form(0).Item("KUBUN").Value="24H" と 値をセットする

    Dim objIE    As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test092-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    'Form(0) の アイテム(名前がKUBUN) の 値(.Value) を 24Hにする(24Hを選択する)
    objIE.Document.Forms(0).Item("KUBUN").Value = "24H"

End Sub
↑の1行でできてしまいました・・・あらら。※スミマセン、遠回りさせてしまって。

関連項目:値を直接セットできるなら、(過去のメルマガ)→ [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のこと?(笑))


[#Select_Multiple][ページ内のTOPへ戻る]

FORM SELECT Size=n行 Multipleで複数選択が可能なOPTION の攻略(選択)サンプル

上で単独のOPTION選択を行ったので、次は、SELECT Size=nで複数表示されたリストボックスから、Ctrl+クリックで複数のOPTIONデータを選択する方法を探ってみたいと思います。
今回のターゲット(操作場所)は [http://www.ken3.org/cgi-bin/test/test093-5.asp] です。下記のようなリストボックスで複数選択可能なSELECTタグとOPTIONタグです。
FORM リストボックスの複数選択(selectタグ multiple で VALUE=を個別に作成)
表示したい・区分を選択後、検索ボタンを押してください
Ctrlキーを押しながらクリックすると、複数を選ぶことができます


↑実際に入力したり、まずは手動で動かしてみてください。
←のソース↓下記、ターゲットの文章(test093-5.asp)から抜き出した<form>の中身(ソース)です。
<font color="blue">FORM リストボックスの複数選択(selectタグ multiple で VALUE=を個別に作成)</font><br>
<FORM ACTION="test093-5.asp" METHOD="POST">
表示したい・区分を選択後、検索ボタンを押してください<br>
Ctrlキーを押しながらクリックすると、複数を選ぶことができます<br>
<SELECT NAME="KUBUN" SIZE="5" multiple>
 <option VALUE="ASP">ASP 感想(ASP)</option> 
 <option VALUE="VBA">VBA 感想(VBA)</option> 
 <option VALUE="24H">コンビニ系(24H)</option> 
 <option VALUE="GUCHI">愚痴系(GUCHI)</option> 
</SELECT><br>
<INPUT TYPE="submit" VALUE="検索する">
</FORM>

↑みたいな感じで、入力用のFORM 選択(SELECT OPTION)が作られています。
この入力フォームに対して、複数選択の操作(データをセット)してみたいと思います。


[#Select_Multiple_Selected][ページ内のTOPへ戻る]

Forms(0).All.tags("OPTION")で探したオブジェクトを.Selected = Trueにする

複数でも単独と同様、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で見えているリストの文章を選択するのもアリかなぁ。)
Sub ie_Select_Multiple_001()
    'For Each objTAG In objIE.Document.Forms(0).All.Tags("OPTION")でループさせ
    ' .Value="VBA" と .InnerTEXT="愚痴系(GUCHI)" の2つを探し.Select=Trueにする

    Dim objIE    As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test093-5.asp"
    
    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    '※FORM(0).Allの下 オブジェクトを1つ1つ探す
    Dim objOPTION As Object  'OPTIONタグのオブジェクト格納用

    'Form(0).All.Tags("OPTION")でOPTIONオブジェクトのみ取り出す
    For Each objOPTION In objIE.Document.Forms(0).All.Tags("OPTION")
        '.Value(値)がVBAのオブジェクトを探す
        If objOPTION.Value = "VBA" Then  '.Valueを見てチェック
            objOPTION.Selected = True    '.Selected = Trueで選択状態にする
        End If
        '.InnerTEXT(表示テキスト)が 愚痴系(GUCHI) のオブジェクトを探す
        If objOPTION.InnerTEXT = "愚痴系(GUCHI)" Then  '.InnerTEXTを見てチェック
            objOPTION.Selected = True    '.Selected = Trueで選択状態にする
        End If
    Next

    'おまけで、 OPTIONの親、SELECTの値をデバックエリアに出力
    Debug.Print "KUBUNの値は[" & objIE.Document.Forms(0).Item("KUBUN").Value & "]です"

End Sub
↑ポイントは、ページ表示後に、
For Each objOPTION In objIE.Document.Forms(0).All.Tags("OPTION")でOPTIONのタグをobjOPTIONに1つ1つ取り出し、
If objOPTION.Value = "VBA" と If objOPTION.InnerTEXT = "愚痴系(GUCHI)" で判断しただけなんですが・・

↑実行結果を見ると、複数の選択はできているのですが、おまけで追加した、親のSELECTタグ 名前KUBUNの値をデバック表示(次の章で使うため)が、VBAと1つだけしか表示されていない・・・検索を手動で押すと無事に2つ検索されるし複数選択はOKなんだけどなぁ、何だろうなぁ、、、何か違うアプローチがあるのかなぁ・・・

できれば、複数選択も値の代入だけですましたかったんだけど・・・これもいつもの調査中で逃げてるって感じですね。(時間を作って、壁に立ち向かわないとダメですね)


[#Form_Input_Checkbox][ページ内のTOPへ戻る]

INPUT TYPE="CHECKBOX" を 操作する

フォームのチェックボックス INPUT TYPE="CHECKBOX"を操作します。
おおまかなタイプは2つあって、NAME="オブジェクト名"が個々に違う場合と、NAME="オブジェクト名"が同じでValue="識別する値"で区別しているパターンです。
読者の声:何言ってるのかわからない、意味不明、日本語でお願いします。。。
日本語かぁ・・・自信がないので下記にHTML言語を書きます(HTML言語で話します)

INPUT TYPE="CHECKBOX"の2パターン
NAME="xxxx"が個々に違う NAME="xxxx"が同じでValue="zzzz"が違う
Formの場所[test093-2.asp]↓入力イメージ
CHECKBOX NAME=を個別に作成 Where句を作成するTEST
表示したい・区分をチェックしてから検索ボタンを押してください
ASP
VBA
コンビニ系
愚痴系

↑の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]
チェックボックス↓入力フォーム
FORM CHECKBOX VALUE=を個別に作成 Where句を作成するTEST
表示したい・区分をチェックしてから検索ボタンを押してください
ASP
VBA
コンビニ系
愚痴系

↑の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"が違うパターンです
見た目は同じでも、中身が違う、そんなパターンです。※中身が違うので操作方法も少し違うんですよ・・・世の中には(Web上には)イロイロな処理方法や表現(Htmlの記述)があって大変です。


[#Form_Input_Checkbox][ページ内のTOPへ戻る]

Name="XXXX"が個別で違う場合

Name="XXXX"が個別に違う場合は、素直に名前で目的のオブジェクトへアクセスできるので、
オブジェクト.Checked = Trueでチェックボックスにチェックを入れてみます

Name="VBA"とName="24H"にチェックを入れてみます。
Sub ie_Input_Checkbox_Checked()    '名前がVBA と 24H の チェックボックスをONにする

    Dim objIE    As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test093-2.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    '素直に Document.Forms(0).Item("名前")でアクセスする
    objIE.Document.Forms(0).Item("VBA").Checked = True   '.CheckedプロパティにTrueをセット
    objIE.Document.Forms(0).Item("24H").Checked = True   '.CheckedプロパティにTrueをセット

    'データをセットしたら 送信する(ここでは、コメント(非実行)にしたけど)
    'objIE.Document.Forms(0).Submit   '.Submitメソッドで送信処理

End Sub
素直に Document.Forms(0).Item("名前")でオブジェクトが特定できるので、あとは.Checked = Trueで選択状態にしました。


[#Input_Checkbox_Value][ページ内のTOPへ戻る]

Name="XXXX"が同じで、Value=(値)が違う場合

次に、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つにチェックを入れる
Sub ie_Input_Checkbox_Value()
    '名前(.Name)がKUBUN で 値(.Value)がASP,VBA,24H の チェックボックスをONにする

    Dim objIE    As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test093-4.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    'Form内を1つ1つ調べて、該当するオブジェクトを操作する
    Dim objTAG  As Object  '取り出したタグを入れる変数
    
    For Each objTAG In objIE.Document.Forms(0) 'フォームの下を1つ1つ取り出す
        If objTAG.Name = "KUBUN" Then  '名前が KUBUN のオブジェクトか?
            If objTAG.Value = "ASP" Then objTAG.Checked = True '値がASPならチェックを入れる
            If objTAG.Value = "VBA" Then objTAG.Checked = True '値がVBAならチェックを入れる
            If objTAG.Value = "24H" Then objTAG.Click  '値が24Hならクリックする(おまけのテスト)
        End If
    Next

    'データをセットしたら 送信する(ここでは、コメント(非実行)にしたけど)
    'objIE.Document.Forms(0).Submit   '.Submitメソッドで送信処理

End Sub
ポイントは、ループで回して、名前(.Name)と値(.Value)をチェックして、目的のチェックボックスなら、.CheckedをTrueにしました。※24Hの時、おまけで.Clickメソッドを発行して遊んでみました。(クリック動作でも チェックを付けたりハズしたりできます)


[#Document_getElementsByName][ページ内のTOPへ戻る]

Document.getElementsByName(.Nameがわかるなら名前で素直に探したら?)

上のチェックボックスの判断で、名前(.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を使ってみます
Sub ie_document_getElementsByName()
    '名前(.Name)をgetElementsByNameで探し 値(.Value)がASP,24H,GUCHI の チェックボックスをONにする

    Dim objIE    As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://www.ken3.org/cgi-bin/test/test093-4.asp"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    '.getElementsByNameで指定した名前のオブジェクトを取り出し、値を見て処理を行う
    Dim objTAG  As Object  '取り出したタグを入れる変数
    
    For Each objTAG In objIE.Document.getElementsByName("KUBUN") '名前がKUBUNのデータを取り出す
        If objTAG.Value = "ASP" Then objTAG.Checked = True   '値がASPならチェックを入れる
        If objTAG.Value = "GUCHI" Then objTAG.Checked = True '値がGUCHIならチェックを入れる
        If objTAG.Value = "24H" Then objTAG.Click  '値が24Hならクリックする(おまけのテスト)
    Next

    'データをセットしたら 送信する(ここでは、コメント(非実行)にしたけど)
    'objIE.Document.Forms(0).Submit   '.Submitメソッドで送信処理

End Sub
オブジェクトを取り出すときに、
For Each objTAG In objIE.Document.getElementsByName("KUBUN")
で、名前指定で取り出す(ここではKUBUNのデータ)ことができるので名前が同じオブジェクトを処理する場合にぜひ使ってみてください。


[#Input_button_Click][ページ内のTOPへ戻る]

HTML入力フォーム外側のボタンを押す(<Form>が無い場合)

次は、<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>

↑こんな感じでFORM無しのINPUT type="button"です。

いままでの例だと 名前が付いていれば objIE.Document.Forms("フォームの名前").Item("ボタンの名前").Click や 名前が無くても番号で objIE.Document.Forms(0).Item(6).Click などFormオブジェクトの下を操作してました。
が、今回の文章(Document)には、<Form>がありません・・・

FORMに属していないので一番上のDocument.all("名前")で指定

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でクリックできるか、テストしてみます。
Sub ie_Input_Button_Click()  'Formが無い(Formに属さない)ボタンを.Click

    Dim objIE      As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://ken3-info.blog.ocn.ne.jp/test/2007/09/post_d21d.html"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend

    '↓デバック用で少し待つ(※これは通常いらないので)
    Application.Wait Time:=Now + TimeValue("00:00:03")  '画面遷移がはやいので3秒間止める

    'htmlドキュメント allの名前がbtopのオブジェクト を クリック(.Click)する
    objIE.Document.all("btop").Click   '単純に名前で指定した対象に.Click
 

End Sub
↑こんな感じで無事 FORM に属さないボタンが押せたと思います。※初めからDocument.all("名前").Clickを教えとけよ・・・と読者の声が聞こえてきたような


[#Input_button_NoNAME][ページ内のTOPへ戻る]

Document.all.tags("INPUT")で抜き出し判断する

ボタンに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しました。
Sub ie_Tags_Input_Button()  'ボタンにName=が無しなので、.tagsでINPUTを抜き .Valueで判断

    Dim objIE      As Object  'IEオブジェクト参照用

    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

    '.Navigate で 指定したURLを開く
    objIE.Navigate "http://ken3-info.blog.ocn.ne.jp/test/2007/09/post_d21d.html"

    'ページが表示される 完了を待つ
    While objIE.ReadyState <> 4  'READYSTATE_COMPLETE = 4
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
    '↓デバック用で少し待つ(※これは通常いらないです)
    Application.Wait Time:=Now + TimeValue("00:00:03")  '画面遷移がはやいので3秒間止める
    
    'htmlドキュメント allのから .tagsでINPUTタグを抜き
    '.Value値(ボタンの名称) が IE操作解説 の オブジェクト を クリック(.Click)する
    Dim objINPUT As Object   'Inputタグ格納用

    For Each objINPUT In objIE.Document.all.tags("INPUT")  'Inputのタグを.allから抜く
        If objINPUT.Value = "IE操作解説" Then '.Value値(ボタンの名称) が IE操作解説 か?
            objINPUT.Click  '見つけたINPUTオブジェクト(ボタン)を.Clickクリックする
            Exit For  '用が済んだので(見つかったので)ループを抜ける
        End If
    Next
    
    '↑上でボタンが見つからなかった時のエラー処理が入っていない手抜きだけど、ご勘弁を
    
End Sub
まぁ、日本語のボタン名称(.Value)を探した方が意外と処理がわかりやすかったり?(ソースを見て何やっているのかわかるかなぁ)

余談:間違っても客先や派遣先で名前がわからないからって、胸の大きいな女性に説明しましたとか、とんでもない発言を客先担当者(納品先の課長)に言っちゃイケマセンよ(あの頃は若かったなぁ それで次の仕事が来なかったのか って、誰の失敗談だよ) じゃなくて、少々パターン違いの 逆にName=砂糖さん と名前が同じ場合もあったり、過去のメルマガ → [No.176 VBAからIE操作 NAMEが同じフォームの項目へデータをセットする] も参考にしてください。※逆の立場で自分が派遣で来ているデブ プログラマーとか社員さん達に言われたらと思うとかなり反省(オイオイ)

Form 終わりの挨拶

まだまだ、書かないといけないForm操作 プロパティやメソッドなどの組み合わせがあるのですが、このあたりで逃げるように失礼します(オイオイ)。更新が遅いけど温かく見守ってください 更新中 まだまだ書きかけ

いろいろな表現があって、かえって迷ってしまうかもしれませんが、数をこなすと見えてくるので、私のサンプルだけじゃなく、いろいろなサンプルを探して見てください。[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]にお勧めのキーワード検索方法を載せてます

ここまでのサンプル Formのデータ登録サンプル:[IE起動とデータセットのサンプル 20080527_IE_Form.zip]←Excel VBAです
保存後、解凍して、テストしてみてください。


[#Document_Links][ページ内のTOPへ戻る]

リンク情報を取り出す(Document.Linksオブジェクト)

はじめに(あいさつ?):インターネットエクスプローラーの操作と一口に言ってもイロイロな操作があると思います。
そのうちの一つが、あるホームページ(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やネットから探してくださいと言えよ?全て丁寧に解説してくれるものだと期待するでしょ

スミマセン、、、と、落ち込みつつ、リンクを取り出すサンプルを作成します


[#Link_TEST][ページ内のTOPへ戻る]

調査したいURLを表示後 リンク先の情報をセルにテストで書いてみた

初めは、どんなことをやるか、仕様(仕様書)を書かないといけないんだっけ、
では、いつもの通用しない箇条書き仕様を軽く書きます。
1.調査したいURLをInputBoxで受け取ります(かなり手抜き・・・)
2.IEを起動させ、目的のページを表示させます。
3.目的のページからリンク先を取り出し、セルに書き出します。
こんな感じかな。※オイオイ、おおまか過ぎでしょ・・・
次章からこの3つに対応したコードを載せます。

1.標準関数のInputBoxを使ってURLを受け取る

もしかして、解説不要?だと思いつつ、標準関数のInputBoxを使ってURLを受け取る(入力してもらう)には、
strURL = InputBox("調査するURLは?", "URL入力", "http://www.ken3.org/backno/backno_vba_mokuji.html")
こんな感じかな?
標準関数なので、よく見かけると思います。

2.IEを起動させ、目的のページを表示させます

IEの起動とページ表示です。最近流行の 高級料亭でも行っている料理の使い回し じゃないけど、解説の使い回しで、
ア.初めは[IEの起動] CreateObject("InternetExplorer.application")でブラウザを起動させます
イ.次に[.Navigateで開く] 目的のページを開くために.Navigateメソッドでページを移動させます。
ウ.最後に[.Busyと.ReadyState]で表示の完了(ページの読み込み)を待ちます。

上記を参考に(って言ってもほぼそのまま、URLが変数に変わっただけですが)
Sub ie_Link_TEST()

'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.目的のページからリンク先を取り出し、セルに書き出します。
    '表示されたら、ここから抜き出す処理を書く

End Sub
と、作成しました。

3.目的のページからリンク先を取り出し、セルに書き出します。

調査対象のページが無事に表示されたら、新しいブックを追加後
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
をセルに書き込みます。

解説の前に 先出しで下記、テストで作ったリンク書き出しのプログラムです。
Sub ie_Link_TEST()

'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 i     As Integer '添え字 i番目などで使用
    Dim yLINE As Integer '行カウンタ、Y行目
   
    '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 i = 0 To objIE.Document.Links.Length - 1
        'データをセルへセットする  'を付けて文字列にする(セルにセットしたいので)
        Cells(yLINE, "A") = "'" & objIE.Document.Links(i).Href      'リンク先
        Cells(yLINE, "B") = "'" & objIE.Document.Links(i).OuterText '自分を含む テキスト(Innerと変わりない?)
        Cells(yLINE, "C") = "'" & objIE.Document.Links(i).OuterHTML '自分を含む HTML
        Cells(yLINE, "D") = "'" & objIE.Document.Links(i).InnerText '内側のテキスト
        Cells(yLINE, "E") = "'" & objIE.Document.Links(i).InnerHTML '内側のHTML
        Cells(yLINE, "F") = "'" & objIE.Document.Links(i).Target    '_Blank や 表示先フレームの名前など
        
        yLINE = yLINE + 1 'セット位置(行)を+1する
    Next i
    
    '抜き出し作業が終わったので、通常.QuitでIEを終了させる が 今回は残す
    'objIE.Quit
    Set objIE = Nothing
   
    MsgBox "処理終了、ブラウザの表示内容 と シートを確認してください"
   
End Sub

操作手順と実行結果:


[#Links_Length][ページ内のTOPへ戻る]

Links.Lengthでデータ数 添え字 Links(i) でアクセス

ループで回す時、最大値・要素の数を知りたいので、そんな時は、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

ActiveWorkbook.Sheets.Count
で、ブックのシート数が取れるので、ループで1からシート数分まわし、
ActiveWorkbook.Sheets(i).Name
で、i番目のシートの名前(.Name)を表示してます。

読者の声:だから何?、ドキュメント内のリンク数は、objIE.Document.Links.Countと言いたいの?感覚的にExcel VBAに慣れた人は.Countを使うと決め付けたいの??でも、リンクの数は.Lengthなんでしょ?

あまり怒らないでくださいよ、リンクの数(要素の数)は.Countじゃなくて.Lengthです、配列も0から始まるので、
For i = 0 To objIE.Document.Links.Length - 1
Cells(yLINE, "A") = "'" & objIE.Document.Links(i).Href


Next i
と、i=0から初めて、.Length - 1までのループとしてます
他のIEオブジェクト操作でも 配列の要素数は、パターン的に.Lengthが多いので覚えておいてください・・それが言いたかっただけなんですが、Excelを例にしてた蛇足の解説でしたね(少々反省)


[#Links_Href][ページ内のTOPへ戻る]

.Href .OuterText .OuterHTML .InnerText .InnerHTML .Target

ドキュメント内 リンクのオブジェクト に
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とOuterHTMLと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は、他のタグでも使うことが多いので、なんとなくでもいいので頭のスミにでも覚えておいてください。


[#Links_For_Each][ページ内のTOPへ戻る]

Linksの参照を Links(i)から For Each に 変更

よし、リンクオブジェクトの説明終了、、、朝までにもう一軒飲み屋じゃなかった、オブジェクトをハシゴするぞと行きたい所ですが、あと一杯、少しだけお時間をとらせてください。

読者の声:だから、余計な会話はいいから、はやくシロ。(※←この読者の心の声もかなりの蛇足なんですが(笑)説明に必要ないでしょと思いつつ)

書き方に好みの問題もあるのですが、
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

みたいに、Dim objSHEET As Worksheetと受け取り用の変数を1つ定義して、 For Each objSHEET In ActiveWorkbook.Sheets
と記述すると、ActiveWorkbook.Sheets分だけ1つ1つ次のオブジェクトを取り出しながらループさせ、objSHEET.Nameみたいに(i)とか添え字や.Countなどの要素数を使わないで処理することができます。
同様に For Each 変数 In objIE.Document.Links とLinksもFor Each IN を使うことができます。
読者の声:デジャブか?この解説前にも見たことがある。
Ken3:ギク、、[Document.AllをFor Eachで回す]とそっくりですね。。。料理じゃなかった、解説の使い回しですね(二度見た人はお許しを)
※逆に言うと For Each 変数 IN オブジェクト はイロイロと使えるってことです。もったいないから・・と言ってみた。(オイオイいい加減にしろよまったく)

話を戻して、下記 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
頭から全てのデータをループさせる場合、For Each objLINK In objIE.Document.Linksとして、使う時は objLINK.プロパティ このほうがスッキリとした記述かなぁ。
※三流君的には、Links(i)とかLinks(n)、の書き方が長くても好きだけど。


[#objIE_Quit][ページ内のTOPへ戻る]

処理が終わったら IEを .Quit で閉じてみた

今回のリンク抜き出し処理にはあまり関係ないのですが、
objIE.Quit
.Quitで、Set objIE = CreateObject("InternetExplorer.application") で作成した IEを終了、閉じることができます。
開発中やデバッグ中はIEをそのまま残しておいたほうが何かと便利なのですが、処理が終わったら.Quitでサヨナラをすることもできます。


[#Amazon_Link][ページ内のTOPへ戻る]

Amazon雑誌から本日発売のリンクを抜く(Document.Allからリンク取り出す)

はじめに(あいさつ?):日々の操作を自動化したい、楽したい。そんな理由でシステム化・プログラムで自動化、寝てても勝手にコンピューターが働いてくれる・・・と夢を見るんだろうなぁ。
そんな迷える読者様から、たまに依頼が来たりする。。。

依頼を受け 仕様を起こす

さてと、依頼内容を理解して、仕様を起こしますか。
今回の依頼内容は: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のトップページを表示まで

IEを起動、Amazon.co.jp TOPページを表示する、表示完了を待つ。
は、解説の使い回しで
ア.初めは[IEの起動] CreateObject("InternetExplorer.application")でブラウザを起動させます
イ.次に[.Navigateで開く] 目的のページを開くために.Navigateメソッドでページを移動させます。
ウ.最後に[.Busyと.ReadyState]で表示の完了(ページの読み込み)を待ちます。
↓こんな感じで、書いてみました。
Sub Amazon_Today_Link_test()
 '1.IEを起動します。
    Dim objIE      As Object  'IEオブジェクト参照用
    
    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)
    
 '2.Amazon.co.jp TOPページを表示する。表示完了を待つ。
    '.Navigate で 指定したURLを開く(www.amazon.co.jpを開く)
    objIE.Navigate "http://www.amazon.co.jp/"

    '表示完了を待つ
    While objIE.ReadyState <> 4  'ステータスが4の完了を待つ(4以外の時ループ)
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
 '3.雑誌のリンクをクリックする
 '4.雑誌のページが表示されるのを待つ
 '5.表示された文章から 本日発売の雑誌 を探す
 '6.その下の 雑誌名とリンク先をシートに書き出す
 '7.IEを閉じる
End Sub


[#Links_Click][ページ内のTOPへ戻る]

雑誌のリンクをクリック .Clickする

トップページから、雑誌のページに移動したいので
[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でクリックメソッドを実行しました。
Sub Amazon_Today_Link_test()
 '1.IEを起動します。
    Dim objIE      As Object  'IEオブジェクト参照用
    
    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)
    
 '2.Amazon.co.jp TOPページを表示する。表示完了を待つ。
    '.Navigate で 指定したURLを開く(www.amazon.co.jpを開く)
    objIE.Navigate "http://www.amazon.co.jp/"
    
    '表示完了を待つ
    While objIE.ReadyState <> 4  'ステータスが4の完了を待つ(4以外の時ループ)
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
 '3.雑誌のリンクをクリックする
    Dim objLINK As Object  'リンクのオブジェクト受け取り用

    For Each objLINK In objIE.Document.Links  'リンクを1つ1つ取り出しobjLINKへ
        If objLINK.InnerTEXT = "雑誌" Then  'オブジェクトのテキストで比較する
            objLINK.Click  '見つけたオブジェクトを素直にクリックする
            Exit For       'クリックしたのでループを抜ける
        End If
    Next   '↑雑誌が見つからなかったときの処理が入っていないような・・・

 '4.雑誌のページが表示されるのを待つ
    '表示完了を待つ ↑上でクリックしてページが遷移するので再度待つ
    While objIE.ReadyState <> 4  'ステータスが4の完了を待つ(4以外の時ループ)
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
 
 '5.表示された文章から 本日発売の雑誌 を探す
 '6.その下の 雑誌名とリンク先をシートに書き出す
 '7.IEを閉じる
End Sub
動画解説:[こんな感じ?]

↑リンクのオブジェクトから雑誌を探してクリックしました
次は、雑誌のページから本日発売の雑誌を探します


[#Link_Document_All_TagName][ページ内のTOPへ戻る]

m/d発売の雑誌 を探し その下のリンクをセルに書き出す

リンクは、.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=を取り出し、セルに書き込みます。

プログラムが無駄に長くなってますが、こんな感じです。
Sub Amazon_Today_Link_test()
 '1.IEを起動します。
    Dim objIE      As Object  'IEオブジェクト参照用
    
    'IEを起動する
    Set objIE = CreateObject("InternetExplorer.application") 'IEのオブジェクトを作る
    objIE.Visible = True '見えるようにする(お約束)

 '2.Amazon.co.jp TOPページを表示する。表示完了を待つ。
    '.Navigate で 指定したURLを開く(www.amazon.co.jpを開く)
    objIE.Navigate "http://www.amazon.co.jp/"
    
    '表示完了を待つ
    While objIE.ReadyState <> 4  'ステータスが4の完了を待つ(4以外の時ループ)
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    
 '3.雑誌のリンクをクリックする
    Dim objLINK As Object  'リンクのオブジェクト受け取り用

    For Each objLINK In objIE.Document.Links  'リンクを1つ1つ取り出しobjLINKへ
        If objLINK.InnerTEXT = "雑誌" Then  'オブジェクトのテキストで比較する
            objLINK.Click  '見つけたオブジェクトを素直にクリックする
            DoEvents
            Exit For       'クリックしたのでループを抜ける
        End If
    Next   '↑雑誌が見つからなかったときの処理が入っていないような・・・

 '4.雑誌のページが表示されるのを待つ
    '表示完了を待つ ↑上でクリックしてページが遷移するので再度待つ
    While objIE.ReadyState <> 4  'ステータスが4の完了を待つ(4以外の時ループ)
        While objIE.Busy = True
            DoEvents  '特に何もしないで.Busyの状態が変わるまで待つ
        Wend
    Wend
    'クリック後 手抜きで2秒待つ (オブジェクトの展開時間を待つ)
    Application.Wait Time:=Now + TimeValue("00:00:02")  '2秒間 ボーっとする
 
 '5.表示された文章から 本日発売の雑誌 を探す
 
    Dim n       As Integer    '.allのn番目を管理する番号 添え字
    Dim strKEYWORD As String  'm/d発売の雑誌(マッチング用のワード)

    'マッチング用のキーワードを作る
    strKEYWORD = Format(Now(), "m/d") & "発売の雑誌"

    '文章(.Document)の全体(.All)から m/d発売の雑誌を見つけ ループを抜ける
    For n = 0 To objIE.Document.All.Length - 1
        If objIE.Document.All(n).InnerTEXT = strKEYWORD Then  '次に中身を比較する
            Exit For       'データを見つけたのでループを抜ける
        End If
    Next n

    'ループの最大値と比べて データが見つからない場合を判断する
    If n >= objIE.Document.All.Length Then  '途中でループを抜けられなかったか?
        MsgBox strKEYWORD & " が見つかりません。今日は休刊日 Or レイアウト変更の可能性があります"
        Exit Sub  'ユーザー確認のため、IEはそのまま閉じないでプログラムを抜ける
    End If
    
 '6.その下の 雑誌名とリンク先をシートに書き出す
    Dim nYLINE  As Integer   'セットするデータの行カウンタ
    '前回の結果を消す
    Sheets("本日発売の雑誌").Select    'シートの選択
    Rows("5:9999").Delete Shift:=xlUp  '5行目から9999行を削除する
    
    '見つけた日付をセットする
    Range("B2") = strKEYWORD
    
    nYLINE = 5   '行カウンタを初期化する(5行目からセットする)
 
    Do While n < objIE.Document.All.Length - 1
        'タグ(.TagName)を見て 処理を行う
        If objIE.Document.All(n).TagName = "A" Then 'A タグ リンクのタグなら
            Cells(nYLINE, "A") = objIE.Document.All(n).InnerTEXT  'アンカーのテキストをセット
            Cells(nYLINE, "B") = objIE.Document.All(n).href       '飛び先をセットする
            nYLINE = nYLINE + 1  'セットする行を+1する(次の行へ)
        End If
        
        '次の区切り タグだったら 次のTDまででOKだけど保険でHRを付けました
        If objIE.Document.All(n).TagName = "TD" Then Exit Do 'TDタグ 次のテーブルセルなら抜ける
        If objIE.Document.All(n).TagName = "HR" Then Exit Do 'HRタグ ラインのタグが来たら

        n = n + 1  '調査対象を次のオブジェクトへ
    Loop

 '7.IEを閉じる
    objIE.Quit
    Set objIE = Nothing

End Sub
動画解説:[m/d発売の文字を探しその下のリンクを書き出す]
ポイントは、strKEYWORD = Format(Now(), "m/d") & "発売の雑誌"で、マッチング用の文字列を作り、
For n = 0 To objIE.Document.All.Length - 1のループでまわし
If objIE.Document.All(n).InnerTEXT = strKEYWORD Then で比較し、見つけたらループを抜けます。
この時、nの値が頭出しされているので、次は、
Do While n < objIE.Document.All.Length - 1で読み飛ばしたnからループを作り、
タグ(.TagName)を見て処理を行います。
If objIE.Document.All(n).TagName = "A" Then でAタグを確認後、
セルに Cells(nYLINE, "A") = objIE.Document.All(n).InnerTEXT でリンク先のタイトル
Cells(nYLINE, "B") = objIE.Document.All(n).href で飛び先のURLをセットしてます
あとは、終わりの判断です。これも.TagNameを利用して、次の"TD"タグが来たら処理を終了させてます(ループを抜けてます)
If objIE.Document.All(n).TagName = "TD" Then Exit Do
いろいろと行った小細工で無事リンクが取り出せたと思います。。。

逃げるように 終わりの挨拶

まだまだ、書かないといけないIE操作 プロパティやメソッドなどの組み合わせがあるのですが、このあたりで逃げるように失礼します(オイオイ)。更新が遅いけど温かく見守ってください 更新中 まだまだ書きかけ

いろいろな表現があって、かえって迷ってしまうかもしれませんが、数をこなすと見えてくるので、私のサンプルだけじゃなく、いろいろなサンプルを探して見てください。[番外編 GoogleでoIE,objIE,WebBrowserをKeyWordにして検索]にお勧めのキーワード検索方法を載せてます


[#BackNoLink][ページ内のTOPへ戻る]

過去のメールマガジンのリンクが長かったので、下記に移動しました。
[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へ戻る]

ページフッター

Googleで情報を探す

せっかくホームページに来ていただいたのに、検索の紹介 ぉぃぉぃ
サイト指定や期間の指定を組み合わせて実行してみてください。

Google
探す言葉:
ググる。↑VBAなど 気になる単語や,オブジェクト(MailItem),プロパティ(.Body)やメソッド(.Move)などを入れて検索してみてください。

サイト指定:人気QAサイト や 一次情報MS本家を指定する
条件無し WWW 全体から検索も良いけど↓で絞り込むのもおススメです
一次情報・二次情報まとめから探る
一次情報は基本のMSDN含む microsoft.comから
まとめ一次・二次情報 Qiita 知識を記録・共有 qiita.comで個人まとめを参考に
手前味噌の三次情報 三流君メモBlog ken3memo.hatenablogから検索
QAサイトの質問から探る
QAはやっぱり人の多いYahoo知恵袋 chiebukuro.yahoo.co.jpから探る
こちらもどうぞ おしえてgoo! oshiete.goo.ne.jp
15分探して見つからなかったら?回答率90%以上 teratail.com
私も利用中 最近過疎ってる失礼 人力検索 q.hatena.ne.jp
意外と穴場? 2ch 5ch.netから探す
検索実行: ←オプション確認後に検索ボタンを押してください

期間指定:情報の鮮度も大切?
指定なし(全て)※不変の情報を得るには指定無しが一番?
3日以内 最新の更新情報を探す時など。
3ヶ月 これはあまり使わないかも
1年以内の更新なら情報鮮度もOK?バランス型
3年も経てばOfficeもバージョンUP?
検索実行: ←オプション確認後に検索ボタンを押してください

メッセージ送信

ここまで、読んでいただきどうもです。ここから下は、三流君宛のメッセージ送信や 三流君のホームページの紹介・案内です
目的の情報が見つかったか?少々心配しつつ、、、

感想や質問・要望・苦情など 三流君へメッセージを送る。
下記のフォームからメッセージを送ることができます。


あなたのお名前(ニックネーム):さん
返信は?:


アドレス:に返事をもらいたい
感想や質問↓:


対応速度・緊急度:
(回答・感想は下記のようにしてHPで記事に載せてます) 例:[XXXXさんへ回答例]←みたいに回答していたり...
とても急ぎで連絡がほしい、そんな時は:[twitter三流君DM]に気軽に連絡してください。

[三流君(TOPへ)] / [VBAで楽しく] / [記事一覧]
カスタム検索