2020年5月24日日曜日

SeleniumBasic:Chromeバージョンアップ後にClickがエラー

コロナが治まるまでChromeのバージョンアップは休止と何かで読んだので、まだ80のままだと思ってました。先日Seleniumで動かそうとしたらドライバが古いとエラーが出て、83に上がってるのに気づきました。知らないうちに81に上がり、82はスキップしていたらしい。

で、80まで動いていたコードの一箇所でエラーが出てしまい焦りました。
検索結果をダウンロードするボタンをClickさせるのですが、対象はこんな感じです。

<form action="download" method="post" name="DataDownload">
    <input name="xxxxx" type="hidden" value="DownloadData" >
    (その他もろもろ)
    <input class="contentsBtn" type="submit" value="検索結果をダウンロード" >
</form>

検索結果が表示されると現れるボタンで、これまでは以下のようにClickさせてました。

Dim objDriver As ChromeDriver
Dim objTemp As Object

(中略)

    Set objTemp = objDriver.FindElementByName("DataDownload")
    If objTemp.IsDisplayed Then objTemp.Click

83ではIsDisplayedまでは通るのですが、Clickでエラーとなりました。

element not interactable: element has zero size

何を怒られているのかはわからない。
しょうがないのでclassの方で要素を取得してみました。

Set objBtns = objDriver.FindElementsByClass("contentsBtn")
For Each objTemp In objBtns
    If objTemp.Value = "検索結果をダウンロード" Then
       objTemp.Click
       Exit For
    End If
Next

これならClickできました。
別のPCでChromeを強制的に80にして試すと、今でも前のコードでClickできました。とにかく81または83で何か仕様が変わったようです。

2020年2月19日水曜日

SeleniumBasic:SendKeysを使わずにテキストを入力

VBAでブラウザを操作するのに、IEからSeleniumBasic+Chromeへ移行してしばらく経ちます。不便に感じていたのがテキストボックスへの文字列の入力です。
IEならValueプロパティに値を設定すればよかったですが、 SeleniumBasicではなぜかそれができません。ネットで調べるとクリップボードに値を設定して、テキストボックス上でCtrl+vをSendKeysで実行するのが定番のようでした。なので今まではこうしていました。

Dim objDriver As ChromeDriver
Dim objKeys As Selenium.Keys
Dim objTemp As Object

    Set objDriver = New ChromeDriver
    objDriver.Get (URL)
    objDriver.Window.Activate
    Set objKeys = New Selenium.Keys

(中略)

    Set objTemp = objDriver.FindElementByName("txtExample")
    objTemp.Clear
    objDriver.SetClipBoard Sheet1.Range("A1")
    objTemp.SendKeys objKeys.Control, "v"

1回入力するくらいなら問題ありませんが、数十回数百回とループさせる場合は実行速度が遅く感じます。また実行中にうっかり他のアプリケーションでコピーしてしまうと、当然それがペーストされてしまいます。

解決しようとさらに調べていたところ、 ExecuteScriptというメソッドがあることに気づきました。JavaScriptの文字列を実行できるようで、これならValueに値を設定できることがわかりました。
上の(中略)以下は1行で済みました。

    objDriver.ExecuteScript "document.getElementsByName('txtExample')[0].value=" & Sheet1.Range("A1")

とりあえずこれで解決です。