ブラウザの選択メニュー、決定ボタンをVBから操作するには

解決


たかぎしき  2003-09-03 09:03:32  No: 79246

こちらの掲示板で教えていただき、VB6 + IE でブラウザの内容を 
SHDocVw.WebBrowserとMSHTML.HTMLDocumentを使って取得している
のですが、(その節は魔界の仮面弁士様ありがとうございました。)

次の段階として、ブラウザ上の日付選択メニューと決定ボタンを
操作したいのです。
SELECTとSUBMITを使うのでしょうが、具体的なオブジェクト宣言や
コードを教えていただければありがたいです、お願いいたします。


魔界の仮面弁士  2003-09-03 09:37:08  No: 79247

『決定ボタン』は、submitエレメントの事だと思いますが、
『日付選択メニュー』とは、何を指しているのでしょうか?

とりあえず、以前、某メーリングリストに回答したコードを挙げておきます。参考になれば。
http://www.users.gr.jp/ml/archive/viewer.aspx?name=vb&no=9517
http://www.users.gr.jp/ml/archive/viewer.aspx?name=vb&no=9519


たかぎしき  2003-09-03 12:19:53  No: 79248

魔界の仮面弁士様、早速のレス、ありがとうございます。

>『日付選択メニュー』とは、何を指しているのでしょうか?

表現が不正確ですみません。
コンボボックスタイプの選択メニューで、具体的には月日を選ぶように
なっているのです。

教えていただいたサンプルで
VBからは、MSHTML.TLB というファイルを参照設定しておいて、とある
のですが、Microsoft HTML Object Library  でよいのでしょうか?

教えていただいたサンプルを私の状況に合わすと

Private ie As SHDocVw.WebBrowser
Private ieDoc As MSHTML.HTMLDocument
Private mobjSelect As Object
'中略
Private Sub selectB1_click()
    Dim objDocument As Object
    Dim objOption As Object
    Combo1.Clear
    Set objDocument = ieDOC.documentElement    
    Set mobjSelect = objDocument.getElementById("sc")  '←
    For Each objOption In mobjSelect.options    
        Debug.Print objOption.text, objOption.Value
        Combo1.AddItem objOption.text
    Next
    Combo1.ListIndex = 0
    Set objDocument = Nothing
End Sub

←の部分でオブジェクトはこのプロパティ、メソッドをサポートしてないと
言われます。その前の行が間違いでしょうか?(汗)
よろしくお願いします。


魔界の仮面弁士  2003-09-03 18:26:03  No: 79249

> Microsoft HTML Object Library  でよいのでしょうか?
はい、それです。
(まぁ、参照設定はせずとも動かせますが、しておいた方が楽でしょう)

>    Set objDocument = ieDOC.documentElement
>    Set mobjSelect = objDocument.getElementById("sc")    '←
ieDocが、WebBrowser1.Documentへの参照を保持しているのであれば、
「objDocument.getElementById(id名)」ではなく、
「ieDoc.getElementById(id名)」となります。

# ちなみに、『ieDOC.documentElement』が返すものは、
# (Dynamic HTMLでいうところの)documentオブジェクトではなく、
# その中のルート要素…すなわち、HTMLエレメントです。


たかぎしき  2003-09-03 21:43:32  No: 79250

魔界の仮面弁士様、お忙しいところ、ありがとうございます。
>ieDocが、WebBrowser1.Documentへの参照を保持しているのであれば、
>「objDocument.getElementById(id名)」ではなく、
>「ieDoc.getElementById(id名)」となります。

getElementById(id名)のid名というのがどうもわからないのですが(汗!!!)、
getElementByTagNameを使って取得はできました。

Private Sub selectB1_click()
    Dim objDocument As Object
    Dim objOption As Object
    Combo1.Clear
    Set objDocument = ieDOC.documentElement    
    Set mobjSelect = ieDoc.getElementsByTagName("OPTION")         
    For Each objOption In mobjSelect                              
        Debug.Print objOption.text, objOption.Value
        Combo1.AddItem objOption.text
    Next

    Combo1.ListIndex = 0
    Set objDocument = Nothing
End Sub

次にsubmitなんですが、(おいおい次に進むのかよと言われそうですが)
ボタンが他にもいくつかあるので決定ボタンをスマートに指定するには
どうしたらいいのでしょうか。
ボタンは Type="SUBMIT" Name="" Value="決定"です。

よろしくお願いします。


魔界の仮面弁士  2003-09-03 22:14:34  No: 79251

> getElementById(id名)のid名というのがどうもわからないのですが(汗!!!)、

HTMLで <select id="hoge"> と書かれていた場合に、
.getElementById("hoge") のように記述する、という事です。

