[トップページ] / [サンプル一覧へ]

2009-03-22 三流解説 VBA IE JRA IPATのページから単勝の表を取り込む サンプルプログラム

Excel UserForm に WebBrowserを貼り、
JRA IPAD から 単勝オッズの作成を開始しました。
最新情報と作成履歴は→[更新履歴と最新を表示]


現物を操作して、システム化の構想を練る。

システム名	JRA IPATのページから単勝の表を取り込む

客先、ユーザーからの要望・希望を聞く
今回は(今回も)かなり、ラフな日本語で、
「JRA IPATのページから単勝の表を取り込みたい」
と、口頭で言われました。。。

まぁ、まずは現物を動かして確認しますか。
※今回、私もIPATの会員だったので、操作しながらデバッグできたので、
 その点は、良かったです。現物が操作できない処理だと精神的にもツラかったり。
 特に月末の振込み処理とか、CSVデータから連続振込みなど、お金がからむと・・・
※※今回、自動投票じゃないので、失敗しても(おいおい)気が楽かなぁ。

そんな、プレッシャー話は置いといて、現物を確認してみます。
03/21 VBA IE操作 単勝表取込み 事前準備で現物操作 : http://www.youtube.com/watch?v=mxyL2OQPgzQ

いいかげんな 基本設計

基本設計・要求設計を兼ねて、
^^^^^^^^^^^^^^^^^^
システム名:JRA IPADのページから単勝の表を取り込む

概要: WebBrowserをExcel User Form に 貼り、
ログイン処理を操作しながら、
JRA IPADのページから単勝の表を取り込む。

必要な環境 : Excel2003 と Windows XP SP2 + IE7 (随時、対応環境をチェックする)

作業日数・費用:  

開発スケジュール:

↑こんな概要・要求設計だと、見積もり誤差が、、、あとあと、要求が増えないように(笑)


さてと、発注されたら、詳細設計に入りますか。

さらにいいかげんな 詳細設計

詳細設計 ^^^^^^^^ ファイル一覧 : なし ファイルの設計は無し ファイルI/Oイメージ: 無し ファイル詳細 : 無し ※データをシートに書き込むので、基本的に無し 画面一覧: Main001 Webの表示画面 ※UserFormに貼った WebBrowserを操作する。 画面遷移図: 1画面なので無し 画面詳細(入出力) Main001詳細 画面名: 入力画面の表示 と 各処理の実行ボタン 処理概要: Webページを表示 したり、各処理の起動ボタンを作成する。 Excel UserFormに下記のイメージでFormを作成する ------------------------------ | WebBrowser1 | | WebBrowserコントロール | | | | | | | | | ------------------------------ [INET-ID 入力](ボタン)bINET_ID_SET [加入者番号・暗証番号・P-ARS入力](ボタン)bINFO_SET [単勝オッズ取り込み](ボタン)bGET_TAN ------------------------------------ オブジェクトの説明(入力・処理・出力) フォーム全体: 初期処理: 初期状態として、 初期ページ http://www.ipat.jra.go.jp/ を表示する。 加入者番号 の ボタンを使用不可にする      単勝オッズ取り込み の ボタンを使用不可にする 終了処理: 特になし WebBrowser1: オブジェクトの種類: WebBrowser 機能:表示が完了したら(表示完了のイベントで) タイトルと中身を判断して、    ア. [加入者番号・暗証番号・P-ARS入力](ボタン) を 使用可能にする、       [INET-ID 入力](ボタン)を使用不可とする イ.[単勝オッズ取り込み](ボタン)を使用可能取る       [加入者番号・暗証番号・P-ARS入力](ボタン) を 使用不可にする [INET-ID 入力](ボタン)bINET-ID-SET INET-ID 入力 C8 の データをINET-IDにセット ログインボタンを押す(ユーザーが自分で押す) [加入者番号・暗証番号・P-ARS入力](ボタン)bINFO-SET 加入者情報 入力 C10 加入者番号 C12 暗証番号 C14 P-ARS入力 ログインボタンを押す(ユーザーが自分で押す) [単勝オッズ取り込み](ボタン) bGET-TAN 情報画面を開き、単勝オッズをシートに取り込む
03/22 VBA IE操作 単勝表取込み ラフな基本設計と詳細設計 : http://www.youtube.com/watch?v=6FiMjjjMltk

プログラムの作成に入る

上記のかなりラフな設計から、プログラムの作成に入ります。

コーディング
画面に(Formに)オブジェクトを配置します。


