はじめに
現在のWebシステムにおいて帳票の出力を行う場合、PDF形式が選択されることが一般的になっています。その理由としては、データサイズをコンパクトにすることができる、情報の改ざんを防止できる、などが挙げられます。一般ユーザにも普及していますので、システム開発時に顧客からPDF形式での情報の出力を求められることも多いのではないでしょうか。
この記事では、「iText」というライブラリを活用して、PDFの出力を行う方法を解説します。
対象読者
Javaプログラミングで開発を行った経験のある方、および、Javaプログラミングに興味をお持ちの方を対象としています。
必要な環境
このサンプルアプリケーションを動作させるには、以下のソフトウェアが最低限必要です。環境についての詳細や設定方法については、サーバサイド技術の学び舎 - WINGSにある「サーバサイド環境構築設定」を参照してください。
サンプルは、必要なjarファイルを含めてwarファイル形式で提供しています。記事上部リンクからファイル「itext.war」をダウンロードし、アプリケーションサーバに配置(ディプロイ)して下さい(Tomcatの場合は、「webapps」フォルダ配下にwarファイルを設定して、再起動して下さい)。アプリケーションサーバ起動後に、「http://localhost:8080/itext」にアクセスすると、サンプルを動作させることができます(ホスト名・ポート番号はご自身の環境に合わせて変更して下さい)。
iTextとは
iTextはPDFをJavaで扱うためのライブラリとしてオープンソースで開発されています。使用する際は、MPL、LGPLから、いずれかのライセンスを選択することとなっています。
ライブラリはjarファイル形式で配布されています。利用する際は、iTextのサイトから「itext-1.3.jar」をダウンロードして下さい。また、日本語を使用する際は、別途日本語フォント用のライブラリが必要となりますのでこちらのサイトから「iTextAsian.jar」をダウンロードして下さい。
サンプルアプリケーションの概要
サンプルとして、iTextを使用して動的にPDFを作成するWebアプリケーションを紹介します。
処理の流れは、以下のようになります。
- ブラウザより名前を入力して送信。
- リクエストを受け取ったサーブレットが、PDF形式でデータをクライアントに返信する。
- ブラウザに動的に作成されたPDFが表示される。
サンプルとして作成するPDFは、業務システムで一般的に作成されるような一覧表をイメージしています。
iTextを使用した動的なPDF作成
iTextでは、出力するPDF全体をDocument
クラスとして表現しています。文字列はPhrase
クラスやParagraph
クラス、表はTable
クラスで表現し、Document#add
メソッドでDocument
クラスにそれぞれのオブジェクトを追加して、出力するPDFを作成する仕組みになっています。
それでは、詳細なアプリケーションの流れを見ていきましょう。
名前の入力
入力画面の「送信」ボタンをクリックすると、itextServlet
クラスのdoPost
メソッドが実行されます。
ここでは、クライアントから送信されてきた名前をrequest
インスタンスから取り出しています。
public class itextServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //入力画面から送信されてきた名称を表示します。 request.setCharacterEncoding("Shift-JIS"); String strName =request.getParameter("input_name");; //(以下略) }
PDF出力用クラスの定義
文書オブジェクトを作成して、PDF出力の準備をします。
//出力用のStreamをインスタンス化します。 ByteArrayOutputStream byteout = new ByteArrayOutputStream(); //文書オブジェクトを生成 //ページサイズを設定します。 Document doc = new Document(PageSize.A4, 50, 50, 50, 50); try { //アウトプットストリームをPDFWriterに設定します。 PdfWriter pdfwriter = PdfWriter.getInstance(doc, byteout); }
Document
クラスは、出力するPDFを表す文書オブジェクトです。Document
クラスのコンストラクタにて、出力するPDFのページサイズと上下左右の余白を設定できます(省略した場合は、デフォルトでA4サイズとなります)。PdfWriter
クラスは、PDFの出力を行うクラスです。PdfWriter
クラスに、出力するDocument
インスタンスと、出力先としてByteArrayOutputStream
インスタンスを設定します。
これでPDF出力の初期設定は完了です。
フォントの設定
出力するフォントの設定を行います。
/* フォント設定部 */ //(ゴシック15pt(太字) Font font_header = new Font(BaseFont.createFont("HeiseiKakuGo-W5","UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED),15,Font.BOLD); //ゴシック11pt Font font_g11 = new Font(BaseFont.createFont("HeiseiKakuGo-W5","UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED),11); //ゴシック10pt Font font_g10 = new Font(BaseFont.createFont("HeiseiKakuGo-W5","UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED),10); //明朝10pt Font font_m10 = new Font(BaseFont.createFont("HeiseiMin-W3", "UniJIS-UCS2-HW-H", BaseFont.NOT_EMBEDDED),10); //ゴシック11pt(下線あり) Font font_underline_11 = new Font(BaseFont.createFont("HeiseiKakuGo-W5","UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED),11,Font.UNDERLINE); //ゴシック11pt(赤) Font font_red_11 = new Font(BaseFont.createFont("HeiseiKakuGo-W5","UniJIS-UCS2-H", BaseFont.NOT_EMBEDDED),11); font_red_11.setColor(new Color(255,0,0));
フォントの設定には、Font
クラスを使用します。文書を出力する際にフォント情報としてFont
クラスのインスタンスを設定します。何度も使用するようなフォントは処理の初期段階で設定しておき、再利用すると処理が冗長にならずに良いと思います。
Font
クラスのインスタンスを作成する際、Font
クラスのコンストラクタの第1引数にフォントの種類を表すBaseFont
クラスのインスタンスを渡しています。第2引数にはフォントタイプ(太字、下線付き)を指定するFont
クラスの定数を、また、第3引数にはint
型で指定したフォントサイズを渡します。フォントに色の設定を行う場合は、Font#setColor
メソッドを使用してRGB形式で色を指定して下さい。
なお、日本語フォントを使用する際は、BaseFont#createFont
メソッドにてBaseFont
インスタンスを作成して下さい。BaseFont#createFont
の第1引数には使用するフォント名を、第2引数にはエンコーディング名を設定します(日本語のフォント、エンコーディングは「iTextAsian.jar」に格納されています)。
フォント名 | 説明 |
KozMinPro-Regular | 明朝体 |
HeiseiMin-W3 | 明朝体 |
HeiseiKakuGo-W5 | ゴシック体 |
エンコーディング名 | 説明 |
UniJIS-UCS2-H | Adobe日本語文字のUniCode用エンコーディング |
UniJIS-UCS2-V | UniJIS-UCS2-Hの縦書きエンコーディング |
UniJIS-UCS2-HW-H | UniJIS-UCS2-Hのうち、プロポーショナル文字のみ半角文字に変更したエンコーディング |
UniJIS-UCS2-HW-V | UniJIS-UCS2-HW-Hの縦書きエンコーディング |
PDFファイルの説明の設定
出力されたPDFに作成者を設定します。
//出力するPDFに説明を付与します。 doc.addAuthor("岡 雅久"); doc.addSubject("iTextサンプル");
出力するPDFに作成者と説明を設定することができます。Document#addAuthor
メソッドで作成者名を、Document#addSubject
メソッドで文書の説明を設定します。
ヘッダーとフッターの設定
出力するPDFのヘッダーとフッターを設定します。
//ヘッダーの設定をします。 HeaderFooter header = new HeaderFooter( new Phrase("○○商事 月間売上実績", font_header), false); header.setAlignment(Element.ALIGN_CENTER); doc.setHeader(header); //フッターの設定をします。 HeaderFooter footer = new HeaderFooter( new Phrase("--"), new Phrase("--")); footer.setAlignment(Element.ALIGN_CENTER); footer.setBorder(Rectangle.NO_BORDER); doc.setFooter(footer);
ヘッダーとフッターの設定には、HeaderFooter
クラスを使用します。
ヘッダーに設定したい文字列は、Phrase
クラスにFont
クラスのインスタンスと合わせて設定します。HeaderFooter#setAlignment
メソッドを使用して表示位置を調整して、Documnet#setHeader
メソッドでPDFに出力する設定を行います。表示位置の指定の際には、Element
クラスに保持している定数を使用すると便利です。
また、フッターの場合も同様に、Phrase
クラスに出力情報を設定し、Documnet#setFooter
メソッドでPDFに出力する設定を行います。なお、HeaderFooter
クラスのコンストラクタで、入力引数を2つ取るメソッドを使用すると、ページナンバーを出力することができます。
文書の出力開始
PDF文書の出力を開始します。
//文章の出力を開始します。 doc.open(); /* 売上実績表のテーブルを作成します */ //帳票明細の条件部分を設定します。 doc.add(new Paragraph("2005年5月実績", font_red_11)); Paragraph para_1 = new Paragraph("担当者:" + strName, font_g11); para_1.setAlignment(Element.ALIGN_RIGHT); doc.add(para_1); doc.add(new Paragraph("")); Paragraph para_2 = new Paragraph("商品名:△△△△", font_underline_11); para_2.setAlignment(Element.ALIGN_LEFT); doc.add(para_2);
文書の出力を開始する際は、Document#open
メソッドを使用します(ヘッダー、フッター、PDFの作成者情報は文書出力開始前に設定しておく必要があります)。出力したい文字列は、Paragraph
クラスにFont
クラスのインスタンスと合わせて設定して、Documnet#add
メソッドでPDFに出力します。Paragraph
クラスは、Phrase
クラスを継承しているので基本的な性質は同じですが、Paragraph
クラスではsetAlignment
メソッドを使用した表示位置の指定などの体裁の設定ができます。
表の出力
業務アプリケーションで帳票を作成する際、表の作成はほぼ必須ではないでしょうか。iTextではライブラリに用意されたクラスを使用することで簡単に表を作成できます。
//帳票明細の明細行を設定します。 Table uriage_table = new Table(4); //売上テーブル全体の幅を設定します。 uriage_table.setWidth(100); //テーブル各列の幅をパーセンテージで設定します。 int uriage_table_width[] = {10,20,40,30}; uriage_table.setWidths(uriage_table_width); //テーブルのデフォルトの表示位置(横)を設定します。 uriage_table.setDefaultHorizontalAlignment(Element.ALIGN_CENTER); //テーブルのデフォルトの表示位置(縦)を設定します。 uriage_table.setDefaultVerticalAlignment(Element.ALIGN_MIDDLE); //テーブルの余白を設定します。 uriage_table.setPadding(3); //テーブルのセル間の間隔を設定します。 uriage_table.setSpacing(0); //テーブルの線の色を設定します。 uriage_table.setBorderColor(new Color(0, 0, 0));
iTextで表を作成するには、Table
クラスを使用します。インスタンス化する際に引数として作成する表の列数を設定します。Table#setWidth
メソッドで表全体の表示幅をパーセンテージで設定します。また、Table#setWidths
メソッドで各列の幅をパーセンテージで設定します。
//明細行の項目名部分のセルの設定を行います //(セルに網掛け設定を行います)。 Cell cell_11 = new Cell(new Phrase("順位", font_g10)); cell_11.setGrayFill(0.8f); Cell cell_21 = new Cell(new Phrase("顧客コード", font_g10)); cell_21.setGrayFill(0.8f); Cell cell_31 = new Cell(new Phrase("顧客名称", font_g10)); cell_31.setGrayFill(0.8f); Cell cell_41 = new Cell(new Phrase("金額", font_g10)); cell_41.setGrayFill(0.8f); //テーブルにセルを設定します uriage_table.addCell(cell_11); uriage_table.addCell(cell_21); uriage_table.addCell(cell_31); uriage_table.addCell(cell_41);
表の各項目を設定するには、Cell
クラスを使用します。出力したい文字列は、Phrase
クラスにFont
クラスのインスタンスと合わせて設定し、Cell
クラスに格納します。セルに網掛け設定を行いたい場合は、Cell.setGrayFill
メソッドを使用します。作成したCell
クラスは、Table#addCell
メソッドで表に追加します。
//合計行を出力します。 Cell cell_goukei = new Cell(new Phrase("合計", font_g10)); cell_goukei.setGrayFill(0.8f); cell_goukei.setColspan(3); uriage_table.addCell(cell_goukei); Cell cell_sum = new Cell(new Phrase("136,900", font_m10)); cell_sum.setHorizontalAlignment(Element.ALIGN_RIGHT); uriage_table.addCell(cell_sum); //テーブルをドキュメントオブジェクトに追加します。 doc.add(uriage_table);
Cell#setColspan
メソッドで列の結合、Cell#setRowspan
メソッドで行の結合が行えます。
Cell
クラスの設定が完了したTable
クラスは、Documnet#add
メソッドでPDFに出力します。
クライアントへの出力
出力したPDFを、クライアントのブラウザへ送信します。
public class itextServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //(省略) // 出力を終了します。 doc.close(); // ブラウザへのデータを送信します //(出力するコンテキストタイプにPDFを指定します)。 response.setContentType("application/pdf"); response.setContentLength(byteout.size()); OutputStream out = response.getOutputStream(); out.write(byteout.toByteArray()); out.close();
Documnet#close
メソッドにてPDFへの出力処理を完了します。出力したPDFは、OutputStream#write
メソッドでクライアントに送信します。
また、PDFタイプのデータであることをクライアントのブラウザに伝えるために、HttpServletResponse#setContentType
にてコンテンツタイプ(MIME)をPDFとして設定しています。
以上で、PDFファイルを動的に作成する処理は終了です。
まとめ
iTextの主なライブラリクラスをまとめます。
クラス名 | 説明 |
Document | 出力するPDF文書を表すクラスです。 |
PdfWriter | 「Document」クラスをもとに、指定された出力先にPDF出力を行うクラスです。 |
Font | フォントを指定するためのクラスです。色の指定も可能です。 |
HeaderFooter | ヘッダー、フッターを設定するためのクラスです。 |
Chunk | 文字列の最小単位を表すクラスです。単一のフォントで表現されます。 |
Phrase | 文字列を設定するためのクラスです。複数のChunk クラスで構成されます。Chunk クラスを使用せずに直接文字列を設定することも可能です。 |
Paragraph | 文字列を設定するためのクラスで、Phrase クラスを継承しています。このクラス独自にインデントや表示位置の設定ができます。複数のChunk クラス、Phrase クラスで構成されますが、直接文字列を設定することも可能です。 |
Table | 表の出力を行うためのクラスです。 |
Cell | 表の各セルの設定を行うためのクラスです。 |
本稿では、簡単な業務帳票を動的に作成する処理を通して、iTextライブラリでPDFを作成する基本的な処理について紹介しました。PDFを作成する基本的な処理はサンプルのとおりですが、iTextにはまだいろいろなライブラリが用意されていますので、興味のある方は、iText付属のAPIドキュメントなどをぜひご一読ください。