質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Windows Server

Windows Serverとは、Microsoft社のサーバ用オペレーティングシステムの総称です。 企業内ネットワークなどで利用されるサーバ機へ導入することを想定して開発されているため高い安定性があり、 管理機能を提供するソフトウェアが多く含まれています。

Q&A

解決済

6回答

24076閲覧

起動されたIEタブのオブジェクトを取得できない

dam9806

総合スコア21

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Windows Server

Windows Serverとは、Microsoft社のサーバ用オペレーティングシステムの総称です。 企業内ネットワークなどで利用されるサーバ機へ導入することを想定して開発されているため高い安定性があり、 管理機能を提供するソフトウェアが多く含まれています。

0グッド

1クリップ

投稿2018/11/28 22:38

編集2018/11/29 06:00

ExcelVBAでIEを操作しています。
VBAより、あるWebページのボタンをクリックすると、自動で新しいタブが追加されます。
クリックボタンのある元のページのタブもそのまま残っています。

この新しいタブのIEオブジェクトを取得したいのですが、できません。
コードの一部を以下に載せます。

' 検索ボタンをクリック objIE.document.getElementById("btnSearch").Click ' 新規タブのIEオブジェクトを取得 Call getIE("XXX", wkObjIE) '"XXX"はタイトル(固定値)が入ります。wkObjIEはアウトプットです (中略) Public Function getIE(title As String, objIE As InternetExplorer) Set sh = CreateObject("Shell.Application") 'ShellWindowから1つずつ取得して処理 For Each win In sh.Windows 'ドキュメントタイトル取得失敗を無視(処理継続) On Error Resume Next document_title = "" document_title = win.document.title On Error GoTo 0 'タイトルバーにfunction引数の"title"が含まれるかチェック If InStr(document_title, title) > 0 Then Set objIE = win Exit For End If Next getIE = 1 End Function

具体的には、こちらのサイト「https://www.books-sanseido.co.jp/」 のメニュー「本を探す」にて、検索BOXに「9784295000396」を入力後、検索BOXの隣のボタンをクリックする操作を行い、これにより追加されるタブのオブジェクトを取得しようとしています。

環境は WindowsServer 2012R2、Excel2016、IEのバージョンは11です。
ウォッチウィンドウで上記コードのsh.Windowsを確認しても、元ページタブはあるのですが、新規タブが見つかりません。

一方で、別PCのWindows7の環境では、同一プログラムで問題なく新規タブのIEオブジェクトを取得できます。
Excel、IEのバージョンは上記と同じです。

試しに、デバッグ実行中に手動で元のページのタブを閉じて、新しいタブだけを残した状態にしたのですが、相変わらずsh.Windowsに当該タブが見つかりません。

ネットで調べても情報が見つからず、行き詰まっています。
原因・対応策などを教えていただけますでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wwbQzhMkhhgEmhU

2018/11/29 04:33

タブを追加するコードと開いた対象の方が重要な気がします。あとWindows7に入っているIEのバージョン。ただ聞いても何一つ分からない可能性大です。
dam9806

2018/11/29 04:46

コメントありがとうございます。「objIE.document.getElementById("btnSearch").Click」のコード実行にて、新しいタブが自動で追加されています。IEのバージョンは11です。また何かありましたらよろしくお願いいたします。
wwbQzhMkhhgEmhU

2018/11/29 05:01

クリックイベント発火で開いた新しいタブ上のドキュメントは何ですか?
dam9806

2018/11/29 05:19

htmlドキュメントという回答でよろしいでしょうか? 新規タブのhtmlソースのheadに、「<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">」の記述がありました。
dam9806

2018/11/29 05:51

https://www.books-sanseido.co.jp/」 こちらのサイトのメニュー「本を探す」にて、検索BOXに「9784295000396」を入力後、検索BOXの隣のボタンをクリックする操作となります。 これにより、新しいタブが追加されます。
wwbQzhMkhhgEmhU

2018/11/29 05:58

