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


About these ads

18 Responses to PDF Generation Using Templates and OpenOffice and Itext in Java

  1. lee says:

    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. Ash says:

    Will it support the Form created in Adobe?

  4. lenar says:

    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(…….

  5. Wim says:

    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();
      }
      }
      }
      }

  6. it is very much helpfull

  7. Raja says:

    This helped me with my task. But where did you use the bytearrayoutputstream?????

  8. Sarayu says:

    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.

  9. cb says:

    Great tutorial , thanks

  10. I want to add barcode as well dynamically. Could you help me in understanding how can we achieve it?

    2 ways are there.
    – Java code can generate barcode image and set field data.
    – Java code can set some value which needs to be converted to barcode .

    I found some thing related to 2nd one , but am not able to make use of it.

    http://www.idautomation.com/openoffice/

    Thanks,
    GK

  11. Pingback: Confluence: Valipac - Leonardo

  12. joarobles says:

    Great explanation, thanks!

  13. bob says:

    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

  14. katherine johanson says:

    You can generate PDF file and add many options in that generated file in java with Aspose.PDF for Java Library. You can sample code for any feature on their documentation page.

  15. Sven Tantau says:

    Hi Ashwin,

    I created an API that builds PDFs out of OpenOffice/LibreOffice templates.
    It suppports lists and images as well and is currently free for low volume usage.

    So in case you are interested: http://template2pdf.com/

    Thanks,
    Regards,
    Sven

  16. Glenn McGee says:

    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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 27 other followers

%d bloggers like this: