[三流君] [VBAで楽しく] [VBA IE 操作]

三流君VBA:VBAからIE操作 TABLEの中にTABLE .getElementsByTagNameほか

発行内容

VBAからIE操作 TABLEの中にTABLE .getElementsByTagNameほか

こんにちは。AB型の変わり者 三流プログラマーのKen3です。

今回は、
IE 操作系でTABLEの中にTABLEタグが存在する、
よくある話にチャレンジしてみます。

/* * 1. 今回のキッカケ */

最近下記の質問をいただく ---- >[No.119 IEを使用して、Web上の表をExcelへ]において、 >頁によっては表以外の記述にもtableタグを多用しているものがありますが、 >欲しい表のみをExcelへ持ってくる方法(tableの見分け方)はありますか? > >具体的には、 >以下の例で試すと、メインの表だけでよいところ、workbookが25個もできました。 >http://table.yahoo.co.jp/t?c=2004&a=10&b=4&f=2005&d=10&e=14&g=d&s=4753.t&y=0&z=4753.t ---- あらら、不必要な表を取得してしまうんですね。 まぁ、レイアウトをきれいにするためにTABLEタグで細工したHTML多いからね。

/* * 2.現象を再現する */

世の中には、いろいろなHTML FORMがあります。 まずは、現象を再現しますか。 No.119 IEを使用して、Web上の表をExcelへ http://www.ken3.org/vba/backno/vba119.html から、 >HTMLの表は、基本のパターンを書くと、 ><TABLE> > <TR> > <TD>XXXXXX</TD> > <TD>YYYYYY</TD> > <TD>ZZZZZZ</TD> > </TR> ></TABLE> >と、 ><TABLE>テーブルのタグから始まり、 ><TR>行の開始 ><TD>列のデータ(<TH>と見出しをキチント書いている人もありです) >の >3つの組み合わせと順番です。 なんて言ってるから、 <TABLE>の中に<TABLE>があると変な処理になるんだよね。 No.119を元に、 URLを変更して、Bookがいっぱいだとうざいのでシートの.addに変えたバージョン
Sub ie_make_table_test()

    Dim objIE    As Object  'IEオブジェクト参照用
    Dim objTAG   As Object  'TAGのオブジェクトを代入
    Dim strURL   As String  'URLの文字列
    Dim y As Integer
    Dim x As Integer
    Dim objTableItem As Object 'TABLE内のITEM検索用

    'インターネットエクスプローラーのオブジェクトを作る
    Set objIE = CreateObject("InternetExplorer.application")
    
    objIE.Visible = True '見えるようにする(お約束)

    '文字列で指定したURLに飛ぶ
    strURL = "http://table.yahoo.co.jp/"                'ベースURL
    strURL = strURL & "t?c=2004&a=10&b=4&f=2005&d=10"   '期間
    strURL = strURL & "&e=14&g=d&s=4753.t&y=0&z=4753.t" '銘柄コードなど???
    objIE.Navigate strURL  'URLへ

    '表示終了まで待つ
     Do While objIE.Busy = True
         '何もしないループ(笑)
         DoEvents
     Loop
     
     '新規ブックを追加する
     Workbooks.Add    'No.177で修正ブックを新規に1つ作る
     
     '.body のデータをループする
     For Each objTAG In objIE.document.body.all
        'テーブルのタグを探す
        If objTAG.tagName = "TABLE" Then
            '新規シートを追加する
            Sheets.Add   'No.177で修正、新規シートを作成する
            'カウンタの初期化
            y = 0 '行カウンタ
            'テーブル内のITEMでループする
            For Each objTableItem In objTAG.all
                If objTableItem.tagName = "TR" Then
                    y = y + 1   '行カウンタを+1
                    x = 1 '列カウンタを1(左端にする)
                End If
                If objTableItem.tagName = "TD" Then
                    'テキストデータをセットする
                    Cells(y, x) = objTableItem.innerText
                    x = x + 1 '列カウンタを+1(次にする)
                End If
            Next
        End If
     Next

End Sub
実行すると、うわっ・・・シートがかなりの数出てきたよ・・・ こりゃここからデータをさらに手作業で編集するのはツライなぁ。

/* * 3.テーブルの中の判断可能な項目名(固定なもの)を探す */