HTMLかつ通常のURLですね。すみませんが、お手上げです。
dam9806

2018/11/29 06:01

いえ、お付き合いくださり、ありがとうございました!
guest

回答6

0

ベストアンサー

がんばってウィンドウハンドルを探すのも良いのですが…。
むしろ対象 Form タグの target="_blank" を書き換えて同じタブで開くようにしてしまうのはダメなのでしょうか?
クローリング先へのセッション数も抑えられますし…。

投稿2019/01/02 19:31

shinobu_osaka

総合スコア456

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dam9806

2019/01/03 09:32

回答ありがとうございます! htmlソースを書き換える発想がなかったので、これだったら成功するかも・・・と思いましたが、プログラムにて target="_blank" を削除するコードを追加したにもかかわらず、新しいタブ(ウィンドウ)が出現しました。 WindowsServerだけでなく、Win7でも同事象となることを確認しました。 デバッグ実行中に target="_blank" が消えていることを確認済みです。 また、これまでと同じく、新しいタブのウィンドウハンドルを取得することが出来ませんでした。 サーバー側で新しいウィンドウを出現させる処理をしているかもしれません。 また何か気づくことがあれば、ぜひ教えてください!
shinobu_osaka

2019/01/03 20:14

ソースを見た感じイケそうだったのに? …と思ったのでコードを書いて試したところ当方では成功しました、 うまく消せてないのかもしれませんので試したコードをのせておきます。 Set objie = CreateObject("InternetExplorer.Application") objie.Visible = True objie.Navigate "https://www.books-sanseido.co.jp/" Do While objie.Busy = True Or objie.ReadyState <> 4 DoEvents Loop For Each dom_form In objie.document.GetElementsByTagName("form") dom_form.target = "" Next dom_form objie.document.getElementById("inputKeyword").Value = "9784295000396" objie.document.getElementById("btnSearch").Click 一度お試しください。
dam9806

2019/01/04 10:45

ご掲載のコードを参考にプログラムを修正し実行したところ、成功しました! formタグのループ箇所がありますが、私の場合は以下のように書いていました。 For Each dom_form In objIE.document.getElementsByTagName("form") If InStr(dom_form.innerText, "検索したいキーワードを入力してください。") > 0 Then '① dom_form.outerHTML = Replace(dom_form.outerHTML, "target=""_blank""", "") '② Exit For End If Next dom_form ①のif文を削除すると、新しいタブが出現しなくなりました。 WindowsServer、Win7の環境で、期待どおりに動作することを確認しました。 未だに明確な原因は分かりませんが、ある程度汎用性があり参考になる回答を得られました。 感謝の気持ちでいっぱいです。 ありがとうございました!!
dam9806

2019/01/04 10:47

追記 ①のif文を除くときに、併せてExit Forも削除しました。
shinobu_osaka

2019/01/04 21:50

動きそうなのになぜ動かないんでしょうね…? ともかくHTMLを書き換えるのではなくて直接targetプロパティーの書き換えや、 innerTextの比較ではなくできるだけIDで指定、 というか全部_blankでなくなっても困らないので全部処理、 みたいな感じで…私のコードみたいに単純化していった方が、 原因不明の不具合に悩まされずうまく動くのかもしれませんね~。 何はともあれ解決してよかったですね! …質問内容とは関係ありませんが、 Microsoft Web Browser ActiveXを挿入でワークシート上に貼り付ければ、 別途ブラウザウィンドウを開くことなく処理できますヨー。
shinobu_osaka

2019/01/04 22:00

あ、ちなみにうまく動かない場合は、 dom_form.outerHTML = Replace(dom_form.outerHTML, "target=""_blank""", "") '② にブレイクポイントをつけてヒットしているかどうかの確認、 ifのところにブレイクポイントをつけて、 手動で0…5とか数値を替えつつヒットするかイミディエイトウィンドウで試す、 などをするとよいですよ~。
shinobu_osaka

2019/01/05 04:06

