PDFライブラリiTextを使う

WebアプリケーションでPDF形式での帳票出力機能が必要になったので、PDFライブラリであるiTextを調べてみた。
Java用のPDF出力コンポーネントiTextが元で、.NETで使用可能なPortもいくつかある。

今回は、日本人の氏原氏によってPortされていて、日本語の情報も豊富なiText.NETを使うことにした。サンプルなど資料が充実しているため非常にとっつきやすいと思う。ありがたやありがたや。

やりたいことは、既存のPDFを読み込んで、そこにDBから読み込んだテキスト・画像を表示した帳票PDFをブラウザに表示する。

まずは、ページサイズと上下左右のマージンを入力してPDFを作成する

Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=test.pdf");

Document doc = new Document(PageSize.A4, 30, 20, 80, 20);
PdfWriter pw = PdfWriter.getInstance(doc, Response.OutputStream);
doc.open();

続いて、既存のPDF文書をテンプレートとして読み込み

PdfReader pr = new PdfReader(Server.MapPath("template.pdf"));
PdfImportedPage page = pw.getImportedPage(pr, 1); // インポートするページを指定する
PdfContentByte pcb = pw.getDirectContent();
pcb.addTemplate(page, 0, 0);

フォントを設定。ちなみにMSゴシックなどWindows内蔵の日本語フォントを指定するには@"c:\windows\fonts\msgothic.ttc,1"など、直接フォントファイルのパスを指定してやる必要がある。

BaseFont bf = BaseFont.createFont(@"c:\windows\fonts\msgothic.ttc,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font font_main = new Font(bf, 10, Font.NORMAL); // 10pt 標準字体

テキストを追加するには、Paragraphオブジェクトを作成してDocument.add()してやるだけ。これだけで自動改行付きの段落を作れる。

Paragraph prg = new Paragraph(11.5f, strDescription, font_main);
prg.setIndentationLeft(20); // 左側のインデントを指定
prg.setAlignment(Element.__Value.ALIGN_LEFT); // アラインメントを指定
doc.add(prg); // ドキュメントに追加


文書への画像の追加もこんな感じで楽々。ただしWindowsの画面とPDFでは画面解像度の違いからか、そのままのサイズで登録してしまうと画面がぼけてしまう。そのためImage.scalePercent()で画像を75%縮小して登録している。ちなみにscalePercent()で縮小しても表示上のサイズが小さくなるだけでデータは下のまま入ってるみたい。あと画像サイズは用紙のサイズに合わせて自動的に変わったりはしないので、大きいサイズの画像を張るときは適宜縮小してやる必要がある。

Image img = Image.getInstance(strImageFilePath);

// PDF(72dpi)とWindows(96dpi)の画面解像度の違いを補正する。
img.scalePercent(72.0f / 96.0f * 100f);

img.setAlignment(Element.__Value.ALIGN_CENTER);
doc.add(img);


最後は、Document.Close()とResponse.End()でブラウザ上に表示させる。

// ドキュメントを閉じる
doc.close();
// レスポンスを返す
Response.End();


ちなみに、Document.add()で次々オブジェクトを追加して行くと、どんどん下へ下へと伸びて行く。指定した絶対位置にテキストを表示させるにはPdfContentByte.beginText()以下を使う。この場合、行末の自動折り返しは使用できないので注意。ちなみにPDFの座標系は左下が(0,0)となる。最初これに気づかずハマタ orz

pcb.beginText();
pcb.setFontAndSize(bf, 10.0f);

pcb.setTextMatrix(460, 815);
pcb.showText("絶対値への表示");

pcb.endText();


これだけ簡単にPDF出力が出来てしまうのはすばらしいですな。あとParagraphをDocument.add()していく手法だと、1ページに収まりきらない場合に勝手に改ページされてしまうのがちょっと困る。この回避方法を書こうと思ったけど眠気MAXなため今度にしよう。


あとiText用の帳票モデリングツールがあるのを発見

これも調べてみよう。