使用iText更改现有PDF中的AcroFields订单?

时间:2015-04-14 16:49:59

标签: pdf itext formfield acrofields

我有一个带有文本表单字段的pdf,一个在另一个上面。当我通过iText填充字段并展平表单时,我在另一个表单字段顶部创建的表单字段现在位于底部。

例如,我有一个名为" number_field"的文本字段。这是在名为" name_field"的第二个文本字段下面。当我通过iText设置这些字段的值时(对于number_field为10和#39;为name_field设置),number_field现在位于name_field的顶部。

如何使用iText更改这些字段页面上的顺序?有可能吗?

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

1 个答案:

答案 0 :(得分:2)

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

  

问题是因为iText将字段项读入   a HashMap,因此无法预测它们的顺序   被夷为平地。这通常不是问题。我不认为这个问题   如果您不压平PDF,则会发生这种情况,因为在这种情况下,   外观存储在窗口小部件注释中,它取决于PDF   查看器在重叠的情况下决定哪个字段覆盖另一个字段   字段。

     

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

     

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

     

但是,如果有人想解决这个问题,我们可以创建   Comparator的{​​{1}}成员变量。如果这样的话   提供了PdfStamperImp(我们甚至可以提供一些实现),   然后,扁平化过程将按照定义的顺序执行   Comparator

这张票的优先级非常低(我假设您不是其中一家iText软件公司的客户),但在写这张票的时候,我有了另一个想法。

我已在评论中提及underline portion of text using iTextSharp。在这种情况下,您将获得所有字段位置(使用Comparator方法)并使用getFieldPositions()以正确的顺序绘制所有内容。这种方法有几个缺点:为了使字体,字体大小,字体颜色正确,您必须检查字段。这需要一些编程。

我现在发布这个作为答案,因为我有一个更好的选择:两遍填写表格!这显示在FillFormFieldOrder示例中。我们填写ColumnText表格,导致展平形式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

如您所见,我们现在将所有字段展平。结果看起来像this

enter image description here

现在,您不再需要担心字段的顺序,而不是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数组。这些字段按您想要的确切顺序填写。这些笔记现在涵盖了日期,而不是相反。