英文:
How to flatten fields with the same names
问题
我使用```itext 7.1.8```,我需要将一个包含相同名称字段的文档压平。我创建文档如下:
```java
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("创建 " + flattenName + ".pdf");
createPdfDocument(flattenName, 2);
System.out.println(flattenName + ".pdf 创建成功");
System.out.println("尝试压平 " + flattenName + "_flatten.pdf...");
flattenPdf(flattenName, flattenName + "_flatten");
}
但在压平后,我得到的文档只包含一个压平字段,而我需要得到两个压平字段。如何解决这个问题?
<details>
<summary>英文:</summary>
I'm using ```itext 7.1.8``` and I need to flatten a document that contains fields with the same names.<br/>
I create the document like the following:
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;
}
after that, I'm trying to flatten document like the following:
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();
}
}
There is my main method:
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");
}
and after flattening I get the document which contains one flatten fields but I have to get two flatten fields.<br/>
How can I fix this issue?
</details>
# 答案1
**得分**: 2
首先,我强烈建议使用最新版本,即7.1.12版本。然而,仅仅使用该版本是不够的,您需要编写一些额外的代码来创建一个带有多个小部件的表单字段,即在多个字段表示之间共享值。关于展开的代码是没问题的,我们只需要修改代码来创建一个文档,因为在您当前的代码中,同一个字段添加到了两个页面,小部件注释和页面之间的关联不一致。以下是修改后的代码:
```java
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);
英文:
First off, I would definitely recommend using the latest version which is 7.1.12. Merely using that version is not enough though and you will need to write some additional code to create a form field with several widgets, i.e. shared value across several field representations. The code for flattening is just fine and we just need to modify the code to create a document because what happens in your current code is that the same field is added to two pages and the association between widget annotations and pages is not consistent. Instead of this code:
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());
}
We need to create a field only once, then add widgets to the field for the remaining pages (except the first one) and associate pages with the widgets (add widget annotation to the corresponding page). Finally, we set the value to the field which generates appearances for all the widget annotations and we add the field to the form. Here is the code:
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);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论