LoginSignup
3
2

VBAからAdobe Acrobatを制御してPDFファイルをデジタル署名する

Last updated at Posted at 2024-03-20

はじめに

証明書ファイル(PFXファイル)を用いて、VBAからAdobe Acrobatを制御してPDFファイルのデジタル署名をしましたので、その方法について整理しました。

環境

・Windows 10 Pro
・Microsoft 365 (Excel)
・Adobe Acrobat Pro

署名方法

事前設定

Acrobatを起動して「メニュ」の「編集」→「環境設定」→分類で「セキュリティ(拡張)」を選択後、「サンドボックスによる保護」の「起動時に保護モードを有効にする」のチェックを外す必要があります。
image.png

VBAからAcrobatを制御するためには

VBAの参照設定でAcrobatのライブラリーを参照することで、PDFファイルを開くなど、一部のAcrobat機能を制御することはできますが、ほとんどの機能を制御することはまだできません。
より多くの機能を制御するため(デジタル証明するため)には、「JSObject」というオブジェクトを呼び出す必要があります。

JSObjectを使うと、Acrobat JavaScriptの機能を使うことができます。
(しかし、VBAからはJavaScriptで使うオブジェクト形式などを作ることができないので、使えられる機能もあります。)
レファレンスは以下のURLで確認できます。

処理の流れ

  1. PDFファイルを開く
  2. JSObjectを呼び出す
  3. 証明書ログインする
  4. PDFファイルに署名フィールドを生成する
  5. 署名フィールドに署名を追加してファイルを出力する
  6. 証明書ログアウトする
  7. PDFファイルを閉じる

コードの例

Public Sub CreateSignaturePdf()
    Dim acroPdObj As New Acrobat.AcroPDDoc
    Dim acroAvObj As New Acrobat.AcroAVDoc
    Dim jsObj As Object
    Dim objSign As Object
    Dim signatureCoords() As Variant
    Dim signField As Object

    Dim bottomLeftX As Long
    Dim bottomLeftY As Long
    Dim signWidth As Long
    Dim signHeight As Long

    Dim targetFilePath As String
    Dim certFilePath As String
    Dim certPassword As String
    Dim outputFilePath As String
    
    targetFilePath = "C:\SignTest\Input\TargetPdf.pdf"
    certFilePath = "C:\SignTest\Certificate\Certificate.pfx"
    certPassword = "password"
    outputFilePath = "C:\SignTest\Output\SignedPdf.pdf"
    
    ' 署名を表示する場合、適切に値を設定します
    bottomLeftX = 200
    bottomLeftY = 100
    signWidth = 200
    signHeight = 100

    ' PDFファイルを開く
    If acroPdObj.Open(targetFilePath) Then
        Set acroAvObj = acroPdObj.OpenAVDoc(targetFilePath)

        ' JSObjectを定義する
        Set jsObj = acroPdObj.GetJSObject

        ' SecurityHandlerを生成
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#gethandler
        Set objSign = jsObj.security.getHandler("Adobe.PPKLite")

        ' 証明書ログイン
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#login
        Call objSign.login(certPassword, certFilePath)
        
        ' パスワードのタイムアウトを設定
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#setpasswordtimeout
        Call objSign.setPasswordTimeout(certPassword, 30)

        ' 署名を付ける座標を設定する
        signatureCoords = Array(bottomLeftX, bottomLeftY + signHeight, bottomLeftX + signWidth, bottomLeftY)

        ' 署名フィールドを生成
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/doc.html#addfield
        Set signField = jsObj.addField("MySignatureField", "signature", 0, signatureCoords)

        ' デジタル署名する
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#id652
        Call signField.signatureSign(objSign, Array(), outputFilePath, False)

        ' 証明書ログアウト
        Call objSign.logout

        ' PDFファイルを閉じる
        Call acroAvObj.Close(1)
        Call acroPdObj.Close
    End If
    
    Set acroPdObj = Nothing
    Set jsObj = Nothing
    Set objSign = Nothing
