VBAでIEのダウンロード釦をクリックして以降に出てくるjavascriptのpromptメソッド、alertメソッド自動入力に関する質問です。特定のWebPageにおいてVBAでバッチ処理によるダウンロード釦をクリックした瞬間に、通常VBEにある実行中のコードを示す黄色いマークが消えてしまいます(制御不能)。そのため、これ以降のVBAによる操作ができなくなってしまいます。マルチプロセス等で対処可能なようですが、こちらでやってみた限りでは、ClickProcを一度も実行しないでobjInput.clickをして黄色いマークが消えてしまいます。そのため、ダイアログのウィンドウハンドルさえ取れません。当然PostMessage等でWM_COMMANDなどのコマンドも送れません。マルチプロセス等が機能するようになったとして、その後どういったスクリプトにすれば良いのでしょうか?スクリプトの横にやっている内容をコメントしてください。参考 http://www.moug.net/faq/viewtopic.php?t=50672

回答の条件
  • URL必須
  • 1人3回まで
  • 登録:
  • 終了:2010/05/03 16:00:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:ardarim No.3

回答回数897ベストアンサー獲得回数145

ポイント10pt

VBAからダウンロードボタンをクリックするということは、VBAを実行するコンテキストからIE内のコンテンツのボタンイベントを呼び出すということと等価です。

要するに、VBA内からMsgBoxで表示したダイアログに対して、自分自身でボタンを押せないのと同じことです。VBAではマルチスレッド動作は出来ませんから、どうしようもありません。


VBAでマルチスレッドは不可能ですが、擬似的にIE側でタイマを使ったスレッドもどきを起こすことで回避は可能です。

例えば、objIEがIEオブジェクトだとして、

    objIE.document.getElementById("test_button").Click

というコードは、IE側のクリック処理(の先のwindow.alertなど)が処理されない限り、呼び出し元のVBAに制御が戻ってきません。


タイマを使って回避するには、

    objIE.document.parentWindow.execScript "window.setTimeout(""document.getElementById('test_button').click();"",10);"

などのようにします。このコードは、10ミリ秒後に「document.getElementById('test_button').click();」を実行するようIE側に設定したあと、すぐVBAに制御が戻ってきます。10ミリ秒後にVBA側は何もしなくてもIE側が自動的にクリック処理を起動してくれるので、VBA側はその後の処理(window.alertの処理など)を継続することが出来ます。


URLはダミー

http://q.hatena.ne.jp/1272265167

その他の回答2件)

id:ko8820 No.1

回答回数1221ベストアンサー獲得回数69

ポイント35pt

WEBブラウザコントロールを使ってみては?

http://www.asahi-net.or.jp/~zn3y-ngi/YNxv9195.html

id:ken3memo No.2

回答回数317ベストアンサー獲得回数115

ポイント35pt

こんにちは。

