LoginSignup
1
1

【Excel】MacでTinySeleniumVBAを使用したい

Last updated at Posted at 2022-05-22

はじめに

Excelでwebブラウザの操作を自動化する最小機能のみ実装したフレームワークの「TinySeleniumVBA」があります。
これは今のところActiveXを使用しているため、Windows専用になっています。ActiveXの部分を取り除き代替部分をVBA-toolsライブラリー群を使えば、Mac上のExcelで動作するかもと取り組みました。

これまで、その準備を着々と進めてきました。

ようやく自分の環境ではありますが、Macで「TinySeleniumVBA」を動かすことができました。

環境

Mac Book Pro(2.3 GHz 8コアIntel Core i9) Monterey 12.2.1
Microsoft Office Home and Student 2019

Excel for Microsoft 365では確認していませんので、テストのご協力をお願いします。

導入方法

下記サイトから「TinySeleniumVBA」をダウンロードします。

MacではActiveXが使用できません。
手順の「ツール>参照設定からMicrosoft Scripting Runtimeに参照を通してください」は不要になります。

今回、Excelには下記2つが追加になります。

  • Dictionary.cls
  • MacWebHelper.bas

image.png

VBA-Dictionary

Microsoft Scripting Runtimeの代替として、VBA-DictionaryのDictionaryクラスを使用します。
これを使用すると、WindowsでもMacでもDictionaryオブジェクトを同様に使うことができるようになります。

下記サイトからダウンロードし、解凍後にVBAプロジェクトに「Dictionary.cls」をインポートします。

MacWebHelper

TinySeleniumVBAをMacで動作させるために独自に作成したモジュールになります。
Shell(WebDriverの起動)とHTTP通信(Curlによる通信)を担っています。

curlの接続時のタイムアウト時間(デフォルト300秒:web_ConnectTimeout)
curlの処理全体にかかる時間のタイムアウト(デフォルトなし:web_MaxTimeout)

Private Const web_ConnectTimeout As Long = 30
Private Const web_MaxTimeout As Long = 60

下記サイトからダウンロードしてください。

AppleScript

Mac版ExcelでShellを使用するにはAppleScriptを使用する必要があります。
Office 2016 for Mac 以降では、MacScript関数の代わりに AppleScriptTask関数を使用するのですが、セキュリティーの関係でスクリプトファイルを特別なフォルダに配置する必要があります。
スクリプトを作成するにはMacに標準に搭載されている「スクリプトエディタ」が必要です。
Spotlight(虫眼鏡アイコン)に「エディタ」と入力すると「スクリプトエディタ」が検索結果に現れるので、そちらにコードを記入していきます。
image.png

shell.scpt
on synchandler(param)
    try
        set ret to do shell script param
        return ret
    on error number n
        return "error " & n
    end try
end synchandler

on ansynchandler(param)
    try
        set ret to do shell script param & "> /dev/null 2>&1 &"
        return ret
    on error number n
        return "error " & n
    end try
end ansynchandler

入力後にトンカチボタン(コンパイルボタン)をクリックします。
image.png
上記コードを入力した「shell.scpt」ファイルを最終的に「~/Library/Application Scripts/com.microsoft.Excel/」に配置してください。
image.png

プログラムの変更

一応、MacとWindowsが共存できるように"#If Mac"条件付きで処理を分けています。
Start関数とSendRequest関数の2箇所を修正します。

WebDriver.cls
' Start WebDriver
Public Sub Start(ByVal driverPath As String, ByVal driverUrl As String, Optional ByVal driverName As String = vbNullString)
    ' Start WebDriver executable
    #If Mac Then
        Dim result As shellResult
        result = MacWebHelper.ExecuteInShell(driverPath)
        If result.ExitCode <> 0 Then
            MsgBox result.Output
            End
        End If
    #Else
        If Shell(driverPath, vbMinimizedNoFocus) = 0 Then
            MsgBox "Failed in starting WebDriver"
            End
        End If
    #End If
    
    ' Set WebDriver url
    UrlBase = driverUrl
    
    ' Initialize driver commands
    InitCommands
    
    ' Set browser name
    BrowserName = driverName
