VBAからAdobe Acrobatを制御してPDFファイルに画像を追加する

# はじめに
AcrobatのGUIから画像を追加する作業は簡単でしたが、スクリプトで画像を追加することは、それほど簡単ではありませんでした。
レファレンスを調査して見ても、明確に画像を追加する関数を発見できず、方法を調べてみても想定した結果とはことなる場合がほとんどでした。
しかし、ファイルからPDFファイルにウォーターマーク（透かし）を追加する関数を活用して画像を追加ができました。
今回は、VBAからAdobe Acrobatを制御してPDFファイルに画像を追加する方法を整理しようと思います。

# 環境
・Windows 10 Pro
・Microsoft 365 (Excel)
・Adobe Acrobat Pro

# 画像追加方法

## 事前設定
PDFファイルを修正後、保存するためには、事前にAcrobatを起動して「メニュ」の「編集」→「環境設定」→分類で「セキュリティ（拡張）」を選択後、「サンドボックスによる保護」の「起動時に保護モードを有効にする」のチェックを外す必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/85e94b62-af34-1423-67b3-f47060644ea5.png)

## 画像追加機能の関数について
JSObjectから使用できる「**addWatermarkFromFile**」という関数があり、ファイル(PDFや画像ファイルなど)からPDFファイルにウォーターマーク (透かし)を追加する機能を持つ関数であります。
ウォーターマークを追加するための関数ですが、この関数を活用して普通に画像を追加することもできました。
以下のURLでも「addWatermarkFromFile」関数について、詳細の確認ができます。(英語)

https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/doc.html#addwatermarkfromfile

### 関数の引数構成
addWatermarkFromFile(cDIPath, nSourcePage, nStart, nEnd, bOnTop, bOnScreen, bOnPrint, nHorizAlign, nVertAlign, nHorizValue, nVertValue, bPercentage, nScale, bFixedPrint, nRotation, nOpacity)

:::note info
cDIPathは**必須**、他の引数は**任意**です。
:::

:::note warn
VBAから**addWatermarkFromFile**を呼び出す時、
前者の引数を指定し後者の引数を省略することはできますが
(例えば、nStartは**指定**、nEndは**省略**)、
前者の引数を省略し後者の引数を指定することはできません。
(例えば、nStartは**省略**、nEndは**指定**)
:::


### cDIPath
 画像ファイルのパスです。
 指定したファイルがPDFファイルではない場合(JPG、PNGなど)、Acrobatから画像ファイルをPDFファイルに変換して追加します。

### nSourcePage
 画像ファイルのどのページを使うかを指定します。
 インデックスは0から始まります。
 デフォルトは 0 です。

:::note info
- **例**
nSourcePage = 0 の場合
PDFファイルの1ページ目が画像として、入力PDFファイルに追加されます。
:::
※ 画像ファイルがPDFファイルではなく、画像ファイル(JPG、PNGなど)の場合、nSourcePage = 0で良いです。

### nStart, nEnd
 入力PDFファイルの何ページから何ページまで画像を追加するか指定します。
 nStartとnEndが同じの場合、指定したページのみに画像を追加します。
 
:::note info
 - **例1**
 nStart = 1、nEnd = 3 の場合
 入力PDFファイルの2ページから4ページまで画像を追加します。

- **例2**
nStart = 0、nEnd = 0 の場合
入力PDFファイルの1ページのみ画像を追加します。
:::

### bOnTop
 追加する画像のz-orderを指定します。
 Trueの場合、すべてのコンテンツの上に画像が追加されます。
 Falseの場合、すべてのコンテンツの下に画像が追加されます。
 デフォルトは True です。

:::note info
 - **例1**
bOnTop = True の場合
「Image」の画像がコンテンツの上にある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/3efca22c-484d-fc3c-5cf8-66ba17f9d128.png)

- **例2**
bOnTop = False の場合
「Image」の画像がコンテンツの下にある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/21b7ac5d-5323-4dde-bf06-73857eedfd3f.png)

:::

### bOnScreen
画面で文書を見る時、画像を表示するかどうかを指定します。
デフォルトは True です。

:::note info
- **例1**
bOnScreen = True の場合
画面上に「Image」の画像あり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/784bf2fa-f303-dec8-6cee-7be1b0abc472.png)

- **例2**
bOnScreen = False の場合
画面上に「Image」の画像なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/df1782ed-80c0-c2dc-117e-e71e2fabba1e.png)

:::

### bOnPrint
文書を印刷する時、画像を表示するかどうかを指定します。
デフォルトは True です。

:::note info
- **例1**
bOnPrint = True の場合
印刷のプレビューに「Image」の画像あり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/0a4101fd-ff86-0fe8-03e0-722c5fa6db0f.png)

- **例2**
bOnPrint = False の場合
印刷のプレビューに「Image」の画像なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/8fb31fc6-ba0d-2204-57dc-9b7b6345ebcd.png)

:::

### nHorizAlign, nVertAlign
nHorizAlignは、画像を水平方向にどのように配置するかを指定します。
デフォルトは 1 (中央) です。
nVertAlignは、画像を垂直方向にどのように配置するかを指定します。
デフォルトは 1 (中央) です。
入力できる値は以下のようになります。
| 値 | 説明 | 使える引数 |
|:-:|:-|:-|
| 0 | 左に配置 | nHorizAlign |
| 1 | 中央に配置 | nHorizAlign<br>nVertAlign |
| 2 | 右に配置 | nHorizAlign |
| 3 | 上に配置 | nVertAlign |
| 4 | 下に配置 | nVertAlign |

