Java Tips | I/O・ネットワーク:PDF生成

Java Java
スポンサーリンク
スポンサーリンク

PDF生成ユーティリティが業務で必要になる理由

PDFは「改ざんされにくい」「どの環境でも同じ見た目で表示できる」「印刷に強い」という特性から、業務システムの出力フォーマットとして非常に多く使われます。 請求書、見積書、契約書、レポート、帳票、ダウンロード資料など、PDF生成はほぼすべての企業システムで必要になります。

しかし、初心者がやりがちな「文字を並べるだけ」「画像を貼るだけ」といった実装では、 レイアウト崩れ、フォント問題、改行制御、ページ分割などで必ず苦労します。

そこで役に立つのが PDF生成ユーティリティ です。 Java では Apache PDFBox が事実上の標準ライブラリで、 初心者でも扱いやすく、業務でも十分使える品質です。

PDF生成の基本発想

「ドキュメント → ページ → 描画コンテキスト」という構造を理解する

PDFは次の階層構造で作られます。

  • PDDocument(PDFファイル)
  • PDPage(ページ)
  • PDPageContentStream(描画コンテキスト)

この流れで「ページを作り、そこに文字や線や画像を描く」というイメージです。

最小構成のPDF生成(初心者向け)

まずは「文字を1行書く」だけのシンプルな例

import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import java.nio.file.Path;

public class SimplePdfWriter {

    public static void write(Path path) throws Exception {
        try (PDDocument doc = new PDDocument()) {
            PDPage page = new PDPage();
            doc.addPage(page);

            try (PDPageContentStream cs = new PDPageContentStream(doc, page)) {
                cs.beginText();
                cs.setFont(PDType1Font.HELVETICA, 16);
                cs.newLineAtOffset(50, 750);
                cs.showText("Hello PDF!");
                cs.endText();
            }

            doc.save(path.toFile());
        }
    }
}
Java

使い方の例です。

SimplePdfWriter.write(Path.of("out/simple.pdf"));
Java

ここで重要なのは 「beginText → endText のペア」 を必ず守ることです。 PDFは描画命令が厳密なため、これを忘れると文字が表示されません。

PDFに複数行のテキストを書く

改行は「newLineAtOffset」で自分で制御する

PDFは「自動改行」がありません。 そのため、行ごとに座標をずらして描画します。

public static void writeLines(PDPageContentStream cs, String[] lines) throws Exception {
    cs.beginText();
    cs.setFont(PDType1Font.HELVETICA, 12);
    cs.newLineAtOffset(50, 750);

    for (String line : lines) {
        cs.showText(line);
        cs.newLineAtOffset(0, -20); // 20px 下に移動
    }

    cs.endText();
}
Java

ここで深掘りしたいポイントは 「PDFは座標ベースで描画する」 ということです。 HTMLのように自動レイアウトはありません。 そのため、行間・段落・余白をすべて自分で制御します。

PDFに画像を貼る

PDImageXObject を使う

import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

PDImageXObject image = PDImageXObject.createFromFile("logo.png", doc);
cs.drawImage(image, 50, 600, 120, 60); // x, y, width, height
Java

画像は「座標とサイズ」を指定して描画します。

PDFに表(テーブル)を書く

線を引きながらセルを描画する

PDFには「表」という概念がありません。 そのため、線を引いてセルを作り、文字を描画します。

public static void drawTable(PDPageContentStream cs, float startX, float startY) throws Exception {
    float rowHeight = 20;
    float colWidth = 100;

    // 行の線
    for (int i = 0; i <= 3; i++) {
        cs.moveTo(startX, startY - i * rowHeight);
        cs.lineTo(startX + colWidth * 3, startY - i * rowHeight);
        cs.stroke();
    }

    // 列の線
    for (int i = 0; i <= 3; i++) {
        cs.moveTo(startX + i * colWidth, startY);
        cs.lineTo(startX + i * colWidth, startY - rowHeight * 3);
        cs.stroke();
    }
}
Java

ここで深掘りしたいポイントは 「PDFは表を自動生成してくれない」 ということです。 表を作るには線を引き、セルに文字を描く必要があります。

実務向け PDF生成ユーティリティ(テンプレート)

テキスト・画像・表をまとめて扱える形

import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.nio.file.Path;

public class PdfUtils {

    public static void createReport(Path path, String title, String[] lines, String imagePath) throws Exception {
        try (PDDocument doc = new PDDocument()) {
            PDPage page = new PDPage();
            doc.addPage(page);

            try (PDPageContentStream cs = new PDPageContentStream(doc, page)) {

                // タイトル
                cs.beginText();
                cs.setFont(PDType1Font.HELVETICA_BOLD, 18);
                cs.newLineAtOffset(50, 780);
                cs.showText(title);
                cs.endText();

                // 本文
                cs.beginText();
                cs.setFont(PDType1Font.HELVETICA, 12);
                cs.newLineAtOffset(50, 740);
                for (String line : lines) {
                    cs.showText(line);
                    cs.newLineAtOffset(0, -18);
                }
                cs.endText();

                // 画像
                if (imagePath != null) {
                    PDImageXObject img = PDImageXObject.createFromFile(imagePath, doc);
                    cs.drawImage(img, 50, 600, 120, 60);
                }
            }

            doc.save(path.toFile());
        }
    }
}
Java

使い方の例です。

PdfUtils.createReport(
        Path.of("out/report.pdf"),
        "売上レポート",
        new String[]{"2026年8月7日", "売上合計: 1,234,567円"},
        "logo.png"
);
Java

PDF生成で必ず意識すべき重要ポイント

1. PDFは「自動レイアウト」がない

HTMLやExcelのように自動で整列してくれません。 座標を自分で指定する必要があります。

2. フォント問題に注意

日本語フォントを使う場合、PDFBox の標準フォントでは表示できません。 NotoSansCJK などの外部フォントを読み込む必要があります。

3. ページ分割は自動ではない

行がページの下に到達したら、自分で新しいページを作る必要があります。

4. PDFは「描画命令の集まり」

テキスト・線・画像はすべて「描画命令」として記録されます。 順番を間違えると表示されません。

PDF生成ユーティリティの実務的な使いどころ

帳票出力

請求書、見積書、契約書などをPDFで出力できます。

レポート生成

売上レポート、分析レポートなどをPDFでダウンロードできます。

外部ベンダーへの資料提供

Excelよりも「見た目が固定される」ため、PDFが好まれます。

バッチ処理での帳票生成

夜間バッチで大量のPDFを生成する場合にもユーティリティ化が有効です。

まとめ:PDF生成ユーティリティで身につけてほしい感覚

PDF生成ユーティリティは、業務データを「見た目を固定した形」で外部へ届けるための重要な仕組みです。 そこには次のようなポイントがあります。

  • PDFは「ページ → 描画コンテキスト → テキスト・画像・線」の構造で作る
  • 自動レイアウトがないため、座標を自分で制御する
  • 日本語フォントは外部フォントを使う必要がある
  • ページ分割は自動ではないため、自分で制御する
  • ユーティリティ化することで帳票出力の品質が統一される

タイトルとURLをコピーしました