如何展平具有相同名称的字段

How to flatten fields with the same names

我正在使用 itext 7.1.8,我需要拼合包含同名字段的文档。
我创建如下文档:

private static PdfDocument createPdfDocument(final String name, final int countFields) {
        PdfDocument pdf;
        try {
            final FileOutputStream os = new FileOutputStream(name + ".pdf");
            PdfWriter pdfWriter = new PdfWriter(os);
            pdf = new PdfDocument(pdfWriter);


            final PdfPage pdfPage = pdf.addNewPage();

            final float height = pdfPage.getCropBox().getHeight();

            final PdfTextFormField txt1Fld = PdfFormField.createText(pdf, new Rectangle( 100, height - 100, 200, 18), "Text_1");
            txt1Fld.setValue("Hello");

            for (int i = 0; i < countFields; i++) {
                PdfAcroForm.getAcroForm(pdf, true)
                        .addField(txt1Fld, i == 0 ? pdfPage : pdf.addNewPage());
            }

            pdf.close();
        } catch (Exception e) {
            e.printStackTrace();
            pdf = null;
        }
        return pdf;
    }

之后,我尝试像下面这样压平文档:

private static void flattenPdf(String name, String flattenName) {
        try {
            OutputStream os = new FileOutputStream(flattenName + ".pdf");
            InputStream is = new FileInputStream(name + ".pdf");
            PdfReader reader = new PdfReader(is);
            PdfWriter writer = new PdfWriter(os);
            final PdfDocument pdfDocument = new PdfDocument(reader, writer);
            final PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, true);
            acroForm.setNeedAppearances(true);
            acroForm.flattenFields();
            pdfDocument.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这是我的主要方法:

public static void main(String[] args) throws IOException {
    final String flattenName = "ItextPdfTwoFields";

    System.out.println("Create " + flattenName + ".pdf");
    createPdfDocument(flattenName, 2);
    System.out.println(flattenName + ".pdf created successfully");
    System.out.println("Trying to flat " + flattenName + "_flatten.pdf...");
    flattenPdf(flattenName, flattenName + "_flatten");
}

展平后,我得到了包含一个展平字段的文档,但我必须获得两个展平字段。
我该如何解决这个问题?

首先,我肯定会推荐使用最新版本 7.1.12。仅仅使用那个版本是不够的,你需要编写一些额外的代码来创建一个带有多个小部件的表单字段,即跨多个字段表示的共享值。扁平化的代码很好,我们只需要修改代码来创建一个文档,因为在你现在的代码中发生的事情是在两个页面中添加了相同的字段,并且小部件注释和页面之间的关联不一致。而不是这个代码:

final PdfTextFormField txt1Fld = PdfFormField.createText(pdf, new Rectangle( 100, height - 100, 200, 18), "Text_1");
txt1Fld.setValue("Hello");

for (int i = 0; i < countFields; i++) {
    PdfAcroForm.getAcroForm(pdf, true)
            .addField(txt1Fld, i == 0 ? pdfPage : pdf.addNewPage());
}

我们只需创建一次字段,然后为其余页面(第一个除外)的字段添加小部件,并将页面与小部件相关联(为相应页面添加小部件注释)。最后,我们将值设置为为所有小部件注释生成外观的字段,并将该字段添加到表单中。这是代码:

Rectangle rect = new Rectangle( 100, height - 100, 200, 18);
final PdfTextFormField txt1Fld = PdfFormField.createText(pdf, rect, "Text_1");

for (int i = 1; i < countFields; i++) {
    PdfWidgetAnnotation annotation = new PdfWidgetAnnotation(rect);
    annotation.makeIndirect(pdf);
    txt1Fld.addKid(annotation);
}

for (int i = 0; i < countFields; i++) {
    if (pdf.getNumberOfPages() <= i) {
        pdf.addNewPage();
    }
    pdf.getPage(i + 1).addAnnotation(txt1Fld.getWidgets().get(i));
}

txt1Fld.setValue("Hello");

PdfAcroForm.getAcroForm(pdf, true).addField(txt1Fld, pdfPage);