時間があったのでテストしてみました、 どうなってるのかはわかりませんがDOMの中身を覗いてみたところ、 目的のフォームは objIE.document.getElementsByTagName("form")(3) なのですが、 なぜか同一の内容が objIE.document.getElementsByTagName("form")(0) にも 入っておりそこでヒットして exit for で止まっていたのですね。 ソースを書き換えると再レンダリングが発生しますし、 対象のページによっては不具合が発生するので、(なにかJavascriptが発火したり) なるべくDOM操作(プロパティー操作)で行ったほうが変な不具合に悩まされないですむことが多いです。 ちなみに手軽にソースを置き換えてしまうのであればいっその事forとかせず… objIE.document.body.innerHTML = Replace(objIE.document.body.innerHTML, "target=""_blank""", "") これ一発で良いかと思いますw
dam9806

2019/01/06 05:01

Microsoft Web Browser ActiveXって初めて知りました。 別途調べてみたいと思います。 >>なるべくDOM操作で行った方が良い まったくその通りだと思います。 今回のように他に手が見つからないときだけ、ソースを書き換えるようにしたいと思います。 最後のソース書き換え方法、楽ちんですね! いろいろとお世話になり、ありがとうございました!! また機会がありましたら、宜しくお願いいたします。
shinobu_osaka

2019/01/06 05:46

Microsoft Web Browser ActiveX は… Excelの開発タブ>挿入>ActiveXコントロールの右下”…”をクリック、 ”Microsoft Web Browser”を選択して、適当にシートをドラッグ、 あとはVBAからWebBrowser1でアクセスできます。 例 : Sheets("Sheet1").WebBrowser1.Navigate "https://www.books-sanseido.co.jp/" おそらく中身はVBAでフォームを作って貼り付けて使うWebbrowserControlと同じです。 Javascriptのエラー処理や使用するIEのエンジンのバージョンなんかはレジストリだったかな…。 ちなみに私のコードはDOM操作でプロパティtargetを変更しており、 HTMLを直接は書き換えてませんよ~。 dom_form.target = "" ちなみに自分で言うのもなんですが… かなりExcelVBAでのクローリングは得意なんで、 何かあればいつでも回答依頼くださいませ。
guest

0

本投稿が今直面している問題に、大変参考になりました。

VBスクリプトを使って、Automation AnywhereのRPAで同様の問題に直面しています。
Windows7,WIndows8.1,Windows10では正常にウインドウのタイトルを検出できるのですが、Windows2012R2では、手動でサブウインドウを開かないとウインドウタイトルを検出できませんでした。
RPAロボットでサブページを開く場合と手動でサブページを開く場合で、マシン上のウンドウタイトルの見え方が違うようです。

IEかシステムのなんらかのセキュリティ設定変更、もしくは、VBスクリプトのコード変更で回避できるものなのかAutomation Anywhereのコミュニティで問い合わせしています。
何かわかりましたら情報を共有させていただきたいと思います。

投稿2019/07/05 01:04

isasan

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

isasan

2019/07/06 11:20 編集

一般ユーザを作成してログインして実行すると、思った通りに動作しました。 Administratorでログインして実行していたのですがこの症状が発生します。 アクセス制御に関係しているのだと思いますが、どのようが設定で解決できるのか調査していません。
isasan

2019/07/07 07:36 編集

追加で調査をしましたので記載させていただきます。 1.レジストリでUAEを完全に無効(a)にする。​この設定でVBScriptは動作しましたが、子ページを検出するAutomation Anywhereのコマンドの修正なしでは動作しませんでした。 2.Internet Explorerのセキュリティ(IS ESC)(b)をオフにすることで、子ページを検出するAutomation Anywhereのコマンドの修正なしで動作しました。ただ、セキュリティが低下するので好ましくないと思います。 もう少し調査した結果、サイトのコードの変更ができる場合、下記の修正で動作することが確認できました。 3.サイトのHTML文で、子ページを開く方法を新規ページとして開く方法へ変更する。 (a) UAEを完全に無効にするレジストリ設定​ HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System "EnableLUA"=dword:00000001 これを0にする。 (b) IE ESCをオフにする設定 サーバーマネージャーを起動して、[このローカルサーバーの構成]をクリックします。 中央にローカルサーバーの設定の[IE セキュリティ強化の構成]項目の[有効]をクリックし、Administratorグループのみ[オフ]にし、[OK]をクリックすることで設定が完了します。 Windows2012R2のセキュリティの勉強になりました。 ありがとうございました。
guest

