このエントリーをはてなブックマークに追加
こんにちは

今回はJavaを使ってPDFを出力するプログラムの話が主な内容です。

発端はお客さまから「PDFを出力するのを一個一個手でやっていると大変なのでテンプレートを用意しておいて変換できないか」というお話を頂いたことでして、帳票のテンプレートとしてExcelファイルを使い、それをJavaから読み込んでPDFに変換する検証を行なってみました。
PDF作成までの流れとしては、テンプレートとして置換文字列を埋め込んだExcelファイルを作成、JavaでExcelファイルを読み込み、Excelファイル内の置換文字列を置換、OpenOfficeに渡しPDF変換、PDFを受け取りファイルに保存、となります。

前準備

今回は以下が必要となるので予めダウンロード(インストール)しておきます。

  • OpenOffice 3.4
    オープンソースの統合オフィスソフトです。PDFへの変換にはこの中に含まれるPDF変換エンジンを使用します。
  • JODConverter 2.2.2
    OpenOfficeのPDF変換エンジンをJavaから使用するためのライブラリです。
  • Apache POI 3.9
    JavaからExcelを操作するためのライブラリです。

Excelでテンプレートを作成

まずはPDFに出力する内容を記載したドキュメントをExcelで作成します。
ここではサンプルとして請求書をイメージしたテンプレートを作成し、置換文字列を埋め込みました。

Excelファイルの読み込み

ここからはApache POIを使ってJavaからExcelファイルを操作します。
まずはExcelファイルを読み込みところから始めます。

// Excelファイルを読み込む
InputStream excel = new FileInputStream("c:/workbook/template.xls");

ワークブックを開いて置換文字を置換

セルを一個一個チェックして置換文字列があったら置換するようにします。

// ワークブックを開く
Workbook workbook = new HSSFWorkbook(excel);

// 最初のシートを開く
Sheet sheet = workbook.getSheetAt(0);

// セル内に埋め込まれている置換文字を置換
for (Iterator<Row> sheetIte = sheet.iterator(); sheetIte.hasNext(); ) {
    // 行を取得
    Row row = sheetIte.next();
    
    for (Iterator<Cell> cellIte = row.iterator(); cellIte.hasNext();) {
        // セルを取得
        Cell cell = cellIte.next();
        
        // 文字列タイプのセルのみを対象
        if (cell.getCellType() != Cell.CELL_TYPE_STRING) {
            continue;
        }
        
        if (cell.getStringCellValue().equals("#NAME#")) {
            // 「#NAME#」を置換
            cell.setCellValue("山田 太郎");
        } else if (cell.getStringCellValue().equals("#BANK_NAME#")) {
            // 「#BANK_NAME#」を置換
            cell.setCellValue("渋谷銀行");
        } else if (cell.getStringCellValue().equals("#BRANCH_NAME#")) {
            // 「#BRANCH__NAME#」を置換
            cell.setCellValue("恵比寿支店");
        } else if (cell.getStringCellValue().equals("#ACCOUNT_NAME#")) {
            // 「#ACCOUNT_NAME#」を置換
            cell.setCellValue("恵比寿 花子");
        } else if (cell.getStringCellValue().equals("#ACCOUNT_NO#")) {
            // 「#ACCOUNT_NO#」を置換
            cell.setCellValue("0123456789");
        } else if (cell.getStringCellValue().equals("#CREATE_DATE#")) {
            // 「#CREATE_DATE#」を置換
            cell.setCellValue(Calendar.getInstance().getTime());
        } else if (cell.getStringCellValue().equals("#NO#")) {
            //「#NO#」を置換
            cell.setCellValue("10020-039");
        } else if (cell.getStringCellValue().equals("#CONTACT_NAME#")) {
            //「#CONTACT_NAME#」を置換
            cell.setCellValue("STSD綿田");
        } else if (cell.getStringCellValue().equals("#TEL_NO#")) {
            // 「#TEL_NO#」を置換
            cell.setCellValue("03-1111-2222");
        } else if (cell.getStringCellValue().equals("#FAX_NO#")) {
            // 「#FAX_NO#」を置換
            cell.setCellValue("03-3333-4444");
        }
    }
}

PDFへの変換

編集したExcelの内容をバッファ内に書き出し、PDFへ変換します。

// バッファ内にExcelの内容を書き出す
ByteArrayOutputStream buff = new ByteArrayOutputStream();
workbook.write(buff);

// PDF変換時に渡すInputStreamを用意
ByteArrayInputStream in = new ByteArrayInputStream(buff.toByteArray());
buff.close();
excel.close();

// PDFの出力先を開く
FileOutputStream out = new FileOutputStream("c:/temp/test.pdf");

// OpenOfficeに接続(localhostの8100番ポート)
SocketOpenOfficeConnection con = new SocketOpenOfficeConnection(8100);
con.connect();

try {
    // ExcelからPDFへ変換
    DocumentConverter converter = new OpenOfficeDocumentConverter(con);
    converter.convert(
            in, new DefaultDocumentFormatRegistry().getFormatByFileExtension("xls"),
            out, new DefaultDocumentFormatRegistry().getFormatByFileExtension("pdf")
    );
} catch (Exception e) {
    e.printStackTrace();
} finally {
    // OpenOfficeから切断
    // ここで確実に切断しないとスレッドが終了しません
    con.disconnect();
}

out.flush();
out.close();
in.close();

OpenOfficeを起動してJavaを実行

JODConverterはOpenOfficeが待ち受けるポートと通信して変換を行います。
ただし、通常の起動方法ではポートで待ち受けるようにならないので、以下のようにオプションを付けて起動します。

soffice.exe -accept="socket,port=8100;urp;"
あとは通常通りJavaを実行するだけです。

出力されたPDFを見てみる

出力されたPDFを見てみると…無事に変換されました!

Excelファイルの読み込み

FAX番号の下にあるボックスはオートシェイプを使ったものですが問題なく表示されています。
複雑なレイアウトは試していませんが簡単なものであればほぼ崩れること無く変換できるようです。
綿田

このコンテンツは参考になりましたか?

送信する

デジタルマーケティングに対する
実体調査アンケート実施中

是非、アンケートにぜひご協力ください。

デジタルマーケティングに対する
実体調査アンケート実施中

是非、アンケートにぜひご協力ください。

 アンケートに回答する  ≫

無料eBookのダウンロード

【今からでも遅くない!】
初心者に贈る「インバウンドマーケティング」の始め方

 無料ダウンロードはこちら  ≫

人気の記事

タグ別