[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『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
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
しかし、おそらく複数のTDで区切っており、<A HREF= > が1つのTD内で切れているのでしょうね。
ならば、テーブル内のTD数分ループさせ、文字列が含まれるTDを探し、その2つ前のTDに含まれるURLを
クリックすればよさそうです。
HTML操作は、そのものずばりのHTMLソースを明示してもらわないと、具体的な解決方法は伝わらないのです。
社内ファイルを公開なんてできないでしょうから、あとはご自身で試行錯誤するのみです。
(???) 2014/09/22(月) 16:53
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
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は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
<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.