Tcheg
Tcheg

Reputation: 71

PDFBox: Fill out a PDF with adding repeatively a one-page template containing a form

Following SO question Java pdfBox: Fill out pdf form, append it to pddocument, and repeat I had trouble appending a cloned page to a new PDF.

Code from this page seemed really interesting, but didn't work for me.

Actually, the answer doesn't work because this is the same PDField you always modify and add to the list. So the next time you call 'getField' with initial name, it won't find it and you get an NPE. I tried with the same pdfbox version used (1.8.12) in the nice github project, but can't understand how he gets this working.

I had the same issue today trying to append a form on pages with different values in it. I was wondering if the solution was not to duplicate field, but can't succeed to do it properly. I always end with a PDF containing same values for each form.

(I provided a link to the template document for Mkl, but now I removed it because it doesn't belong to me)

Edit: Following Mkl's advices, I figured it out what I was missing, but performances are really bad with duplicating every pages. File size isn't satisfying. Maybe there's a way to optimize this, reusing similar parts in the PDF.

Upvotes: 0

Views: 2690

Answers (1)

Tcheg
Tcheg

Reputation: 71

Finally I got it working without reloading the template each time. So the resulting file is as I wanted: not too big (4Mb for 164 pages). I think I did 2 mistakes before: one on page creation, and probably one on field duplication. So here is the working code, if someone happens to be stuck on the same problem.

Form creation:

    PDAcroForm finalForm = new PDAcroForm(finalDoc, new COSDictionary());
    finalForm.setDefaultResources(originForm.getDefaultResources())

Page creation:

    PDPage clonedPage = templateDocument.getPage(0);

    COSDictionary clonedDict = new COSDictionary(clonedPage.getCOSObject());

    clonedDict.removeItem(COSName.ANNOTS);
    clonedPage = new PDPage(clonedDict);
    finalDoc.addPage(clonedPage);

Field duplication: (rename field to become unique and set value)

    PDTextField field = (PDTextField) originForm.getField(fieldName);
    PDPage page = finalDoc.getPages().get(nPage);
    PDTextField clonedField = new PDTextField(finalForm);
    List<PDAnnotationWidget> widgetList = new ArrayList<>();
    for (PDAnnotationWidget paw : field.getWidgets()) {
        PDAnnotationWidget newWidget = new PDAnnotationWidget();
        newWidget.getCOSObject().setString(COSName.DA,  paw.getCOSObject().getString(COSName.DA));
        newWidget.setRectangle(paw.getRectangle());
        widgetList.add(newWidget);
    }
    clonedField.setQ(field.getQ()); // To get text centered
    clonedField.setWidgets(widgetList);
    clonedField.setValue(value);
    clonedField.setPartialName(fieldName + cnt++);
    fields.add(clonedField);

    page.getAnnotations().addAll(clonedField.getWidgets());

And at the end of the process:

    finalDoc.getDocumentCatalog().setAcroForm(finalForm);
    finalForm.setFields(fields);
    finalForm.flatten();

Upvotes: 2

Related Questions