[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『vbaで操作』(あや)
XP Excel2003 IE6
vbaでweb操作をしております。
人が作ったWebページに vbaから検索文字を入力し 検索ボタンを押して 結果を出すようにしております。
検索ボタンを押した直後、画面がついてきていないので
Do While ObjIE.readystate <> 4 Do While ObjIE.Busy = True Loop Loop を入れて、待っています。
これで待つのは待てておりますが、 検索後の結果のページにあるリンクが、 クリック出来ない状態になるときがあります。
クリック出来ない状態は…
青字に下線にはなっているのですが、
マウスを持っていくと『I』になってテキストに合わせるのと
同じ状態。
クリックしても反応なし、です。
コードはこんな感じです(省略してる部分はあります) ---------------------------------------------------- StrCODE = Range("B3")
'検索ボタンを押す ObjIE.navigate "javascript:clickSearchBtn(**********);"
'待つ Do While ObjIE.readystate <> 4 Do While ObjIE.Busy = True Loop Loop
'検索後結果画面のコードをクリック For Each Obj In ObjIE.Document.getElementsByTagName("a") If Obj.innertext = StrCODE Then Obj.Click Exit For End If Next -------------------------------------------------------
重めのページなんで、リンク先まで読み込むのが待てずに Loopが抜けている感じなのかな?とか思うのですが ほとんど知識がないので、予想もあやふやです…
1行デバッグで進めていくと、必要なリンクにたどり着けています。
しかし、最後まで一気にすると、上記の『I』になってWeb画面が途中で止まります。
説明不足かとは思いますが、何か教えて頂けると助かります。
ReadyState がComplete(4)でも Busy が True の状態がありえるので Do While ObjIE.readystate <> 4 Or ObjIE.Busy = True DoEvents Loop のようにしてどうでしょうか。 それでもうまくいかない場合は(ありえるので)、より細かい条件判定が必要に なるかと思います。 http://d.hatena.ne.jp/language_and_engineering/20100410/p1 (Mook)
Mookさんありがとうございます。
教えて頂いた Do While ObjIE.readystate <> 4 Or ObjIE.Busy = True DoEvents Loop でも画面更新が待てていませんでした。
URLを見て、前提知識のところを読ませてもらったのですが (まだあやふやな感じです) WSHの使える環境が必要なのかな?といったことに気がついたところです。
WSHがダウンロードできない環境のため 手詰まりになってしまいました…
ほおり投げるつもりはないのですが、 ひとまずの現状報告にさせてもらいます。
新しい知識を調べながらなのもあって いろいろ質問が変化してまうかとは思いますが またなにかご助言いただければ助かります。
(あや)
WSH といっているのは Windows の VBS/JScript のことで XP 以降であれば標準で 使用できます。
VBS は文法的には VBA と同じく VB ですが、メモ帳などで作成できるテキスト ファイルです。 VBSはマクロでもほぼ(例外はあり)そのまま利用できますが、例示のサイトの 例は JScript(ほぼ JavaScript)で記載されているので、文法を VB に変更して あげる必要があります。
今回対象となっている WebSite はフレームを利用しているのでしょうか。 まじめにやるといろいろ対策が必要ですが、端折ってステータス監視の後に 3秒(フレームの中がこの時間内に読み込み完了するならば)くらいの Sleep を置いたらどうでしょうか。 (Mook)
'// 標準モジュールの先頭に追記 Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) : Sub Sample() : Do While ObjIE.readystate <> 4 Or ObjIE.Busy = True DoEvents Loop Sleep 3000 '// 時間は調整してください。 1000(ms) = 1 秒 : End Sub
まともな回答でなくてすみませんが、
(1) 手で検索操作した場合、平均何秒くらいで読み込みが完了するのでしょうか? その秒数は、強制的にSleepかなんかで待ったみたら如何ですか?(その後、チェック用ループに突入する) (2)ループを抜けるのが早すぎた場合、ここの部分に来る訳ですが、
> For Each Obj In ObjIE.Document.getElementsByTagName("a") > If Obj.innertext = StrCODE Then > Obj.Click > Exit For > End If > Next >
ここで、If文の条件がTrueになることがあるのでしょうか? もしならないのなら、もう一度チェック用ループに戻るように塩梅したら如何ですか? (それでも上手く行かず、無限ループになると厄介なので、TIMEOUTする条件は入れた方がいいと思いますけど)
(半平太) 2012/12/20(Thu) 12:31
Mookさん 半平太さん ありがとうございます
>今回対象となっている WebSite はフレームを利用しているのでしょうか。 フレームは使ってないのです
WSHについてもっと勉強したいのですが、今後の課題として ひとまず。
検索ボタン後 Msgboxを出して 画面更新の確認ができたら、 OKを押して進めるといった方法で 流れを作っていましたが… なんか不満な感じで…^^;
画面更新に10秒〜20秒ほどかかったりするので 20秒 Sleepも試したのですが、 確実ではないのと、遅すぎるので…
とかなんとか試行錯誤していて、 旧ページに無くて、新ページにあるリンク先の文字を 指定してあるか無いかで判断してみる
Label検索結果待ち: If ObjIE.Document.Links(9).outerText <> "検索後ページ" Then Sleep 1000 GoTo Label検索結果待ち End If
という、怒られそうなGotoを使って 必要な動きが得られました。
とりあえずいいかなぁ……… もし検索後ページという文字が無かった場合、 エラー処理をしないといけませんね。
ひとまずの報告とさせて頂きます。 また教えてくださいm(_ _)m
(あや)
解決済みですので蛇足ですが、
試行錯誤して動くようになったというのはそれはそれで、素晴らしいことなのですが 中身を把握できずに終わってしまうというのが、ちょっと危うい感じがしました。
断片的な上記の記述だけを見ると ObjIE.Document.Links(9).outerText は必ずしも目的の場所を特定するのに十分な記述方法ではなさそうです。
想定するページが恒久的に変わらないとしても、後からこの変更をしようとした 他の人には、何をしているかわからないコードですよね。 それを心配する必要がないとしても、「1年後のコードは他人のコード」というのが 私の信条です(最近は1年どころか1か月後ですが・・・)。
期待する位置を明確に特定する指定のしかた、というのを修得されると Web の制御 は幅が広がりますし、イメージしやすくなると思います。 (Mook)
この質問でWebBrawserを使ったコードを提示しました。結果、質問者の意図したコードではなかったのですが、 この時のコードをIEに置き換えると、
新規ブックにて、
参照設定で「Microsoft Internet Controls」にチェックを入れます
Thisworkbookのモジュールに
'============================================================================ Option Explicit Private Declare Function ShowWindow Lib "user32" (ByVal hwindow As Long, ByVal cmdshow As Long) As Long Private WithEvents ie As InternetExplorer Public 表示住所 As Variant Private evcnt As Long '============================================================================ Sub map_disp() Dim idoc As Object Dim ele As Object Set ie = CreateObject("InternetExplorer.Application") With ie ShowWindow .Hwnd, 3 .Visible = True .Navigate "http://www.google.co.jp/maps?ie=UTF-8&oe=UTF-8&hl=ja&tab=wl&q=" Do While .Busy = True Or .readyState <> 4 DoEvents Loop Set idoc = .Document On Error Resume Next With idoc .forms(0).all("q").Value = 表示住所 .forms(0).all("q-sub").Click evcnt = 0 Do While evcnt <= 6 DoEvents Loop For Each ele In .getElementsByTagName("IMG") If ele.classname = "collapse-left3" Then ele.Click Exit For End If Next End With Set idoc = Nothing Set ie = Nothing On Error GoTo 0 End With End Sub '============================================================================ Private Sub ie_DocumentComplete(ByVal pDisp As Object, URL As Variant) evcnt = evcnt + 1 End Sub '============================================================================ Private Sub ie_DownloadComplete() evcnt = evcnt + 1 End Sub
標準モジュールに
'============================================================================== Sub test() With ThisWorkbook .表示住所 = "東京都墨田区押上1" .map_disp End With End Sub
上記のコードは、GoogleMAPを表示し、指定住所(ここでは、「東京都墨田区押上1」) の地図を表示後、パネルを隠すボタンをクリックして、地図を横いっぱいに表示する
という操作を行っていますが、この パネルを隠すボタンが地図表示後、
Do While .Busy = True Or .readyState <> 4 DoEvents Loop
上記のコードで待機しただけでは、ボタンクリックが出来ませんでした。
そこで、DocumentCompleteイベントとDownloadCompleteイベントの発生回数を調べて イベント発生回数6を実験結果(何回か試行した結果6回発生後だとパネルを隠すボタンが有効になった)から 求めて、発生回数になるまでループさせた例です。
何かの参考になれば、幸いです
ichinose@今日は、クリスマス♪
Mookさんいつもご丁寧にありがとうございます。
期待する位置を明確に特定する指定のしかた となりますと、仰ったWSHになってくるのでしょうか。
私の打開策は、後から見てどうか、 Webページ の変更があった場合どうか、といった場面もしかり 今後の考え方にも ぜんぜんいい記述ではない感じはしています +д+
また質問させてもらうと思いますので 教えていただけると助かります。
ichinoseさん、新しい知識をありがとうございます。 WebBrawserってなんだろう?といったところから入ります
落ち着いて調べていきたいと思います。 また教えてください。
(あや)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.