# 逆にいうと、id属性の無いエレメントの場合は、
# このメソッドでは取得できない事に注意してください。

> getElementByTagNameを使って取得はできました。
…getElementsByTagName の事ですよね?(^_^;)

id属性というのは、1つのHTML文書中で、同じ値が重複して現れてはいけないのです。
だから、get「Element」ByID なわけですね。
一方、要素名(TagName)は、同じ名前が使われることもありますので、
複数形で get「Elements」ByTagName というわけで。

で、提示されたコードですと、HTML中にSELECT要素が複数あった場合に、
どちらの項目(OPTION要素)なのかを判断できません。
この場合はまずSELECT要素を取得してから、そのSELECT要素が持つ
optionsコレクションを取得するようにした方が良いと思いますよ。

> 次にsubmitなんですが、
もし、submitボタンにid属性かname属性が付いているなら、
getElementById/getElementsByNameメソッドが使えるでしょう。

それらの属性が付加されていない場合は、INPUT要素をFor Each〜Nextで
列挙して、その中で、typeプロパティがsubmitになっているものを
探す事になると思います。

ただし、INPUT TYPE="submit"要素があるという事は、通常、
その祖先要素としてFORM要素があると思いますので、id/nameが無い場合は、
FORM要素を取得するだけでも十分かも知れません。もし、submitボタンを
押すことだけが目的なのであれば、FORM要素のsubmitメソッドを
呼び出すだけで済みますの。
(FORM要素は、documentのformsコレクション経由で取得出来ます)

ただし、submitボタンのonclickイベントに処理が割りあたっている時は、
submitボタンのclickメソッドを呼ぶ必要があるでしょうけれども。

> (おいおい次に進むのかよと言われそうですが)
もし、きちんと勉強する気があるなら、HTMLの基本的なタグと、
DHTMLについて簡単に学んでおくと、コーディングがスムーズに進みますよ。


たかぎしき  2003-09-04 04:42:42  No: 79252

魔界の仮面弁士様、たびたびありがとうございます。

>で、提示されたコードですと、HTML中にSELECT要素が複数あった場合に、
>どちらの項目(OPTION要素)なのかを判断できません。
>この場合はまずSELECT要素を取得してから、そのSELECT要素が持つ
>optionsコレクションを取得するようにした方が良いと思いますよ。

なるほど、気がつきませんでした、大変勉強になります。

>それらの属性が付加されていない場合は、INPUT要素をFor Each〜Nextで
>列挙して、その中で、typeプロパティがsubmitになっているものを
>探す事になると思います。

下のようなアプローチでいいでしょうか?
    Dim mobjInput As Object
    Dim objInput As Object

    Set mobjInput = ieDoc.getElementsByTagName("INPUT")    
    For Each objInput In mobjInput                                
        Debug.Print objInput.Type
       If objInput.Value = "SUBMIT" And objInput.Value = "決定" Then
        ieDoc.form.submit
       End If
    Next

しかし ieDoc.form.submit  はエラーになってしまいます。
結局もformもオブジェクトとして取得しないといけないのでしょうか。 

だとしたら魔界の仮面弁士様が下のように言われている部分
>押すことだけが目的なのであれば、FORM要素のsubmitメソッドを
>呼び出すだけで済みますの。
>(FORM要素は、documentのformsコレクション経由で取得出来ます)
これを採用した方が効率的かと思いますが、
 colForms  objform を列挙した後、FORM要素を取得する手順が
わかりません。.elements を指定してもエラーになって……。
何度も手間を取らせて恐縮ですがお願いします。

>もし、きちんと勉強する気があるなら、HTMLの基本的なタグと、
>DHTMLについて簡単に学んでおくと、コーディングがスムーズに進みますよ。
その通りです、オブジェクトブラウザで探しても、何をどういう手順で
使えばいいのかわからないんですよね、勉強します(汗!!)。


魔界の仮面弁士  2003-09-04 10:00:46  No: 79253

> 下のようなアプローチでいいでしょうか?
「INPUT TYPE=SUBMIT要素を探す」しておいて、
「FORM要素のsubmitメソッドを呼び出す」のは無駄かと。

ボタンを探したなら、そのclickメソッドを呼べば良いし、
ボタンを探さないなら、FORMのsubmitメソッドを呼べばOK。

