[[20140922132355]] 『VBAでIE操作』(あや) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『VBAでIE操作』(あや)

 教えて下さい

 VBAでIE操作をしており、
 過去に[[20130516115449]]などで質問させてもらっております

 Webページ内にある"あいうえお"という文字をクリックさせるといった動きで
 以下のように使っています

 For Each Obj In ObjIE.Document.getElementsByTagName("a")

   If Obj.outerText = "あいうえお" Then
        Obj.Click
        Exit For

     End If
 Next

 ここで
 教えていただきたいことがあります

 なんで ("a")のaなのか
 Obj.outerText なのか

 ボタンを押す場合には ObjIE.Document.forms(0)で
 Obj.Name なのか

 ネットの記述から拾ってきて、
 ウォッチで値を確認しながら使っていて
 なんとなくで検討をつけている状態です

 リンクとボタンは上の記述で取れるけれど、
 必要としている文字をどのようにすれば取ってこれるかなど
 しっかりと勉強をしたいのです

 なんとなくでは、HTMLのタグに合わせて変わるのだろうなぁといった
 ぼんやりとした理解です…

 Webのソースが見れれば良いのですが、
 右クリックが効かないようにされており
 (裏技で、ソースを表示させるといった方法もありそうですが…)

 こんな感覚で使っているよ、とか
 こんな勉強したらわかりやすいのでは?など
 (HTML?JavaScript?)
 幅広く教えて頂けるとうれしいです

< 使用 Excel:Excel2010、使用 OS:WindowsXP >


 >なんで ("a")のaなのか

 HTML で<A> というタグ( おそらく Anchor から来ている)は Link の機能を持つタグです。
 ですので、
     ObjIE.Document.getElementsByTagName("a")
「リンクのオブジェクトを取得する」という処理になっています。

 テーブルを取得するなら
     ObjIE.Document.getElementsByTagName("TABLE")
 になります。

 Form、Name もいずれも HTML の文法の上での話なので、気になるのであれば、HTML 
 の基礎を勉強してみると良いかと思います。

 こんなあたり?
http://ykr.main.jp/html/

(Mook) 2014/09/22(月) 13:59


"a" を探しているのは、<A HREF=URL名>という構成のタグを見つけるため。
OBJ.outerText を調べているのは、目的の文字列(ブラウザに表示されているもの)を見つけるため。
見つかった場合、そのURL名をクリックする、というコードですね。
(???) 2014/09/22(月) 14:29

 Mookさんありがとうございます

 TABLEで試してみたのですが、
 取りたかった項目がTABLEではなかったようでした

 もやっとですが、追加ご説明させて頂きます

 (社内のシステムなので)
 画面を伝えるため変わりのアドレスです
 http://dynabook.com/pc/index_j.htm
 の左下のほうにある、
 『dynabook.comのお知らせ』のように
 スクロールで見る部分があります

 社内システムでは、
 スクロールの中に
 │NO │ 名前 │ 数字   │▲
 │0001 │ AAA │ 123456  │
 │0002 │ BBB │ 234567 │
 │0003 │ CCC │ 345678 │
 │   │    │     │▼
               
 こんな表が表示されており

 00001(リンク) AAA(テキスト) 123456(テキスト)
 で、

 変数で123456を渡して 00001をクリックさせたいと考えており

 For Each Obj In ObjIE.Document.getElementsByTagName("?????")

   If Obj.????? = "123456" Then

 	123456の行のNOを選択し
        Obj.Click
        Exit For

    End If

 Next
 という形をイメージしております

 教えて頂いた、HTMLで探していたりもするのですが…
 フォーム?なんでしょうか?

 ???さん勉強になりますありがとうございます
 また教えて下さい
(あや) 2014/09/22(月) 15:49

 TABLE は説明のための例示として書きました。

 でも表(EXCELのような罫線からなる表示)の中のデータのことでしたら、ちょっと話は
 面倒です。

 HTML で TABLE はその中に行(TR) と 列(TD)という階層構造を持っています。
 この辺りを理解しないと、どのデータを見るかということが絞れません。

 また FORM は ボタンを押したときにサーバに送信するデータをまとめた単位のもので、
 マクロで言う引数は、FORM の中の INPUT に入れてから、ボタンをクリックするといった
 制御にする必要があります。

 この辺り、思うように制御しようと思うと、VBA だけでなく HTML の基本的なデータの
 やり取りを含めた知識が必要になります。

 まぁ外見的には、テキストボックスのようなフィールド(INPUT)に値を入れてボタンを
 押すという操作なのですが、外に見せない非表示の送信データ( HIDDEN 属性)なども
 ありますので、その辺りは処理したいページのソース(HTML)やコード(Script)を
 確認しないと、はっきりしたことはわかりません。
(Mook) 2014/09/22(月) 16:29

dynabookのお知らせ部分ならば、元と同様に "A" で探して、そのテキストに探す文字が含まれていたらクリック、
という、そのままのロジックで動きそうですよ。

しかし、おそらく複数のTDで区切っており、<A HREF= > が1つのTD内で切れているのでしょうね。
ならば、テーブル内のTD数分ループさせ、文字列が含まれるTDを探し、その2つ前のTDに含まれるURLを
クリックすればよさそうです。

HTML操作は、そのものずばりのHTMLソースを明示してもらわないと、具体的な解決方法は伝わらないのです。
社内ファイルを公開なんてできないでしょうから、あとはご自身で試行錯誤するのみです。
(???) 2014/09/22(月) 16:53


「Excel VBAでIEを思いのままに操作できるプログラミング術」
「IEを自在に操るExcel VBAプログラミング入門」等の書籍を読まれるとか。
IE11なら右クリックから要素の検査ってのがありますが、XP/IE8なら、マウスカーソル直下の要素を取得するコードで調べるとか。
https://gist.github.com/kumatti1/7779267

Webのソースが見れれば良いのですが、 右クリックが効かないようにされており

IEのメニューバーから表示(V)で行けるのでは。
(kumatti) 2014/09/23(火) 06:54


 Mookさん???さんkumattiさん
 幅広い知識を教えてくださり
 ありがとうございます
 心強いです&勉強になります

 試していてわかったことがあり
 ぼやっとですが書き込みさせてもらいます

 For Each Obj1 In ObjIE.Document.getElementsByTagName("TD")
 で、必要としている 123456 が取れました

 Mookさんのおっしゃった
 >HTML で TABLE はその中に行(TR) と 列(TD)という階層構造を持っています。
 >この辺りを理解しないと、どのデータを見るかということが絞れません。
 のお話しになるのかな?と思うのですが、
 『123456 が取れたときの、2つ前のセル 00001をクリックする』としたいのですが

 2つ前のセルという指示をどうすればよいのか?で止まっております
 (概念自体がおかしいのかもしれませんが…)

 ---状況---

 │NO │ 名前 │ 数字   │▲
 │0001 │ AAA │ 123456  │
 │0002 │ BBB │ 234567 │
 │0003 │ CCC │ 345678 │
 │   │    │     │▼

 For Each Obj In ObjIE.Document.getElementsByTagName("TD")

 Next

 でObjに入って来る値は、
 0001  
 AAA
 123456
 0002
 BBB
 234567
 0003
 CCC
 345678

 なので、Objを毎回変数に入れておいて
 Obj=123456になったときに
 2つ前のobjをクリックできればと考えております…

 ---考えていること---
 配列変数で入れておいて -2をすれば良い?(出来るのかはまだ不明)なんて考えましたが
 -2をしたところで、00001を”選択しているタイミングでないと”Obj.Clickができない

 そこで、
 Obj=123456になったときに-2の00001を変数に入れて
 もう一度
 For Each Obj In ObjIE.Document.getElementsByTagName("TD")
 を走らせて、先ほど変数に入れた00001のときに Obj.Click をする?
 とか…

 ウーン?
 そんな簡単なものでもなさそうな感じもしています…

 わかりにくい説明ですみませんが、
 考え方など教えていただければ助かります

 >IEのメニューバーから表示(V)で行けるのでは
 説明不足ですみません
 メニューバーも使えないようにされておりました
