Wie kann man mit Java PDF-Dateien erstellen?

Die iText-Bibliotheken stellen umfangreiche Funktionen zur Bearbeitung von PDF-Dateien zur Verfügung. Zur Verwendung müssen sie als externe Bibliothek geladen werden. Siehe hierzu: Bibliotheken laden.

Das Erzeugen und Beschreiben einer *.pdf-Datei erfolgt prinzipiell in fünf Schritten:

  1. Erzeugen eines Document-Objektes
  2. Erzeugen eines Writers, der in die PDF-Datei schreibt
  3. Öffnen der PDF-Datei
  4. Schreiben des Textes
  5. Schließen der PDF-Datei

Die wesentlichen Routinen zur Erzeugung der *.pdf-Datei werden in der Methode createPdf() ausgeführt. Sie muss zum Abfangen von Fehlern bei der Erzeugung des Dokumentes und bei dessen Export DocumentException und IOException abfangen können. Zu Beginn werden dann die ersten drei der o.a. Vorgänge ausgeführt.
Der eigentliche Schreibvorgang kann auf zwei übereinander angeordneten Schichten ausgeführt werden. Auf ihnen können Text und Bilder beliebig vom Entwickler eingefügt werden. Hierzu werden Objekte vom Typ PdfContentByte entweder von der unteren über die Methode PdfWriter.getDirectContentUnder() oder von der oberen über die Methode PdfWriter.getDirectContent() erzeugt. Die Elemente der oberen Ebene überlappen insgesamt diejenigen der unteren. Innerhalb beider Schichten überlappen sich die eingefügten Elemente gemäß ihrer Einfügungsreihenfolge. D.h. dass die später eingefügten Elemente die vorhergehenden überdecken.

Um Text darzustellen muss zunächst ein BaseFont-Objekt gebildet und diesem eine Font-Familie mit der gewünschten Größe zugewiesen werden. Das erledigt die Methode BaseFont.createFont(), von denen die Klasse BaseFont einige überladene Versionen bereitstellt. Die hier verwendete parameterlose Variante erzeugt eine nicht eingebettete winansi-codierte Helvetica.
Die Methode PdfContentByte.moveText() definiert den Initialisierungspunkt des einzufügenden Textes. Bezugspunkte sind hierbei auf Seiten der Darstellungsfläche die untere linke Ecke und auf Seiten der Schrift das linke Ende der Baseline. PdfContentByte.showText() übergibt schließlich den einzufügenden String an der spezifizierten Position.
Um gesperrte Schriften zu erzeugen, können Wort- und Buchstabenabstände bei Bedarf mit den Methoden PdfContentByte.setWordSpacing() und PdfContentByte.setCharacterSpacing() manipuliert werden.

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;

public class PDFSchreiben {

    public static final String PDF = "/Users/joecze/Desktop/iText/document.pdf";

    public void createPdf(String filename) throws DocumentException,
            IOException {
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(filename));
        document.open();

        PdfContentByte cb = writer.getDirectContent();
        BaseFont bf = BaseFont.createFont();
        setImage(cb, "img/memory.png", 40);
        cb.beginText();
        cb.setFontAndSize(bf, 12);
        cb.moveText(20, 105);
        cb.showText("Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.");
        cb.moveText(120, -16);
        cb.setCharacterSpacing(2);
        cb.setWordSpacing(12);
        cb.newlineShowText("Erst recht auch jeden kleineren.");
        cb.endText();

        document.close();

    }

    private void setImage(PdfContentByte cb, String imgPath, float scalePercent)
            throws MalformedURLException, IOException, DocumentException {
        Image img = Image.getInstance(imgPath);
        img.scalePercent(scalePercent);
        img.setAbsolutePosition(cb.getXTLM(), cb.getYTLM());
        cb.addImage(img);
    }

    private void printMeasures(){
        System.out.println("A4-Ma\u00DFe: " + PageSize.A4.getWidth() + "pt x "
                + PageSize.A4.getHeight() + "pt - "
                + (PageSize.A4.getWidth() * 0.3527) + "mm x "
                + (PageSize.A4.getHeight() * 0.3527) + "mm");
    }

    public static void main(String[] args) throws DocumentException,
            IOException {
        PDFSchreiben ps = new PDFSchreiben();
        ps.createPdf(PDF);
        ps.printMeasures();
        System.out.println("done");
    }
}

Das Einbetten eines Bildes in eine *.pdf-Datei erfolgt im Beispiel in der Methode setImage(), der ein Objekt der Einfügungsebene, der Bildpfad als String und ein float-Wert zur Skalierung des Bildes übergeben werden. Sie wird in createPDF() aufgerufen.
Ein Image-Objekt wird von der Singleton-Klasse com.itextpdf.text.Image durch Übergabe des Pfades erzeugt. Es kann in der Folge auf die gewünschte Kantenlänge über eine prozentuale Angabe skaliert und an einer absoluten Position in die *.pdfDatei eingefügt werden. Die Position wird über die zu Grunde liegende Text-Matrix bestimmt, die jedoch auch durch die dreifach überladene Methode PdfContentByte.setTextMatrix() beeinflusst werden kann.

Die Methode printMeasures() demonstriert abschließend, dass, wie im Print-Bereich üblich, das Flächenmaß der zu Grunde liegenden Datei in Punkt angegeben wird und bei Bedarf entsprechend umgerechnet werden muss:

1pt = 1/72 inch = 0,3527mm