End Sub

コード例の説明

    Dim acroPdObj As New Acrobat.AcroPDDoc
    Dim acroAvObj As New Acrobat.AcroAVDoc
    ...
    ' PDFファイルを開く
    If acroPdObj.Open(targetFilePath) Then
        Set acroAvObj = acroPdObj.OpenAVDoc(targetFilePath)

PDFファイルを開きます。
Acrobat.AcroPDDocでPDFを開いたら、バックグラウンドでAcrobatが起動しますが、デジタル署名は、Acrobatがバックグラウンドの状態ではうまく動作できない場合があります。
そのため、Acrobat.AcroAVDocでファイルを開くようにして、Acrobatが画面上で表示するようにします。

        ' JSObjectを定義する
        Set jsObj = acroPdObj.GetJSObject

JSObjectを取得します。
JSObjectは、Acrobat.AcroPDDocから取得できます。

        ' SecurityHandlerを生成
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#gethandler
        Set objSign = jsObj.security.getHandler("Adobe.PPKLite")

        ' 証明書ログイン
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#login
        Call objSign.login(certPassword, certFilePath)
        
        ' パスワードのタイムアウトを設定
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#setpasswordtimeout
        Call objSign.setPasswordTimeout(certPassword, 30)

証明書を使うため、SecurityHandlerを生成します。
Handlerは、例の「Adobe.PPKLite」以外にも、下記のURLの方法で使用できるものを確認することができます。

その後、証明書ファイルにログインします。
また、パスワードのタイムアウトを設定します。
(タイムアウト時間をデフォルト値(0)にすると、正しく署名処理ができない場合があります。)

        ' 署名を表示する場合、適切に値を設定します
        bottomLeftX = 200
        bottomLeftY = 100
        signWidth = 200
        signHeight = 100
        ...
        ' 署名を付ける座標を設定する
        signatureCoords = Array(bottomLeftX, bottomLeftY + signHeight, bottomLeftX + signWidth, bottomLeftY)

        ' 署名フィールドを生成
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/doc.html#addfield
        Set signField = jsObj.addField("MySignatureField", "signature", 0, signatureCoords)

署名を表示する位置を指定して、PDFファイルに署名を付けるFieldを追加します。
署名位置は、(x1, y1, x2, y2)であり、「x1 = x2」かつ「y1 = y2」の場合、非表示で署名を付けます。

非表示署名の座標設定の例
' bottomLeftX = 200
' bottomLeftY = 100
' signWidth = 0
' signHeight = 0
signatureCoords = Array(200, 100, 200, 100)

「addField」は、以下のように構成されます。

パラメーター 説明
cName フィールド名
自由に設定
"MySignatureField"
cFieldType フィールドタイプ
「signature」に固定
"signature"
nPageNum ページ番号
0から始める
0
oCoords 署名表示の座標
配列
Array(200, 100, 400, 200)

詳細は以下のレファレンスを確認してください。

        ' デジタル署名する
        ' https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/JS_API_AcroJS.html#id652
        Call signField.signatureSign(objSign, Array(), outputFilePath, False)

指定したフィールドにデジタル署名を付けて、ファイルを出力します。
「signatureSign」は、以下のように構成されます。

パラメーター 説明
oSig SecurityHandlerのオブジェクト objSign
oInfo SignatureInfoのオブジェクト
VBAからは作成できない形式
Array()
cDIPath 出力ファイルパス "C:\SignTest\Output\SignedPdf.pdf"
bUI 署名のためのユーザインタフェース表示
「True」の場合、署名ダイアログから署名
「False」(デフォルト)の場合、ユーザインタフェースなしで署名
False
        ' 証明書ログアウト
        Call objSign.logout

        ' PDFファイルを閉じる
        Call acroAvObj.Close(1)
        Call acroPdObj.Close
    End If

証明書ログアウトして、PDFファイルを閉じます。

参考

3
2
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
3
2