(あや) 2014/09/24(水) 13:23

 [ツール]→[開発者ツール](F12) も使えなくなっていますか。
(たいふ) 2014/09/24(水) 14:49

 たいふさんありがとうございます

 メニューバーが出ていないため、
 開発ツールも出ないのです
(あや) 2014/09/24(水) 14:57

 対象となるページがわからない以上、一般論になってしまうのですが、
 Web では複数テーブルがあった場合、

 ObjIE.Document.getElementsByTagName("TD")

 は全部のテーブルのセルが対象になります。
 なので下のような二つのテーブルがあるページで上記を実行すると、10個の TD 要素が
 戻ります。

 +-----+-----+-----+
 |  A1 |  B1 |  C1 |
 +-----+-----+-----+
 |  A2 |  B2 |  C2 |
 +-----+-----+-----+

 +-----+-----+
 |  E1 |  F1 |
 +-----+-----+
 |  E2 |  F2 |
 +-----+-----+

 通常はそうしたことを避けるために、まずテーブルを限定し、その下の行、列でデータを
 特定しながら処理をするのですが、どのようにテーブルを絞るかは、テーブルの名前かID
 無ければそのテーブルが置かれている Form や Div などの上位タブを利用して、絞って
 いきます。

 一番はテーブルにIDが着いているといいのですけれど。
 そうすればテーブルは

 Set tbl = ObjIE.Document.getElementByID("テーブルのID")
 For Each td In tbl.getElementsByTagName("TD")

 のようにも処理できます。

 最もテーブルに絞れれば、
 tbl.rows(行) や  tbl.rows(行).cells(列) のように、行と列で指定できますけれど。

 このように、EXCEL でセルの指定がいろいろあるように、HTML ではHTML のいろいろな
 指定の仕方がありますので、本当であればまずはその辺りを習得すると、今後が楽になる
 と思います。

 VBS ですけれど、基本 VBA でも同じ書き方になると思います。
http://ken3hitori.g.hatena.ne.jp/bbs/30/9
(Mook) 2014/09/24(水) 15:05

別件で私が回答したソースをみてください。
http://www.excel.studio-kazu.jp/kw/20140918210837.html

For Each ではなく、普通にForループで回せば、2つ前とかも簡単に得られます。
(???) 2014/09/24(水) 16:07


メニューバーが出ていないため、 開発ツールも出ないのです 一応、開発者ツールが実装されたのはIE9以降なので、それでXPにはIE8までしかありませんから、
無効なのではなくて、初めから存在しないですね。
(kumatti) 2014/09/25(木) 07:18

 Mookさんありがとうございます

 ちょっと理解力がなく
 テーブルのIDを取ってくる方法がわからないのですが
 今使っているページには、表がひとつしかないです

 HTMLも勉強していきます

 ???さんありがとうございます

 With IE.document
 For i = 0 To .getElementsByTagName("TABLE").Length - 1
    For j = 0 To .getElementsByTagName("TABLE")(i).getElementsByTagName("TR").Length - 1
       For k = 0 To .getElementsByTagName("TABLE")(i).getElementsByTagName("TR")(j).getElementsByTagName("TD").Length - 1
                        Cells(iR, k + 1).Value = .getElementsByTagName("TABLE")(i).getElementsByTagName("TR")(j).getElementsByTagName("TD")(k).innerHTML
       Next k
       iR = iR + 1
    Next j
 Next i
 End With

 この部分を使わさせてもらっています
 iでテーブルの最大行を取得し、
 Jでテーブルの最大列を取得
 Kは何をしているのですか?

 kumattiさんありがとうございます

 社内システムを起動して、ログインIDとパスワードを入力する画面では
 (IE9の中に、ログインIDとパスワードを入力する画面)
 メニューバーが出ているのですが、
 ログインすると、バーがなくなってしまうようにしてあります
