PDF Generation Using Templates and OpenOffice and Itext in Java


Recently i had a task where in i had to create PDF dynamically by merging data and template. I have been using lots of pdf libraries since i started my programming to do such tasks. The previous one i admired a lot was Jasper Reports. But after researching some more time i found out that IText with Openoffice Draw is a simplest way we can generate PDF forms.

This visual tutorial first Explain’s how to Create PDF forms in Openoffice Draw

Save PDF to folder where you have your program or just change path for input source in program

Now here is java code which can convert this pdf to final pdf by filling in Values using IText

/**
 *
 */
package com.linkwithweb.reports;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

/**
 * @author Ashwin Kumar
 *
 */
public class ITextStamperSample {

	/**
	 * @param args
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static void main(String[] args) throws IOException,
			DocumentException {
		// createSamplePDF();
		generateAshwinFriends();
	}

	/**
	 *
	 */
	private static void generateAshwinFriends() throws IOException,
			FileNotFoundException, DocumentException {
		PdfReader pdfTemplate = new PdfReader("mytemplate.pdf");
		FileOutputStream fileOutputStream = new FileOutputStream("test.pdf");
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		PdfStamper stamper = new PdfStamper(pdfTemplate, fileOutputStream);
		stamper.setFormFlattening(true);

		stamper.getAcroFields().setField("name", "Ashwin Kumar");
		stamper.getAcroFields().setField("id", "1\n2\n3\n");
		stamper.getAcroFields().setField("friendname",
				"kumar\nsirisha\nsuresh\n");
		stamper.getAcroFields().setField("relation", "self\nwife\nfriend\n");

		stamper.close();
		pdfTemplate.close();

	}

}

Here is sample pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.linkwithweb.reports</groupId>
  <artifactId>ReportTemplateTutorial</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>ReportTemplateTutorial</name>
  <description>ReportTemplateTutorial</description>
  <dependencies>
  	<dependency>
  		<groupId>com.lowagie</groupId>
  		<artifactId>itext</artifactId>
  		<version>2.1.7</version>
  	</dependency>
  </dependencies>
</project>

 

A pdf file with data filled in placeholders is created with name test.pdf


23 thoughts on “PDF Generation Using Templates and OpenOffice and Itext in Java

  1. In the code above:

    stamper.getAcroFields().setField(“name”, “Ashwin Kumar”);

    How does the java class know what “name” is? How does it know to put Ashwin Kumar under the Name field??

  2. Adobe has something called AcroForms. AcroForms have been introduced from Acrobat Specification 1.2. They can be used to replace parameters at runtime. It’s like template merging with model. IText provides library which can read pdf and replace those Acroform fields. You can create PDF with those fields using Openoffice Draw as described in the article. Let me know if you have any questions

  3. I use linux platform and want to generate pdf in UTF-8 platform, because I use polish language with specjal letters (not ISO-8592-1).
    I had to add:
    BaseFont bf = BaseFont.createFont(“DejaVuSansCondensed.ttf”,BaseFont.IDENTITY_H, true);
    //”/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansCondensed.ttf”,
    stamper.getAcroFields().addSubstitutionFont(bf);

    before stamper.getAcroFields().setField(…….

  4. Is it possible to create one pdf document using that stamper object for repeating values ?

    Something like :

    PdfReader pdfTemplate = new PdfReader(“mytemplate.pdf”);
    FileOutputStream fileOutputStream = new FileOutputStream(“test.pdf”);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PdfStamper stamper = new PdfStamper(pdfTemplate, fileOutputStream);
    stamper.setFormFlattening(true);

    for ( … ) {
    String name_value = ……..
    stamper.getAcroFields().setField(“name”, name_value);
    …….
    ?????? stamper.newpage() ?????
    }

    stamper.close();
    pdfTemplate.close();

    • You cant do it that but you have to do it in differrent way.
      For each page use stamper and then append each page using Itext PDF Merge

      Example program

      public class MergePDF {
      public static void main(String[] args) {
      try {
      List pdfs = new ArrayList();
      pdfs.add(new FileInputStream(“c:\\pdf\\2.pdf”));
      pdfs.add(new FileInputStream(“c:\\pdf\\3.pdf”));
      OutputStream output = new FileOutputStream(“c:\\pdf\\merge.pdf”);
      MergePDF.concatPDFs(pdfs, output, true);
      } catch (Exception e) {
      e.printStackTrace();
      }
      }

      public static void concatPDFs(List streamOfPDFFiles, OutputStream outputStream, boolean paginate) {

      Document document = new Document();
      try {
      List pdfs = streamOfPDFFiles;
      List readers = new ArrayList();
      int totalPages = 0;
      Iterator iteratorPDFs = pdfs.iterator();

      // Create Readers for the pdfs.
      while (iteratorPDFs.hasNext()) {
      InputStream pdf = iteratorPDFs.next();
      PdfReader pdfReader = new PdfReader(pdf);
      readers.add(pdfReader);
      totalPages += pdfReader.getNumberOfPages();
      }
      // Create a writer for the outputstream
      PdfWriter writer = PdfWriter.getInstance(document, outputStream);

      document.open();
      BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
      PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
      // data

      PdfImportedPage page;
      int currentPageNumber = 0;
      int pageOfCurrentReaderPDF = 0;
      Iterator iteratorPDFReader = readers.iterator();

      // Loop through the PDF files and add to the output.
      while (iteratorPDFReader.hasNext()) {
      PdfReader pdfReader = iteratorPDFReader.next();

      // Create a new page in the target for each source page.
      while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
      document.newPage();
      pageOfCurrentReaderPDF++;
      currentPageNumber++;
      page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
      cb.addTemplate(page, 0, 0);

      // Code for pagination.
      if (paginate) {
      cb.beginText();
      cb.setFontAndSize(bf, 9);
      cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + " of " + totalPages, 520, 5, 0);
      cb.endText();
      }
      }
      pageOfCurrentReaderPDF = 0;
      }
      outputStream.flush();
      document.close();
      outputStream.close();
      } catch (Exception e) {
      e.printStackTrace();
      } finally {
      if (document.isOpen())
      document.close();
      try {
      if (outputStream != null)
      outputStream.close();
      } catch (IOException ioe) {
      ioe.printStackTrace();
      }
      }
      }
      }

  5. As a beginner It is very useful for me. In my scenario i need to pass the xml file as input and it will produce pdf file. (XML to Pdf Conversion). How can I merge xml data in template pdf. Can you please provide some sample snippet.

  6. hi ashwinrayaprolu
    is it possible to create “fileds” from Open Writer (a template document) and update theses fields from stamper ? How to do same think as you in Writer ?
    thks
    Chris

  7. Hello There. I found your blog the usage of msn. That is a very neatly written article.

    I will be sure to bookmark it and return to learn more of your
    useful information. Thanks for the post. I’ll definitely comeback.

  8. Hi Ashwin,

    How can i dynamically increase a table’s no.of rows depending on that data that i am inserting. In such case, how should i prepare the template initially..?

    Awaiting your reply. Thanks.

Leave a comment