JavaでPDF作成してみた。


はじめに

帳票出力なんてどこのシステムでも見られたものですが、最近はペーパーレス化だなんだで、紙で出力すること自体減ってきているような気がしています。とはいえ帳票的なものはまだまだ必要な商習慣。簡単にPDFデータを作ってみましょう。

ライブラリ

pdfbox-2.0.8

ダウンロードはこちらから。
公式

まずはファイルを作成してみる

package pdf;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;

public class PdfTest {

    public static void main(String args[]) {
        try {

            // ドキュメントオブジェクトの作成
            PDDocument document = new PDDocument();

            // ページオブジェクトの作成
            PDPage page = new PDPage();
            document.addPage(page);

            // ドキュメントを保存します
            document.save("test.pdf");
            document.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果

1ページだけのファイルが出来ましたね。

文字を出力する

次に文字の出力です。

package pdf;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

public class PdfTest {

    public static void main(String args[]) {
        try {

            // ドキュメントオブジェクトの作成
            PDDocument document = new PDDocument();

            // ページオブジェクトの作成
            PDPage page = new PDPage();
            document.addPage(page);

            //文字出力処理
            PDPageContentStream contentStream = new PDPageContentStream(document, page);
            contentStream.beginText();
            //フォント指定
            PDFont font = PDType1Font.TIMES_ITALIC;
            contentStream.setFont(font, 12);
            //出力位置指定
            contentStream.newLineAtOffset(0f, 0f);
            //出力文字列
            contentStream.showText( "HelloWorld" );
            contentStream.endText();
            contentStream.close();

            // ドキュメントを保存します
            document.save("test2.pdf");
            document.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果

出力位置をcontentStream.newLineAtOffset(0f, 0f)としていますので、一番左下に出力されます。出力フォントも色々種類がありますよ。

日本語を出力する

package pdf;

import java.io.File;

import org.apache.fontbox.ttf.TrueTypeCollection;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;

public class PdfTest {

    public static void main(String args[]) {
        try {

            // ドキュメントオブジェクトの作成
            PDDocument document = new PDDocument();

            // ページオブジェクトの作成
            PDPage page = new PDPage();
            document.addPage(page);

            //文字出力処理
            PDPageContentStream contentStream = new PDPageContentStream(document, page);
            contentStream.beginText();
            //フォント指定
            File file = new File("C:/Windows/Fonts/msmincho.ttc");
            TrueTypeCollection collection = new TrueTypeCollection(file);
            PDFont font = PDType0Font.load(document, collection.getFontByName("MS-Mincho"), true);

            contentStream.setFont(font, 12);
            //出力位置指定
            contentStream.newLineAtOffset(0f, 755f);
            //出力文字列
            contentStream.showText( "こんにちは世界" );
            contentStream.endText();
            contentStream.close();

            // ドキュメントを保存します
            document.save("test3.pdf");
            document.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果

フォントファイルは.ttfと.ttcで若干扱いが変わってきます。今回は.ttcを使用しています。

ファイルを作成せず、PDFデータのみ保持する

業務のケースによっては実ファイルを作成せず、データのみ保存しておきたい、というような要件があるかもしれません。特に問題なく実現できます。

package pdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.fontbox.ttf.TrueTypeCollection;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;

public class PdfTest {

    public static void main(String args[]) {
        try {

            // ドキュメントオブジェクトの作成
            PDDocument document = new PDDocument();

            // ページオブジェクトの作成
            PDPage page = new PDPage();
            document.addPage(page);

            //文字出力処理
            PDPageContentStream contentStream = new PDPageContentStream(document, page);
            contentStream.beginText();
            //フォント指定
            File file = new File("C:/Windows/Fonts/msmincho.ttc");
            TrueTypeCollection collection = new TrueTypeCollection(file);
            PDFont font = PDType0Font.load(document, collection.getFontByName("MS-Mincho"), true);

            contentStream.setFont(font, 12);
            //出力位置指定
            contentStream.newLineAtOffset(0f, 755f);
            //出力文字列
            contentStream.showText( "こんにちは世界。データのみ保存。" );
            contentStream.endText();
            contentStream.close();

            // ドキュメントデータを保存します
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            document.save(out);
            document.close();

            InputStream streamData =new ByteArrayInputStream(out.toByteArray());

            System.out.println("確認------------");
            System.out.println("streamData" + streamData);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

このままblob型カラムなどに保存できます。

作成したPDFから文字列を抽出する。

package pdf;

import java.io.File;
import java.io.StringWriter;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;

public class GetPdfText {

    public static void main(String args[]) {
        try {

            String pdfFile = "test3.pdf";
            PDDocument document = PDDocument.load(new File(pdfFile));
            StringWriter output = new StringWriter();
            PDFTextStripper stripper = new PDFTextStripper();
            stripper.setStartPage(1);
            stripper.setEndPage(1);
            stripper.setSortByPosition(false);
            stripper.setShouldSeparateByBeads(true);
            stripper.writeText(document, output);
            String content = output.toString();
            System.out.println("---------出力開始-------------");
            System.out.println(content);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果

---------出力開始-------------
こんにちは世界

他にも画像埋め込みや罫線など、色々な機能がありますので、機会を見て追記していこうと思います。