VBAマクロでPDFを印刷する方法およびプリンタ情報を取得する

## VBAマクロでPDF印刷をする

業務でExcelを処理しつつPDFを印刷する必要があったので、マクロでPDFを印刷する処理も組み込みました。

意外とすんなりいかなかったので記事にしました。

## 処理の概要

1. プリンタ情報を取得
1. PDFファイルのパスを取得
1. Adobe Acrobat Reader DCを起動して、PDFファイル一つ一つを印刷する

## 事前準備
1. Shellを使いますので、[VBE]-[ツール]-[参照設定]にて、「Microsoft Shell Controls And Automation」にチェックが入っていることを確認してください。
1. Adobe Reader DCが必要なので、インストールしておいてください。
1. 印刷に使いたいプリンタを「通常使うプリンターに設定」にチェックを入れてください。


## プリンタ情報を取得
VBAでは`Application.activePrinter`で通常使うプリンタを取得できます。
形式は「プリンタ名 on ポート名:」です。
「プリンタ名」以外は不要なので、プリンタ名だけに切り分ける処理が必要です。

```VB

    '通常使うプリンターを取得
    Dim activePrinter As String
    activePrinter = Application.activePrinter
    
    '取得できなかった時の処理
    If activePrinter = "" Then
        MsgBox "プリンター情報が取得できませんでした" & Chr(13) & "プリンターが接続されていることを確認してください"
        End
    End If
    
    Dim intPoint1 As Long           'プリンタ名を切り出す為の文字数

    'ファイル名（" on"の前まで）とポート名("on "の後から最後まで）を切り出す
    '※プリンタによって形式が異なるかもしれませんので、お使いの環境に合わせてください
    intPoint1 = InStr(activePrinter, "on") - 2
    
    Dim usePrinter As String 'ポートを除いたプリンタ名
    usePrinter = Left(activePrinter, intPoint1)
    
```

マクロの都合により、プリンタ名をそのまま変数として持っているか、どこかのセルに書き込んだりしてください。

## PDFファイルのパスを取得
印刷したいPDFファイルのフルパスとファイル名を取得します。
ファイル名の取得はもっといい方法あると思うので、あくまで参考くらいの感じでｵﾅｼｬｽ。

なお、以下ではDirを使っていますが、[別記事](https://qiita.com/shimayu22/items/2335d9d723a04b2b83ba)で指摘いただいた通り、Dirだとファイル名が文字化けする可能性があるので、FileSystemObjectを使った方が事故が防げるかと思われ。

<details><summary>サンプルコード</summary><div>

```VB

    'フォルダに格納しているserchFileファイル名を取得する
    Dim strPdfName() As String                                  'PDFファイルのフルパス配列
    ReDim strPdfName(0)                                         'まず0で初期化
    Dim serchFile As String
    serchFile = Dir("【フォルダの絶対パス】\*.pdf")               '指定のフォルダに置き換えてください
                                                                '拡張子がpdfのファイルを検索
    
    Do While serchFile <> ""
        strPdfName(UBound(strPdfName)) = "【フォルダの絶対パス】\" & serchFile
                                                                'パス+ファイル名追加
        ReDim Preserve strPdfName(UBound(strPdfName) + 1)     '配列を拡張
        serchFile = Dir()                                       '次のファイル名を取得
    Loop
    
    If UBound(strPdfName) > 0 Then
        ReDim Preserve strPdfName(UBound(strPdfName) - 1)     '余分な要素を削除
    End If

```

</div></details>

## PDFファイルを印刷する

コマンドラインから起動して印刷します。
[公式](https://helpx.adobe.com/jp/acrobat/kb/510705.html)に書いてありました。

>AcroRd32.exe /t path printername drivername portname
>Adobe Reader を起動し、印刷ダイアログボックスを表示せずに PDF ファイルを印刷し、Adobe Reader を終了する

公式ページだと上記コマンドですが、色々試したところ、`AcroRd32.exe /t path printername`で良さそうです。プリンタや環境によってdrivernameやportnameが必要かもしれませんが、今回は割愛します。

上記コマンドをテキスト形式で作成して、`shellObj.Run`で実行させます。


```VB

    'シェルオブジェクトの作成
    Dim shellObj As Object
    Set shellObj = CreateObject("WScript.shell")

    Dim itm As Variant
    Dim exeStm As String
    
    '先ほど取得したPDFファイルのフルパス配列をforeachで回す
    For Each itm In strPdfName
        
        exeStm = ""
        
        'コマンドラインの文字列を作成する
        exeStm = "AcroRd32.exe /t" & " " & itm & " " & printername
        shellObj.Run (exeStm)   '印刷する
        
        '1秒待機（不要かもしれない）
        Application.Wait [Now() + "0:00:01"]
       
    Next itm
    
    'お片づけ
    Set shellObj = Nothing

```

また、説明だと「Adobe Reader を終了する」とありますが、私の環境だと終了されませんでした。
印刷終わったら手動で閉じてください。

## おわりに
これ作るためにめちゃくちゃテスト印刷した。
※この後スタッフが裏紙として使用しました