I am trying to create a multi-page PDF document in iText with filled forms, one for each person. I have looked up examples of how to do this on the internet and used those examples in my solution.
The PDF template is one created with Adobe Acrobat Pro.
I have been able to successfully fill in and return a single-page PDF document from my template using iText, but the multi-document process doesn't seem to work right.
This my program that demonstrates what I am trying to do:
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfSmartCopy;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.NumberFormat;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
public class ITextTest
{
public static final String TEMPLATE =
"C:\\RAD7_5\\iTextTest\\iTextTest\\input\\LS213_1.pdf";
public static void main(String[] args)
{
ITextTest iTextTest = new ITextTest();
iTextTest.doItextTest();
}
public void doItextTest()
{
try
{
PdfReader pdfReader;
PdfStamper pdfStamper;
ByteArrayOutputStream baos;
Document document = new Document();
PdfSmartCopy pdfSmartCopy = new PdfSmartCopy(document,
new FileOutputStream("C:\\RAD7_5\\iTextTest\\iTextTest\\output\\LS213_1MultiTest.pdf"));
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
Date currDate = new Date();
NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
double amount = 4127.29d;
document.open();
for(int i = 1; i <= 5; i++)
{
pdfReader = new PdfReader(TEMPLATE);
baos = new ByteArrayOutputStream();
pdfStamper = new PdfStamper(pdfReader, baos);
AcroFields acroFields = pdfStamper.getAcroFields();
//key statement 1
acroFields.setGenerateAppearances(true);
//acroFields.setExtraMargin(5, 5);
acroFields.setField("Name and Address", "John Doe\n123 Anywhere St.\nAnytown, USA 12345");
acroFields.setField("Case Number", "123456789");
acroFields.setField("Employer", "Employer Co., Inc.\n456 Anyhow ln.\nAnyville, USA 67890");
acroFields.setField("Date", dateFormat.format(currDate));
acroFields.setField("Name", "John Doe");
acroFields.setField("restitution check No", "65432" + i);
acroFields.setField("in the sum of", numberFormat.format(amount));
//key statement 2
pdfStamper.setFormFlattening(false);
pdfStamper.close();
pdfReader.close();
pdfReader = new PdfReader(baos.toByteArray());
pdfSmartCopy.addPage(pdfSmartCopy.getImportedPage(pdfReader, 1));
pdfSmartCopy.freeReader(pdfReader);
pdfReader.close();
}
document.close();
}
catch(DocumentException dex)
{
dex.printStackTrace();
System.exit(1);
}
catch(IOException ex)
{
ex.printStackTrace();
System.exit(1);
}
}
}
In the code above, you can see two key statements that affect the result of the filled template:
acroFields.setGenerateAppearances(true);
pdfStamper.setFormFlattening(false);
With the above two statements, if I set the first one to true and the second one to false, it fills the fields, but they are misaligned with the labels. Also, after the first template copy, each copy after that has some unfilled fields for some reason.
If I set them both to true:
acroFields.setGenerateAppearances(true);
pdfStamper.setFormFlattening(true);
it sets all of the fields in all of the template copies. This is the most successful result for me so far, but the filled fields are still misaligned with the labels and setting form flattening to true no longer allows a user to correct a field manually afterwards if the data in the application is wrong.
If I set the first one to false and the second one to true:
acroFields.setGenerateAppearances(false);
pdfStamper.setFormFlattening(true);
all of the fields are completely blank (worst result).
If I set them both to false:
acroFields.setGenerateAppearances(false);
pdfStamper.setFormFlattening(false);
then the fields are filled and appear in the right alignment with the labels. But the fields appear blank for some reason until you click on them. And the problem with some fields being wiped out in subsequent pages occurs like in the true false scenario (first scenario mentioned).
I am wondering if it is possible to get this to work without misaligned field values, without flattening the fields, and without lost fields on subsequent pages.
I know you can adjust margins afterwards using
acroFields.setExtraMargin(extraMarginLeft, extraMarginTop)
but using
acroFields.setGenerateAppearances(false)
works perfectly for a single form without having to adjust margins and I want it to work for a multi-page document as well.
Also, using
acroFields.setGenerateAppearances(true)
causes the text to move and be displaced a little bit in the textbox when you click on it. This happens for both single-page documents and multi-page documents. There seems to be a bug in either iText or PDF templates created with Adobe Pro when setting fields with setGenerateAppearances(true).
I am currently using iText 5.5.8.
Any help with this issue would be greatly appreciated. Thanks for taking the time to read this.