这是情况。我有一个带有自动生成的pdf表单字段名称的PDF。问题是这些名称不是非常用户友好。它们看起来像: topmostSubform [0] .Page1 [0] .Website_Address [0]
我希望能够更改它们以便它们类似于WebsiteAddress。我可以访问ABCPDF并且我有使用iTextSharp的经验,但我尝试使用这些API来执行此操作(访问表单字段并尝试重命名),但似乎不可能。
是否有人尝试通过某种API(最好是开源)尝试这样做。代码也是.Net。
答案 0 :(得分:10)
好消息:您可以在iTextSharp中更改字段名称。
您实际上无法编辑PDF。您已阅读现有PDF,在内存中更新您的字段名称,然后写出您修改后的PDF。要更改字段名称,请调用AcroFields.RenameField方法。
这是一个片段:
PdfReader reader = new PdfReader(PDF_PATH);
using (FileStream fs = new FileStream("Test Out.pdf", FileMode.Create)) {
PdfStamper stamper = new PdfStamper(reader, fs);
AcroFields fields = stamper.AcroFields;
fields.RenameField("oldFieldName", "newFieldName");
stamper.Close();
}
现在是坏消息:您可以在重命名的字段中使用的字符存在限制。
我使用您的示例字段名称测试了上面的代码段,但它无效。删除期间虽然它确实有效。我不确定是否有解决方法,但这对您来说可能是一个问题,
答案 1 :(得分:6)
AcroForm字段的全名未明确存储在字段中。它实际上是从一个字段层次结构派生出来的,左边是一个以点分隔的祖先列表。
只需将'topmostSubform [0] .Page1 [0] .Website_Address [0]'中的字段重命名为'WebsiteAddress'就不太可能产生正确的结果。
你会发现PDF参考的第8.6.2节“字段字典”提供了字段命名如何工作的一个很好的解释; - )
基本上,AcroForm中的每个字段都由字典定义,字典可能包含与字段名称相关的某些可选条目。
键'/ T'指定部分名称。在您的问题中,'topmostSubform [0]','Page1 [0]'和Website_Address [0]都代表部分名称。
Key'/ TU'为字段指定了另一个“用户友好”名称,可用于代替实际字段名称以识别用户界面中的字段。
考虑添加/ TU条目,而不是重命名有关字段!
下面的示例使用ABCpdf遍历AcroForm中的所有字段,并根据其部分名称在字段中插入备用名称。
的VBScript:
Set theDoc = CreateObject("ABCpdf7.Doc")
theDoc.Read "myForm.pdf"
Dim theFieldIDs, theList
theFieldIDs = theDoc.GetInfo(theDoc.Root, "Field IDs")
theList = Split(theFieldIDs, ",")
For Each fieldID In theList
thePartialName = theDoc.GetInfo(fieldID, "/T:text")
theDoc.SetInfo fieldID, "/TU:text", thePartialName
Next
theDoc.Save "output.pdf"
theDoc.Clear
将"/TU:text"
更改为"/T:text"
会设置字段的部分名称。
使用C#和VB.NET编写的函数可以在这里找到: Doc.GetInfo,Doc.SetInfo。另请参阅Object Paths上的文档。
答案 2 :(得分:6)
我昨天遇到了这个问题,在论坛和其他人那里尝试了答案后却没有取得任何进展。我的代码看起来像这样。
// Open up the file and read the fields on it.
var pdfReader = new PdfReader(PATH_TO_PDF);
var fs = new FileStream(pdfFilename, FileMode.Create, FileAccess.ReadWrite)
var stamper = new PdfStamper(pdfReader, fs);
var pdfFields = stamper.AcroFields;
//I thought this next line of code I commented out will do it
//pdfFields.RenameField("currentFieldName", "newFieldName");
// It did for some fields, but returned false for others.
// Then I looked at the AcroFields.RenameField method in itextSharp source and noticed some restrictions. You may want to do the same.
// So I replaced that line pdfFields.RenameField(currentFieldName, newFieldName); with these 5 lines
AcroFields.Item item = pdfFields.Fields[currentFieldName];
PdfString ss = new PdfString(newFieldName, PdfObject.TEXT_UNICODE);
item.WriteToAll(PdfName.T, ss, AcroFields.Item.WRITE_VALUE | AcroFields.Item.WRITE_MERGED);
item.MarkUsed(pdfFields, AcroFields.Item.WRITE_VALUE);
pdfFields.Fields[newFieldName] = item;
这就完成了工作
答案 3 :(得分:3)
也许你可以考虑这个:
我必须说我们有AbcPDF许可证,我们在Java项目中也使用iText 2.1.7 ...所以我可以说我同意以前的答案,但是,你不能使用/购买这个产品,您可以尝试将该名称替换为纯pdf代码(作为普通的txt文件),遵循PDF规范:
签名字段的示例:
35 0 obj
<<
/AP <<
/N 37 0 R
>>
/DA (/TimesRoman 0 Tf 0 g)
/F 4
/FT /Sig
/P 29 0 R
/Rect [ 86 426 266 501 ]
/Subtype /Widget
/T (FIELD_MODIF)
/Type /Annot
/V 36 0 R
>>
endobj
“FIELD_MODIF”在哪里放置新名称。
答案 4 :(得分:2)
虽然您无法使用javascript重命名字段,但您可以添加新字段并删除现有字段。您还可以在文档之间剪切和粘贴。所以......
<强>一即可。开发重命名脚本,例如:
var doc = app.activeDocs[0];
var fnames = new Array();
for ( var i = 0; i < doc.numFields - 1; i++) {
fnames[i] = doc.getNthFieldName(i);
}
for (var i = 0; i < doc.numFields - 1; i++){
var f = doc.getField(fnames[i] + ".0");
var nfn = fnames[i].replace("1","2");
var rb = doc.addField(nfn,"radiobutton",0,f.rect)
for ( var j = 1; j < 9; j++){//Add the other 8
f = doc.getField(fnames[i] + "." + j);
doc.addField(nfn,"radiobutton",0,f.rect)
}
rb.setExportValues([1,2,3,4,5,6,7,8,9]);
rb.borderStyle = f.borderStyle;
rb.strokeColor = f.strokeColor;
rb.fillColor = f.fillColor;
doc.removeField(fnames[i]);
console.println(fnames[i] + " to " + nfn);
}
注意:
重命名字段可能会更改getNthFieldName的字段顺序,因此请先获取这些字段
一组radiobuttons是一个字段(getField(“Groupname”)),要获得同一组中的n'使用getField(“Groupname.n”),您需要这些用于位置矩形。适用于所有人的属性可以设置为enmase
addField参数有:字段名称,字段类型,页面,位置矩形)
在该示例中,每组中有9个radiobutton
<强>两个即可。将要重命名的字段剪切并粘贴到空白pdf(我假设上面有一页)。运行脚本。剪切并粘贴。
如果在运行脚本时保持两个文档都打开,您可能需要将app.activeDocs [0]更改为app.activeDocs [1]或将“doc”替换为“this”
答案 5 :(得分:1)
最好的方法是存储字段rect然后创建具有所需名称和存储的rect位置的新字段,新字段将与旧字段位于相同位置,ta da :) 这是代码:
Sub CreateNewField()
Create = "var f = this.getField('" & oldFieldName & "'); var rect = f.rect;
this.addField('" & newFieldName & "','text',0,rect);"
FormFields.ExecuteThisJavascript Create
DeleteField 'sub to delete old field
End Sub
答案 6 :(得分:0)
是的,可以重命名表单字段。我没有任何使用源代码API的经验可以帮助您解决这个问题,但是我的公司PDF SDK can help您这样做,并且从一点点搜索看来iText will indeed let you rename form fields。
答案 7 :(得分:0)
以下是本书中的“iText in Action”
中的java示例这是从他们的书的示例源代码中获取的,并且极大地帮助了我同样的问题。 part2.chapter06.ConcatenateForms2
public static void main(String[] args)
throws IOException, DocumentException {
// Create a PdfCopyFields object
PdfCopyFields copy
= new PdfCopyFields(new FileOutputStream(RESULT));
// add a document
PdfReader reader1 = new PdfReader(renameFieldsIn(DATASHEET, 1));
copy.addDocument(reader1);
// add a document
PdfReader reader2 = new PdfReader(renameFieldsIn(DATASHEET, 2));
copy.addDocument(reader2);
// Close the PdfCopyFields object
copy.close();
reader1.close();
reader2.close();
}
private static byte[] renameFieldsIn(String datasheet, int i)
throws IOException, DocumentException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// Create the stamper
PdfStamper stamper = new PdfStamper(new PdfReader(datasheet), baos);
// Get the fields
AcroFields form = stamper.getAcroFields();
// Loop over the fields
Set<String> keys = new HashSet<String>(form.getFields().keySet());
for (String key : keys) {
// rename the fields
form.renameField(key, String.format("%s_%d", key, i));
}
// close the stamper
stamper.close();
return baos.toByteArray();
}
答案 8 :(得分:0)
这对我使用 iText 7 有用:
PdfReader reader = new PdfReader("Source.pdf");
using (FileStream fs = new FileStream("Dest.pdf", FileMode.Create))
{
using (var pdfDoc = new PdfDocument(reader, new PdfWriter(fs)))
{
PdfAcroForm pdfForm = PdfAcroForm.GetAcroForm(pdfDoc, true);
pdfDoc.GetWriter().SetCloseStream(true);
var Fields = pdfForm.GetFormFields().Select(x => x.Key).ToArray();
for (int i = 0; i < Fields.Length; i++)
{
pdfForm.RenameField(Fields[i], "new_" + Fields[i]);
}
}
}