03/22 VBA IE操作 単勝表取込み Excel UserForm 作成 : http://www.youtube.com/watch?v=BMFB6hbnjI4


あとは、↑各オブジェクトに対して、処理を記述します。↓

INET-ID 入力

>[INET-ID 入力](ボタン)bINET-ID-SET >INET-ID 入力 > C8 の データをINET-IDにセット > ログインボタンを押す(ユーザーが自分で押す) Htmlソースから、HTML入力FormのInput項目を探り、名前を取り出します。 その名前を使用して、セルC8のデータをセットします。
Private Sub bINET_ID_SET_Click()
    'C8のデータセット name="inetid"
    Me.WebBrowser1.Document.all("inetid").Value = Range("C8")
    '↑Document.allから名前inetidのオブジェクトを指定して値.Valueをセットした。
End Sub
↑名前が重複していないので、単純に .All("名前")でオブジェクトを指定して、 データをセットしました。
03/22 VBA IE操作 単勝表取込み INET-IDのセット : http://www.youtube.com/watch?v=YrcVPFbtwZY

新規のウインドウ(IE)が起動する。

シートのC8から転記する Or 心配だからユーザーが入力する。
どちらのルートを通っても、次は、ログインのボタンを押します。

ここで、一つ問題が、ログインのボタンが押されると、新規のウインドウが起動します。。。
コイツを回避したいなぁ。。。ってことで、IE WebBrowser の イベントを探ってみます。

新規で、WebBrowser2 の オブジェクトを作ります。
いきなり、プライドの高いSE様が作った仕様を変更します。
(※話を通さないでやると、本当にヘソ曲げるよ設計したプライドの高いSE様が、
  なので、原因を話して、一言ことわってから変更してね。)

WebBrowser1のNewWindow2 新しくウインドウが作られる処理で、
Set ppDisp = Me.WebBrowser2
と1つ呪文を書きます。

Private Sub WebBrowser1_NewWindow2(ppDisp As Object, Cancel As Boolean)
    Debug.Print "_NewWindow2 に 入りました。"
    Set ppDisp = Me.WebBrowser2  '新しいウインドウはWebBrowser2を代入
End Sub
↑この1行で、新しく開かれるウインドウを Me.WebBrowser2 で開くことができます。 あとは、Me.WebBrowser2 で捕まえているので、 Me.WebBrowser2 に対して処理を書きます。(処理をかけます。) なんか、小細工だけど、ゆるしてね。。。
03/22 VBA IE操作 単勝表取込み NewWindow2で捕まえる : http://www.youtube.com/watch?v=GZyAdkBVAik

加入者情報 入力

>[加入者番号・暗証番号・P-ARS入力](ボタン)bINFO-SET
>加入者情報 入力
>      C10  加入者番号
>      C12  暗証番号
>      C14  P-ARS入力
>      ログインボタン を押す(ユーザーが自分で押す)

Private Sub bINFO_SET_Click()
    '名前が i,p,r にそれぞれセットする。 セットする場所がWebBrowser2 2に注意
    Me.WebBrowser2.Document.forms("FORM1").Item("i").Value = Range("C10") '加入者番号
    Me.WebBrowser2.Document.forms("FORM2").Item("p").Value = Range("C12") '暗証番号
    Me.WebBrowser2.Document.forms("FORM3").Item("r").Value = Range("C14") 'P-ARS
    '↑同じ名称が使われているので、forms("FORM1"),2,3を指定しました。
End Sub
↑Me.WebBrowser2.Document.all が 同じ名前があったので、使えなかったので、 .forms("フォーム名").Item("INPUTの名前") で データをセットしました。
03/22 VBA IE操作 単勝表取込み 加入者情報のセット : http://www.youtube.com/watch?v=YCyV-YBDQp0

時間外の判断

よし、あと少し・・・と思ったら、時間外のメッセージが。。。
当日の最終投票までしか、使えないみたいですね。。。
※朝からやってて、ここまでしかできなかった。

で、終わってしまうと、悔しいので、
"投票のお申込みを受け付けておりません"
を見つけたら、メッセージを表示して、userformを閉じる、そんなコードを書いてみました。

Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
    If InStr(Me.WebBrowser1.Document.body.innerTEXT, "投票のお申込みを受け付けておりません") > 0 Then
        MsgBox "投票のお申込みを受け付けておりません 時間内に実行してください。"
        Unload Me  'フォームを閉じる
    End If
End Sub
↑単に、InStr で .Document.body を 探っただけでした。 次の土日で決めないとなぁ。。。
03/22 VBA IE操作 単勝表取込み 受付時間外の処理 : http://www.youtube.com/watch?v=QY0NE1GPWKo