URLの先を見ると、 ライブドア、株価・・・ オイオイ、株価のデータ取り込みかよ。 これのサンプル作るとほかにもいろいろと質問来るんだろうなぁと思いつつ、 数あるテーブルの中で、ほしいのは、 日付 始値 高値 安値 終値 出来高 調整後終値* の表なんですよねキット。 そこで、簡単な逃げ手としては、 TABLEタグを見つけたら、その要素の中に終値とか出来高なんて項目があるか、 探してみるのがいいのかなぁ。 要素を1つ1つ探すと大変なので、 手抜きで.InnerTEXTをInStr関数で If InStr(objTAG.InnerText, "終値") > 0 Then ↑こんな感じでTABLEの中をチェックしてみます。
Sub ie_make_table_test()

    Dim objIE    As Object  'IEオブジェクト参照用
    Dim objTAG   As Object  'TAGのオブジェクトを代入
    Dim strURL   As String  'URLの文字列
    Dim strTAGNAME As String  'タグの名前保存用
    Dim y As Integer
    Dim x As Integer
    Dim objTableItem As Object 'TABLE内のITEM検索用

    'インターネットエクスプローラーのオブジェクトを作る
    Set objIE = CreateObject("InternetExplorer.application")
    
    objIE.Visible = True '見えるようにする(お約束)

    '文字列で指定したURLに飛ぶ
    strURL = "http://table.yahoo.co.jp/"                'ベースURL
    strURL = strURL & "t?c=2004&a=10&b=4&f=2005&d=10"   '期間
    strURL = strURL & "&e=14&g=d&s=4753.t&y=0&z=4753.t" '銘柄コードなど???
    objIE.Navigate strURL  'URLへ

    '表示終了まで待つ
     Do While objIE.Busy = True
         '何もしないループ(笑)
         DoEvents
     Loop
     
     '新規ブックを追加する
     Workbooks.Add    'No.177で修正ブックを新規に1つ作る
     
     '.body のデータをループする
     For Each objTAG In objIE.document.body.all
        'テーブルのタグを探す
        If objTAG.tagName = "TABLE" Then
            'TABLEの中、テキスト文字で[終値]があるか、チェックする No.177
            If InStr(objTAG.InnerText, "終値") > 0 Then  '終値見つかったか?
                '新規シートを追加する
                Sheets.Add   'No.177で修正、新規シートを作成する
                'カウンタの初期化
                y = 0 '行カウンタ
                'テーブル内のITEMでループする
                For Each objTableItem In objTAG.all
                    strTAGNAME = objTableItem.tagName  'テーブル、タグ名
                    If strTAGNAME = "TR" Then
                        y = y + 1   '行カウンタを+1
                        x = 1 '列カウンタを1(左端にする)
                    End If
                    '↓No.177でTHもセットするように変更 TD or THの時
                    If strTAGNAME = "TD" Or strTAGNAME = "TH" Then
                        'テキストデータをセットする
                        Cells(y, x) = objTableItem.InnerText
                        x = x + 1 '列カウンタを+1(次にする)
                    End If
                Next
            End If
        End If
     Next

End Sub
よし、OK...と思ったら、ほかにも2つ変なシートができてるよ・・・

/* * 4.TABLEの中、InnerHTMLにTABLEが存在するか? */

原因は大外のワク(TABLE)の中でも、 InStr(objTAG.InnerText, "終値") が存在すると判断してしまったみたいですね。 チョコレートやお菓子の多重包装、 箱の中にさらに個別の包装じゃないんだからさ・・ そこで、 InStr(objTAG.InnerHTML, "TABLE") = 0 とテーブルタグが見つからない、、と条件を+してみます。 ※オイオイ、、なめんなよ、Instrだけだと、 もしTABLEって文字があったらどうすんの?  タグじゃなくてさ・・・ まぁ、今回は手抜きでInStrでTABLEの文字を探しますが、  汎用性のあるシステムでは、TABLEタグを探してくださいね。 TABLEの中、テキスト文字で[終値]があるか、子TABLEは無しかチェック If InStr(objTAG.InnerText, "終値") > 0 _ And InStr(objTAG.InnerHTML, "TABLE") = 0 Then '終値在り、TABLE無しか 上記2行を+してみます。
Sub ie_make_table_test()

    Dim objIE    As Object  'IEオブジェクト参照用
    Dim objTAG   As Object  'TAGのオブジェクトを代入
    Dim strURL   As String  'URLの文字列
    Dim strTAGNAME As String  'タグの名前保存用
    Dim y As Integer
    Dim x As Integer
    Dim objTableItem As Object 'TABLE内のITEM検索用

    'インターネットエクスプローラーのオブジェクトを作る
    Set objIE = CreateObject("InternetExplorer.application")
    
    objIE.Visible = True '見えるようにする(お約束)

    '文字列で指定したURLに飛ぶ
    strURL = "http://table.yahoo.co.jp/"                'ベースURL
    strURL = strURL & "t?c=2004&a=10&b=4&f=2005&d=10"   '期間
    strURL = strURL & "&e=14&g=d&s=4753.t&y=0&z=4753.t" '銘柄コードなど???
    objIE.Navigate strURL  'URLへ

    '表示終了まで待つ
     Do While objIE.Busy = True
         '何もしないループ(笑)
         DoEvents
     Loop
     
     '新規ブックを追加する
     Workbooks.Add    'No.177で修正ブックを新規に1つ作る
     
     '.body のデータをループする
     For Each objTAG In objIE.document.body.all
        'テーブルのタグを探す
        If objTAG.tagName = "TABLE" Then
            'TABLEの中、テキスト文字で[終値]があるか、子TABLEは無しかチェック
            If InStr(objTAG.InnerText, "終値") > 0 _
              And InStr(objTAG.InnerHTML, "TABLE") = 0 Then '終値在り、TABLE無しか
                '新規シートを追加する
                Sheets.Add   'No.177で修正、新規シートを作成する
                'カウンタの初期化
                y = 0 '行カウンタ
                'テーブル内のITEMでループする
                For Each objTableItem In objTAG.all
                    strTAGNAME = objTableItem.tagName  'テーブル、タグ名
                    If strTAGNAME = "TR" Then
                        y = y + 1   '行カウンタを+1
                        x = 1 '列カウンタを1(左端にする)
                    End If
                    '↓No.177でTHもセットするように変更 TD or THの時
                    If strTAGNAME = "TD" Or strTAGNAME = "TH" Then
                        'テキストデータをセットする
                        Cells(y, x) = objTableItem.InnerText
                        x = x + 1 '列カウンタを+1(次にする)
                    End If
                Next
            End If
        End If
     Next