> しかし ieDoc.form.submit  はエラーになってしまいます。
先にも回答しましたように、FORM要素は『documentのformsで』取得します。
『documentのformで』取得するのではありません。(^^;

例えば、
    Set objForms = Me.WebBrowser1.Document.forms
のように書けば、そのページに含まれるFORM要素のコレクションがとれますし、
    Set objForm = objForms(0)
とするか、もしくはFor Eachを使うなどすれば、個々のFORMが得られます。
(formsコレクションの数は、objForms.length にて得られます)

ちなみに、今見ているこのページであれば、
   Set F = Me.WebBrowser1.Document.forms(0)
   F.NAME.value = "ぐぅぐる"
   F.EMAIL.value = "japanese@google.com"
   F.HPAGE.value = "http://www.google.co.jp/"
   F.SOLVED.checked = False
   F.MESSAGE.value = "これは" & vbCrLf & "本文です。"
   F.submit
   Set F = Nothing
などとすれば、メッセージの送信が行われます。
(他にも、いろいろな指定方法があります)

> その通りです、オブジェクトブラウザで探しても、何をどういう手順で
デバッグ時に、VB6の『ローカル ウィンドウ』も併用すると良いですよ。

> 使えばいいのかわからないんですよね、勉強します(汗!!)。
HTMLの操作は、(VBの知識ではなく)DHTMLの知識が必要とされますので、
基本的な部分だけでも、頑張って学習してください。


たかぎしき  2003-09-04 11:42:13  No: 79254

魔界の仮面弁士様、何度も丁寧なレス、ありがとうございます。

>『documentのformで』取得するのではありません。(^^;

あ、また魔界の仮面弁士様に《こいつ、トンチンカンやなー》マークを
出されてしまった(大汗!!!!)。

>  Set objForm = objForms(0)
>とするか、もしくはFor Eachを使うなどすれば、個々のFORMが得られます。
>(formsコレクションの数は、objForms.length にて得られます)

そこまではなんとか自力で気づいたのですが、求める決定ボタンに
Name、IDがないので何番目のFORMに含まれるか調べるところで
足踏みしています。

ちょっとDHTMLも勉強してトライしてみます。

魔界の仮面弁士様、ありがとうございました。


魔界の仮面弁士  2003-09-04 21:10:30  No: 79255

> 求める決定ボタンにName、IDがないので
そうですね。input type="text" や input type="hidden" には、
大抵 name が付けられますが、ボタンに関しては、idもnameも付いていない事が
少なくありません。

> 何番目のFORMに含まれるか調べるところで
一つのHTML中に、複数のFORMエレメントがあるという事ですか?

ところで……今回の『決定ボタン』というのは、どのエレメントなのでしょうか?

もし、input type="submit"エレメントのボタンを押すのであれば、
》      F.submit
だけで済みますが(FはFORMエレメントを指しています)、input type="button"エレメントや
buttonエレメントなどを押すのであれば、それぞれのエレメントオブジェクトを取得してから、
clickする事になりますね。

もし、後者の「clickメソッド」による方法で取得するのであれば、
以下のように、幾つかの手法が考えられます。

Option Explicit

'フォームの送信ボタンを押すためのコード
Private Sub Command1_Click(Index As Integer)
    Dim objDocument    As Object    'As MSHTML.HTMLDocument
    Dim objForm        As Object    'As MSHTML.HTMLFormElement
    Dim objElement     As Object    'As MSHTML.IHTMLElement
    Dim objElements    As Object    'As MSHTML.IHTMLElementCollection

    '最初のフォームを取得します。なお、フォームにnameかidがあるなら、
    'それらも利用して取得した方が良いでしょう。
    Set objDocument = Me.WebBrowser1.Document
    Set objForm = objDocument.forms(0)

    'フォームデータを送信します。
    Select Case Index
     'formオブジェクトのsubmitメソッドを呼び出す方法
     '→送信ボタンが、そのFORM中に一つしか無い時に使えます。
     Case 0
        objForm.submit

     'elements + インデックス番号でinput type="submit"を探し、
     'そのclickメソッドを呼び出す方法
     '→送信ボタンのインデックスが分かっている時に使えます。
     Case 0
        'elementsは、コントロールのみを含んだコレクションです。
        'つまり、INPUT/TEXTAREA/SELECTなどが返されます。
        objForm.elements(6).click

     'all + インデックス番号 で input type="submit"を探し、
     'そのclickメソッドを呼び出す方法
     '→送信ボタンのインデックスが分かっている時に使えます。
     Case 1
        'allは、コントロール以外のエレメントも返します。
        'つまり、NOBR/BR等も含まれます。
        objForm.all(15).click

     'elementsまたはallを列挙して、最初のinput type="submit"を探し、
     'そのclickメソッドを呼び出す方法
     '→送信ボタンのインデックスが分からない時に使えます。
     Case 2
        Set objElements = objForm.elements
        For Each objElement In objElements
            If objElement.tagName = "INPUT" Then
                If LCase(objElement.Type) = "submit" Then
                    objElement.click
                    Exit For
                End If
            End If
        Next

    End Select

    Set objForm = Nothing
    Set objDocument = Nothing
End Sub

Private Sub Form_Load()
    Dim Cmd As VB.CommandButton
    For Each Cmd In Me.Command1
        Cmd.Enabled = False
    Next
    Me.WebBrowser1.Navigate2 "http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200309/03090009.txt"
End Sub

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    Dim Cmd As VB.CommandButton
    For Each Cmd In Me.Command1
        Cmd.Enabled = True
    Next
End Sub


たかぎしき  2003-09-05 07:04:18  No: 79256

魔界の仮面弁士様、何度も何度もありがとうございます。
場合分けしてコードまで示していただいて、大変よくわかりました。

僕はsubmitがFORMの要素で、(誤解を受けるかもしれない言い方ですが)
個々のFORMに従属してIndexを持っていると勘違いしてました。
formsコレクションの要素なのですべてが一挙に列挙取得できるのですね。

>一つのHTML中に、複数のFORMエレメントがあるという事ですか?
そうなんです、3つのFORMがあるんです。

>ところで……今回の『決定ボタン』というのは、どのエレメントなのでしょうか?
SUBMITです。 ID や  NAMEはなく  VALUE="決定"です。

そして3つのFORMにひとつずつ<INPUT TYPE="SUBMIT" が含まれています。

今回の決定ボタンは3つ目のFORMだとわかっているので
  objDocument.forms(2).submit
でもよいということですね。

ただひとつのFORMに複数のsubmitというケースがあるなら、最初のsubmitが
実行されてしまうのでしょうかね?
将来的にページ構造が作り手により変更されてしまう可能性も考えると
For Each で列挙検索した方がより実践的ということですか。

    Set Input = ieDoc.getElementsByTagName("INPUT")        
    For Each objInput In mobjInput                               
       If Lcase(objInput.Type) = "submit" and objInput.Value = "決定" Then
  objInput.click
       End If
    Next

Lcase()というのも実践的な小技ですよね、感心しました。

idもnameもValueもない場合は、いただいたサンプルのCase 2の形を利用
すればよいのですね。

おかげさまで少しずつHTMLについてわかってきたように思います。
魔界の仮面弁士様、本当にありがとうございました。


魔界の仮面弁士  2003-09-05 11:19:53  No: 79257

> 場合分けしてコードまで示していただいて、大変よくわかりました。
ありゃ……良く見たら『Case 0』が2つありましたね。失礼しました。(^_^;)

> ただひとつのFORMに複数のsubmitというケースがあるなら、最初のsubmitが
> 実行されてしまうのでしょうかね?

いえ、違います。どちらのボタンも押されないのです。

例えば……以下のようなHTML FORMがあったとします。

  <form method="post" action="http://〜〜〜">
    <input type="hidden" name="A" value="myData">
    <input type="text"   name="B" value="foo">
    <input type="submit" name="C" value="1">
    <input type="submit" name="D" value="2">
  </form>

この時、ユーザーがデータを送信する為には、
  [1] テキストボックス上で Enter を押した時
  [2] ボタン1を押下した時
  [3] ボタン2を押下した時
のいずれかの動作を行うわけですが、form.submit()というのは、
このうちの[1]の動作に相当する行為になります。

ちなみに[1]やform.submit()の場合は、form.actionで指定したURLに対して
『A=myData&B=foo』というデータが送られるのですが、[2]の操作では
『A=myData&B=foo&C=1』というデータが送られますし、[3]の操作ならば
『A=myData&B=foo&D=2』というデータが送られる事になります。


たかぎしき  2003-09-06 09:06:03  No: 79258

魔界の仮面弁士様、重ねてありがとうございました。

この手の問題になると、参考書も触れてないので、あきらめてしまう人も
多いと思うのですが、魔界の仮面弁士様はすばらしい指導者です。

プログラムも問題なく動くように出来ました。
もう、大感謝です。

DHTMLも少しずつ勉強して、そのうちデータバインドも
手を出してみようかと考えています。

また何かありましたら、なんて図々しくて書けませんが、
(いや既に書いてますが)、教えていただければ幸いです。
本当にありがとうございました。


J_Name  2005-03-12 12:17:17  No: 79259

J_Message


J_Name  2005-03-12 12:17:19  No: 79260

J_Message


J_Name  2005-03-12 12:17:21  No: 79261

J_Message


J_Name  2005-03-12 12:17:22  No: 79262

J_Message


J_Name  2005-03-12 12:17:24  No: 79263

J_Message


Pix  2005-03-12 12:18:05  No: 79264

スイマセン。。。誤射してしまいました汗


J_Name  2005-03-12 12:30:01  No: 79265

J_Message


J_Name  2005-03-12 12:30:02  No: 79266

J_Message


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加