情報メニューをクリックする

無事にログインできたので、
次は、情報メニューを起動したいです。

普通に操作する時は、クリック・画像のボタンを押す、なので、
リンクを探してみます。

リンクを探るには、イロイロな方法があるのですが、
今回は、
ウォッチ式に Me.WebBrowser2 を セットして、
その下の .Document .links を 探ってみました。

探っていくと、6番目に、
.title に タイトル(そのままかよ)が入ってました。

? Me.WebBrowser2.Document.links(6-1).title
情報メニュー

なので、そのまま、テストで
Me.WebBrowser2.Document.links(6-1).Click
と、.Clickしてみました。

文字で説明するより、今回は下記の動画を見てもらったほうがいいのかなぁ。
03/28 Document.Linksを探り 情報メニューを探す : http://www.youtube.com/watch?v=ke-Kgfms6tk

固定場号は危険だよね Document.Links(n).Titleを探り .Clickする

おっと、そのまま進めて行くところだった
Me.WebBrowser2.Document.links(6-1).Click
なんか、違和感あるよね。

えっ、どこが、動いているからいいのでは?
これって、たまたま、今は6番目で6-1とかやってるけど、
将来レイアウトなど変更があった時(もしかしてしばらく変わらないかもしれないけど)、違う6番目をクリックしてしまうのでは?

ドキっ、確かに〜(←は、古いかな)、

.Title で 
? Me.WebBrowser2.Document.links(6-1).title
情報メニュー
と、取れるなら、タイトルが情報メニューのリンクを探しクリックに変更したら?
If Me.WebBrowser2.Document.links(n).title = "情報メニュー" Then
※↑まぁ、これも、タイトルが"情報メニュー"から変わったら使えないんだけどね。

これを考慮して、情報メニューを見つけ起動する、そんな処理を書いてみました。

Private Sub bGET_TAN_Click()
    '情報メニューを起動する(クリックする)
    Dim n       As Integer 'ループのカウンター
    Dim nLinkNo As Integer '見つけたメニューの番号
    
    nLinkNo = -1   'エラーの-1で初期化する
    For n = 0 To Me.WebBrowser2.Document.Links.Length - 1 'リンクオブジェクトから探る
        'タイトルが情報メニューのリンクを探す
        If Me.WebBrowser2.Document.Links(n).Title = "情報メニュー" Then
            nLinkNo = n   '見つけた番号をセットする。
            Exit For  '見つけたのでループを抜ける。
        End If
    Next n
    
    'エラーの判断
    If nLinkNo = -1 Then   '-1のまま、見つからなかったら、エラーにする。
        MsgBox "情報メニューが見つかりません、システム管理者に連絡してください"
        Exit Sub  '関数を抜ける
    End If
    
    '見つけたリンクを押す .Click
    Me.WebBrowser2.Document.Links(nLinkNo).Click  '単純に.Clickメソッドを使う
    '↑次は、ここで起動した 情報メニューを捕まえないとなぁ。。。

End Sub
※↑今回、画像のメニューボタンだったので、 .Document.Links(n).Title で チェックしました。 多いパターンはテキストリンクだと .Document.Links(n).InnerTEXT が 多いかなぁ。 あとは、飛び先が変わらないことが多いので .Document.Links(n).
03/28 Document.Links(n).Titleを探り .Clickする : http://www.youtube.com/watch?v=OxeD_xZwrSA

また 新しいウインドウが起動した(情報ウインドウを捕まえる)

新しいウインドウが起動したので、
Me.WebBrowser3
を新たに作って、捕まえてみます・・・

だと、面白くないので(※面白くなくても簡単にできれば、そっちの解説が聞きたいよ)
使っていない、上部の Me.WebBrowser1 を 代入してみます。

Private Sub WebBrowser2_NewWindow2(ppDisp As Object, Cancel As Boolean)
    Debug.Print "WebBrowser2_NewWindow2 に 入りました。"
    Set ppDisp = Me.WebBrowser1  '新しいウインドウはWebBrowser1を代入
End Sub
↑単純に、WebBrowser2_NewWindow2 の イベントで、 Set ppDisp = Me.WebBrowser1 と新しいウインドウはWebBrowser1ですよ・・って感じにしました。
03/28 _NewWindow2 の イベントで新規ウインドウ捕まえる : http://www.youtube.com/watch?v=SvDM2JnaUbE

オッズのボタンを押す