End Sub
これで、無事に終値を含む表を1つだけ取り出すことができました。

/* * 5.だから、.getElementsByTagName使えよ */

ホント、三流君って、.ALLから1つ1つ.TAGNAMEとかで探すの好きだよね。 できたからいいでしょ、動けばあとはアレンジしてよ。。。 私の記憶が正しければ、過去のメルマガに、 No.164 IE .getElementsByTagNameでタグ指定 .Quitで閉じる http://www.ken3.org/vba/backno/vba164.html こんなのあったよね? うん、あったよ。 .getElementsByTagName("TEXTAREA").Item(0).InnerTEXT とこんな感じで、TEXTAREAのアイテムを取り出してたよ。 だったら、If文でTABLEを探さないで、 .getElementsByTagName("TABLE") で、探してもらえば??? うるさいなぁ、もう!!!書けばいいんだろ、書けば。 (より良い方法を親切に教えられるとなぜかキレる子供プログラマー多いよね) '.body のデータをループする For Each objTAG In objIE.document.body.all 'テーブルのタグを探す If objTAG.tagName = "TABLE" Then こいつを '.document から.getElementsByTagName("TABLE")でオブジェクトを取り出す For Each objTAG In objIE.document.getElementsByTagName("TABLE") の1行に書き換えられるって言いたいのかい? こんな感じで、 .getElementsByTagName("TABLE") で、テーブルオブジェクトのみを取り出して処理する方法がスマートかも。 ※三流君的には.allから探すの好きだけどね。
Sub ie_make_table_test()

    Dim objIE    As Object  'IEオブジェクト参照用
    Dim objTAG   As Object  'TAGのオブジェクトを代入
    Dim strURL   As String  'URLの文字列
    Dim strTAGNAME As String  'タグの名前保存用
    Dim y As Integer
    Dim x As Integer
    Dim objTableItem As Object 'TABLE内のITEM検索用

    'インターネットエクスプローラーのオブジェクトを作る
    Set objIE = CreateObject("InternetExplorer.application")
    
    objIE.Visible = True '見えるようにする(お約束)

    '文字列で指定したURLに飛ぶ
    strURL = "http://table.yahoo.co.jp/"                'ベースURL
    strURL = strURL & "t?c=2004&a=10&b=4&f=2005&d=10"   '期間
    strURL = strURL & "&e=14&g=d&s=4753.t&y=0&z=4753.t" '銘柄コードなど???
    objIE.Navigate strURL  'URLへ

    '表示終了まで待つ
     Do While objIE.Busy = True
         '何もしないループ(笑)
         DoEvents
     Loop
     
     '新規ブックを追加する
     Workbooks.Add    'No.177で修正ブックを新規に1つ作る
     
     '.document から.getElementsByTagName("TABLE")でオブジェクトを取り出す
     For Each objTAG In objIE.document.getElementsByTagName("TABLE")
        'TABLEの中、テキスト文字で[終値]があるか、子TABLEは無しかチェック
        If InStr(objTAG.InnerText, "終値") > 0 _
          And InStr(objTAG.InnerHTML, "TABLE") = 0 Then '終値在り、TABLE無しか
            '新規シートを追加する
            Sheets.Add   'No.177で修正、新規シートを作成する
            'カウンタの初期化
            y = 0 '行カウンタ
            'テーブル内のITEMでループする
            For Each objTableItem In objTAG.all
                strTAGNAME = objTableItem.tagName  'テーブル、タグ名
                If strTAGNAME = "TR" Then
                    y = y + 1   '行カウンタを+1
                    x = 1 '列カウンタを1(左端にする)
                End If
                '↓No.177でTHもセットするように変更 TD or THの時
                If strTAGNAME = "TD" Or strTAGNAME = "TH" Then
                    'テキストデータをセットする
                    Cells(y, x) = objTableItem.InnerText
                    x = x + 1 '列カウンタを+1(次にする)
                End If
            Next
        End If
     Next

