PDFBox:通过重复添加包含表单的单页模板来填写 PDF
PDFBox: Fill out a PDF with adding repeatively a one-page template containing a form
关注 SO 问题 我在将克隆页面附加到新 PDF 时遇到问题。
此页面中的代码看起来很有趣,但对我不起作用。
实际上,答案不起作用,因为这是您经常修改并添加到列表中的同一个 PDField。所以下次你用初始名称调用 'getField' 时,它不会找到它,你会得到一个 NPE。我尝试在漂亮的 github 项目中使用相同的 pdfbox 版本 (1.8.12),但不明白他是如何让这个工作的。
我今天遇到了同样的问题,试图在具有不同值的页面上附加一个表单。我想知道解决方案是否不是复制字段,但无法正确完成。我总是以包含每个表单相同值的 PDF 结尾。
(我为Mkl的模板文档提供了一个link,但现在我删除了它,因为它不属于我)
编辑:按照 Mkl 的建议,我弄清楚了我遗漏了什么,但是复制每一页的性能真的很差。文件大小不令人满意。也许有一种方法可以优化这一点,重复使用 PDF 中的相似部分。
我终于让它工作了,而无需每次都重新加载模板。所以生成的文件是我想要的:不太大(164 页为 4Mb)。
我想我之前犯了 2 个错误:一个是关于页面创建的,另一个可能是关于字段复制的。
所以这里是工作代码,如果有人碰巧遇到同样的问题。
表单创建:
PDAcroForm finalForm = new PDAcroForm(finalDoc, new COSDictionary());
finalForm.setDefaultResources(originForm.getDefaultResources())
页面创建:
PDPage clonedPage = templateDocument.getPage(0);
COSDictionary clonedDict = new COSDictionary(clonedPage.getCOSObject());
clonedDict.removeItem(COSName.ANNOTS);
clonedPage = new PDPage(clonedDict);
finalDoc.addPage(clonedPage);
字段重复:(将字段重命名为唯一并设置值)
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());
并且在过程结束时:
finalDoc.getDocumentCatalog().setAcroForm(finalForm);
finalForm.setFields(fields);
finalForm.flatten();
关注 SO 问题
此页面中的代码看起来很有趣,但对我不起作用。
实际上,答案不起作用,因为这是您经常修改并添加到列表中的同一个 PDField。所以下次你用初始名称调用 'getField' 时,它不会找到它,你会得到一个 NPE。我尝试在漂亮的 github 项目中使用相同的 pdfbox 版本 (1.8.12),但不明白他是如何让这个工作的。
我今天遇到了同样的问题,试图在具有不同值的页面上附加一个表单。我想知道解决方案是否不是复制字段,但无法正确完成。我总是以包含每个表单相同值的 PDF 结尾。
(我为Mkl的模板文档提供了一个link,但现在我删除了它,因为它不属于我)
编辑:按照 Mkl 的建议,我弄清楚了我遗漏了什么,但是复制每一页的性能真的很差。文件大小不令人满意。也许有一种方法可以优化这一点,重复使用 PDF 中的相似部分。
我终于让它工作了,而无需每次都重新加载模板。所以生成的文件是我想要的:不太大(164 页为 4Mb)。 我想我之前犯了 2 个错误:一个是关于页面创建的,另一个可能是关于字段复制的。 所以这里是工作代码,如果有人碰巧遇到同样的问题。
表单创建:
PDAcroForm finalForm = new PDAcroForm(finalDoc, new COSDictionary());
finalForm.setDefaultResources(originForm.getDefaultResources())
页面创建:
PDPage clonedPage = templateDocument.getPage(0);
COSDictionary clonedDict = new COSDictionary(clonedPage.getCOSObject());
clonedDict.removeItem(COSName.ANNOTS);
clonedPage = new PDPage(clonedDict);
finalDoc.addPage(clonedPage);
字段重复:(将字段重命名为唯一并设置值)
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());
并且在过程结束时:
finalDoc.getDocumentCatalog().setAcroForm(finalForm);
finalForm.setFields(fields);
finalForm.flatten();