iTextSharpでPDFフォームに出力

仕事でiTextSharpを使ったのでメモ。

フォーム付きのPDFを読み込んで値を設定し、新しいPDFに保存するっていう要件。
雑に使ってみたけど簡単で処理速度も速くてこりゃいいやと思った。
(エクセルに出力してPDF変換とか遅すぎてはげた)

後半にはまりポイントをピックアップしてます。

■サンプルソース

Dim dstPath = "C:\work\sample.pdf"
Dim srcPath = "C:\work\input.pdf"
'日本語フォント
Dim font = BaseFont.CreateFont("c:\windows\fonts\msgothic.ttc,1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED)

Using doc As New Document() _
        , dstStream As New FileStream(dstPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None) _
        , copy As New PdfSmartCopy(doc, dstStream)
    '保存先PDFオープン
    Call copy.SetMergeFields()
    Call doc.Open()

    '元のPDFを読み込んで編集する
    Using ms As New MemoryStream _
            , srcStream As New FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) _
            , reader As New PdfReader(srcStream)

        'ページレベルにフィールドが設定されている場合は
        'ドキュメントレベルにフィールドを複製する
        Dim form = reader.Catalog.GetAsDict(PdfName.ACROFORM)
        Dim fields = form.GetAsArray(PdfName.FIELDS)
        If fields.Count = 0 Then
            For i = 1 To reader.NumberOfPages
                Dim page = reader.GetPageN(i)
                Dim annots = page.GetAsArray(PdfName.ANNOTS)

                For j = 0 To annots.Size - 1
                    Call fields.Add(annots.GetAsIndirectObject(j))
                Next
            Next
        End If

        'コピー対象のページを選択
        Call reader.SelectPages("1-1")

        'PDF編集
        Using stamper As New PdfStamper(reader, ms)
            '保存後はフォーム入力不可にする
            stamper.FormFlattening = True

            With stamper.AcroFields
                '日本語フォントを設定
                Call .AddSubstitutionFont(font)

                'フォームに値を設定
                Call .SetField("Text1", "abcdEFG")
                Call .SetField("Text2", "あいうえお")
                Call .SetField("Text5", "123456", "123,456", True)
            End With
        End Using

        '作成したPDFを保存先PDFに追加
        Call copy.AddDocument(New PdfReader(ms.ToArray))
    End Using
End Using

'保存したPDFを表示
Call Process.Start(dstPath)

■日本語が表示されない場合

PDFに日本語フォントを設定してあげるとよい。
外字などなければ埋め込みなしでいいと思う。

■AcroFieldsでフィールドが取得できない場合

おそらくPDFフォームの作り方の違いで発生するのでしょう。
ページレベルで定義されたフィールドをドキュメントレベルにも追加するといいみたいです。

参考:Why are the AcroFields in my document empty?