(あや) 2014/09/25(木) 13:20

 当方のWinXP,IE8には開発者ツールはあります。
 メニューバーの ツール(T) → 開発者ツール(L)  F12
 または コマンドバーの ツール(O) → 開発者ツール(D)  F12
 F12キーでも呼び出せます。

(たいふ) 2014/09/25(木) 13:36


> iでテーブルの最大行を取得し、
> Jでテーブルの最大列を取得
> Kは何をしているのですか?

惜しい。
iはTABLE数分のループ。
jはTR数(つまりTABLE内の行数)分のループ。
kはTD数(つまりTABLE内の列数)分のループです。

TABLEが1つしかないならば、0番固定で、iのループは不要にできますね。
(???) 2014/09/25(木) 14:31


 ちょっと書き方が冗長ですね。

 表示ページ内のテーブルを列挙する例です。
 新規ファイルで試してみてください。

 Sub Sample()
    Const READYSTATE_COMPLETE = 4

    Dim objIE As Object
    Set objIE = CreateObject("InternetExplorer.Application")

    objIE.Visible = True
    objIE.navigate "http://www.excel.studio-kazu.jp/func/"

    Do While objIE.Busy Or objIE.readyState <> READYSTATE_COMPLETE
        DoEvents
    Loop

    Dim tables
    Dim tRows
    Dim tCells

    Dim i As Long
    Dim r As Long
    Dim c As Long
    Dim ro As Long
    ro = 1
    Set tables = objIE.document.getElementsByTagName("TABLE")
    For i = 0 To tables.Length - 1
       Set tRows = tables(i).getElementsByTagName("TR")
       For r = 0 To tRows.Length - 1
            Set tCells = tRows(r).getElementsByTagName("TD")
            For c = 0 To tCells.Length - 1
                Cells(ro + r, c + 1).Value = tCells(c).innerText
            Next
       Next
       ro = ro + tRows.Length + 1
    Next
 End Sub

 HTML のソースを見て

 <TABLE id="user_list">
 などとなっていたら(タグ名の大文字小文字は識別されません) user_list が ID です。
 その場合は、
    objIE.document.getElementByID("user_list")
 と直接指定できます。

(Mook) 2014/09/25(木) 15:10


 あら、失礼。
 質問者さんのコードだと思ったら、違ってましたね。

 上のコメントの前半は無視してください。
(Mook) 2014/09/25(木) 15:23

 事のついでに、先のコメントのコードを変更して、
 「年、月、日をシリアル値に変換」を検索して左隣のセルのリンクをクリックする例です。
 A タグのインデックスが 0 ではなく 1 なのはセルの中に A タグが二つあり、リンクは2番目にあたるからです。

 このあたりはサイトのソースを表示して状況を確認する必要があります。

 Sub Sample2()
    Const READYSTATE_COMPLETE = 4

    Dim objIE As Object
    Set objIE = CreateObject("InternetExplorer.Application")

    objIE.Visible = True
    objIE.navigate "http://www.excel.studio-kazu.jp/func/"

    Do While objIE.Busy Or objIE.readyState <> READYSTATE_COMPLETE
        DoEvents
    Loop

    Dim tables
    Dim tRows
    Dim tCells

    Dim i As Long
    Dim r As Long
    Dim c As Long
    Set tables = objIE.document.getElementsByTagName("TABLE")
    For i = 0 To tables.Length - 1
       Set tRows = tables(i).getElementsByTagName("TR")
       For r = 0 To tRows.Length - 1
            Set tCells = tRows(r).getElementsByTagName("TD")
            If tCells(1).innerText = "年、月、日をシリアル値に変換" Then
                tCells(0).getElementsByTagName("A")(1).Click
                Exit Sub
            End If
       Next
    Next
 End Sub
