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
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??
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
Will it support the Form created in Adobe?
yes
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(…….
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();
}
}
}
}
it is very much helpfull
This helped me with my task. But where did you use the bytearrayoutputstream?????
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.
Great tutorial , thanks
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
Genereren van pdf’s…
Er werden 2 mogelijkheden getest: JasperReports IText JasperReports JasperReports kan op een zeer eenvoudige manier met templates werken. In het programma IReport (…
Great explanation, thanks!
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
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.
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
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.
You can also use the free/open source template designer Dhek: https://github.com/applicius/dhek . It allows to define areas (bounds + some properties) over any existing PDF where you want later to writer dynamic/user data (e.g. from Web form) to generate custom document.
Good article, but are there any templates of generate bitmap in java with itext?
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.
Thank you very much Sir!
Nice idea..and a good pointer