0

dam9806 さん
改めて、初めのソースコードを読み取ってみました。
これは、勘ですが、オブジェクトの指定さえ間違いなければ、取得できると思います。

document_title = win.document.title

ここで、タイトルを取得しているようですが、取得しようとする対象オブジェクトが"Internet Explorer"です。このオブジェクトでは、タイトルは取得できません。
ここから、HTMLのオブジェクトを作成して、そこからタイトルを取得するのが良いと思います。

またサンプルですが、下の様に実行すれば、ウィンドウを全部調査しますので、間違いなく取得できると思います。

VBA

1Sub test03() 2 Dim IE As InternetExplorer 3 Dim Doc As HTMLDocument 4 Dim sh As Object 5 Dim win As Object 6 7 Set sh = CreateObject("Shell.Application") 8 For Each win In sh.Windows 9 If win.Name = "Internet Explorer" Then 10 Set IE = win 11 IE.navigate IE.LocationURL 12 IE.Visible = True 13 Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE 14 DoEvents 15 Loop 16 Set Doc = IE.document 17 Debug.Print IE.LocationURL, Doc.Title 18 End If 19 Next 20 Set win = Nothing 21 Set sh = Nothing 22 Set Doc = Nothing 23 Set IE = nothoing 24End Sub

また、ホームページの作成方法(コード)によって、やり方を変更することが重要だと思います。
私も人に教える立場ではありませんが、Excelからインターネットを操作するとき、対象のホームページのコードを読む様にしています。
サンプルのコードは、下図のようになっており、
イメージ説明
form method="post" action="アドレス"
で、他の実行ファイルにデータを送っており、検査した結果は、新たに取得しないとできない仕様になっているように読み取れます。

今回の様に、対象のオブジェクトを表示する方法も3種類もあり、他にも方法がありそうです。
参考までに、今回回答しました。

投稿2018/12/24 04:44

kai_keitai

総合スコア344

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dam9806

2018/12/27 04:09

kai_keitaiさん、回答ありがとうございます! 返信が遅くなり、申し訳ありません。 「document_title = win.document.title」このコードではIEのタイトルを取得できないとのご指摘ですが、取得できます。sh.Windowsには、IE以外のウィンドウオブジェクトも含まれます。ループでIEオブジェクトが処理対象となった場合は、先のコードでタイトルを取得できます。 また、「HTMLのオブジェクトを作成して、そこからタイトルを取得するのが良いと思います。」とのご提案について。 提示されたコードのループ中の「IE.navigate IE.LocationURL」、これがそれにかかるコードだと思いますが、これはリフレッシュしているようなものです。実際、デバッグ実行しても、リフレッシュと同じ動作が見て取れます。私にはどのような意味があるのか、理解不能です。 提示コードを今回調査しているサイト用に修正して実行しましたが、やはり検索後に出現するIE上のタブ(IEオブジェクト)は取得できませんでした。sh.Windowsにも存在しないことを確認済みです。 試みに、デバッグ実行中に手動でIEタブを追加したところ、そのオブジェクトは取得できました。 プログラムでIE操作により出現したIEタブのオブジェクトは取得できず、一方で、手動で追加したIEタブのオブジェクトは取得できるという状況です。
guest

0

dam9806 様
申し訳ございません、質問の意図を読み間違えました。
https://www.books-sanseido.co.jp/」のサイトのソースコードの検索の所を見ると、なんとなくではございますが、検索用のアドレスに検索値を渡して、自動的に結果が表示されています。自分も色々試した結果、検索結果のオブジェクトを取得する方法は、かなり難しいです。
そこで、直接検索用のアドレスを指定する方法なら、検索結果のオブジェクトを取得できました。
サンプルコードではございますが、参考にしてください。

このコードで、検索結果をデバックプリントで出力しています。
尚、実行するには、参照設定が必要です。
mshtml.tlb (Microsoft HTML Object Library)
ieframe.dll (Microsoft Internet Controls)

VBA

1Sub test02() 2 3 Dim IE As InternetExplorer 4 Dim Doc As HTMLDocument 5 Dim objTag As IHTMLElement 6 Dim strURL As String 7 Dim MOJI As String 8 9 10 MOJI = "9784295000396" 11 12 13 strURL = "https://www.books-sanseido.jp/booksearch/BookSearchExec.action" 14 Set IE = CreateObject("Internetexplorer.Application") 15 IE.navigate strURL 16 IE.Visible = True 17 18 Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE 19 DoEvents 20 Loop 21 22 Set Doc = IE.document 23 24 For Each objTag In Doc.getElementsByTagName("input") 25 If InStr(objTag.outerHTML, "キーワード") > 0 Then 26 Doc.querySelector("input[type=text]").Value = MOJI 27 Doc.querySelector("input[type=submit]").Click 28 Exit For 29 End If 30 Next 31 32 Do Until Doc.readyState = "complete" 33 DoEvents 34 Loop 35 36 37 Debug.Print Doc.Title 38 Debug.Print Doc.Url 39 40 Dim i As Long 41 For i = 1 To Doc.getElementsByClassName("results_mes").Length 42 Debug.Print Doc.getElementsByClassName("results_mes").Item(, i).textContent 43 Next i 44 45 Set Doc = Nothing 46 Set IE = Nothing 47 48End Sub

投稿2018/12/24 02:21

kai_keitai

総合スコア344

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dam9806

2018/12/24 03:11

回答ありがとうございます。 これなら新しいIEオブジェクトは生成されないので、処理可能ですね。 実は今回提示したサイトは例です。 どこのサイトだったか忘れてしまいましたが、検索結果が別タブや別ウィンドウで表示されることがありました。そのときも、IEオブジェクトを取得することが出来ませんでした。 Windows Serverに限る現象なのでしょうか。Win7やWin10だと、ふつうにIEオブジェクトを取得出来るのですが。。
guest

0

https://www.books-sanseido.co.jp/」のサイトのソースコードを見ると、Inputタグによる操作をする必要があります。

これであれば、検索結果のウィンドウが表示されると思います。

VBA

1Sub test01() 2 3 Dim IE As InternetExplorer 4 Dim Doc As HTMLDocument 5 Dim objTag As IHTMLElement 6 Dim strURL As String 7 Dim MOJI As String 8 9 10 MOJI = "9784295000396" 11 12 13 strURL = "https://www.books-sanseido.co.jp/" 14 Set IE = CreateObject("Internetexplorer.Application") 15 IE.navigate strURL 16 IE.Visible = True 17 18 Do While IE.Busy = True Or IE.readyState < READYSTATE_COMPLETE 19 DoEvents 20 Loop 21 22 Set Doc = IE.document 23 24 For Each objTag In Doc.getElementsByTagName("input") 25 26 Debug.Print objTag.outerHTML 27 If InStr(objTag.outerHTML, "キーワード") > 0 Then 28 Doc.querySelector("input[type=text]").Value = MOJI 29 Doc.querySelector("input[type=submit]").Click 30 Exit For 31 End If 32 Next 33 34 Do Until Doc.readyState = "complete" 35 DoEvents 36 Loop 37 38 Set Doc = Nothing 39 Set IE = Nothing 40 41End Sub

尚、実行するには、参照設定が必要です。
mshtml.tlb (Microsoft HTML Object Library)
ieframe.dll (Microsoft Internet Controls)

上手く、構造化すれば便利なマクロが完成すると思います。
頑張って下さい。

投稿2018/12/22 04:35

kai_keitai

総合スコア344

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dam9806

2018/12/23 09:53

回答ありがとうございます。 当方の質問の意図としては、検索結果のウィンドウのオブジェクトが取得出来ないので、それを取得する方法を教えていただきたいことでした。 ご呈示されたコードも試してみましたが、やはり、検索結果のウィンドウのオブジェクトを取得することは出来ませんでした。 また何か気づくことがあれば、ぜひ教えて下さい。 宜しくお願いいたします!
guest

0

同じExcel2016、IE11で挙動が異なるのは、OSのbit数の違いかも
しれません。
Windows7 32bit
WindowsServer 2012R2 64bit

下記サイトが参考なると思いましたが、実行させるために
64bit用のAPI関数を準備する必要があります。
https://www.ka-net.org/blog/?p=7697

まずは、上記サイトにある、以下の関数を参考にして、
新規タブのIEオブジェクトを取得できないでしょうか。
Private Function GetActiveIE(ByVal url As String) As Object
'URLを指定して起動中のIE取得
(後略)

私は試しておりませんが、やってみる価値はあると思います。

<追記>
WindowsのAPI関数を64bitと32bitのどちらでも呼び出しできる記述を
以下に示します。ただし、よく理解しないままにAPI関数を使うことは
お勧めしません。

VBA

1'API関数 2#If VBA7 And Win64 Then 3 Private Declare PtrSafe Function FindWindowEx Lib "User32" Alias "FindWindowExA" ( _ 4 ByVal hWndParent As LongPtr, _ 5 ByVal hWndChildAfter As Long, _ 6 ByVal lpszClass As String, _ 7 ByVal lpszWindow As String) As LongPtr 8 Private Declare PtrSafe Function ShowWindow Lib "User32" ( _ 9 ByVal hWnd As Long, _ 10 ByVal nCmdShow As Long) As LongPtr 11 'FindWindowExの戻り値を入れる変数 12 Dim hNavBar As LongPtr 13#Else 14 Private Declare Function FindWindowEx Lib "User32" Alias "FindWindowExA" ( _ 15 ByVal hWndParent As Long, _ 16 ByVal hWndChildAfter As Long, _ 17 ByVal lpszClass As String, _ 18 ByVal lpszWindow As String) As Long 19 Private Declare Function ShowWindow Lib "User32" ( _ 20 ByVal hWnd As Long, _ 21 ByVal nCmdShow As Long) As Long 22 'FindWindowExの戻り値を入れる変数 23 Dim hNavBar As Long 24#End If

投稿2018/12/08 02:33

編集2018/12/08 05:47
TanakaHiroaki

総合スコア1063

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dam9806

2018/12/08 05:21

TanakaHiroakiさん コメントありがとうございます。(先日の別の質問ではお世話になりました!) ご指示に従ってGetActiveIEを盛り込んで実行したところ、Windows7(32bit)では正常に処理できて、WindowsServer2012R2(64bit)ではIEオブジェクトが取得できずエラーとなりました。 上記は、全く同じコードで実行しています。 64bit用のAPI関数とは具体的にどのようなものでしょうか。
dam9806

2018/12/08 05:25

なお、GetActiveIEの引数はURLとなっていましたが、都合によりどうしてもURLを渡せないため、タイトルを渡してLocationNameと比較するように修正しました。
TanakaHiroaki

2018/12/08 05:34

引数については、タイトルに修正されたのですね。 GetObject("new:{9BA05972-F6A8-11CF-A442-00A0C90A8F39}") で IEオブジェクトを取得できないとのことで迷宮入りかもしれません。
dam9806

2018/12/23 09:49

追加コードをお示し下さり、ありがとうございます! また、返信送れて済みませんでした。 理解しないままに使うことはお勧めしないとのことでしたが、とりあえず使ってみました。 結果は、やはり正常にオブジェクトを取得出来ませんでした。 いろいろと調べて下さり、感謝します!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問