Issue
I have a PDTextField with two widgets. Setting value with saveIncremental does not work.
PDFBox Version - 2.0.24
Code to add PDTextField with multiple widgets with fill. Form fields in saved file disappear. I tried without objectsToWrite but it did not work.
My Sample Code:
try (FileOutputStream output = new FileOutputStream("src/main/resources/Sample_form.pdf");
PDDocument document = PDDocument.load(new File("src/main/resources/Sample.pdf"))) {
PDFont font = PDType1Font.HELVETICA;
PDResources resources = new PDResources();
resources.put(COSName.HELV, font);
PDAcroForm acroForm = new PDAcroForm(document);
document.getDocumentCatalog().setAcroForm(acroForm);
acroForm.setDefaultResources(resources);
String defaultAppearanceString = "/Helv 0 Tf 0 g";
acroForm.setDefaultAppearance(defaultAppearanceString);
PDTextField textBox = new PDTextField(acroForm);
textBox.setPartialName("SampleFieldMultiwidget");
defaultAppearanceString = "/Helv 12 Tf 0 0 1 rg";
textBox.setDefaultAppearance(defaultAppearanceString);
acroForm.getFields().add(textBox);
PDPage page1=document.getPage(0);
PDPage page2=document.getPage(1);
PDAnnotationWidget widget1 = new PDAnnotationWidget();
PDRectangle rect = new PDRectangle(50, 750, 250, 50);
widget1.setRectangle(rect);
widget1.setPage(page1);
widget1.setParent(textBox);
PDAnnotationWidget widget2 = new PDAnnotationWidget();
PDRectangle rect2 = new PDRectangle(200, 650, 100, 50);
widget2.setRectangle(rect2);
widget2.setPage(page2);
widget2.setParent(textBox);
List<PDAnnotationWidget> widgets = new ArrayList<>();
widgets.add(widget1);
widgets.add(widget2);
textBox.setWidgets(widgets);
widget1.setPrinted(true);
widget2.setPrinted(true);
page1.getAnnotations().add(widget1);
page2.getAnnotations().add(widget2);
document.save(output);
} catch (Exception e) {
throw new RuntimeException(e);
}
And this for filling
try (FileOutputStream output = new FileOutputStream("src/main/resources/Sample_form_filled.pdf");
PDDocument document = PDDocument.load(new File("src/main/resources/Sample_form.pdf"))) {
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
PDTextField field = (PDTextField)acroForm.getField("SampleFieldMultiwidget");
field.setValue("Sample Value");
field.setReadOnly(true);
COSDictionary fieldDictionary = field.getCOSObject();
fieldDictionary.setNeedToBeUpdated(true);
COSArray cosArray = (COSArray)field.getCOSObject().getDictionaryObject(COSName.KIDS);
cosArray.setNeedToBeUpdated(true);
for (int i = 0; i < cosArray.size(); i++) {
COSObject cosObject = (COSObject) cosArray.get(i);
COSDictionary dictionary = (COSDictionary) cosObject.getDictionaryObject(COSName.AP);
dictionary.setNeedToBeUpdated(true);
COSStream stream = (COSStream) dictionary.getDictionaryObject(COSName.N);
stream.setNeedToBeUpdated(true);
COSDictionary dictionary2 = (COSDictionary) cosObject.getDictionaryObject(COSName.PARENT);
while (dictionary2 != null) {
dictionary2.setNeedToBeUpdated(true);
dictionary2 = (COSDictionary) dictionary2.getDictionaryObject(COSName.PARENT);
}
}
Set<COSDictionary> objectsToWrite = new HashSet<>();
for (PDPage pdPage: document.getPages()) {
objectsToWrite.add(pdPage.getCOSObject());
objectsToWrite.add(field.getCOSObject());
}
//Added - post comment
objectsToWrite.add(field.getWidgets().get(0).getAppearance().getCOSObject());
objectsToWrite.add((COSDictionary) field.getWidgets().get(0).getAppearance().getNormalAppearance().getCOSObject());
objectsToWrite.add(field.getWidgets().get(1).getAppearance().getCOSObject());
objectsToWrite.add((COSDictionary) field.getWidgets().get(1).getAppearance().getNormalAppearance().getCOSObject());
document.saveIncremental(output,objectsToWrite);
} catch (Exception e) {
throw new RuntimeException(e);
}
What do I miss? Thanks!
Added.
Update: It is resolved. I missed setting widget appearance. Now renders on all viewers.
Thank you
Solution
Adding appearance to widget resolved the issue.
PDAppearanceDictionary pdAppearanceDictionary = new PDAppearanceDictionary();
widget1.setAppearance(pdAppearanceDictionary);
pdAppearanceDictionary.setNormalAppearance(new PDAppearanceStream(document));
Answered By - Vas K
Answer Checked By - Timothy Miller (JavaFixing Admin)