Beliebte Suchanfragen

Cloud Native

DevOps

IT-Security

Agile Methoden

Java

|
//

PDF Generierung mit iText

7.8.2010 | 3 Minuten Lesezeit

Rückblick: In unserem letzten Sprint Planning Meeting stand die Aufgabe einer PDF-Generierung an. Wir hatten eine grobe Layout-Vorlage vom Kunden bekommen und die Service-Klassen zur Bereitstellung der benötigten Klassen waren ebenfalls schon vorhanden. Dennoch schätzten wir das zugehörige Ticket erstaunlich hoch. Kein Entwickler im Team hatte Erfahrung mit iText , gleichzeitig hatte jedoch jeder gruselige iText-Geschichten von anderen Entwickler gehört. Ein Zitat schwebte uns im Ohr: „Wenn du mit iText arbeitest, liest du früher oder später die Spezifikation des PDF-Formats .“

Nach einiger Recherche im Internet und mehreren Interviews anderer Projekt-Teams von codecentric möchte ich heute einen aus meiner Sicht sehr einfachen, robusten und vor allem schnellen Weg vorstellen, PDFs mit iText zu generieren. Das oben genannte Ticket wurde mit diesem Ansatz in einem Viertel der Zeit umgesetzt und die Angst der Team-Mitglieder vor iText ist deutlich gesunken.

iText bietet viele Möglichkeiten, PDFs komplett über die API zu erzeugen; mit allen Linien, Bildern, festen Texten, Farben uvm. Dieser Ansatz wird jedoch schnell sehr komplex und erzeugt sehr langen und fehleranfälligen Quellcode. Einfacher ist hier die Erzeugung eines „Vordrucks“ mit definierten Inhaltsfeldern. Dieser Vordruck wird in Form eines PDFs mit Formularfeldern gespeichert. Dieses Template-PDF kann jederzeit, z.B. im Adobe Reader , betrachtet werden und könnte so z.B. auch schon vor der Befüllung mit Daten mit dem Kunden abgestimmt werden.

Teil 1 – PDF-Formular erzeugen

PDF-Formulare lassen sich sehr einfach mit OpenOffice erzeugen. In meinem Beispiel habe ich OpenOffice Draw verwendet, der Ansatz funktioniert aber gleicherweise mit OpenOffice Writer oder Calc. Im jeweiligen Programm einfach ein neues Dokument anlegen und anschließend nach Belieben mit Texten, Farben oder Linien gestalten. Sobald das Layout fertig ist, müssen die Inhaltsfelder definiert werden. Dabei ist es hilfreich, wenn die Symbolleisten für Formular-Entwurf und Formular-Steuerelemente ausgewählt sind (Ansicht -> Symbolleisten). Mit diesen neuen Icons kann man unter anderem den Formular-Entwurfsmodus aktivieren. Jetzt kann z.B. aus den Formular-Steuerelementen ein Textfeld ausgewählt und in das Dokument eingefügt werden. Über einen Rechtsklick lassen sich die Eigenschaften des Textfelds definieren. Folgende Einstellungen sind interessant:

  • Name : Dieser Name wird später im Java Code zum Befüllen des Feldes referenziert.
  • Rahmen : Default ist 3D-Look – Normalerweise wird wohl ohne Rahmen besser passen.
  • Hintergrundfarbe, Ausrichtung, Schrift : Hier kann das Layout bestimmt werden. Layout-Angaben im Java Code sind damit überflüssig.
  • Text-Typ: Normalerweise einzeilig, möchte man jedoch im Java Code Text mit Umbrüchen einfüllen muss hier mehrzeilig ausgewählt werden.

Sobald die Formular-Felder keinen Rahmen haben, kann man diese im Dokument nicht mehr einfach erkennen. Hier hilft der Formular-Navigator.

Nach dem Layout und der Erstellung der Formular-Felder kann das Dokument in eine PDF-Vorlage exportiert werden. Die geht mittels Datei –> Exportieren als PDF. Im folgenden Dialog muss PDF-Formular erzeugen markiert sein.

Editing a formular in OpenOffice

OpenOffice - PDF Template

Generated PDF Template

Teil 2 – PDF-Formular mit iText befüllen

Zum Befüllen des PDF-Formulars nutze ich in meinem Beispiel iText in der Version 2.1.7, da in späteren Versionen eine verschärfte Lizenz verwendet wurde.
Zunächst wird das PDF-Formular eingelesen…

1PdfReader pdfTemplate = new PdfReader(pdfTemplateFile);

… und ein Stamper mit einem OutputStream erzeugt.

1ByteArrayOutputStream out = new ByteArrayOutputStream();
2PdfStamper stamper = new PdfStamper(pdfTemplate, out);

Damit im erzeugten PDF keine Formularfelder mehr enthalten sind, muss dem Stamper dies über folgendem Aufruf mitgeteilt werden.

1stamper.setFormFlattening(true);

Zum Abschluß können jetzt die Felder gefüllt werden…

1stamper.getAcroFields().setField("name", "Daniel Reuter");
2stamper.getAcroFields().setField("adress", "Merscheider Str.1 – 42699 Solingen");
3stamper.getAcroFields().setField("dates", "2008\n2009\n2010\n");
4stamper.getAcroFields().setField("titles", "JAX\nDevoxx\nJavaOne\n");

…und natürlich die Resourcen geschlossen werden.

1stamper.close();
2pdfTemplate.close();

Fazit

Aus meiner Sicht ein sehr einfacher und leicht verständlicher Ansatz. Sicherlich wird es Szenarien geben, in denen der beschriebene Weg nicht passt. Insbesondere bei dynamischen Layouts stößt man hier an die Grenzen. Dennoch würde ich versuchen, als Grundlage immer ein PDF Template zu verwenden.



PDF Result

|

Beitrag teilen

Gefällt mir

1

//

Weitere Artikel in diesem Themenbereich

Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.

//

Gemeinsam bessere Projekte umsetzen.

Wir helfen deinem Unternehmen.

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.