End Sub

/* * 6.終わりの挨拶 */

今回は、 TABLEがいっぱいのHTMLから、 終値が含まれている表をInStr関数で探し、 Excelへセットしてみました。 ポイントは、 ^^^^^^^^^^^^ .InnerTextからInStrで終値の文字を探すことと、 TABLEが2重化されていないか、TABLEの文字を.InnerHTMLから探して判断しました。 おまけで、 .document.getElementsByTagName("TABLE") で、テーブルオブジェクトのみ取り出すことができました。 そんな話でした。 プログラム作りは ^^^^^^^^^^^^^^^^ う〜ん・・・ まぁ、人それぞれ、十人十色、百社百色だけどね。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 今回も逃げるように失礼します。 AB型の変わり者、三流プログラマーのKen3でした。

フィードバック

VBA系の→[掲示板]←を覗く、質問を書き込む

評価・感想

No.177を読んだ満足度(評価)は?
5満足(参考になった)
4まぁまぁ(一部参考になった)
3普通(どちらとも言えない)
2なんかなぁ(期待と違った)
1不満(読んで損した気分)
作者に感想・質問を送る場合は下記に気軽に書いてください
あなたのお名前(ニックネーム) さん

作者からの返信は、 不用 E-mail で受信したい
*質問・感想はメルマガで紹介する場合があります


ページフッター(リンクや広告など)

[三流君(TOP ken3.org へ戻る)]
-- [VBA系TOPへ]
---- [VBA系バックナンバー目次へ移動]
------ [VBAでIEを操作 CreateObject("InternetExplorer.application")]・・・実は当店一番人気、VBAでIEを操作するサンプルです
------ [VBAでOutlookの操作 CreateObject("Outlook.Application")]・・・Outlookを使い、メール関係の処理です
------ [Access から Excel 連携 CreateObject("Excel.Application")]・・・人気のAccessからExcelへデータ書き出しなどです
------ [AccessのUserForm/サブフォームを操作]・・・アクセスでフォームを使ったサンプルです
------ [Accessのレポートを操作]・・・レポートを操作してみました
------ [Access クエリー関係やその他関数]・・・あまりまとまってませんが、スポット的な単体関数の解説です
------ [Excel UserForm(ユーザーフォーム)を操作する]・・・エクセルでユーザーフォームを作成して入力などを行ってます
------ [ExcelからAccessを操作する]・・・ExcelからAccessのマクロを起動してみました、
------ [Excel関係 関数、その他]・・・その他Excel関係です
------ [VBAでテキストファイル(*.txt,*.html,*.csv)の操作]・・・テキストファイルを使ったサンプルです
------ [VBA 標準関数関係とその他解説]・・・その他、グダグタ解説してます


広告
-- [通販系の売れ筋広告へ] ←主に楽天やAmazonのランキングです
blog
-- [三流君の作業日記] ← 日々の作業を少々
-- [通販あしあと] ← 通販ページの足跡を一覧で羅列

書籍の購入

Webだけじゃさすがに勉強しきれないので、プログラミング関係の書籍も読んでみては??

コンピュータ書籍の発送がハヤイ専門店

コンピュータの本・専門店
種類が豊富で探し易いです。※在庫ありが48時間以内発送が急ぎで資料や書籍がほしい時、とても助かります。
お奨め本の目次を見るだけでも勉強になったり

amazon.co.jpでキーワード別チェック

下記、私が設定したキーワードですが、こんな感じで資料や書籍を探ってみては?
[VBA全体を把握する] -- やはり全体をさらっと見たいですよね。
[SQL関連でDB力UP] -- システムはデータベース設計が重要
[ADO接続を探る] -- VBAなのでADO接続を押さえておく
[Windows APIを探る] -- さらにAPIになて知ってれば強力だ!
[.NETを探る] -- と言っても時代は.NETに流れてるし
プログラミング以外でも知りたいことは多くって、
[人間関係] -- で、客先・上司、まわりに気を使い。
[プログラマーの自己啓発] -- プログラムだけじゃなくいろいろと向上したいよ
[コーチング・育成] -- 先輩になったら後輩(部下)の面倒をみてね。
そんなこんなでプログラマーっていろいろと大変なんだってば・・・