Java pdfBox:填写pdf表单,将其附加到pddocument,然后重复 [英] Java pdfBox: Fill out pdf form, append it to pddocument, and repeat

查看:251
本文介绍了Java pdfBox:填写pdf表单,将其附加到pddocument,然后重复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个pdf表格,我正在尝试使用pdfBox填写表格并打印文档.我的工作非常适合1页打印作业,但是我不得不尝试修改多个页面.基本上,这是一个具有基本信息和内容列表的表格.好吧,如果内容大于表格所能容纳的空间,则必须将其设为多页文档.我最终得到一个文档,该文档的第一页漂亮,然后其余所有页面都是空白模板.我在做什么错了?

I have a pdf form made and I'm trying to use pdfBox to fill in the form and print the document. I got it working great for 1 page print jobs but i had to try and modify for multiple pages. Basically it's a form with basic info up top and a list of contents. Well if the contents are larger than what the form has room for I have to make it a multiple page document. I end up with a document with a nice page one and then all the remaining pages are the blank template. What am I doing wrong?

PDDocument finalDoc = new PDDocument();
File template = new File("path/to/template.pdf");

//Declare basic info to be put on every page
String name = "John Smith";
String phoneNum = "555-555-5555";
//Get list of contents for each page
List<List<Map<String, String>>> pageContents = methodThatReturnsMyInfo();

for (List<Map<String, String>> content : pageContents) {
    PDDocument doc = new PDDocument().load(template);
    PDDocumentCatlog docCatalog = doc.getDocumentCatalog();
    PDAcroForm acroForm = docCatalog.getAcroForm();

    acroForm.getField("name").setValue(name);
    acroForm.getField("phoneNum").setValue(phoneNum);

    for (int i=0; i<content.size(); i++) {
        acroForm.getField("qty"+i).setValue(content.get(i).get("qty"));
        acroForm.getField("desc"+i).setValue(content.get(i).get("desc"));
    }

    List<PDPage> pages = docCatalog.getAllPages();
    finalDoc.addPage(pages.get(0));
}

//Then prints/saves finalDoc

推荐答案

您的代码中存在两个主要问题:

There are two major issues in you code:

  • PDF的AcroForm元素是文档级对象.您仅将填写的模板页面复制到finalDoc.因此,表单字段仅作为其各自页面的注释添加到finalDoc中,而没有添加到finalDoc的AcroForm中.

  • The AcroForm element of a PDF is a document level object. You only copy the filled-in template page into finalDoc. Thus, the form fields are added to finalDoc only as annotations of their respective page but they are not added to the AcroForm of finalDoc.

这在Adobe Reader中并不明显,但是表单填充服务通常会从文档级AcroForm条目中识别可用字段,并且不会在页面上搜索其他表单字段.

This is not apparent in Adobe Reader but form filling services often identify available fields from the document level AcroForm entry and don't search the pages for additional form fields.

实际的显示停止符:您将具有相同名称的字段添加到PDF.但是PDF表单是文档范围的实体. IE. PDF中只能有一个具有给定名称的单个字段实体.(此字段实体可能具有多个可视化效果,也称为小部件,但这需要您构造一个具有多个孩子小部件的单个字段对象.小部件应该显示相同的值,这不是您想要的值...)

The actual show stopper: You add fields with identical names to the PDF. But PDF forms are document-wide entities. I.e. there can be only a single field entity with a given name in a PDF. (This field entity may have multiple visualizations aka widgets but this requires you to construct a single field object with multiple kid widgets.Furthermore these widgets are expected to display the same value which is not what you want...)

因此,必须将字段唯一地重命名,然后才能将其添加到finalDoc.

Thus, you have to rename the fields uniquely before adding them to the finalDoc.

这里是简化示例,该模板可用于只有一个字段"SampleField"的模板:

Here a simplified example which works on a template with only one field "SampleField":

byte[] template = generateSimpleTemplate();
Files.write(new File(RESULT_FOLDER,  "template.pdf").toPath(), template);

try (   PDDocument finalDoc = new PDDocument(); )
{
    List<PDField> fields = new ArrayList<PDField>();
    int i = 0;

    for (String value : new String[]{"eins", "zwei"})
    {
        PDDocument doc = new PDDocument().load(new ByteArrayInputStream(template));
        PDDocumentCatalog docCatalog = doc.getDocumentCatalog();
        PDAcroForm acroForm = docCatalog.getAcroForm();
        PDField field = acroForm.getField("SampleField");
        field.setValue(value);
        field.setPartialName("SampleField" + i++);
        List<PDPage> pages = docCatalog.getAllPages();
        finalDoc.addPage(pages.get(0));
        fields.add(field);
    }

    PDAcroForm finalForm = new PDAcroForm(finalDoc);
    finalDoc.getDocumentCatalog().setAcroForm(finalForm);
    finalForm.setFields(fields);

    finalDoc.save(new File(RESULT_FOLDER, "form-two-templates.pdf"));
}

如您所见,所有字段都已重命名,然后再添加到finalForm:

As you see all fields are renamed before they are added to finalForm:

field.setPartialName("SampleField" + i++);

,它们被收集在列表fields中,该列表最终被添加到finalForm AcroForm中:

and they are collected in the list fields which finally is added to the finalForm AcroForm:

    fields.add(field);
}
...
finalForm.setFields(fields);

这篇关于Java pdfBox:填写pdf表单,将其附加到pddocument,然后重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