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?

【VBA × WebView2】脱IE! 「Edge内蔵PDFビューア」からPDFをダウンロードする(続き)

0
Posted at
  1. はじめに
    Fetch APIを使ったサイレントダウンロードの続きです。
    AI困惑、(レガシーな)業務システムや、動的にPDFを生成するWebシステムでは、教科書通りにいかない事が多いようです。参考事例に成れば。(と言っても、忘れっぽい私の忘却禄程度ですが)

最初は、有るはず要素に拘って色々検討したAIさん。

   ' embedタグのsrc属性(絶対URL)を返すJS
   getPdfUrlJs = "var el = document.querySelector('embed[type=''application/pdf'']'); return el ? el.src : '';"

なぞ1:消えた type="application/pdf"
例えば、業務システムが動的生成する以下のようなHTML画面に遭遇したとします。

<!DOCTYPE html>
<html lang="ja">
<head>
    <TITLE>PDF PREVIEW</TITLE>
    <!-- 中略 -->
</head>
<body id="pdfbodyarea">
    <div id="pdfarea" class="pdfareastyle">
        <!-- ! type="application/pdf" が存在しない -->        
        <embed class="pdfareastyle" src="http://WIN-**/NS**prt/pdf/N99xx-2026072113574928.pdf">
    </div>
</body>
</html>

ここで、 embed[type="application/pdf"] という厳密なCSSセレクタで待機しようとすると、属性が存在しないためタイムアウト・エラーになってしまいます。
(ブラウザはHTTPレスポンスヘッダを見て自動的にPDFだと推測し、HTML上には情報がないケースが多々あるようです。)

この場合、セレクタを緩めて embed や embed[src*=".pdf"] としてターゲットを捕捉する柔軟性が求められます。

なぞ2:相対パスと絶対パス
ターゲット(embed要素)を見つけても、まだ動きません。
要素の src 属性を取得した際、http://~ という絶対URLではなく、/NS01prt/pdf/xxxx.pdf のような「相対パス」が格納されていた。このままダウンロード処理(Fetch API)に渡しても「どのサーバーへのリクエストか分からない」とまたエラー!!。

解決:JavaScriptを使って「どんな形であれ、必ず絶対URL(http://~)に変換して抽出する」

// PDFのURLを安全かつ確実に取得するJS
var el = document.querySelector('embed');
if (!el) return '';

try {
    // 相対パスを絶対URLに確実変換する魔法のコード
    return new URL(el.getAttribute('src') || el.src, location.href).href;
} catch(e) {
    // 万が一の予備ルート
    return el.getAttribute('src') || el.src || '';
}

実体URLさえ確実に取得できれば、Invoke-WebFetchDownload の出番です。

    Dim savePath As String
    Dim actualPdfUrl As String
    savePath = "C:\Desktop\テストデータ\DummyPDF_20260722.pdf"
    ' 1. ダウンロードの事前予約
    rpaEngine.RunAction "Enable-SilentDownload", CreateParams("DownloadDirectory", "C:\Desktop\テストデータ", "FileName", "DummyPDF_20260722.pdf")
    ' 2. PDF画面へ遷移&待機
    rpaEngine.RunAction "Invoke-WebNavigation", CreateParams("Url", "https://.../preview")
    rpaEngine.RunAction "Wait-WebElement", CreateParams("Selector", "embed", "TimeoutSec", 15)
    
    ' 3. PDFの実体URL(絶対パス)を取得
    actualPdfUrl = rpaEngine.RunAction("Get-WebEmbedPdfUrl")
    ' 4. URLを指定してFetchダウンロード発火
    rpaEngine.RunAction "Invoke-WebFetchDownload", CreateParams("TargetUrl", actualPdfUrl)
    ' 5. ダウンロード完了待機
    rpaEngine.RunAction "Wait-FileDownload", CreateParams("FilePath", savePath, "TimeoutSec", 30)
    
    ' 6. PDF画面を閉じる

後処理:不要になったPDF画面を美しく閉じる
ダウンロードが完了した後は、不要になったPDFのプレビュー画面を片付けます。
システムの仕様(別タブで開くか、同じ画面で遷移するか)に合わせて、以下のコマンドで元の画面に復帰させます。

パターン1:別ウィンドウ(新しいタブ)でPDFが開いている場合

    ' JavaScript経由で画面を閉じる(エンジン側でゴーストタブも自動破棄されます)
    rpaEngine.RunAction "Invoke-WebScript", CreateParams("Js", "window.close();")
    Sleep 1000 ' 親画面へのフォーカス復帰待機

パターン2:同じ画面内でPDFに遷移している場合

    ' JavaScript経由でブラウザの「戻る」を実行
    rpaEngine.RunAction "Invoke-WebScript", CreateParams("Js", "window.history.back();")
    rpaEngine.RunAction "Wait-WebPageLoad"

と、今回も、Get-WebEmbedPdfUrl を追加しました。

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?