gpt4 book ai didi

java - 如何仅重命名pdf中第一个找到的重复acrofield?

转载 作者:行者123 更新时间:2023-12-02 04:31:29 25 4
gpt4 key购买 nike

在我的 PDF 中,我有一个名为 Text1 的重复字段。现在我想将第一个找到的名为 Text1 的 acrofield 重命名为 foobar。名称为 Text1 的另一个字段应保持不变,以便我的新表单包含字段 Text1 和 foobar。

我正在使用 itext 库,并且有重命名函数,但此方法会将名称为 Text1 的所有字段重命名为 foobar。

如果有人想用我的pdf来测试它,here is a link .

public class RenameField
{
public static final String SRC = "c:\\test_duplicate_field2.pdf";
public static final String DEST = "c:\\test_duplicate_field_mod.pdf";

public static void main(String[] args)
throws DocumentException, IOException
{
File file = new File(DEST);
file.getParentFile().mkdirs();
new RenameField().manipulatePdf(SRC, DEST);
}

public void manipulatePdf(String src, String dest)
throws DocumentException, IOException
{
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
form.renameField("Text1", "foobar");
stamper.close();
reader.close();
reader = new PdfReader(dest);
form = reader.getAcroFields();
Map<String, AcroFields.Item> fields = form.getFields();
for (String name : fields.keySet()) {
System.out.println(name);
}
}
}

另一种方法是迭代 AcroField.Items。如果某个项目有多个值字典(在这种情况下该字段存在多次),则更改将完成。

for (Map.Entry<String, AcroFields.Item> entry: fieldMap.entrySet())
{
// extract Values for Field
String fieldKey = entry.getKey();

AcroFields.Item item = entry.getValue();
PdfDictionary dict;

int numberOfDuplicates = item.values.size();

if (numberOfDuplicates > 1) {
for (int i = 0; i < numberOfDuplicates; i++) {
if (i == 0) {
log.info("first field wont be changed");
} else {
log.info("renaming field " + fieldKey + " round " + i );
item.getMerged(i).put(PdfName.T, new PdfString(fieldKey + "_" + i ));
item.getValue(i).put(PdfName.T, new PdfString(fieldKey + "_" + i));
form.regenerateField(fieldKey);
}
}
}
}

但这会导致与上面使用 itext 中的 renameField 函数的方法产生相同的结果,两个字段名称都会更改。在调试过程中,我可以看到该项目的两个值字典具有相同的对象 ID,因此当我更改字典 [0] 的值时,字典 [1] 中的值也会更改

enter image description here

最佳答案

On my PDF I have a duplicate field named Text1

正如布鲁诺已经在评论中解释的那样,这是错误的。您的 PDF 只有一个名为“Text1”的字段:

34 0 obj
<</DA(/Helv 12 Tf 0 g)/FT/Tx/Kids[28 0 R 29 0 R]/T(Text1)>>
endobj

这个字段有两个子字段

28 0 obj
<</F 4/MK<<>>/P 3 0 R/Parent 34 0 R/Rect[70.305 698.209 220.305 720.209]/Subtype/Widget/Type/Annot>>
endobj
29 0 obj
<</DA(/Helv 12 Tf 0 g)/F 4/MK<<>>/P 3 0 R/Parent 34 0 R/Rect[240.02 697.453 390.02 719.453]/Subtype/Widget/Type/Annot>>
endobj

这些 child 只是小部件注释,它们本身并不是字段。

因此,您的请求

sample code how to rename one of the two widgets annotations instead of the field

没有意义:没有两个可以重命名的,因为只有字段被命名,并且只有一个字段。

您要做的就是创建一个名为“foobar”的新字段(复制原始字段的所有属性,除了KidsT),然后移动其中之一将 Text1 child 发送到 foobar。

针对您的用例的示例代码:

PdfReader reader = new PdfReader(resource);

PdfDictionary form = reader.getCatalog().getAsDict(PdfName.ACROFORM);
PdfArray fields = form.getAsArray(PdfName.FIELDS);
for (PdfObject object: fields)
{
PdfDictionary field = (PdfDictionary) PdfReader.getPdfObject(object);
if ("Text1".equals(field.getAsString(PdfName.T).toString()))
{
PdfDictionary newField = new PdfDictionary();
PRIndirectReference newFieldRef = reader.addPdfObject(newField);
fields.add(newFieldRef);
newField.putAll(field);
newField.put(PdfName.T, new PdfString("foobar"));
PdfArray newKids = new PdfArray();
newField.put(PdfName.KIDS, newKids);
PdfArray kids = field.getAsArray(PdfName.KIDS);
PdfObject widget = kids.remove(0);
newKids.add(widget);
PdfDictionary widgetDict = (PdfDictionary) PdfReader.getPdfObject(widget);
widgetDict.put(PdfName.PARENT, newFieldRef);
break;
}
}

PdfStamper stamper = new PdfStamper(reader, result);
stamper.close();

( SameFieldTwice.java 方法 testWidgetToField)

显然,对于通用可用的解决方案,还有很多工作要做。

关于java - 如何仅重命名pdf中第一个找到的重复acrofield?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31402602/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com