我有一个带有文本表单字段的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
答案 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:
现在,您不再需要担心字段的顺序,而不是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
数组。这些字段按您想要的确切顺序填写。这些笔记现在涵盖了日期,而不是相反。