(Mook) 2014/09/25(木) 19:31

当方のWinXP,IE8には開発者ツールはあります

あらら、失礼。XPでもあるのですね(;・∀・)
(kumatti) 2014/09/26(金) 07:00


 ???さん ありがとうございます

 なるほど
 もやっとわかったつもりだったりすることが多いので
 教えて頂けるのは、ほんと勉強になります

 Mookさん ありがとうございます

 一つ前の書き込みで頂いたコードを動かすと、
 エクセルシートに、Webページの表になっている部分が
 セルに落とし込まれていきます

 この動きで教えていただきたいのが、

     Set tables = objIE.document.getElementsByTagName("TD")
  
   ’☆1 テーブルの個数
     For i = 0 To tables.Length - 1
        Set tRows = tables(i).getElementsByTagName("TR")

     ’☆2 テーブル内の列数
        For r = 0 To tRows.Length - 1
             Set tCells = tRows(r).getElementsByTagName("TD")

       ’☆3 テーブル内のセル???
             For c = 0 To tCells.Length - 1
                 Cells(ro + r, c + 1).Value = tCells(c).innerText
             Next
        Next
        ro = ro + tRows.Length + 1
     Next

 ☆1と☆2は理解しているつもりなのですが、
 ☆3は、変数にセルを入れている?のでしょうか?

 *検証&理解しながらで、ひとつひとつですみません…
(あや) 2014/09/26(金) 10:58

 > *検証&理解しながらで、ひとつひとつですみません…
 というよりは、むしろそういうことをして欲しいです。

 EXCEL でも同じ意味ですけれど、Cell というのは表の中の一つの項目(最小単位の四角)
 をさします。

 ですので☆3は一行の中の各列を意味します。

 ■■■■■■ これが 一つのTABLE
 ■■■■■■
 ■■■■■■

 ■■■■■■  これが 一行の TR
 □□□□□□
 □□□□□□

 ■□□□□□ これが 一つの TD
 □□□□□□
 □□□□□□

 tCells 全体が一行のセルのオブジェクトリストです(一行分のセル)。
 Cells は EXCEL のセル、tCells は HTML 内のセルを扱っています。

 >☆3は、変数にセルを入れている?のでしょうか?
 は Web のテーブルの各セルを EXCEL のセルに「転記」しています。

(Mook) 2014/09/26(金) 11:36


 Mookさん

 わかりやすい図入りのご説明いただき
 ありがとうございます
 ガンバリマス

 ただいまぼんやり理解で、応用が効かない状態の頭なのですが…

 次に教えて頂いた記述の

  If tcells(1).innerText = "年、月、日をシリアル値に変換" Then

     tcells(0).getElementsByTagName("A")(1).Click
     Exit Sub

  End If

 を、自分のwebページに対応したいと思っていて
 IF tcells(1).innerText = "******* " then
 ここまでは、正しく動いていて

 tcells(0).getElementsByTagName("A")(1).Click
 の対応方法がわからないところで、止まっております

 tables(0)は、指定したテーブルの(上の記述ですと0)
 getElementsByTagName("A")リンクをクリックする
 だと思うのですが、
 getElementsByTagName("A")(1)←(1)は何の指定ですか?

 質問の仕方もいまいちかと思います…すみません
