iText 7:设置文本字段一次,即使它存在多次同名

iText 7 : Set text field once even if it exists multiple times with the same name

我有一个包含多个同名文本字段的 PDF 文档。

我想设置一次值 (field.setValue("text")) 以及每次出现该字段时显示的值。这些字段可能位于同一页面或不同页面(显然是同一文档)。

当只有一个这样的字段时,生成PDF就可以了。如果超过一个,则所有字段都显示为空。如果我禁用扁平化,我可以在每个字段中看到文本(尽管只有在单击该字段后 - 很奇怪...)。

这里是 test PDF.


编辑:

问题似乎只有在我设置字段的字体时才会发生。您可以使用 this font 和以下代码进行重现:

PdfFont font = PdfFontFactory.createFont("src/main/resources/fonts/Arimo-Regular.ttf", PdfEncodings.IDENTITY_H);
PdfFormField textField = acroForm.getField("test");
textField.setValue("שלום", font, 11.0f);

更新后的问题

使用 OP 提供的字体和 setValue 重载以及额外的字体和字体大小参数,我可以重现该问题。

实际问题

问题与您使用的特定字体或文本无关,它与您使用的 setValue 重载有关:

  • PdfFormField.setValue(String)(除非字段是按钮字段)遍历当前字段后代的整个层次结构,并为每个后代调用另一个 setValue 重载,最终也是当前字段。
  • 另一方面,PdfFormField.setValue(String, boolean)PdfFormField.setValue(String, PdfFont, float) 假定当前字段实际上是要添加外观的单个小部件。

因此,任何具有多个小部件的表单字段(甚至是具有单个小部件但未与该字段合并的字段)将不会为其小部件检索正确的外观,如果只是 setValue 超载后一种是需要的。

解决方法

考虑到以上所述,解决方法是以某种方式使用单个参数 setValue 重载。可以通过将字体和字体大小显式设置到表单字段来实现,只需替换

textField.setValue("שלום", font, 11.0f);

来自

textField.setFont(font);
textField.setFontSize(11f);
textField.setValue("שלום");

(SetTextField 测试 testSetFontAndTextToFieldWithManyVisualizationsWorkAround)

现在字段确实已填满,并且它们的内容出现在展平的结果中。

不幸的是,这里又出现了另一个问题:字母出现的顺序错误。单独使用基本的 iText 组件似乎不支持 RTL 语言。可能使用 pdfCalligraph 附加模块增加了对希伯来语等的支持,但我不知道。

原问题的原答案

我无法用您的示例文档重现该问题。

我这样更改字段值

PdfReader reader = new PdfReader(resource);
PdfDocument pdfDocument = new PdfDocument(reader, new PdfWriter(outputStream));
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDocument, false);

PdfFormField testField = acroForm.getField("test");
testField.setValue("My test text...");

acroForm.flattenFields();

pdfDocument.close();

(SetTextField 测试 testSetTextToFieldWithManyVisualizations)

但结果是预期的:

该字段的所有三个实例都已填写。这对扁平化和不扁平化都有效,并且它对 7.​​1.4 和当前的 7.1.5-SNAPSHOT 都有效。

不过有一个问题,查看结果 PDF 的内部结构会发现

V 在抽象字段和每个小部件中都设置了。应该只在外地。