・最近フットワークの軽くない 腰高ディフェンダーみたい( http://www.ken3.org/vba/backno/vba170.html )

・言い訳ばかり(できない予防線貼りまくり http://www.ken3.org/guchi/backno/guchi188.html )

三流プログラマー ken3memoです

なんて挨拶は、おいといて、

動作しない原因

javascript prompt alert で VBAに処理が返らない(帰ってこない)

(自分でもテストしてみました

VBA IE操作 javascript の prompt alert で処理が止まってしまうダメパターン を 紹介する http://d.hatena.ne.jp/ken3memo/20100428/1272442497 )

解決案

javascript prompt alert で VBAに処理が返らないなら、prompt alertをつぶしたいので、一つの実験をしてみました。

実験内容は、単純に同じ名前の関数が存在したらどちらが優先されるか?

なんて、三流だから考えつく発想でテストしてみました。(一流のプログラマーは関数名が一致するなんてミスしたことないよね、私はだいぶまえにあったり)

javascriptの実験 同じ名前の関数 promptとalertを作るとどちらが有効か?※標準関数をつぶす実験

http://d.hatena.ne.jp/ken3memo/20100428/1272460241

↑で、同じ名前だと 自分で作ったニセモノの方が優先されるみたいなので、

あとは応用するために、HTMLの文章を読み込んだあとにニセのprompt alertを挿入する方法を探ってみます。

VBA IE操作 ニセのpromptとalert() を 挿入する そんな実験

動的に JavaScriptを読み込む

http://zombiebook.seesaa.net/article/22810383.html

■ 外部スクリプトではなく生成したコードを突っ込む場合

var ele = document.createElement("script");

ele.type = "text/javascript";

ele.text = "突っ込むコード";

document.body.appendChild(ele);

を参考にして、

VBAから読み込んだページに

ニセのpromptとalert()をぶち込んでみます。

ページ読み込み後に、

'04/28 ページが読み込まれたので、ニセのjavascriptを挿入、毒を喰わせる?
'>動的に JavaScriptを読み込む http://zombiebook.seesaa.net/article/22810383.html を参考にしました
    Dim ele As Object  'エレメント(script)を1つ作りたいので。
    Set ele = objIE.document.createElement("SCRIPT")
    
    ele.Type = "text/javascript"
    Dim strJCODE As String   '挿入するコード(文字列)
    strJCODE = "function prompt() { return ('123固定で返したい文字');}"
    strJCODE = strJCODE & vbCrLf & "function alert() {  return ;}"
    ele.Text = strJCODE  'コードをセットする
    
    Call objIE.document.body.appendChild(ele)  '上↑で作った要素・エレメントをドキュメントに挿入する
'↑ここまでで、ニセjavascriptの関数作成終了、あとはいつものように処理すると

↑みたいな感じで、ニセのjavascriptを組み込む(毒を喰わせられるので)

これを応用すれば、

javascript prompt alert で VBAに処理が返らない(帰ってみない)

を回避できるのでは?

strJCODE = "function prompt() { return ('123固定で返したい文字');}"

ここの固定文字を入力したいコメントにすれば、目的の動作になると思います。

テストページと無駄に迷っているテスト動画は

http://www.youtube.com/watch?v=k6XIeMITqDg

VBA IE操作 ニセのpromptとalert() を 挿入する そんな実験

http://d.hatena.ne.jp/ken3memo/20100428/1272467509

を見て笑ってください。

読み込み確認後とボタンを押す前に入れれば動くと思います。

ソース全体

Option Explicit

Sub ie_Test_Button()  'ボタンを押した先で javascript の prompt/alert が 走ったら、止まる...

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

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

    '.Navigate で 指定したURLを開く
    Dim strURL As String        'テストのHTML置き場
    strURL = "http://ken3-info.blog.ocn.ne.jp/objie/2010/04/0428_javascript.html" 'テストページ
    
    objIE.Navigate strURL  'テストページを開く

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

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

'04/28 ページが読み込まれたので、ニセのjavascriptを挿入、毒を喰わせる?
'>動的に JavaScriptを読み込む http://zombiebook.seesaa.net/article/22810383.html を参考にしました
    Dim ele As Object  'エレメント(script)を1つ作りたいので。
    Set ele = objIE.document.createElement("SCRIPT")
    
    ele.Type = "text/javascript"
    Dim strJCODE As String   '挿入するコード(文字列)
    strJCODE = "function prompt() { return ('123固定で返したい文字');}"
    strJCODE = strJCODE & vbCrLf & "function alert() {  return ;}"
    ele.Text = strJCODE  'コードをセットする
    
    Call objIE.document.body.appendChild(ele)  '上↑で作った要素・エレメントをドキュメントに挿入する
'↑ここまでで、ニセjavascriptの関数作成終了、あとはいつものように処理すると
    
    '↓デバック用で少し待つ(※これは通常いらないです)
    Application.Wait Time:=Now + TimeValue("00:00:02")  '画面遷移がはやいので2秒間止める
    
    'htmlドキュメント allのから .tagsでButtonタグを抜き
    '.InnerTEXT値(ボタンの名称) が VBA解説 の オブジェクト を クリック(.Click)する
    Dim objButton As Object   'Buttonタグ格納用

    For Each objButton In objIE.document.all.tags("Button")  'Buttonのタグを.allから抜く
        If objButton.InnerTEXT = "ダウンロード" Then '.InnerTEXT値(ボタンの名称) で判断する
            objButton.Click  '見つけたButtonオブジェクト(ボタン)を.Clickクリックする
            Exit For  '用が済んだので(見つかったので)ループを抜ける
        End If
    Next
    
    '↑上でボタンが見つからなかった時のエラー処理が入っていない手抜きだけど、ご勘弁を

    Debug.Print Now & "に処理終了"

End Sub

かなり 三流な逃げ手 ですが、応用して使えたらいいなぁと思いつつ、失礼します。

id:ardarim No.3

回答回数897ベストアンサー獲得回数145ここでベストアンサー

ポイント10pt

VBAからダウンロードボタンをクリックするということは、VBAを実行するコンテキストからIE内のコンテンツのボタンイベントを呼び出すということと等価です。

要するに、VBA内からMsgBoxで表示したダイアログに対して、自分自身でボタンを押せないのと同じことです。VBAではマルチスレッド動作は出来ませんから、どうしようもありません。


VBAでマルチスレッドは不可能ですが、擬似的にIE側でタイマを使ったスレッドもどきを起こすことで回避は可能です。

例えば、objIEがIEオブジェクトだとして、

    objIE.document.getElementById("test_button").Click

というコードは、IE側のクリック処理(の先のwindow.alertなど)が処理されない限り、呼び出し元のVBAに制御が戻ってきません。


タイマを使って回避するには、

    objIE.document.parentWindow.execScript "window.setTimeout(""document.getElementById('test_button').click();"",10);"

などのようにします。このコードは、10ミリ秒後に「document.getElementById('test_button').click();」を実行するようIE側に設定したあと、すぐVBAに制御が戻ってきます。10ミリ秒後にVBA側は何もしなくてもIE側が自動的にクリック処理を起動してくれるので、VBA側はその後の処理(window.alertの処理など)を継続することが出来ます。


URLはダミー

http://q.hatena.ne.jp/1272265167

  • id:ken3memo
    自分でも、テスト↓してみました。
    http://d.hatena.ne.jp/ken3memo/20100428/1272442497
    確かに、
    javascript の prompt alert で処理が止まって戻ってきませんね。

    あまり関係ないのですが、起動のボタンって
    <button onclick="submitF3('DDDD')">ダウンロード</button>
    とか?
    それとも
    submit の ボタンに割り当ててあるのかなぁ?

    submitF3のソースの中で、ダウンロード処理にどうやって飛ばしているのかわからなかったんで。
    最後、コマンドを作っている? command += "#" + comment;
    と openerForm.target="_parent"; の 開き方を変えているだけかなぁと思って。

    あっ、あまり今回の問題(VBAに処理が戻らない)と関係ないので、スルーしてください。

    何か うまい 逃げ手 でも、考えたらまた書き込みます。
    (その前に、識者からの回答が付くことを願いつつ、失礼します。)

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません