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

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

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

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

Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

1回答

8743閲覧

seleniumbasic + VBA を利用してchormeに印刷指示を出したい。

tetrisuehara

総合スコア20

VBA

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

Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

1クリップ

投稿2021/04/09 05:02

前提・実現したいこと

seleniumbasicを利用して、エクセルに日々のデータを入力しています。
必要なデータ自体の取り込みはできるようになったのですが、chromeへ印刷指示を出す方法を探しています。
現在 sendkey でctrl+p を入力して無理やり印刷画面を呼び出してコマンド入力で印刷指示を出しているのですが、chromeの状況に左右されてしまいうまく行かない事もあり、
Python selenium Chromeにて「#shadow-root (open)」に関する質問

Selenium WebDriverでWebページを印刷する方法
を参照して、shadow-root 内の要素を取得するという方法を試みています。
しかしながら、全く上手く行きません。
手探りな中コードを読んでいるので意味が理解できない状況です。
ご教授お願いします。

試したこと1

①にて、解決として上がっている方法を試すと
まずこのshaddow_rootという変数の型がわかりません。
そもそも変数なのかどうかもわからない状況です。
この構文の意味はどういった意味なのでしょか?

該当のソースコード

VBA

1shadow_root = driver.execute_script( 2 'return arguments[0].shadowRoot', element)

試したこと2

同じくPython selenium Chromeにて「#shadow-root (open)」に関する質問
から、提案のあった方法を試してみました。
javaも読めないので推測ですがこちらも同じくdocumentという変数に対して2行目以降のコマンドを当てているというように読んだのですが、同じく変数の指定がわからない。
また、該当するコマンド(.querySelectorなど)がライブラリーから候補として出てきていないので、なにか参照設定にて読み込みをしなければいけないのか?

該当のソースコード

java

1document 2.querySelector('body > print-preview-app') 3.shadowRoot.querySelector('#sidebar > print-preview-header') 4.shadowRoot.querySelector('#button-strip > paper-button.action-button') 5.click();

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

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

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

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

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

guest

回答1

0

ベストアンサー

shaddow_rootという変数の型

selenium上で印刷ダイアログを表示させた場合は、下の画像のように、印刷元のページに#shadow-rootというIDが特別に差し込まれた形になります。
イメージ説明

この#shadow-root配下の要素をどうやって取得するか...そのあたりの話が質問文中の①のページでされています。
調べたところ、XpathではShadow-root配下の要素を取得できないようです。

ただ、解決回答となっている

shadow_root = driver.execute_script( 'return arguments[0].shadowRoot', element)

