3

我有一个 pdf,其中的文本表单字段一层层叠加。当我通过 iText 填写字段并展平表单时,我在另一个表单字段顶部创建的表单字段现在位于底部。

例如,我有一个名为“number_field”的文本字段,它位于名为“name_field”的第二个文本字段下方。当我通过 iText 为这些字段设置值时(因此 number_field 为 10,name_field 为 'John'),number_field 现在位于 name_field 之上。

如何使用 iText 更改这些字段在页面上的顺序?是否可以?

链接到示例 PDF:https ://freecompany.sharefile.com/d-s84f6d63e7d04fe79

4

1 回答 1

2

我在 iText Group 的问题跟踪器中制作了以下票证:

问题是由 iText 将字段项读入 a 的事实引起的HashMap,因此无法预测它们将以何种顺序展平。这通常不是问题。如果您不展平 PDF,我认为不会出现此问题,因为在这种情况下,外观存储在小部件注释中,并且在重叠字段的情况下由 PDF 查看器决定哪个字段覆盖另一个字段.

但是,如果表单字段重叠,那么您无法预测在展平时哪个字段将覆盖哪个字段。

假设我们使用 aTreeMap而不是 a HashMap,这会解决问题吗?不是真的,因为Comparator我们会使用哪个?有时会定义 Tab 顺序,但并非总是如此。/Fields如果没有定义,我们是否应该按照它们在数组中出现的顺序对字段进行排序?/Annots或者根据数组中小部件注释的顺序对它们进行排序是否更有意义?另一种选择是根据它们在页面上的位置对它们进行排序。简而言之:这不是 iText 应该做出的决定。

但是,如果有人想解决这个问题,我们可以ComparatorPdfStamperImp. 如果 Comparator提供了这样的 a(我们甚至可以提供一些实现),那么展平过程将按照Comparator.

这张票的优先级很低(我假设您不是 iText Software 公司之一的客户),但在写这张票时,我有了另一个想法。

我已经在评论中使用 iTextSharp提到了文本的下划线部分。在这种情况下,您将获取所有字段位置(使用该getFieldPositions()方法)并使用ColumnText. 这种方法有几个缺点:为了使字体、字体大小、字体颜色正确,您必须检查字段。这需要一些编程。

我现在将其发布为答案,因为我有一个更好的选择:分两次填写表格!这在FillFormFieldOrder示例中显示。我们填写表格src,生成扁平表格dest,如下所示:

public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
    go2(go1(src), dest);
}

如您所见,我们go1()首先执行该方法:

public byte[] go1(String src) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfStamper stamper = new PdfStamper(reader, baos);
    AcroFields form = stamper.getAcroFields();
    form.setField("sunday_1", "1");
    form.setField("sunday_2", "2");
    form.setField("sunday_3", "3");
    form.setField("sunday_4", "4");
    form.setField("sunday_5", "5");
    form.setField("sunday_6", "6");
    stamper.setFormFlattening(true);
    stamper.partialFormFlattening("sunday_1");
    stamper.partialFormFlattening("sunday_2");
    stamper.partialFormFlattening("sunday_3");
    stamper.partialFormFlattening("sunday_4");
    stamper.partialFormFlattening("sunday_5");
    stamper.partialFormFlattening("sunday_6");
    stamper.close();
    reader.close();
    return baos.toByteArray();
}

这会填写所有sunday_x字段并使用部分表单展平来仅展平这些字段。该go1()方法以src参数为参数并返回一个byte[]将部分展平的形式。

byte[]用作该go2()方法的参数,该方法dest作为其第二个参数。现在我们要填写以下sunday_x_notes字段:

public void go2(byte[] src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    AcroFields form = stamper.getAcroFields();
    form.setField("sunday_1_notes", "It's Sunday today, let's go to the sea");
    form.setField("sunday_2_notes", "It's Sunday today, let's go to the park");
    form.setField("sunday_3_notes", "It's Sunday today, let's go to the beach");
    form.setField("sunday_4_notes", "It's Sunday today, let's go to the woods");
    form.setField("sunday_5_notes", "It's Sunday today, let's go to the lake");
    form.setField("sunday_6_notes", "It's Sunday today, let's go to the river");
    stamper.setFormFlattening(true);
    stamper.close();
    reader.close();
}

如您所见,我们现在展平了所有字段。结果如下所示

在此处输入图像描述

现在,您不再需要担心字段的顺序,不在/Fields数组中,不在/Annots数组中。这些字段按照您想要的确切顺序填写。注释现在涵盖了日期,而不是相反。

于 2015-04-16T15:01:29.003 回答