ExcelVBAでWordドキュメントを軽量PDF化する

ExcelでWordドキュメントを軽量PDF化する

ExcelでWordドキュメントのファイル名の一覧表を作って、必要なものだけPDF化する、というのがお題。

ExportAsFixedFormatメソッドを使うやつは既に作成済みなので、PDF化部分を差し替えるのが目標。

ドキュメントを軽量PDF化するメソッド

ひとまず、コードだけ載っけておこう。

テストが不十分なので、ご利用の際は自己責任でどうぞ。

リスト1 標準モジュール
    Public Function convertDocumentToLightPDF( _
                ByVal targetDocument As Word.Document, _
       Optional ByVal PDFPrinter As String, _
       Optional ByVal printRange As WdPrintOutRange = wdPrintAllDocument, _
       Optional ByVal printFrom As Long, _
       Optional ByVal printTo As Long, _
       Optional ByVal printPages As String) As Boolean
On Error GoTo errorHandler
  Dim wordApp As Word.Application
  Set wordApp = targetDocument.Parent
  If PDFPrinter = "" Then PDFPrinter = wordApp.ActivePrinter
  If InStr(PDFPrinter, "PDF") < 1 Then _
    convertDocumentToLightPDF = False: Exit Function
  Dim currentPrinter As String
  currentPrinter = wordApp.ActivePrinter
  wordApp.ActivePrinter = PDFPrinter
  If printRange = wdPrintFromTo And _
     printFrom * printTo = 0 Then
    printFrom = 1
    printTo = 1
  End If
  If printRange = wdPrintRangeOfPages And _
     printPages = "" Then
    printPages = "1"
  End If
  If Not wrappedPrintOutMethod( _
           targetDocument:=targetDocument, _
           printRange:=printRange, _
           printFrom:=printFrom, _
           printTo:=printTo, _
           printPages:=printPages) Then GoTo errorHandler
  DoEvents
  convertDocumentToLightPDF = True
errorHandler:
  If Err.Number > 0 Then Err.Clear
  wordApp.ActivePrinter = currentPrinter
  Set wordApp = Nothing
  If Not convertDocumentToLightPDF Then _
    convertDocumentToLightPDF = False
End Function

Public Function wrappedPrintOutMethod( _
            ByVal targetDocument As Word.Document, _
            ByVal printRange As WdPrintOutRange, _
            ByVal printFrom As Long, _
            ByVal printTo As Long, _
            ByVal printPages As String) As Boolean
  With targetDocument
    If printRange = wdPrintAllDocument Or _
       printRange = wdPrintCurrentPage Or _
       printRange = wdPrintSelection Then _
         Call .PrintOut(Range:=printRange): GoTo Finalizer
    If printRange = wdPrintFromTo Then _
         Call .PrintOut(Range:=printRange, _
                        From:=printFrom, _
                        To:=printTo): GoTo Finalizer
    If printRange = wdPrintRangeOfPages Then _
         Call .PrintOut(Range:=printRange, _
                        Pages:=printPages): GoTo Finalizer
  End With
errorHandler:
  Err.Clear
  wrappedPrintOutMethod = False: Exit Function
Finalizer:
  wrappedPrintOutMethod = True
End Function

Boolean型のメソッドにした。途中でエラーが出たりしたら、Falseを返す。

あと、渡された引数に合わせてWord.Document.PrintOutメソッドを呼び出す分岐がめんどくさかったので、別途Word.Document.PrintOutメソッドをラップしたメソッドを作った。

2つ目のwrappedPrintOutMethodがそれ。

Word.Document.PrintOutは結構引数が多く、引数チェックが煩雑になるので、メインの方では致命的な不正引数だけチェックして、後はサブのメソッドの方で印刷範囲別(引数「Range」の値別)に対応することにした。

実行結果

Xドライブに「中野 浩一.docx」というドキュメントを置いて、次のコードで実験。

スト2 標準モジュール
Public Sub testConvertDocumentToLightPDF()
  Dim wordApp As New Word.Application
  Dim targetDoc As Word.Document
  Set targetDoc = wordApp.Documents.Open("X:中野 浩一.docx")
  Call convertDocumentToLightPDF(targetDoc, PDF_PRINTER)
  Set wordApp = Nothing
  Set targetDoc = Nothing
End Sub

途中「PDF_PRINTER」とあるのは、ウチの環境での「JUST PDF 3」のプリンタ名が入った定数。ちなみに、JUST PDF 3 on Ne03:という文字列が当てられている。

JUST PDF 3 側の設定で、黙って指定済みのフォルダに保存するようにしているので、実行するといつの間にか

f:id:akashi_keirin:20180430172716j:plain

こんな風にPDFができている。

画像ではPDFが2つできているが、上がconvertDocumentToLightPDFメソッドで作成したもの。

下は、

f:id:akashi_keirin:20180430173141j:plain

Wordの「名前を付けて保存」でPDF化したもの。

「最小サイズ」を指定しても48キロバイトもある。それに比べてconvertDocumentToLightPDFメソッドで作成した方は27キロバイト

なかなか優秀といえるのではなかろうか。

おわりに

ちなみに、元のドキュメントは16キロバイトである。