1

I have generated a PDF from a template. The PDF has a field in the middle of it that is of variable length. I am trying to work it so that if the field's content overflows, then the program will use a second instance template as a second page and continue in the same field there. Is this possible?

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
Carlos Mendieta
  • 860
  • 16
  • 41
  • 1
    You mention a field. Is it an actual dynamic form field (xfa or acroform) or is it merely something looking like a form field? – mkl Nov 10 '14 at 23:11
  • Apologies mkl, I didn't see your comment. Its an actual acroform field. – Carlos Mendieta Nov 12 '14 at 16:26
  • You cannot split a single Acroform field over multiple pages. An AcroForm field may have multiple visualization on multiple pages, so you can have the same field on both pages, but each of these visualizations would carry the whole content. Instead you can either flatten the field as proposed in Brunos answer or split the content into *different* fields. This would mean, though, that the person or program eventually processing the filled-in form needs to know about this new overflow field and explicitly join the contents of the fields. – mkl Nov 13 '14 at 08:59

1 Answers1

3

This will only work if you flatten the form. I've written a proof of concept where I have a PDF form src that has a field named "body":

public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
    PdfReader reader = new PdfReader(src);
    Rectangle pagesize = reader.getPageSize(1);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    Paragraph p = new Paragraph();
    p.add(new Chunk("Hello "));
    p.add(new Chunk("World", new Font(FontFamily.HELVETICA, 12, Font.BOLD)));
    AcroFields form = stamper.getAcroFields();
    Rectangle rect = form.getFieldPositions("body").get(0).position;
    int status;
    PdfImportedPage newPage = null;
    ColumnText column = new ColumnText(stamper.getOverContent(1));
    column.setSimpleColumn(rect);
    int pagecount = 1;
    for (int i = 0; i < 100; ) {
        i++;
        column.addElement(new Paragraph("Hello " + i));
        column.addElement(p);
        status = column.go();
        if (ColumnText.hasMoreText(status)) {
            newPage = loadPage(newPage, reader, stamper);
            triggerNewPage(stamper, pagesize, newPage, column, rect, ++pagecount);
        }
    }
    stamper.setFormFlattening(true);
    stamper.close();
    reader.close();
}

public PdfImportedPage loadPage(PdfImportedPage page, PdfReader reader, PdfStamper stamper) {
    if (page == null) {
        return stamper.getImportedPage(reader, 1);
    }
    return page;
}

public void triggerNewPage(PdfStamper stamper, Rectangle pagesize, PdfImportedPage page, ColumnText column, Rectangle rect, int pagecount) throws DocumentException {
    stamper.insertPage(pagecount, pagesize);
    PdfContentByte canvas = stamper.getOverContent(pagecount);
    canvas.addTemplate(page, 0, 0);
    column.setCanvas(canvas);
    column.setSimpleColumn(rect);
    column.go();
}

As you can see, we create a PdfImportedPage instance and we insert a new page with this page as background. We add the content at the position defined by the field using ColumnText.

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • Bruno, how would you do this in version 4.1.6? Rectangle rect = form.getFieldPositions("body").get(0).position; Its giving me an error – Carlos Mendieta Nov 12 '14 at 15:29
  • There is no such thing as iText 4.1.6. If there is, it is not an official version. The code could contain anything. We (the official iText company) are not responsible for any version other than the ones we officially distribute. Hence we can not comment on the version you are using. – Bruno Lowagie Nov 12 '14 at 21:55
  • 2
    @BrunoLowagie *There is no such thing as iText 4.1.6* - I think the OP is talking about iTextSharp, at least that's how the question is tagged. As far as I remember iTextSharp 4.1.6 was an official release more or less equivalent to iText 2.1.6. Carlos, this in turn means that **A** you have to do some translation from Bruno's Java sample anyways and **B** you search a solution for an *ancient* iTextSharp version, not a current one, a fact you should have mentioned in your question to start with. – mkl Nov 13 '14 at 08:30
  • When the form is flattened, it doesn't recognize the field name. `form.getFieldPositions("body").get(0)` would give a null pointer because `form.getFieldPositions("body")` is empty. The field names are no more there when the form is flattened – Danyal Sandeelo Apr 16 '19 at 12:19