Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Itext - How to clone pages with acrofields?

Tags:

java

itext

I'm writing a program in Java that prints PDF files of Bingo Cards. Each page is one card. To make it easy for me, I created a template PDF file with acrofields, so that the program will only need to create a copy of this template, fill the acrofields with numbers, then flatten it. As of now, I can create 1 bingo card. I want to have multiple pages (thus, multiple cards) in one PDF file. But I do not have an idea how to do this. What I read is that a PDFStamper is associated to a one and only one PDFReader object. Is there a way I can do this without resorting to creation of multiple PDF files and combining them into one (I did this last time and I found really slow) Thanks in advance!

like image 396
John Bautista Avatar asked Apr 28 '11 11:04

John Bautista


2 Answers

Took me a while to figure this out. It's not the most efficient way to code, but here's essentially what it does:

  • create a document
  • for each page(s) with an acrofield:
  • copy your template
  • fill the form
  • flatten the form
  • add the page

Here's my implementation that you can try and modify to fit your needs:

private void createPdf() throws Exception {
    Document doc = new Document();
    PdfSmartCopy copy = new PdfSmartCopy(doc, new FileOutputStream("result.pdf"));
    doc.open();

    PdfReader reader;
    PdfStamper stamper;
    AcroFields form;
    ByteArrayOutputStream baos;

    for(int i = 0; i < getTotalPages(); i++) {
        copyPdf(i);

        reader = new PdfReader(String.format("%d%s", i, "template.pdf"));
        baos = new ByteArrayOutputStream();
        stamper = new PdfStamper(reader, baos);
        form = stamper.getAcroFields();

        //methods to fill forms

        stamper.setFormFlattening(true);
        stamper.close();

        reader = new PdfReader(baos.toByteArray());
        copy.addPage(copy.getImportedPage(reader, 1));
    }

    doc.close();
}

private void copyPdf(int currentPage) throws Exception {
    PdfReader reader = new PdfReader("timesheet.pdf");
    Document doc = new Document();
    File file = new File(String.format("%d%s", currentPage, "template.pdf"));
    file.deleteOnExit();
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(file));
    stamper.close();
}

The copyPdf() method creates temporary files that are used to allow form filling without affecting the entire document. If you find a more efficient way to do this, let me know.

Also, I've found that on Intel Based Mac vs Windows Computer, the Mac completes this much faster.

If you're not opposed to getting a reference book for iText, I would recommend "iText in Action, Second Edition" by Bruno Lowagie. It is a great book and very helpful.

like image 121
Zach Avatar answered Nov 09 '22 02:11

Zach


So, here's the code without using Zach's "copyPdf" method, as Mark Storer and MaxArt suggested:

private void createPdf() throws Exception {
    Document doc = new Document();
    PdfSmartCopy copy = new PdfSmartCopy(doc, new FileOutputStream("result.pdf"));
    doc.open();
    
    PdfReader mainReader = new PdfReader("timesheet.pdf");
    
    PdfReader reader;
    ByteArrayOutputStream baos;
    PdfStamper stamper;
    AcroFields form;
    
    for(int i = 0; i < getTotalPages(); i++) {
        
        reader = new PdfReader(mainReader);
        baos = new ByteArrayOutputStream();
        stamper = new PdfStamper(reader, baos);
        form = stamper.getAcroFields();
        
        //methods to fill forms
        
        stamper.setFormFlattening(true);
        stamper.close();
        
        reader = new PdfReader(baos.toByteArray());
        copy.addPage(copy.getImportedPage(reader, 1));
    }

    doc.close();
}
like image 40
nonzaprej Avatar answered Nov 09 '22 02:11

nonzaprej