これで、新しく開かれたウインドウを捕まえました。
あとは、Me.WebBrowser1 に 対して、処理を書きます。

    'WebBrowser1に切り替わり、表示を待つ
    While Me.WebBrowser1.Busy Or Me.WebBrowser1.ReadyState <> READYSTATE_COMPLETE
        DoEvents
    Wend
    
    '表示完了後、INPUTタグ オッズのボタンを探す
    Dim tagINPUT As Object  'INPUTのタグを保存する
    Dim nInputNo As Integer '見つけたオブジェクトの場所
    Set tagINPUT = Me.WebBrowser1.Document.all.tags("INPUT") 'INPUTのタグを取り出す

    nInputNo = -1   'エラーの-1で初期化する
    For n = 0 To tagINPUT.Length - 1  'INPUTのタグを頭から探る
        If tagINPUT(n).Value = "オッズ" Then
            nInputNo = n   '見つけた番号をセットする。
            Exit For  '見つけたのでループを抜ける。
        End If
    Next n

    'エラーの判断
    If nInputNo = -1 Then   '-1のまま、見つからなかったら、エラーにする。
        MsgBox "オッズボタンが見つかりません、システム管理者に連絡してください"
        Exit Sub  '関数を抜ける
    End If
    
    '見つけた場所 nInputNoのINPUTを押す .Click
    tagINPUT(nInputNo).Click  '単純に.Clickメソッドを使う
    '↑次は、ここで起動した オッズの表を操作する

こんな感じの流れで、オッズのボタンを押しました。
ポイントは、
Set tagINPUT = Me.WebBrowser1.Document.all.tags("INPUT")
で、INPUTのタグを取り出し
For n = 0 To tagINPUT.Length - 1
のループで、
If tagINPUT(n).Value = "オッズ" Then
を判断して、見つけた場所を保存(nInputNo = n)

あとは、
tagINPUT(nInputNo).Click
で、単純に.Clickメソッドを使いボタンを押しました。

↑なんて、簡単に書いてますが、↓こんな感じで試行錯誤・長い道のりでした。
03/28 INPUTタグ から オッズのボタンを探す : http://www.youtube.com/watch?v=1uKxrpIMEQE

単・複・枠連オッズ を 選択する

次は、単・複・枠連オッズ の 選択です。

<SELECT name="g">
  <OPTION value="Ota01">単・複・枠連オッズ</OPTION>
  <OPTION value="Oum01" selected>馬連オッズ</OPTION>
  <OPTION value="Out01">馬単オッズ</OPTION>  

↑ここから、単・複・枠連オッズ を 選択したいです。

タグがSELECTで名前が"g"かぁ

手前味噌サンプルですが、
http://www.ken3.org/cgi-bin/group/vba_ie_form.asp#Select_Value'Form(0) の アイテム(名前がKUBUN) の 値(.Value) を 24Hにする(24Hを選択する)
    objIE.Document.Forms(0).Item("KUBUN").Value = "24H"
でセットできました。

これを応用して、

    'SELECT タグから 単・複・枠連オッズ を 選択
    Dim tagSELECT As Object  'タグ保存用
    Set tagSELECT = Me.WebBrowser1.Document.all.tags("SELECT")  'SELECTのタグを抜き出す
    tagSELECT.Item("g").Value = "Ota01"  'アイテム g に Ota01 を セット、選択されている値を直接代入で変更

で、セットしました。

次は、決定ボタンを押したいので、決定ボタンのフォームを探します。
わざわざ、難しくすることも無いのですが、
<Form>
 <タグA>
 <タグB>
 <SELECT name="g">
   <OPTION value="Ota01">単・複・枠連オッズ</OPTION>
みたいに、階層構造になっているので、
tagSELECT.Item("g") の 上、上、上、と<FORM>まで、親のオブジェクトをたどります。
※これも手前味噌なんだけど、
  [No.180 IE操作 .parentElement で親のタグを参照?]
  http://www.ken3.org/vba/backno/vba180.html
  で、 .parentElement で親のタグを参照できたので、
 .TagNameが"FORM"となるまで、探り、.Submitしてみます。

    '上の階層、Formを探して、.Submitする。
    Dim objOYA_TAG As Object    '親のオブジェクトを入れる
    Set objOYA_TAG = tagSELECT.Item("g").parentElement
    While objOYA_TAG.tagname <> "FORM"  'タグの名前がFORMになるまで(FORM以外の間まわる)
        Set objOYA_TAG = objOYA_TAG.parentElement  'さらに、一つ上の親タグを代入
    Wend
    objOYA_TAG.Submit   '上へ行き、見つけたフォームを.Submit 送信処理

↑なんか、無理やり 作った感があるなぁ・・・
※後で直しておこう。。今回も無理やり .parentElement を使いました。
03/29 SELECTタグ 単・複・枠連オッズ を 選択 : http://www.youtube.com/watch?v=RDrrHMwQ4Ho

終わりの挨拶

いいところで、終わってしまった。。。
続きは、→[2009-04-05 表の取り込みへ]
最新情報と作成履歴は→[更新履歴と最新を表示]


ページフッター リンクや広告、質問送信など

三流解説を読んでいただき、どうもです。ここから下は、三流君宛のメッセージ送信や 三流君のホームページの紹介・案内です
目的の情報が見つかったか?少々心配しつつ、、、※質問や感想は、気軽に送ってくださいね。

質問や要望など メッセージを送る(三流君に連絡する)

三流プログラマーのKen3 が 皆さんの質問にお答えします
と カッコつけて言っても、実力不足ですべての質問に回答することはできないのが現実なのですが、できる範囲で 三流的な逃げ手 や 解決方法 を探します(回答します)。

感想や質問・要望・苦情など 三流君へメッセージを送る。
時間的余裕のある要望・質問・苦情の場合は、下記のフォームからメッセージを送ることができます。
あなたのお名前(ニックネーム):さん
返信は?: 不用(HP更新を待つ) , E-mail→ アドレス:に返事をもらいたい



(感想や質問・要望 メッセージはHPで記事に載せることがあります。)

急ぎで連絡がほしい、そんな時は:[三流君連絡先]に連絡してください。

IE関係、VBA関係 の 三流君のホームページの紹介・案内

[IE操作 三流解説のトップページへ 戻る] / [IE操作の三流サンプル一覧へ 戻る]

[三流君 VBAでWebBrowser IEを操作する] / [三流君 VBAで楽しくプログラミング] / [AB型の変わり者 三流プログラマー Ken3 三流君Top]

F1でヘルプを見たり、デバック時にDebug.Print使ったり、イミディエイト ウインドウで簡単な確認したり。
なれると当たり前に操作している方法が↓かなぁ。
[F1ヘルプ マクロ記録ほか]・・・基本のF1を押してヘルプを見る方法など
[実行時エラー、デバッグモード]・・・デバッグの流れを簡単に(ハマった時はツライけど)
[イミディエイト ウインドウ と Debug.Print]・・・プログラム作成時に便利なイミディエイト ウインドウ
[VBA ウォッチ式とSTOPを使ってみた]・・・STOPで止め、ウォッチ式でオブジェクトの中身を確認する方法など
[参照設定のお話]・・・設定すると便利な(設定しないと使えない)、参照設定のお話

項目別に↓にプログラマーの本音?それとも建て前?的な記事をまとめました。お探しのジャンルを選択してください。
[プログラムは心? spirit]・・・プログラマー 心・気質・魂
[学ぶ study]・・・学習、技術の取得
[仕様書 doc]・・・仕様書・設計書関係の話

項目別に↓に人気の記事をまとめてみました。お探しのジャンルを選択してください。
[VBAでIE ウェブブラウザーを操作]・・・VBAでIE,WebBrowserを操作する サンプルです
[MSアクセス から エクセル を呼ぶ Excel.Application]・・・AccessからExcelを操作したりデータの書き出しなどです
[アウトルック メールの操作 Outlook.Application]・・・VBAからOutlookを使い、メール関係を処理するサンプルです
↑上記3つみたいなCreateObjectで他のアプリケーションを操作するサンプルが人気です。

Excel関係:
[エクセル ユーザーフォームを操作する]・・・エクセルでユーザーフォームを作成して入力などを行ってます
[エクセルからアクセスを操作する]・・・ExcelからAccessのマクロを起動してみました、
[エクセル関係 関数、その他]・・・その他Excel関係です

Access関係:
[アクセス ユーザーフォーム/サブフォーム 操作]・・・アクセスでフォームを使ったサンプルです
[アクセス レポート操作]・・・レポートを操作してみました
[アクセス クエリーやその他関数]・・・あまりまとまってませんが、スポット的な単体関数の解説です

その他:VBAの共通関数やテキストファイルの操作など
[テキストファイルの操作(Open,Close,Print,Input)]・・・普通のテキストファイルを使ったサンプルです

Blog:[三流君の作業日記]/ [objIEを使用したサンプルコードを見る]/ 広告-[通販人気商品の足跡]



[トップページへ 戻る] / [サンプル一覧へ 戻る]