(あや) 2014/09/26(金) 12:51

 > getElementsByTagName("A")(1)←(1)は何の指定ですか?
 の説明は上で書いた、

 >A タグのインデックスが 0 ではなく 1 なのはセルの中に A タグが二つあり、リンクは2番目にあたるからです。
 です。

 その数字が何になるかは Web の構造によります。
 たまたま EXCEL の学校のそのページは TD の中に A が二つある構造だったため、
 (1) になりましたが、おそらく (0) にすればよいと思います。

 該当部分ですが
   <table>
  ■ここから一行の記述↓↓↓↓↓↓
      <tr class="bc1">
     ●[1]ここから一つのセルの記述↓↓↓↓↓↓
        <td class="tl1">
      	  <h3 id="date" class="es0_h3">
            <a name="date"></a>   ← ここが1番目 (0)
      	    <a href="../func/date.html">DATE 関数</a>     ← ここが 2番目 (1)
          </h3>
        </td>
     ●[1]ここまでが一つのセルの記述↑↑↑↑↑↑↑↑↑
     ●[2]ここが2番目のセルの記述 一行で完結
        <td class="tl2">年、月、日をシリアル値に変換</td>
    </tr>
  ■ここまでが一行の記述↑↑↑↑↑↑↑↑↑

 そのあたりは、本来は開発ツール等で、ページの構成を調べてそれにあわせて書くのですけれど。

(Mook) 2014/09/26(金) 13:00


 Mookさんありがとうございます
 説明いただいてたのに、ついていけてなくてすみません

 tcells(0).getElementsByTagName("A")(0).Click
 の指定方法はよくわかりました

 ---この場合はOK---- 
  │NO │ 名前 │ 数字   │▲
   ---------------------------
  │0001 │ AAA │      │

 If tcells(1).innerText = "AAA" Then

   tcells(0).getElementsByTagName("A")(0).Click
   Exit Sub

 End If

 ---Webページに対応をしている途中---
 こちらのページの構造が

  │NO │ 名前 │ 数字   │▲
   ---------------------------
  │0001 │ AAA │      │
  │   │ あ1│ 123456  │
  ---------------------------
  │0002 │ BBB │     │
  │   │ い1│ 234567 │
  ---------------------------
  │0003 │ CCC │     │
  │   │ う1│ 345678 │▼

 こんなのなんです
 それで、123456のときに、
 00001をクリックするように対応をしようとしています

 教えて頂いた感じだと、
 tcells(0).getElementsByTagName("A")(0).Click
 でも動くのかな?と理解しているのですが
 実際は、(画面の反応がないので)動いていません

 If tcells(1).innerText = "123456" Then

  tcells(0).getElementsByTagName("A")(0).Click
   Exit Sub

 End If

 tcells(1).innerText=123456
 のときに、
 tcells(0).getElementsByTagName("A")(0)は
 Nothingとなっております

 状況説明のみになってしまいますが…
 もうちょっと試してみます

(あや) 2014/09/26(金) 16:03


fCells に入っている値は、TD毎ですよね。

<A HREF=> の数が、表の行数に一致しているならば、TRのインデックス、つまり、
tcells(0).getElementsByTagName("A")(r).Click だったりしませんか?

(もし<A HREF=>のない行も存在する場合、TDの0番目の文字列から、改めて"A"タグのインデックスを探しましょう)
(???) 2014/09/26(金) 16:21


 一つ気になったのは3番目のセルは
 >If tcells(1).innerText = "123456" Then
 は tcells(2) ですね。

 あとは適当に書くのではなく、HTML の実際の構造を確認したほうが良いと思います。
 開発ツールが使えれば楽ですけれど、IE で右クリックで「ソースの表示」でもHTML
 ソースは見れるので、文字列検索等で探してみてはと思います。

 Web サーバの構成によっては、ソースが見れないこともありますけれど、その場合は
 開発ツールを使いたいところですね・・・。
(Mook) 2014/09/26(金) 16:26

 Mookさん
 >HTML の実際の構造を確認したほうが良いと思います
  最初からこうおっしゃってる中
  何度も回答いただきありがとうございます

  もうちょっと検証してみます

(あや) 2014/09/26(金) 17:10


 ???さん ありがとうございます
 IEを小さくしていたので、一番下の書き込みしか見ていなく
 回答が遅れました

 また確認し、回答させてもらいます
(あや) 2014/09/27(土) 15:11

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.