開発者ブログ

ユーザー目線に立った使い心地の良いユーザビリティの設計と、Javaのオブジェクト指向を駆使して、パフォーマンスの最大化を追及。STSD株式会社の開発エンジニアによるブログです。

[Java] 帳票をPDFで出力する時にExcelをテンプレートとして使う方法

Javaを使って帳票類をPDFで出力・変換する時にExcelをテンプレート(雛形)として使えないか実際に作って検証してみました。

こんにちは

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

発端はお客さまから「PDFを出力するのを一個一個手でやっていると大変なのでテンプレートを用意しておいて変換できないか」というお話を頂いたことでして、帳票のテンプレートとしてExcelファイルを使い、それをJavaから読み込んで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番号の下にあるボックスはオートシェイプを使ったものですが問題なく表示されています。
複雑なレイアウトは試していませんが簡単なものであればほぼ崩れること無く変換できるようです。
綿田

Javaエンジニア募集中

歯車の一つにならない働き方をしませんか?

残業ゼロ。ワークライフバランス重視。 多くの企業に選ばれる自社製品の開発にあなたも参加しませんか?

Latest Posts