については前後のコードがないため、何を意味しているのか明確にはわかりませんでした。
(おそらく#shadow-rootの要素をshadow-rootという変数に格納しているという意味だと思いますが、elementが何を意味するか分からず、手元環境で試してもエラーになりました。)

該当するコマンド(.querySelectorなど)がライブラリーから候補として出てきていないので、なにか参照設定にて読み込みをしなければいけないのか?

記載の「document.querySelector~」で始まるコマンドが、印刷ダイアログのOKボタンを指定してクリックするためのJavaScriptになっています。

このJavaScriptのうち.click()を除く部分は、下記の手順で取得できます。
・selenium の driver.get(url) で適当なページを表示させます。
・Ctrl+Pを押して印刷ダイアログを表示させます。
・印刷ダイアログの適当な部分で右クリックし、コンテキストメニューの一番下の「検証」をクリックすると、印刷ダイアログに対するDevToolsが起動します。
・「要素の選択」ボタン(下の画像のオレンジ色で囲まれたボタン)をクリックして要素選択モードにしたあと、印刷ダイアログのOKボタンを右クリックします。
・すると、OKボタンに対応するHTMLソースが選択されるので、選択されているソース部分を右クリックし「Copy → Copy JSPath」を選択します。
・クリップボードに、選択した要素のJSPathが格納されます。
イメージ説明

driver.execute_script(JavaScript実行文)と書くことにより、特に参照設定を行わなくとも、selenium内で任意のJavaScriptを実行できます。


色々なサイトを調べて試行錯誤した結果、手元の環境では下記スクリプトだとうまく行きました。

キモとなる点というか、たどり着くのに苦労した点は
・印刷ボタンをクリックさせるには、setTimeOut関数を使ってwindow.print()を呼び出さないといけない(理由不明)
・印刷ダイアログは別ウィンドウ扱いなので、SwitchToNextWindow で指定対象を切り替える必要がある。
・(当然ですが)印刷ダイアログの構築完了前にボタンクリックのJSを実行してしまうとボタンをクリックできないため、一定時間待つ必要がある。
の3点です。

あと現在のOKボタンのPathは、①のページに記載のPathとは若干変わっていました。
バージョンアップに伴って変わる可能性があるとすれば、Chromeのバージョンごとに確認とメンテナンスが必要かもしれませんね。

VBA

1Sub CommandButton1_Click() 2 Dim s As String 3 s = "document.querySelector(""body > print-preview-app"").shadowRoot.querySelector(""#sidebar"").shadowRoot.querySelector(""print-preview-button-strip"").shadowRoot.querySelector(""div > cr-button.action-button"").click();" 4 5 Dim Driver As New Selenium.WebDriver 6 Driver.Start "chrome", "http://www.selenium.jp/test-site" 7 Driver.Get "/" 8 9 Driver.ExecuteScript "setTimeout(function(){window.print();}, 0);" 10 'VBAの場合十分な時間待たないと失敗する。 11 Driver.Wait (10000) 12 13 Driver.SwitchToNextWindow 14 Driver.ExecuteScript s 15 16 'VBAの場合Closeで勝手に閉じるので十分な時間WAIT。 17 Driver.Wait (20000) 18 Driver.Close 19 20End Sub

(参考)下記は検証に用いた(上のVBAコードの元にした)pythonスクリプトです。

python

1from selenium import webdriver 2import chromedriver_binary # 手元環境で使っているため指定。chromedriver.exeを直接利用している場合は不要。 3import time 4 5driver = webdriver.Chrome() 6driver.get('http://www.selenium.jp/test-site') 7driver.implicitly_wait(10) 8 9# 印刷ダイアログを開く。 10driver.execute_script("setTimeout(function(){window.print();}, 0);") 11driver.implicitly_wait(10) 12 13'''印刷ダイアログの構築完了前に要素を選択してしまう場合があるため、 14下記time.sleepで印刷ダイアログの完全表示まで強制的 15にウェイトをかけています。 16driver.implicitly_wait(10)だけではうまく行かない場合があるため、time.sleepを使用して強制的に待機させています。 17なくてもうまく動くなら削除して構いません。 18本来なら WebDriverWait.untilを使うところですが、要素の指定にJSPathしか使えない状況での 19untilの使い方が分かりませんでした。 20''' 21time.sleep(3) 22 23# 指定対象を印刷ダイアログに切り替える。 24driver.switch_to.window(driver.window_handles[-1]) 25 26# 印刷ダイアログのokボタンをクリックするJavaScript 27js = 'document.querySelector("body > print-preview-app").shadowRoot.querySelector("#sidebar").shadowRoot.querySelector("print-preview-button-strip").shadowRoot.querySelector("div > cr-button.action-button").click();' 28 29# OKボタンのクリックを実行。 30driver.execute_script(js) 31

検証環境:
Windows 10
Python 3.8.4
Chrome 89.0.4389.114(Official Build) (64 ビット)
chromedriver-binary 89.0.4389.23.0
selenium 3.141.0

投稿2021/04/09 17:00

編集2021/04/10 00:28
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tetrisuehara

2021/04/10 01:00

丁寧なご回答頂きましてありがとうございます。 月曜日に会社で改めて入力してみます。 VBAのコードを読ませていただいてようやく意味がわかりました。 やはり自分の触れているものじゃ無いと理解は難しいですね。 取り急ぎお礼のためご返答いたします。 また来週に結果を返答させていただきます!
tetrisuehara

2021/04/12 00:40

お世話になっております。 ご回答頂きました方法を実際に試したところ、見事に動きました。 あとは自分で勉強しつつ構文をいじってみたいと思います。 本当にありがとうございました。
退会済みユーザー

退会済みユーザー

2021/04/12 03:07

うまく行ってよかったです。お役に立てて何よりです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問