IE 画面を、スクリプトで操作する
目次
Excel マクロ(VBA) や VBScript (WSH) で、インターネット・エクスプローラの画面にデータを入力する方法について、私が体験したものを、備忘録としてまとめています。
ウェブスクレイピング(Web scraping)
https://ja.wikipedia.org/wiki/ウェブスクレイピング
株取引に VBA を使う も参照下さい。
IE を使い続ける
2022年6月15日、Internet Explorer(IE)のサポートが終了しました。
しかし、VBA などのスクリプトでホームページを操作するために、Internet Explorer(IE)が必要になる場面が残ります。
サポート終了以降も、IE を起動したときに下記画面が表示されるだけで、従来通り使い続けることができます。
注: IE を実行しようとしても Microsoft Edge が起動するようになってしまった場合は、OpenInternetExplorer を使ってみて下さい。
注:エッジの IE モードは、IEそのものです。エッジでIEモードを使うと、Windows の[タスクマネージャー]で IE の実行ファイル「iexplore.exe」が動作していることが分かります。
エッジのIEモードでは、IEのプラグインである ActiveX(アクティブエックス)コントロールも利用できます。
https://www.nikkei.com/article/DGXZQOUC2115Z0R21C21A0000000/
Microsoft Edgeで閲覧しているページをInternet Explorerで開くには
https://hamachan.info/win10-edge-iemode/
Edge のIEモードで登録サイトを日数制限なしで自動で開く
https://www.pasoble.jp/tips/automatic-ie-mode.html
Internet Explorer(IE)モードのローカルサイト リストを構成する
https://docs.microsoft.com/ja-jp/deployedge/edge-ie-mode-local-site-list
Microsoft Edgeで特定URLを自動的にIEモードで開く方法【30日間の日付制限無し】
https://www.kit-post.com/edge-ie-mode-1024
EdgeのIEモードの有効期限を無期限にする方法
https://ittrip.xyz/soft/browser/edge-idmode-forever
Internet Explorer(IE)完全終了に備える
https://atmarkit.itmedia.co.jp/ait/articles/2205/11/news021.html#utm_medium=email&utm_source=ait-tsushin&utm_campaign=20220518
参考にさせていただいたサイト
貴重なノウハウを公開していただき、感謝いたします!
三流解説 VBA IE プロパティの一覧
http://ie.vba-ken3.jp/Property/
★VBA便利帳
http://www2s.biglobe.ne.jp/~iryo/
ExcelVBAでIEを自由に操作する
http://www2s.biglobe.ne.jp/~iryo/vba/part4/m4.html
★三流君 VBAで楽しくプログラミング
http://www.ken3.org/vba/
三流君 VBAでIE操作 InternetExplorer.Applicationを操作する
http://www.ken3.org/cgi-bin/group/vba_ie.asp
★VBA WEB上の画像をクリック
http://okwave.jp/qa/q5351296.html
★Microsoft Internet Explorer 5 およびドキュメント オブジェクト モデル
http://msdn.microsoft.com/ja-jp/library/cc326858.aspx
★DHTMLリファレンス
http://msdn.microsoft.com/ja-jp/library/cc409720.aspx
(英語:Internet Explorer Scripting Object Model)
http://msdn.microsoft.com/en-us/library/ms970457.aspx
★とほほのWWW入門
https://www.tohoho-web.com/
ドキュメントオブジェクトモデル(DOM)
https://www.tohoho-web.com/js/dom.htm
★フォーム部品の入力確認
http://www.sm.rim.or.jp/~shishido/chkform.html
Excel VBA の場合は、Microsoft Internet Controls を参照設定
Excel VBA の場合は、
Microsoft Internet Controls と
Microsoft HTML Object Library
を参照設定しておくと、コーディングで、.(ドット)を押したときに、プロパティやメソッドの候補が出てくるので便利です。
参考:
VBAでIE制御するためのライブラリ追加(参照設定)
http://www.vba-ie.net/library/
エクセルVBAでIE(Internet Explorer)を操作する時に役に立つプロシージャまとめ
http://matome.naver.jp/odai/2137349926300192301
三流君VBAでIE操作 まずは、参照設定から
http://www.ken3.org/cgi-bin/group/vba_ie_object.asp
IEを開く
URL もしくは、URL と引数を渡して、インターネット・エクスプローラの画面を開く操作です。
株取引に VBA を使う も参照下さい。
新しい IE ウインドウを開く
Set IEオブジェクト = CreateObject("InternetExplorer.Application")
With IEオブジェクト
.Navigate URL
.Visible = True
End With
Call IE表示待ち
Sub IE表示待ち()
Do While IEオブジェクト.Busy = True Or IEオブジェクト.readystate <> 4
WScript.Sleep 100
Loop
WScript.Sleep 1000
End Sub
VBA での待ちの設定方法は、待ちの設定 を参照下さい。
下は、IE6 と、IE7 以降のタブブラウザを考慮したコードです。
IE7 以降のブラウザでも、タブ・ブラウズを無効にすれば 、一つのコードで動作させることができ、コードが簡単になります。
If IEバージョン > "6" Then
IEオブジェクト.Navigate2 対象URL '★IE7の場合、既存or新しいウィンドウで表示される
If 入力行 = 1 Then
IEオブジェクト.Quit '★IE7の場合、ここで閉じるのはCreateObject で作成したウィンドウ
Set IEオブジェクト = Nothing '★IE7の場合、いったんオブジェクトをクリア
Application.Wait Now + TimeValue("00:00:01")
End If
処理 = "Shell.ApplicationオブジェクトのWindowオブジェクトからIEオブジェクトを取り出す"
'作成されているポイントは、Windowsコレクションの最後の要素
Set IEオブジェクト = Shellオブジェクト.Windows.Item(Shellオブジェクト.Windows.Count - 1)
'これ以降は、従来と同様の方法で操作が可能
Else
IEオブジェクト.Navigate 対象URL '★IE6以前の場合
End If
既存の IE ウインドウに、新しい URL を開く
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run(URL)
開いている IE をつかむ
シェルオブジェクトを使う
シェル(shell32.dll)オブジェクトを使うと、シェルを使っている、ファイルエクスプローラー、コントロールパネル、Internet Explorer などの中から、現在起動中のものをコレクションとして取得できます。
起動済み画面のHTMLを取得する
https://moripro.net/vbaie-gethtml/
TypeNameとShell.Applicationを使い起動済みのIEを探す
http://www.ken3.org/vba/backno/vba156.html
次のコードは、SMBC日興証券オンライントレード売買注文登録 で「受付完了」のポップアップ画面が表示されたかどうかをチェックする部分です。
Dim シェルオブジェクト As Object
Dim ウインドウ As Object
Dim 受付完了 As Boolean
Sleep (1000)
'受付完了をチェック*************ここから
Set シェルオブジェクト = CreateObject("Shell.Application")
受付完了 = False
For Each ウインドウ In シェルオブジェクト.Windows '起動中のウィンドウを順番にみていく
'IEとエクスプローラがシェルで取得されるため、IEのみを対象にする
If TypeName(ウインドウ.Document) = "HTMLDocument" Then
If InStr(ウインドウ.Document.Title, "受付完了") > 0 Then
'約定登録したことを示すため、「注文数」のセル背景を黄緑色にする
Range("E1").Cells(処理行 + 9, 1).Interior.ColorIndex = 4 '黄緑色
受付完了 = True
Exit For
End If
End If
Next
If 受付完了 = False Then
MsgBox "受け付けられませんでした!", vbExclamation
Stop
End If
Set シェルオブジェクト = Nothing
一番後ろの画面と決め付けて取得
下の例は、このサイトのように、フレームを使っているホームページを、単独で開いた場合は、その内容を、上位から開いた場合は、その構成部分を表示するようになっています。
'シェルのオブジェクトを作成する
Set Shellオブジェクト = CreateObject("Shell.Application")
'起動した IE が 必ず 絶対 一番後ろ と決め付けて(プログラマーに絶対は無いだろクソ三流)
Set 開いているIEオブジェクト = Shellオブジェクト.Windows(Shellオブジェクト.Windows.Count - 1)
'↑配列が0からなのでカウント-1 一番後ろのWindowをobjIEに代入
Set Shellオブジェクト = Nothing 'この変数は 三流君みたいにもう用済みなので、バイバイ
'その後、いつものステータスを見ますか。
'開いているIEオブジェクトの表示を待つ
While 開いているIEオブジェクト.readyState <> 4 Or 開いているIEオブジェクト.Busy = True
Sleep (100)
Wend
Sleep (1000)
HTMLソース = 開いているIEオブジェクト.document.body.innerHTML
開いているURL = 開いているIEオブジェクト.LocationURL
フレーム数 = 開いているIEオブジェクト.document.frames .Length
Set Frameオブジェクト = 開いているIEオブジェクト.document.frames
'Debug.Print HTMLソース
'Debug.Print フレーム数
If フレーム数 > 0 Then
' For カウンタ = 0 To フレーム数 - 1
' Debug.Print Frameオブジェクト(カウンタ).Name
' Next カウンタ
' Debug.Print Frameオブジェクト(フレーム数 - 1).document.body.innerText
HTMLソース = Frameオブジェクト(フレーム数 - 1).document.body.innerHTML
開いているURL = Frameオブジェクト(フレーム数 - 1).document.URL
End If
'Debug.Print 開いているIEオブジェクト.Document.body.innerText
frames オブジェクト は、指定されたドキュメント内で定義された全てのwindowオブジェクト、あるいは指定したwindowオブジェクトに関連するドキュメントによって定義されたwindowオブジェクトのコレクションを読み出します。
length プロパティ で、コレクションの中にあるエレメントの数を取得できます。
item メソッド で、指定したコレクションから、エレメントやコレクションを読み出すことができます。
ウインドウハンドルを使う
下記のサイトで、「IE7/IE8で、現在または最後にアクティブなIEを捕捉する」スクリプトを紹介していただいているのを見つけました。
http://app.m-cocolog.jp/t/typecast/221427/189040/59273927
このスクリプトを利用して、IEで現在表示しているURLの、一階層上のURLを開くスクリプト を作ってみました。
ウィンドウの操作 一覧表示
http://www.winapi-database.com/Window/Change/
参考:Windows Scripting Host 23
http://homepage3.nifty.com/aya_js/wsh/wsh23.htm
参考:最前面表示
http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1217957967
参考:ウィンドウハンドル番号を取得する
http://www.happy2-island.com/excelsmile/smile04/capter00302.shtml
参考:VB テクニック編2 - Windows API、ウィンドウハンドル取得、ウィンドウ制御
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_t02.htm
' IEで表示中のURLを取得
Option Explicit
Dim バージョン
Call IEバージョン(バージョン)
If バージョン > 6 Then
'**********************************************************************
' IE7/IE8で、現在または最後にアクティブなIEを捕捉
'Windows Script Programming
'http://app.m-cocolog.jp/t/typecast/221427/189040/59273927
'------------------------------------------------------------------
'Win32APIのFindWindow()を併用すれば、正確に捕捉できます。
Dim ウインドウハンドル
Dim IE
Dim 現在のURL
Dim 表示するURL
'Excel の関数を使った版
ウインドウハンドル = CreateObject("Excel.Application").ExecuteExcel4Macro ("CALL(""user32"",""FindWindowA"",""JCJ"",""IEFrame"",0)")
'SFC mini版 *******ここから******************
'Excel をインストールしていないパソコンの場合は、下 URL の「SFC mini 」をインストールして、
'以下のソース部分6行のコメント を外して、上のExcel版の一行のコードを、コメント・アウトします。
'http://kandk.cafe.coocan.jp/sfcmini/
'参考にさせていただいたサイト「タスクバーを透明化するVBScript」
'http://d.hatena.ne.jp/Shinez/20100121
' Dim FindWindow
' Set FindWindow = CreateObject("SfcMini.DynaCall")
' FindWindow.Declare "user32", "FindWindowA"
' Do Until ウインドウハンドル <> 0
' ウインドウハンドル = FindWindow("IEFrame")
' Loop
'SFC mini版 *******ここまで******************
For Each IE In CreateObject("Shell.Application").Windows()
If ウインドウハンドル = IE.HWND Then
IE.StatusText = CStr(ウインドウハンドル)
' MsgBox IE.StatusText
If IE.StatusText = CStr(ウインドウハンドル) Then Exit For
End If
Next
If IsEmpty(IE) Then
MsgBox "IE6には対応していません。" & vbNewLine & "または、Not Found"
Else
現在のURL = IE.LocationURL ?
' MsgBox IE.LocationURL
End If
'アクティブなIEウィンドウはFindWindow("IEFrame",0)で分かりますが、アクティブなタブは分かりません。
'しかし、StatusTextが変更可能なのはアクティブなタブだけなようなので、それで区別できます。
'**********************************************************************
Else
'**********************************************************************
' アクティブなIE6のURLを取得
'http://d.hatena.ne.jp/md2tak/20090822/p1
Dim Shell, window, activeWin
Set Shell = CreateObject("Shell.Application")
Set activeWin = Shell.Windows.Item
' MsgBox activeWin.document.url
現在のURL = activeWin.document.url ?
Set activeWin = Nothing
Set Shell = Nothing
'**********************************************************************
End If
ExecuteExcel4Macro
みおんこ - ほぼVBメモ
おまいら!ExecuteExcel4Macro がすごいぞ!
http://d.hatena.ne.jp/miopenguin/20070628
『ExecuteExcel4Macroの使用方法』(わかあゆ)
http://www.excel.studio-kazu.jp/kw/20100208214907.html
ExecuteExcel4Macroについて
http://excel-ubara.com/excelvba4/EXCEL219.html
ブックを開かないで読む
http://www.officetanaka.net/excel/vba/tips/tips28.htm
Application.ExecuteExcel4Macro メソッド (Excel)
http://msdn.microsoft.com/ja-jp/library/ff193589.aspx
Excel 2007 以降のバージョンで Application.ExecuteExcel4Macro("get.document(50)") を実行しても正しいページ数が取得できない
http://support.microsoft.com/kb/2838848/ja
html から文字列を取得
(table タグを使って表データを配列に読込む)
以下は、
HTMLソース = IEオブジェクト.Document.Body.InnerHtml
で Body.InnerHtml を HTMLソース として取得したテキストから、必要な文字列を取得しています。
IEオブジェクトを使って、HTMLソースを取得
テキスト・データを取得
も、合わせて参照下さい。
この例では、HTMLの内容をテキストとして扱っています。
まず Split関数 を使って、HTMLソース を行単位に分割して、「文字配列」 に格納します。
そして、「文字配列」 を一行ずつ、キーとなる文字列で検索して、取得したい文字列を含む、対象行を摘出します。
摘出した行に対して、正規表現文字列置換して、html タグを取り除いて、必要な文字列だけを、配列(ここでは、ヘッダ配列(ヘッダ項目数) )に格納しています。
正規表現で置換
http://codezine.jp/article/detail/1655?p=3
で公開いただいている、「正規表現置換関数」を使って、html のタグを取り除いて、必要な文字列を抽出しています。
正規表現を使う場合は、参照設定を追加 します。
HTMLの内容を、DOM(Document Object Model)として、HTMLドキュメント要素にアクセスして、操作やデータ取得する例 も、参照下さい。
Option Explicit
Option Base 1
Dim ヘッダ配列(10)
Dim 配列(20, 30)
Dim HTMLソース As String
Dim 最終行 As Integer
Dim As Integer
Dim 品番 As String
Dim 日付 As String
Dim 追加シート名 As String
Dim 行 As Integer
Dim 開始行 As Integer
Dim IEオブジェクト As Object
Dim 出力行 As Integer
Dim 出力行数 As Integer
Dim 正規表現オブジェクト As RegExp
Dim カウンタ As Integer
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'これで Sleepを使ってミリ秒単位で処理にウェイトを入れることができます。
Sub 品番供給ルート参照()
Dim URL As String 'URL
Dim URL中 As String
Dim 環境 As Integer
Dim 開始日時 As Variant
Dim 終了日時 As Variant
開始日時 = Now ' 開始時刻を変数に格納します。
' 処理を高速化するため、画面描画停止、自動計算停止
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Call 書き出しシート作成
ThisWorkbook.Worksheets("スタート").Activate
環境 = Range("F2").Value
開始行 = Range("G5").Value
If 環境 = 1 Then 'インターネット
URL = "http://company.co.jp/test.do?EVENT_ID=E02&inputPn="
Else 'イントラネット
URL = "http://company.net/test.do?EVENT_ID=E02&inputPn="
End If
URL中 = "&inputDate="
最終行 = Cells(ActiveSheet.Rows.Count, 2).End(xlUp).Row
' = 0
出力行 = 2
For 行 = 6 To 最終行
品番 = Range("B1").Cells(開始行 + 行 - 6, 1).Value
If 品番 = "" Then
Exit For
End If
品番 = Replace(品番, "#", "%23") '★ #をエンコード
品番 = Replace(品番, "+", "%2b") '★ +をエンコード
日付 = Format(Date, "yyyy/mm/dd")
'Webページ表示
Set IEオブジェクト = CreateObject("InternetExplorer.Application")
With IEオブジェクト
.Navigate URL & 品番 & URL中 & 日付
.Visible = True
End With
Call IE表示待ち
Call 待ち(1)
Call IE表示待ち
Call 待ち(8)
'表示したページの<BODY>部のHTMLを取得し、イミディエイト・ウインドウに表示
HTMLソース = IEオブジェクト.Document.Body.InnerHtml
Debug.Print HTMLソース
= + 1
Call テーブルデータ抽出
IEオブジェクト.Quit
Call 書き出し
ThisWorkbook.Worksheets("スタート").Activate
Range("G5").Value = 開始行 + 行 - 6
Next 行
Set IEオブジェクト = Nothing
' 画面描画再開、自動計算停止解除
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
ThisWorkbook.Worksheets(追加シート名).Activate
終了日時 = Now
MsgBox "処理時間は、" _
& Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。"
End Sub
Private Sub テーブルデータ抽出()
Dim 文字配列
Dim ページ行数 As Integer
Dim 行文字列 As String
Dim 行数 As Integer
Dim 出力列数 As Integer
Dim 読み込み対象 As String
Dim ヘッダ項目数 As Integer
'1行ずつに分割
文字配列 = Split (HTMLソース , vbNewLine )
'全体行数を取得
ページ行数 = UBound(文字配列)
If ページ行数 = 0 Then
Erase 文字配列
'1行ずつに分割
文字配列 = Split (HTMLソース, vbLf ) '★★★ HTML の改行が Lf (UNIX系OS)の場合にも対応 ★★★
'全体行数を取得
ページ行数 = UBound(文字配列)
End If
'1行目から順に、最後の行まで
読み込み対象 = ""
出力列数 = 0
ヘッダ項目数 = 0
出力行数 = 0
Erase ヘッダ配列
Erase 配列
For 行数 = 1 To ページ行数
行文字列 = 文字配列(行数)
Debug.Print 行数
Debug.Print 行文字列
If InStr (行文字列, "該当品番が存在しません") _
Or InStr (行文字列, "There is no corresponding record") Then
配列(1, 1) = "該当品番が存在しません。"
ElseIf InStr (行文字列, "該当するレコードはありません") Then
配列(1, 1) = "該当するレコードはありません。"
ElseIf InStr (行文字列, "入力された品番は存在しません") Then
配列(1, 1) = "入力された品番は存在しません。"
ElseIf InStr (行文字列, "構成情報が存在しません") Then
配列(1, 1) = "構成情報が存在しません。"
End If
'★★★★ヘッダ部★★★★
If 行数 > 60 And 行数 < 75 Then
If InStr (行文字列, "width35per inputzone nowrap") > 0 Then '品名
ヘッダ項目数 = 1
ヘッダ配列(ヘッダ項目数) = Trim(正規表現で置換 ("<(.*?)> ", 行文字列, ""))
ElseIf InStr (行文字列, "width07per inputzone nowrap") > 0 Then '品目コード
ヘッダ項目数 = 2
ヘッダ配列(ヘッダ項目数) = Trim(正規表現で置換 ("<(.*?)> ", 行文字列, ""))
ElseIf InStr (行文字列, "width04per inputzone nowrap") > 0 Then '分類コード
ヘッダ項目数 = 3
ヘッダ配列(ヘッダ項目数) = Trim(正規表現で置換 ("<(.*?)> ", 行文字列, ""))
ElseIf InStr (行文字列, "width05per inputzone nowrap") > 0 Then '対象
ヘッダ項目数 = 4
ヘッダ配列(ヘッダ項目数) = Trim(正規表現で置換 ("<(.*?)> ", 行文字列, ""))
ElseIf InStr (行文字列, "width06per inputzone nowrap") > 0 Then 'DC
ヘッダ項目数 = 5
ヘッダ配列(ヘッダ項目数) = Trim(正規表現で置換 ("<(.*?)> ", 行文字列, ""))
End If
'★★★★検索結果部★★★★
ElseIf 行数 >= 80 Then
'レコード無しは、出力行を1行設定して終わる
If 出力行数 = 0 And 配列(1, 1) <> "" Then
出力行数 = 1
Exit For 'Body 読み込みを終わる
End If
If 出力行数 > 0 And InStr (UCase (行文字列), "</TABLE> ") > 0 Then '検索結果のテーブルが終わった
'タグが小文字の時にも対応できるように UCase する
Exit For 'Body 読み込みを終わる
End If
'検索結果の行数を取得
If InStr (UCase (行文字列), "<TR ") > 0 Then
' 行データ開始
出力行数 = 出力行数 + 1
出力列数 = 0
End If
If 出力行数 > 0 And InStr (UCase (行文字列), "<TD " & Chr(34) & UCase ("fontsizesmall")) > 0 Then
'列データを配列に格納
出力列数 = 出力列数 + 1
If 出力列数 > 16 Then
Exit For 'Body 読み込みを終わる
End If
配列(出力行数, 出力列数) = Trim(Replace(正規表現で置換 ("<(.*?)> ", 行文字列, ""), vbTab , ""))
'空白が、スペースではなく Tab の場合にも対応
End If
End If
Next 行数 'html の Body データを一行ごとに読む
End Sub
'正規表現で置換
'http://codezine.jp/article/detail/1655?p=3
'ツール(T)→参照設定(R)を選択して、表示される画面で、
'「Microsoft VBScript Regular Expressions 5.5」にチェックを付けます。
'[引数]
'検索文字列:置換元の文字列
'正規表現パターン:検索する文字列
'置換文字列 正規表現パターンに ()を使って保存した部分は、置換文字列 $n で呼び出せます。
'[返り値]
'検索文字列内に正規表現パターンが見つかった場合:置換文字列に置き換えた結果を返す
'検索文字列内に正規表現パターンが見つからなかった場合
':検索文字列に変更を加えずそのまま返す
Function 正規表現で置換 (検索文字列 As String, 正規表現パターン As String, 置換文字列 As String) As String
Dim 正規表現 As New RegExp ' 正規表現を作成します。
正規表現.Pattern = 正規表現パターン ' パターンを設定します。
正規表現.Global = True ' 一致するもの全てを対象とするように設定します。
正規表現で置換 = 正規表現.Replace(検索文字列, 置換文字列) ' 置換します。
End Function
正規表現で置換関数を使った文字列置換関数の例:
Function 索引抽出(ByVal 文字列 As String) As String 'ByVal にしないと引数の値が変わってしまう!
'1358174_info_20220408_135717_2.jpg
Dim 正規表現パターン1 As String: 正規表現パターン1 = "([0-9]{6,7}_info_[0-9]{8}).*"
Dim 正規表現パターン2 As String: 正規表現パターン2 = "_.*$"
'1187030_19143894_k3.jpg
'845884_17350365_k3.jpg
Dim 正規表現パターン3 As String: 正規表現パターン3 = "([0-9]{6,7}_[0-9]{8}).*"
文字列 = 正規表現で置換 (文字列, 正規表現パターン1, "$1")
文字列 = 正規表現で置換 (文字列, 正規表現パターン3, "$1")
If InStr(文字列, "jpg") > 0 Or InStr(文字列, "JPG") > 0 Then
文字列 = 正規表現で置換 (文字列, 正規表現パターン2, "")
End If
索引抽出 = 文字列
' Stop
End Function
TABLE の内容をExcel シートに出力
(IEオブジェクトを使って表データを配列に読込む)
この例は、開いているサイトのタイトルを指定して、そのホームページに含まれている表(Table)の内容を、Excel シートに書き出すものです。
Table が入れ子になっている場合は、一番内側の表データを取得することで、Table のネストにも対応しています。
Table タグだけでなく、<OL>タグ(Ordered List)と、<UL>タグ(Unordered List)の内容も、出力対象にしています。
上の例 は、HTMLの内容をテキストとして扱っています。ここでは、DOM(Document Object Model)として扱うことで、HTMLドキュメント要素にアクセスして、操作やデータ取得をしています。
このため、Excel VBA で、下記を参照設定します。
Microsoft Internet Controls
Microsoft HTML Object Library
参考にさせていただいたサイト:
ドキュメントオブジェクトモデル(DOM)について
http://hakuhin.jp/js/dom.html
DOM(Document Object Model)の基本
http://javascript123.seesaa.net/article/129066563.html
HTML DOM Table rows,cellsコレクション
http://javascript123.seesaa.net/article/199403038.html
ExcelVBA.net タグ要素の取得
http://excel-vba.net/excel-ie-004.html
VBAでHTMLのTableタグ内データを取得する
http://oirnao.blogspot.jp/2011/07/vbahtmltable.html
VBAでIE(InternetExplorer)のHTMLコードを取得する
http://www.vba-ie.net/element/html-text.html
VBAのIEエレメント実践操作
http://www.vba-ie.net/element/practice.html
VBAでHTMLドキュメントの要素数を取得
http://www.vba-ie.net/element/document-all2.html
VBAでtable要素のデータを取得
http://www.vba-ie.net/element/table.html
VBAでtable要素のセルを取得
http://www.vba-ie.net/element/rowscells.html
VBAでIEの親要素と子要素を取得
http://www.vba-ie.net/element/parent-children.html
VBAで画像要素を取得するImagesプロパティ
http://www.vba-ie.net/element/image.html
IEを使用して、Web上の表をExcelへ
http://www.ken3.org/vba/backno/vba119.html
三流君VBA:VBAからIE操作 TABLEの中にTABLE
http://www.ken3.org/vba/backno/vba177.html
JavaScript/DOM ≫ Tableオブジェクト
http://phpjavascriptroom.com/?t=js&p=tableobject
JavaScript/DOM ≫ Cellオブジェクト
http://phpjavascriptroom.com/?t=js&p=cellobject
JavaScript/DOM ≫ Rowオブジェクト
http://phpjavascriptroom.com/?t=js&p=rowobject
innerText、innerHTML、outerText、outerHTMLは何がちがう
http://www.makoto3.net/dhtml_ie/dhtml_ie0016.html
【Excel VBA備忘ログ】FRAMEを持つサイトの構造を調べるには
http://tandyco.cocolog-nifty.com/blog/2008/05/excel_vbaframe_8cda.html
Option Explicit
Option Base 1
Dim IEオブジェクト As InternetExplorer
Dim カウンタ As Integer
Dim HTML文書 As HTMLDocument
Dim テーブル数 As Integer
Public Sub 開いているホームページの表データを取得()
Dim タイトル As String
Dim 開始日時 As Variant
Dim 終了日時 As Variant
Dim シート As Worksheet
タイトル = InputBox("対象画面のタイトル文字列の一部を入力してください")
If タイトル <> "" Then
Set IEオブジェクト = ウインドウを特定(タイトル) 'ウインドウをIEオブジェクトとして取得
End If
If IEオブジェクト Is Nothing Then
MsgBox "タイトル未入力または対象画面が見つかりません"
Exit Sub
End If
開始日時 = Now ' 開始時刻を変数に格納します。
'前回表データを取得して作成したシートがあれば削除
For Each シート In ThisWorkbook.Worksheets
If シート.Name <> "Sheet1" Then
'シート名 Sheet1 以外のシートを削除
Application.DisplayAlerts = False
シート.Delete
Application.DisplayAlerts = True
End If
Next シート
テーブル数 = 0
Set HTML文書 = IEオブジェクト.Document 'HTML文書をDOMとして取得
Call HTMLの表データを取得
Set HTML文書 = Nothing
Set IEオブジェクト = Nothing
終了日時 = Now
MsgBox "処理時間は、" _
& Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。"
End Sub
Private Sub HTMLの表データを取得()
For カウンタ = 0 To HTML文書.all.Length - 1
If UCase(HTML文書.all(カウンタ).tagName) = "TABLE" Then
'表の開始
If InStr(UCase(HTML文書.all(カウンタ).innerHTML), "<TABLE") = 0 Then
'表の入れ子の親は除外
Call 表のデータをシートに書き出し
End If
ElseIf UCase(HTML文書.all(カウンタ).tagName) = "OL" _
Or UCase(HTML文書.all(カウンタ).tagName) = "UL" Then
Call 表のデータをシートに書き出し
End If
Next カウンタ
End Sub
Private Sub 表のデータをシートに書き出し()
Dim 表のデータ配列(1000, 1000) As Variant
Dim 列数 As Integer
Dim 行数 As Integer
Dim 表内カウンタ As Integer
行数 = 0
For 表内カウンタ = カウンタ + 1 To HTML文書.all.Length - 1
'表の場合
If UCase(HTML文書.all(表内カウンタ).tagName) = "TR" Then
'表の行の開始
Debug.Print 表内カウンタ, "TR"
行数 = 行数 + 1
列数 = 0
ElseIf UCase(HTML文書.all(表内カウンタ).tagName) = "TD" _
Or UCase(HTML文書.all(表内カウンタ).tagName) = "TH" Then
'表のセルの開始
Debug.Print 表内カウンタ, "TD or TH"
列数 = 列数 + 1
表のデータ配列(行数, 列数) = HTML文書.all(表内カウンタ).innerText
ElseIf UCase(HTML文書.all(表内カウンタ).tagName) = "LI" Then
'Ordered List と Unordered List の場合
行数 = 行数 + 1
列数 = 1
表のデータ配列(行数, 列数) = HTML文書.all(表内カウンタ).innerText
ElseIf UCase(HTML文書.all(表内カウンタ).tagName) = "TABLE" _
Or UCase(HTML文書.all(表内カウンタ).tagName) = "OL" _
Or UCase(HTML文書.all(表内カウンタ).tagName) = "UL" Then
'次の表の開始
Exit For
End If
Next 表内カウンタ
'シートを追加
If UCase(HTML文書.all(カウンタ).tagName) = "TABLE" Then
テーブル数 = テーブル数 + 1
Worksheets.Add after:=Worksheets(テーブル数) 'Table の出力シートは左(Sheet1に近く)にする
Else
Worksheets.Add after:=Worksheets(Worksheets.Count)
End If
ActiveSheet.Name = UCase(HTML文書.all(カウンタ).tagName) & Space(1) & ActiveSheet.Name
'取得した表データを貼付け
Range("A1").Resize(行数, 列数) = 表のデータ配列
Cells.EntireColumn.AutoFit '列幅を自動調整
Cells.VerticalAlignment = xlTop
カウンタ = 表内カウンタ - 1
End Sub
Private Function ウインドウを特定(引数タイトル As String) As InternetExplorer
Dim IEオブジェクト As InternetExplorer
Dim シェル As Object
Dim ウインドウ As Object
Dim タイトル As String
Set シェル = CreateObject("Shell.Application")
For Each ウインドウ In シェル.Windows
タイトル = ""
On Error Resume Next
タイトル = ウインドウ.Document.Title
On Error GoTo 0
If InStr(タイトル, 引数タイトル) > 0 Then
Set IEオブジェクト = ウインドウ
Exit For
End If
Next
Set ウインドウを特定 = IEオブジェクト
End Function
TABLE の内容をExcel シートに出力
(URLから 直接 HTMLDocument を取得して、表データを配列に読込む)
URL を指定して、直接 HTMLDocument オブジェクトを作成できることを、下記のサイトで教えていただきました。
VBAでWebページを取得する方法
http://so-zou.jp/software/tech/programming/vba/sample/web.htm#no3
教えていただいた方法を使うと、IEオブジェクトを使う より少し高速に処理できました。
この例は、サイトの URL を指定して、そのホームページに含まれている表(Table)の内容を、Excel シートに書き出すものです。
Table が入れ子になっている場合は、一番内側の表データを取得することで、Table のネストにも対応しています。
Table タグだけでなく、<OL>タグ(Ordered List)と、<UL>タグ(Unordered List)の内容も、出力対象にしています。
マクロを作成する時には、参照設定で[Microsoft HTML Object Library]を参照する必要があります。
インターネットから株価を取得3 (createDocumentFromUrl を使う) も参照下さい。
その他参考サイト:
MSHTMLを参照設定後、As HTMLDocument と.createDocumentFromUrlで文章を読み込み使うテスト
http://d.hatena.ne.jp/ken3memo/20090904/1252025888
HTML 内の URL 解析
http://osuna.hatenablog.jp/entry/2011/11/06/130853
VBAでHTMLをダウンロードしてタグ解析する方法
http://tiger-ti.jugem.jp/?eid=2
Option Explicit
Option Base 1
Dim カウンタ As Integer
Dim テーブル数 As Integer
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'これで Sleepを使ってミリ秒単位で処理にウェイトを入れることができます。
Sub 開いているホームページの表データを取得()
Dim 対象URL As String
Dim 開始日時 As Variant
Dim 終了日時 As Variant
Dim シート As Worksheet
Dim フレーム数 As Integer
Dim フレームカウンタ As Integer
Dim フレーム文書 As HTMLDocument
Dim HTML文書 As HTMLDocument
Dim 対象HTMLDocument As HTMLDocument
Dim ループ回数 As Integer
開始日時 = Now ' 開始時刻を変数に格納します。
対象URL = ThisWorkbook.Worksheets("Sheet1").Range("A2").Value
'前回表データを取得して作成したシートがあれば削除
For Each シート In ThisWorkbook.Worksheets
If シート.Name <> "Sheet1" Then
'シート名 Sheet1 以外のシートを削除
Application.DisplayAlerts = False
シート.Delete
Application.DisplayAlerts = True
End If
Next シート
テーブル数 = 0
'URLからHTMLDocument を取得する
Set 対象HTMLDocument = New HTMLDocument
Set HTML文書 = 対象HTMLDocument.createDocumentFromUrl(対象URL, vbNullString) 'HTML文書をDOMとして取得
' ダウンロード待ち
ループ回数 = 0
Do While HTML文書.readyState <> "complete"
DoEvents ' Sleep しているときに、画面を書き換えできるように、OS に制御を渡す。
Sleep (100)
ループ回数 = ループ回数 + 1
Range("H1").Value = ループ回数
If ループ回数 > 1000 Then
MsgBox "サイトのデータ取得に時間がかかっているので、一旦 中断します"
Exit Sub
End If
Loop
'フレーム数をカウント
フレーム数 = HTML文書.frames.Length
'指定したURL直下のフレーム数(3つなら3を返す)
'0 ならフレームを使用していない。
If フレーム数 = 0 Then
Call HTMLの表データを取得(HTML文書)
Else
For フレームカウンタ = 0 To フレーム数 - 1
Set フレーム文書 = HTML文書.frames(フレームカウンタ).document
Call HTMLの表データを取得(フレーム文書)
Set フレーム文書 = Nothing
Next フレームカウンタ
End If
Set HTML文書 = Nothing
Set 対象HTMLDocument = Nothing
終了日時 = Now
MsgBox "処理時間は、" _
& Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。"
End Sub
Private Sub HTMLの表データを取得(コンテナ As HTMLDocument)
Dim DOM文書 As HTMLDocument
Set DOM文書 = コンテナ
For カウンタ = 0 To DOM文書.all.Length - 1
If UCase(DOM文書.all(カウンタ).tagName) = "TABLE" Then
'表の開始
If InStr(UCase(DOM文書.all(カウンタ).innerHTML), "<TABLE") = 0 Then
'表の入れ子の親は除外
Call 表のデータをシートに書き出し(DOM文書)
End If
ElseIf UCase(DOM文書.all(カウンタ).tagName) = "OL" _
Or UCase(DOM文書.all(カウンタ).tagName) = "UL" Then
Call 表のデータをシートに書き出し(DOM文書)
End If
Next カウンタ
Set DOM文書 = Nothing
End Sub
Private Sub 表のデータをシートに書き出し(コンテナ As HTMLDocument)
Dim 表のデータ配列(1000, 1000) As Variant
Dim 列数 As Integer
Dim 行数 As Integer
Dim 表内カウンタ As Integer
Dim 最終列 As Integer
Dim DOM文書 As HTMLDocument
Set DOM文書 = コンテナ
行数 = 0
For 表内カウンタ = カウンタ + 1 To DOM文書.all.Length - 1
'表の場合
If UCase(DOM文書.all(表内カウンタ).tagName) = "TR" Then
'表の行の開始
Debug.Print 表内カウンタ, "TR"
行数 = 行数 + 1
列数 = 0
ElseIf UCase(DOM文書.all(表内カウンタ).tagName) = "TD" _
Or UCase(DOM文書.all(表内カウンタ).tagName) = "TH" Then
'表のセルの開始
Debug.Print 表内カウンタ, "TD or TH"
列数 = 列数 + 1
表のデータ配列(行数, 列数) = DOM文書.all(表内カウンタ).innerText
'カッコつき数字 (1) などがExcelシートでマイナス数とならないようにする。
If Left(表のデータ配列(行数, 列数), 1) = "(" _
And Right(表のデータ配列(行数, 列数), 1) = ")" Then
表のデータ配列(行数, 列数) = "'" & 表のデータ配列(行数, 列数)
End If
If 表のデータ配列(行数, 列数) = "" Then
If InStr(UCase(DOM文書.all(表内カウンタ).innerHTML), "ALT") > 0 Then
'セルのテキストが空白のとき、alt 情報があれば、これを取得する
If UCase(DOM文書.all(表内カウンタ + 1).tagName) = "IMG" _
Or UCase(DOM文書.all(表内カウンタ + 1).tagName) = "INPUT" Then
表のデータ配列(行数, 列数) = DOM文書.all(表内カウンタ + 1).alt
ElseIf UCase(DOM文書.all(表内カウンタ + 2).tagName) = "IMG" _
Or UCase(DOM文書.all(表内カウンタ + 2).tagName) = "INPUT" Then
表のデータ配列(行数, 列数) = DOM文書.all(表内カウンタ + 2).alt
End If
End If
End If
If 表のデータ配列(行数, 列数) = "" Then
If InStr(UCase(DOM文書.all(表内カウンタ).innerHTML), "SRC") > 0 Then
'セルのテキストが空白のとき、alt 情報が無ければ SRC を取得する
If UCase(DOM文書.all(表内カウンタ + 1).tagName) = "IMG" _
Or UCase(DOM文書.all(表内カウンタ + 1).tagName) = "INPUT" Then
表のデータ配列(行数, 列数) = DOM文書.all(表内カウンタ + 1).src
ElseIf UCase(DOM文書.all(表内カウンタ + 2).tagName) = "IMG" _
Or UCase(DOM文書.all(表内カウンタ + 2).tagName) = "INPUT" Then
表のデータ配列(行数, 列数) = DOM文書.all(表内カウンタ + 2).src
End If
End If
End If
ElseIf UCase(DOM文書.all(表内カウンタ).tagName) = "LI" Then
'Ordered List と Unordered List の場合
行数 = 行数 + 1
列数 = 1
表のデータ配列(行数, 列数) = DOM文書.all(表内カウンタ).innerText
ElseIf UCase(DOM文書.all(表内カウンタ).tagName) = "TABLE" _
Or UCase(DOM文書.all(表内カウンタ).tagName) = "OL" _
Or UCase(DOM文書.all(表内カウンタ).tagName) = "UL" Then
'次の表の開始
Exit For
End If
Next 表内カウンタ
'シートを追加
If UCase(DOM文書.all(カウンタ).tagName) = "TABLE" Then
テーブル数 = テーブル数 + 1
Worksheets.Add after:=Worksheets(テーブル数) 'Table の出力シートは左(Sheet1に近く)にする
Else
Worksheets.Add after:=Worksheets(Worksheets.Count)
End If
ActiveSheet.Name = UCase(DOM文書.all(カウンタ).tagName) & Space(1) & ActiveSheet.Name
'取得した表データを貼付け
Range("A1").Resize(行数, 列数) = 表のデータ配列
Cells.EntireColumn.AutoFit '列幅を自動調整
Cells.VerticalAlignment = xlTop
'列幅が50を超える場合は、50に狭める
最終列 = ActiveSheet.UsedRange.Find("*", , xlFormulas, , xlByColumns, xlPrevious).Column
For 列数 = 1 To 最終列
If Columns(列数).ColumnWidth > 50 Then
Columns(列数).ColumnWidth = 50
End If
Next 列数
カウンタ = 表内カウンタ - 1
Set DOM文書 = Nothing
End Sub
Titleと見出しを取得
VBAで開いているページのタイトルを取得する
https://www.vba-ie.net/element/title.php
処理CのDocumentオブジェクトのtitleプロパティが一番処理が速い
h1タグのなかの文字列「タイトル1」だけを取ってきたいような場合はtextContentというプロパティを使います。
textContentというプロパティを使えば、指定した要素のテキスト部分のみを取り出すことができます。
https://developer.mozilla.org/ja/docs/Web/API/Node/textContent
VBAによるIE自動制御
https://vba-code.net/ie/about/
ページのタイトルを取得する
https://vba-code.net/ie/get-page-title/
いつも隣にITのお仕事
https://tonari-it.com/
【エクセルVBAでIE操作】
エクセルVBAでIEを操作してWEBスクレイピング
https://tonari-it.com/ie-setting-navigate/
★【エクセルVBAでIE操作】HTMLタグと要素そしてドキュメントの取得
https://tonari-it.com/vba-ie-html-document/
下記のマクロは、このコードをベースにさせて頂きました。
VBAでIEを操る (DOMから要素を取得)
http://kouten0430.hatenablog.com/entry/2018/08/16/135207
HTMLタグと要素そしてドキュメントの取得
https://tonari-it.com/vba-ie-html-document/
ブラウザの読み込み待ちをしないとダメなのです
https://tonari-it.com/vba-ie-wait/
hタグなどの要素をタグ名でGetする
https://tonari-it.com/vba-ie-get-tagname/
Option Explicit
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
'これで Sleepを使ってミリ秒単位で処理にウェイトを入れることができます。
Dim 最終行 As Integer
Dim 処理行 As Integer
Dim URL As String
Dim タイトル As String
Dim ヘッダー As String
Sub セルに登録したURLのタイトルとヘッダーを取得()
Dim 開始日時 As Variant
Dim 終了日時 As Variant
開始日時 = Now ' 開始時刻を変数に格納します。
ThisWorkbook.Worksheets("Sheet1").Activate
最終行 = ActiveSheet.UsedRange.Find("*", , xlFormulas, , xlByRows, xlPrevious).Row
For 処理行 = 2 To 最終行
URL = Range("A1").Cells(処理行, 1).Value
Call タイトルとヘッダーを取得
Range("B1").Cells(処理行, 1).Value = タイトル
Range("C1").Cells(処理行, 1).Value = ヘッダー
Next 処理行
終了日時 = Now
MsgBox "処理を終了しました。" & vbNewLine & "処理時間は、" _
& Format(終了日時 - 開始日時, "hh時間nn分ss秒") & " でした。"
End Sub
Private Sub タイトルとヘッダーを取得()
Dim IEオブジェクト As Object 'IEオブジェクトを準備
Dim HTMLドキュメント As Object 'HTMLドキュメントオブジェクトを準備
Dim HTMLエレメントコレクション As Object 'IHTMLエレメントコレクションを準備
Set IEオブジェクト = CreateObject("Internetexplorer.Application") '新しいIEオブジェクトを作成してセット
IEオブジェクト.Visible = True 'IEを表示
IEオブジェクト.navigate URL 'IEでURLを開く
Do While IEオブジェクト.Busy = True Or IEオブジェクト.readyState <> 4 '読み込み待ち
DoEvents
Sleep (1000)
Loop
Set HTMLドキュメント = IEオブジェクト.document 'objIEで読み込まれているHTMLドキュメントをセット
'タイトルを取得
タイトル = IEオブジェクト.document.Title
Set HTMLエレメントコレクション = HTMLドキュメント.getElementsByTagName("h1") 'HTMLドキュメント内のh1要素をコレクションとしてGet
ヘッダー = HTMLエレメントコレクション(0).innerText '一つ目の T1 のテキストを取得
Set HTMLエレメントコレクション = Nothing
Set HTMLドキュメント = Nothing
DoEvents: Sleep (1000) ' Sleep しているときに、画面を書き換えできるように、OS に制御を渡す。
IEオブジェクト.Quit
DoEvents: Sleep (1000) ' Sleep しているときに、画面を書き換えできるように、OS に制御を渡す。
Set IEオブジェクト = Nothing
DoEvents: Sleep (30000) ' Sleep しているときに、画面を書き換えできるように、OS に制御を渡す。
End Sub
テキスト・ボックスへの入力
通常のテキスト・ボックスへの入力
form の「id」と、要素の「ID」を使って指定します。
<form id="formTrans" method="post" action="/world/english/">
<div class="taFrame">
<div class="taTab">原文</div>
<textarea name="before" id="before" onfocus="javascript:beforeClick();">こちらに翻訳したい文章を入力してください。</textarea>
</div>
</form>
IEオブジェクト.Document.forms("formTrans").before .Value = 文字列
form の「番号」と、要素の「name」を使って指定します。
<form name="GD01021000Form" method="post" action="GD010210.do">
<input type="text" name="inputPn" maxlength="18" size="18" value="" nameforcheck="品目" typeforcheck="withoutKanaAndWC" essentialforcheck="false" maxlengthforcheck="18" onblur="this.value=this.value.toUpperCase();" class="inputenable" />
</form>
IEオブジェクト.document.forms(0)("inputPn").Value = 品目
form の「id」と、要素の item 「name」を使って指定します。
<form action="/text/" id="TranslationForm" name="TranslationForm" method="post">
<textarea id="source-lang-text" name="translateParams.originalText" cols="" rows="" wrap="SOFT" tabindex="0" dir="ltr" >ここに原文を入力してください</textarea>
</form>
IEオブジェクトld.Document.forms("TranslationForm").item("translateParams.originalText").value = 文字列
textarea への文字入力
form を使わない テキスト・ボックスが有ります。
Google 翻訳と DeepL 翻訳がこのタイプです。
<textarea id="source" class= "orig tlid-source-text-input goog-textarea" rows="1" spellcheck="false" autocapitalize="off" autocomplete="off" autocorrect="off" style="overflow: auto hidden; box-sizing: border-box; height: 47px; padding-bottom: 18px;">
</textarea>
<textarea class= "lmt__textarea lmt__source_textarea lmt__textarea_base_style" data-gramm_editor="false" autofocus="" tabindex="110" dl-test="translator-source-input" lang="" style="height: 300px;">
</textarea>
どちらもユニークな class を持っていたので、getElementsByClassName を使ってテキスト入力ができました。
参考にさせていだいたサイト
https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName
https://developer.mozilla.org/ja/docs/Web/API/Element/getElementsByClassName
https://www.sejuku.net/blog/68588
Google と DeepL で翻訳比較
Set objInpTxt = objIE.document.getElementsByClassName _
("orig tlid-source-text-input goog-textarea")(0)
'テキストボックスに値を入力
objInpTxt.Value = 文字列
ファイル名(ファイル・パス)を入力
IEの画面のテキスト・ボックスには、value= で文字を入力できますが、input type="file" の要素の場合は、セキュリティのためこの方法が使えません。
<form name="GUForm" method="POST" action="GU.do" enctype="multipart/form-data">
<input type="hidden" name="EVENT_ID" value="" />
<legend>ファイル選択</legend>
<table summary="" cellspacing="1" cellpadding="1" width="100%">
<tbody>
<tr>
<td class="searcharealabelnecessary nowrap">*アップロードファイル</td>
<td class="inputzone">
<input type="file" name="uploadingFile" size="70" value="" />
</td>
</tr>
</tbody>
</table>
</form>
このため、下記のマクロでは、IEの画面を前面表示させて、SendKeys(キー入力)でファイル・パス名をセットしています。
Set WshShell = CreateObject("Wscript.Shell")
WshShell.AppActivate "ファイルアップロード" 'タイトルが左記で終わるウィンドウを探し、前面に表示させる。
Set WshShell = Nothing
SendKeys ファイル名, True
ところが、IE を、IE8 にアップしたところ、上のマクロが動かなくなりました。
ググッたところ、セキュリティ改善?のため、ファイル名を SendKeys で登録できなくなっていました。
(ファイル名を入力するテキスト・ボックスは、リードオンリー!)
さらにググッてみたら、世の中には、奇特な人がいて、WSHを使って、ファイル名を入力させる方法を紹介していただいているサイトを見つけました。
主に言語とシステム開発に関して
の、「IE8で,ファイルのアップロードを自動化する方法 」です。
http://d.hatena.ne.jp/language_and_engineering/20100909/p1
(このサイトで公開いただいているコードは、他にも利用させていただいています。)
このサイトの管理人さんに連絡する方法が分からないので、無断引用させていただきます。
以下は、上のサイトで公開していただいている JScript の部分を、Excelマクロ(VBA)に書き換えたものです。
注意:パスとファイル名は英数のみ可能です!
' WSHを使って、ファイルを開くダイアログを表示させて、参照フィールドにファイルパスをセットする
Sub type_file_path(IEオブジェクト, 名前 As String, file_path)
Dim WSオブジェクト As Object
Dim objElement As Object
Set WSオブジェクト = CreateObject("WScript.Shell")
'ファイルパス入力欄にフォーカス
Set objElement = IEオブジェクト.document.getElementById(名前)
objElement.Focus
Sleep (1000)
' その右隣にある「参照」ボタンに、WSを使ってフォーカス
WSオブジェクト.SendKeys ("{TAB}")
Sleep (1000)
' SPACEキー押下で,ファイル参照ダイアログを開く
WSオブジェクト.SendKeys (" ")
Sleep (1000)
' ファイルパスをキー入力
WSオブジェクト.SendKeys (file_path)
Sleep (1000)
' ファイルを開くダイアログを閉じる
WSオブジェクト.SendKeys ("{ENTER}")
Sleep (1000)
Set WSオブジェクト = Nothing
End Sub
マウスでクリック
フォームをクリック
何も無ければ、フォームの Submit メソッドを指定します。
IEオブジェクトld.Document.forms("TranslationForm").Submit
ボタンをクリック
all オブジェクトを使って、オブジェクトに含まれている「id」を参照しています。
<form id="formTrans" method="post" action="/world/english/">
<table id="transTextButton" border="0" cellspacing="0" cellpadding="0">
<tr><td><input type="submit" id="t-submit" value="翻訳"/></td></tr>
</table>
<table id="reverseCheck" border="0" cellspacing="0" cellpaddinc="0">
<tr>
<td><input type="checkbox" name="reverse_option" id="reverse_checkbox" value="yes"></td>
<td id="reverseText">再翻訳</td>
</tr>
</table>
</form>
IEオブジェクトEx.Document.forms("formTrans").all ("t-submit").Click
文字列を見つけてクリック
ボタンに name が無い場合は、文字列を見つけてクリックします。
<form name="GD01021000Form" method="post" action="GD010210.do">
<input type="button" value="検索" class="buttonenable" id="E02" onclick="if(doE02(this.form)){doSubmit(this.form,'GD010210.do','E02')};" />
</form>
エレメント(Element)http://www.tohoho-web.com/js/element.htm
For Each Inputタグオブジェクト In IEオブジェクト.document.all.tags ("INPUT") 'Inputのタグを.allから抜く
If Inputタグオブジェクト.Value = "検索" Then '.Value値(ボタンの名称) が 「検索」 か?
Inputタグオブジェクト.Click '見つけたINPUTオブジェクト(ボタン)を.Clickクリックする
Exit For '用が済んだので(見つかったので)ループを抜ける
End If
Next
Call IE表示待ち
リンク・オブジェクトをクリック
この事例は、リンクがフォームの外に有る場合です。
<div class="r-boxes-middle" id="active-memo">
<a href="#" id="goTaiyaku" >対訳表示</a>
<form action="/world/english/taiyaku/" method="post" name="formTaiyaku" id="formTaiyaku" target="_blank">
<input type="hidden" name="wb_lp" id="go-wb_lp" value=""/>
<input type="hidden" name="before" id="go-before" value=""/>
</form>
</div>
要素を参照する方法には、次の4つがあります。
getElementById():id 属性で指定した名前で要素を参照します。
getElementsByName():タグ名から要素リスト を参照します。
getElementsByTagName():name 属性で指定した名前で要素リスト を参照します。
getElementsByClassName() :与えられたクラス名で得られる要素の集合を返します。
http://www.tohoho-web.com/js/dom.htm
https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName
HtmlDocument.GetElementById メソッド
http://msdn.microsoft.com/ja-jp/library/cc190057(VS.95).aspx
Set Linkオブジェクト = IEオブジェクト.Document.getElementById ("goTaiyaku") '対訳表示のリンク
Linkオブジェクト.click()
次は、リンクの文字列を探して、クリックする例です。
<a href="http://www.webranking.net/ranking.cgi?id=174519" target="_blank">WEB RANKING PC関連</a>
links オブジェクトは、ドキュメント内の HREF= 属性および AREA エレメントを指定している、全ての A エレメントのコレクションを、読み出します。
LinkID = "http://www.webranking.net/ranking.cgi?id=174519"
For Each Linkオブジェクト In IEオブジェクト.Document.links
If Linkオブジェクト.href = LinkID Then
Linkオブジェクト.Click
Exit For
End If
Next
画像をクリック
画像のファイル名を使って、特定しています。
<p class="changeBtn">
<a href="#" title="言語の入れ替え"><img src ="/img/btn_change.gif " width="22" height="21" alt="" /></a>
</p>
srcプロパティは、イメージが格納されている場所(URL)の値を読み取ったり、設定したり、できます。
For n = 0 To IEオブジェクト.Document.images .Length - 1 'イメージ数ループする。
Set IMGオブジェクト = IEオブジェクト.Document.images(n) 'n番目のイメージを代入
If InStr (IMGオブジェクト.src , "btn_change.gif") > 0 Then '"言語の入れ替え") '合致した画像のボタンの場合
IMGオブジェクト.Click
Exit For
End If
Next
alt を使ってクリック
name や id が無い場合に、クリック対象を特定する方法を、unibon
さんが書いていただいていたので、転載させていただきます。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=44506&forum=7
HTML ドキュメント内にある最初の Form にある要素をすべて For Each で列挙
列挙したものが HTMLInputElement 型であるかどうか確認
HTMLInputElement 型であるなら、alt 属性の値が "ログイン" かどうか検証
"ログイン" であるなら、Click メソッドを呼ぶ
Dim x As Object
For Each x In objIE.Document.Forms(0).All
If TypeName(x) = "HTMLInputElement" Then
If x.alt = "ログイン" Then
Call x.Click
Exit For
End If
End If
Next
redfox63 さんの書き込み
http://oshiete.goo.ne.jp/qa/6841884.html
for each oEml as HtmlElement in objIE.Document.Links
' Count -> length
if oEml.Childen.length > 0 then
' 子供がいるならその子を取得
oEml = oEml.Childen(0)
end if
' alt属性をチェック
if oEml.GetAttribute("alt").ToString = "翌年" then
' oEml.InvokeMember("click")
oEml.click()
Exit For
end if
next
VBレスキュー(花ちゃん) の投稿も参考になります。
http://www.hanatyan.sakura.ne.jp/patio/read.cgi?no=314
ひこなんのVBAサンプルコード も参考になります。
IE操作_inputタグからalt属性で「検索する」を見つけてクリックする(MSHTML.HTMLImg.altプロパティ)
http://www.geocities.jp/samplecode_20130202/Sample/39845502762427578621927533367210465433073247662476393678643923581.html
SMBC日興証券オンライントレード売買注文登録 は、これを使わせていただきました。
項目を選択
ドロップダウン・リストで選択
フォームの「id」と、要素の「id」を使って指定しています。
<form id="formTrans" method="post" action="/world/english/">
<select id="swb_lp" name="wb_lp" size="2">
<option value="ENJA" selected>英→日</option>
<option value="JAEN" >日→英</option>
</select>
</form>
IEオブジェクト.Document.forms("formTrans").swb_lp .value = "JAEN"
フォームの「番号」と、要素の「name」を使って指定しています。
<form name="GU12010000Form" method="POST" action="GU120100.do" enctype="multipart/form-data">
<input type="hidden" name="EVENT_ID" value="" />
<select name="classification" class="inputenable"><option value="">---</option>
<option value="item">品目ファイル</option>
<option value="model">機種ファイル</option>
<option value="struct">構成ファイル</option>
<option value="chain">チェーンファイル</option>
<option value="factory">工場ファイル</option>
</select>
</form>
'ドロップダウンリストの選択
Select Case ファイル種別
Case "品目ファイル"
IEオブジェクト.Document.forms(0)("classification").Value = "item"
Case "機種ファイル"
IEオブジェクト.Document.forms(0)("classification").Value = "model"
Case "構成ファイル"
IEオブジェクト.Document.forms(0)("classification").Value = "struct"
Case "チェーンファイル"
IEオブジェクト.Document.forms(0)("classification").Value = "chain"
Case "工場ファイル"
IEオブジェクト.Document.forms(0)("classification").Value = "factory"
End Select
ラジオ・ボタンで選択
ラジオ・ボタンで、選択を指定します。
フォームの「番号」と、要素の「name」と「id」を使って指定しています。
<form name="GU12004000Form" method="POST" action="GU120040.do">
<input type="hidden" name="EVENT_ID" value="" />
<legend class="searchareatitleopen" onclick="openCloseCriteria(this, 'GU120040');">検索条件<input type="hidden" name="closeCriteria" value="false">
</legend>
<input type="radio" name="oldpnflg" value="true" checked="checked" class="inputenable" id="old" /><label for="old">旧品</label>
<input type="radio" name="oldpnflg" value="false" class="inputenable" id="new" /><label for="new">新品</label>
</form>
IEオブジェクト.Document.forms(0)("oldpnflg").old .Click
チェック・ボックスで選択
フォームの「番号」と、要素の「name」を使って指定しています。
<form name="GU12005000Form" method="POST" action="GU120050.do">
<input type="hidden" name="EVENT_ID" value="" />
<table summary="" cellspacing="1" cellpadding="1" width="100%">
<tbody id="details">
<tr class="outputnormal">
<td class="outputzonecenter">
<input type="checkbox" name="result[0].selflg" value="on" class="inputenable" />
</td>
</tr>
<tr class="outputnormal">
<td class="outputzonecenter">
<input type="checkbox" name="result[1].selflg" value="on" class="inputenable" />
</td>
</tr>
<tr class="outputnormal">
<td class="outputzonecenter">
<input type="checkbox" name="result[2].selflg" value="on" class="inputenable" />
</td>
</tr>
</tbody>
</table>
<input type="hidden" name="orgnscrnid" value="" />
</form>
For 検索数 = 1 To 同一品目数
Select Case 同一品目(検索数, 2)
Case "0"
IEオブジェクト.Document.forms(0)("result[0].selflg").Checked = True
Case "1"
IEオブジェクト.Document.forms(0)("result[1].selflg").Checked = True
Case "2"
IEオブジェクト.Document.forms(0)("result[2].selflg").Checked = True
End Select
Next 検索数
IE のバージョンを調べる
'**********************************************************************
' インストールされている Internet Explorer のバージョンを調べる
Sub IEバージョン(バージョン)
Dim IEバージョン 'As String
Dim ファイルシステムオブジェクト 'As Object
Set ファイルシステムオブジェクト = CreateObject("Scripting.FileSystemObject")
IEバージョン = ファイルシステムオブジェクト.GetFileVersion _
("C:\Program Files\Internet Explorer\IEXPLORE.EXE ")
' MsgBox IEバージョン
バージョン = CInt(Left(IEバージョン, InStr (IEバージョン, ".") - 1)) ?
Set ファイルシステムオブジェクト = Nothing
End Sub
'**********************************************************************