0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SeleniumVBA】起動済EdgeからOfficeファイルを指定フォルダにダウンロードする

Last updated at Posted at 2025-06-28

1 はじめに

諸事情により、やむを得ずリモートデバッグモード(port 9222)で作成したショートカットのアイコンで起動して手動でログインしたブラウザを起点として、自動化処理を行っている事例もあるかと思いますが、制約があります

Discordコミュニティ「Excel-Fun.xls*」の議論で、リモートデバッグモードではcaps.SetDownloadPrefsによりダウンロード先を指定しようとしても、設定できずにエラーになることが判明しました。
1.png

また、driver.SetDownloadFolder(内部でCDPのPage.setDownloadBehavior を実行)しているが非推奨とされている)を利用すれば指定フォルダにはダウンロードできますが、その後手作業でダウンロードしようとすると動作不具合が起こることも判明しました。
2.png

さらに、Edgeのお節介機能が邪魔して、Officeファイルをダウンロードしようとすると新規のタブが開いて、ブラウザ上のタブ内でファイルを開こうとするのでダウンロードできない問題があることも確認されています。
3.png

2 対応

様々な手法を検討しましたが、ダウンロードURLを取得できてWebDriver上での操作にこだわりがなければ WindowsAPIの「UrlDownloadToFile」の利用により、問題なく処理できるものと思われます。

「UrlDownloadToFile」は、SeleniumVBAにおいてWebDriverの自動ダウンロードで利用していますので、すでに宣言済です。

テスト用のサイトとして、RPA Challengeを利用させていただき、Excelファイルをダウンロードできるようにしました。

3 処理手順

(1) 作成したショートカット(※)により、リモートデバッグモード(port 9222)でEdgeを手動で起動する。

(2) (以下自動処理)起動したEdgeを起点として、 自動処理を新規タブ(作業用タブ)を開いて開始する。その際、リモードデバッグモードでEdgeが立ち上がっていない場合はエラーになる関数(@いおり様提供)で判断して終了する。

(3) WindowsAPIの「UrlDownloadToFile」を利用して、Excelファイルを指定フォルダにダウンロード後、確認作業のため一旦停止する

(4) 作業用タブ(RPA Challenge)を閉じて処理を終了して初期状態のタブのみ残す

(※)ショートカットのリンク先は以下に設定(ログイン継続希望の場合は --guestは削除)
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --remote-debugging-port=9222 --user-data-dir="C:\EdgeDebugProfile --guest --disable-sync"
4.png

4 ExcelVBAコード紹介

以下のコードを丸ごとコピーして、新規の標準モジュールに貼り付けますと動作確認ができます。もし、SeleniumVBAがまったく初めての方は、こちらの記事を参考に新規の標準モジュール作成まで行ってください。

ダウンロードURLの特定は、XPathによりaタグをテキストから特定して、
そのhref属性の値をGetAttributeすることで取得しています。
ダウンロードフォルダの指定の際、ファイル名を指定する必要がありますが、
ファイル名は任意に設定できます。

VBA
Option Explicit

Sub Edge_RemoteDebugger()
'=================================================
'リモートデバッグによりログイン状態のブラウザを自動操作する。
'ショートカットにより、すでに立ち上げた状態から始める。
'=================================================
'ショートカットのリンク先は以下に設定(ログイン継続希望の場合は --guestは削除)
"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --remote-debugging-port=9222 --user-data-dir="C:\EdgeDebugProfile --guest --disable-sync"
'=================================================
    'URLの設定(RPA Challenge)
    Const strURL As String = "https://www.rpachallenge.com"
'=================================================
    Dim driver As SeleniumVBA.WebDriver
    Dim caps As SeleniumVBA.WebCapabilities
    '作業用タブ
    Dim winTmp   As SeleniumVBA.WebWindow
    Dim wshell As Object
    
    '9222ポートが開いていない場合は終了
    If GetIs9222PortListening = False Then MsgBox "ショートカットを開いてください": Exit Sub
  
    Set driver = SeleniumVBA.New_WebDriver
    Set wshell = CreateObject("WScript.Shell")
    
    driver.StartEdge
    Set caps = driver.CreateCapabilities(initializeFromSettingsFile:=False)
    caps.SetDebuggerAddress "localhost:9222"
    driver.OpenBrowser caps
    
    '作業用タブ(タブを新規で開く)
    Set winTmp = driver.Windows.SwitchToNew(windowType:=svbaTab)
    driver.NavigateTo strURL & "/?lang=ja"

   'ダウンロードURLを特定する
    Dim URL As String
    URL = driver.FindElement(By.XPath, "//a[text()=' Excelファイルをダウンロード ']").GetAttribute("href")
    URL = strURL & URL

   'ファイル名を取得する(実際のところ拡張子が整合していればファイル名は任意)
    Dim arrURL As Variant
    Dim FileName As String
    arrURL = Split(URL, "/")
    FileName = arrURL(UBound(arrURL))

   'downloadパスを現在のフォルダに指定する。ファイル名まで指定する必要あり
    Dim downloadPath As String: downloadPath = ThisWorkbook.Path & "\" & FileName

    '保存フォルダにdownloadする(UrlDownloadToFileはSeleniumVBAでは宣言済)
    UrlDownloadToFile 0&, StrPtr(URL), StrPtr(downloadPath), 0&, 0

    'ファイルが指定フォルダに存在するまで待機
    Do While Dir(ThisWorkbook.Path & "\" & FileName, vbDirectory) = ""
      driver.Wait 300 '300ミリ秒待機
    Loop

   Stop  ’確認のため一時停止

   '作業用タブを閉じる
    winTmp.CloseIt
    '元のタブを残したまま終了
    driver.Shutdown
    
End Sub

Public Function GetIs9222PortListening() As Boolean
    Dim t As Double
    t = Timer
    Dim wsh As Object
    Set wsh = CreateObject("WScript.Shell")
    
    'コマンドプロンプトで実行した結果を取得する
    'netstatコマンドについて
    'a:全てのリッスンのポートを表示する
    'n:数値に変換する(n入れないと遅いので注意)
    'p:指定したプロトコルのみ表示する。TCPを指定するとIPv4のTCPのみ表示
    
    Dim Exec As Object '今回9222がリッスンかどうかのみみるので、プロセスIDを取得する「o」は入れてない
    Set Exec = wsh.Exec("cmd /c netstat -an -p TCP|find ""9222""|find ""LISTENING""")
    
    Dim stdout As Object
    Set stdout = Exec.stdout
    Do While Exec.Status = 0
        DoEvents
'        Sleep 100
    Loop
    
'    Dim str As String
'    str = Exec.stdout.ReadAll 'Exec.Status=1になった後なら、ReadAllでも素早く取得できる
    
    Dim IsRtn As Boolean
    IsRtn = False
    Dim StrLine As String
    Do Until stdout.AtEndOfStream
        '1行ずつ読み出し
        StrLine = stdout.ReadLine()
        If StrLine Like "*TCP*:9222*:*LISTENING*" Then
            '目的の行が見つかった時点でループから抜ける
            IsRtn = True
            Exit Do
        End If
    Loop
    GetIs9222PortListening = IsRtn
    Debug.Print Round(Timer - t, 2) & "秒"
    
End Function
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?