:::note info 
- **例1**
nHorizAlign=1, nVertAlign=1 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/aba9aecb-7016-8e47-5cf8-3e9f3d206ab7.png)

- **例2**
nHorizAlign=0, nVertAlign=3 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/fc2c3a85-f480-f873-b0d7-d10c0db49cf9.png)

- **例3**
nHorizAlign=2, nVertAlign=4 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/76cbd060-3fea-185e-6147-e2d841fd89c3.png)

:::

### nHorizValue, nVertValue, bPercentage
nHorizValueは、画像を水平位置を移動するために使用される数値です。
デフォルトは 0 です。

:::note info
nHorizValue > 0 の場合、画像が右に移動します。
nHorizValue < 0 の場合、画像が左に移動します。
:::


nVertValueは、画像を垂直位置を移動するために使用される数値です。
デフォルトは 0 です。

:::note info
nVertValue > 0 の場合、画像が上に移動します。
nVertValue < 0 の場合、画像が下に移動します。
:::

bPercentageは、nHorizValueとnVertValueの数値をページサイズの割合にするか、明示的なポイント数にするかを指定します。
デフォルトは False です。

:::note info
※ 例は、nHorizAlign=1, nVertAlign=1の前提です。
- **例1**
nHorizValue=100, nVertValue=200, bPercentage=False の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/484f912f-c640-a74f-c01a-55b41dbffecd.png)

- **例2**
nHorizValue=-0.1, nVertValue=-0.2, bPercentage=True の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/69a9576a-468a-0a59-699b-7b7fecf95f5c.png)

:::

### nScale
画像のスケールです。
デフォルトは 1.0 (100%) です。
※ nScale = -1 の場合、ページサイズに合わせて画像のスケールを調整します。

:::note info
- **例1**
nScale = 1.0 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/e11feee5-6861-845d-03a3-2fea985779c4.png)

- **例2**
nScale = 0.5 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/abb8dbaf-6cd0-a675-a7fb-3ee5622e9b53.png)

- **例3**
nScale = -1 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/6023d34a-7fb7-b524-5595-a9b14c96ba6c.png)

:::

### bFixedPrint
画像をFixedPrintウォーターマーク注釈として追加を指定します。
Trueの場合、印刷されるページのサイズに関係なく、固定のサイズ/位置に画像の印刷されます。
また、bOnTopの指定は無視されます。
デフォルトは False です。

:::note info
- **例**
bOnTop = False, bFixedPrint = True の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/1861573c-76de-48d1-94c7-0776e4ff9ebe.png)

:::

### nRotation
画像を反時計回りに回転します。
デフォルトは 0 です。

:::note info
- **例1**
nRotation = 0 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/1205e3c6-d360-727b-7be3-27420036a6d6.png)

- **例2**
nRotation = 90 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/21e1f3b5-bf9a-afa1-f001-165f5f7a9561.png)

- **例3**
nRotation = -90 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/843e014b-494a-d9ff-f118-d345797f53c3.png)

:::

### nOpacity
画像の不透明度を指定します。
0 は透明、1.0 は不透明です。
デフォルトは 1.0 です。

:::note info
- **例1**
nOpacity = 1.0 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/117605e2-e8a0-275b-7ca5-08a47a35dbb6.png)

- **例2**
nOpacity = 0.5 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/e6e9709a-6282-0ca0-2a42-578b562b4197.png)

- **例3**
nOpacity = 0 の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184971/436a1bda-3a42-eafd-6af7-b98dab8b2c82.png)

:::

## コードの例
```vb
Public Sub InsertImageInPdf()
    Dim acroPdObj As New Acrobat.AcroPDDoc
    Dim jsObj As Object

    Dim inputFilePath As String
    Dim paramObj As Dictionary
    
    Dim srcFilePath As String
    Dim dstFilePath As String
    Dim imageFilePath As String
    
    srcFilePath = "C:\AddImage\Input\InputPdfFile.pdf"
    dstFilePath = "C:\AddImage\Output\OutputPdfFile.pdf"
    imageFilePath = "C:\AddImage\Image\TargetImage.png"
    

    If acroPdObj.Open(srcFilePath) Then
        Set jsObj = acroPdObj.GetJSObject

        ' PDFファイルに画像を追加する
        ' 参照先：https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/doc.html#addwatermarkfromfile
        ' addWatermarkFromFile(cDIPath, nSourcePage, nStart, nEnd, bOnTop, bOnScreen, bOnPrint, nHorizAlign, nVertAlign, nHorizValue, nVertValue, bPercentage, nScale, bFixedPrint, nRotation, nOpacity)
        Call jsObj.addWatermarkFromFile(imageFilePath, 0, 0, 5, True, True, True, 0, 3, 100, -100, False, 0.5, False, 0, 0.7)

        ' PDFファイルを保存
        Call acroPdObj.Save(1, dstFilePath)

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

    Set acroPdObj = Nothing
    Set jsObj = Nothing
End Sub
```

# 参考

https://opensource.adobe.com/dc-acrobat-sdk-docs/library/jsapiref/doc.html#addwatermarkfromfile