End Sub

' Send HTTP request
Private Function SendRequest(method As String, url As String, Optional Data As Dictionary = Nothing) As Dictionary
    Dim client As Object
    Dim JsonString As String
    
    #If Mac Then
        Dim response As WebResponse
        If method = "POST" Or method = "PUT" Then
            response = MacWebHelper.PostJson(url, Data)
        Else
            response = MacWebHelper.GetJson(url)
        End If
        
        JsonString = response.Content
        If response.StatusCode = InternalServerError And InStr(JsonString, "version") > 0 Then
            ' version mismatch error
            MsgBox JsonString
        End If
    #Else
        Set client = CreateObject("MSXML2.ServerXMLHTTP")
    
        client.Open method, url
    
        If method = "POST" Or method = "PUT" Then
            client.setRequestHeader "Content-Type", "application/json"
            client.send JsonConverter.ConvertToJson(Data)
        Else
            client.send
        End If

        Do While client.readyState < 4
            DoEvents
        Loop
        
        JsonString = client.responseText
    #End If

    Dim Json As Object
    Set Json = JsonConverter.ParseJson(JsonString)
    Set SendRequest = Json
End Function

For Eachの部分

TinySeleniumVBAのissuesにも書いたので、新しいバージョンになれば修正される可能性があります。

修正箇所は2箇所になります。「For Each」で検索してください。
For Eachのコレクション側に.Keysを追加します。

WebDriver.cls
Public Function Execute(driverCommand, Optional parameters As Dictionary = Nothing, Optional asRawResponse As Boolean = False)
    For Each paramKey In parameters.Keys

Private Function ScriptDictToConvertedDict(Dict As Variant, Optional ByVal sessionId As String = vbNullString) As Object
    For Each key In dict.Keys

注意点

これまでWindows版で作成したサンプルや質問の回答したコードをMac版で試した中で見つけた修正点がありました。

WebDriverの配置

自分はWebDriverを/usr/local/bin/に配置しました。
実行時に「開発元を検証できないため開けません」が表示されたら、下記サイトを参考にしてください。

Example
Driver.Chrome "/usr/local/bin/chromedriver"
 Or
Driver.Edge "/usr/local/bin/msedgedriver"

囲み記号

文字列の中の囲み記号はダブルクォーテーションにしないと正しい結果が得られませんでした。
※Content-Lengthの長さが一致しなくなるため、タイムアウトエラーになる。

例1
csvanchors = Driver.FindElements(By.XPath, "//a[@data-file_type='CSV']")

csvanchors = Driver.FindElements(By.XPath, "//a[@data-file_type=""CSV""]")
例2
contents = Driver.ExecuteScript("return document.getElementsByClassName('datatable')[0].outerHTML;")

contents = Driver.ExecuteScript("return document.getElementsByClassName(""datatable"")[0].outerHTML;")

パス区切り

末尾の& "\\"が不要でした。これがあると例として"DownLoad\"というフォルダが作成されてしまいます。
Windowsはパス区切りが複数回続けて書いても問題ないですがMacは駄目です。

cap.AddPref "download.default_directory", ThisWorkbook.path & "\"

cap.AddPref "download.default_directory", ThisWorkbook.path

Sleep

MacのVBAで待機する(秒単位)

' 1秒待機
Application.Wait (Now() + TimeValue("0:00:01"))

最後に

MacでExcelを使用してWebスクレイピングをするという需要はかなり少ないです。
2020年にMacとMicrosoft Office Home and Student 2019を購入しました。parallels desktop 17 for MacでWindows 11環境もありますが、Windows版のExcelはありません。Microsoft 365をサブスクリプションで購入するのももったいないのよね。大分前に1か月間無料は試しちゃったし。
TinySeleniumVBAを自宅で動かすにはMacに対応するしなかったのです。幸いMacで動作させることができました。

TinySeleniumVBAのバージョンアップでMac対応が組み込まれるように、作者であるuezoさんと協力していきます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1