2010-02-26 74 views
5

这是情况。我有一个PDF自动生成的PDF表单字段名称。问题是这些名称不是非常用户友好的。他们看起来像这样: topmostSubform [0] .Page1 [0] .Website_Address [0]是否可以修改PDF表格字段名称?

我希望能够改变它们,使它们像WebsiteAddress。我有权访问ABCPDF,并且我有使用iTextSharp的经验,但我尝试过使用这些API来做到这一点(访问表单字段并尝试重命名),但似乎并不可行。

没有任何人有任何试图通过某种(最好是开放源代码)的API做这方面的经验。代码也是.Net也是。

回答

7

好消息:你可以改变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(); 
} 

现在的坏消息:有似乎是,你可以在重命名字段中使用的字符限制。

我测试上面的代码片段与您的示例字段名称和它没有工作。尽管删除时段,它确实有效。我不知道是否有一种解决方法,但是这可能是你的问题,

6

的AcroForm领域的全名并没有明确存储在一个领域内。它实际上是从一个字段层次结构派生而来的,左边出现一个以点分隔的祖先列表。

因此,将'topmostSubform [0] .Page1 [0] .Website_Address [0]''字段重命名为'WebsiteAddress'不太可能产生正确的结果。

你会找到PDF参考第8.6.2田间字典“提供的字段命名如何工作;-)

基本上每场在AcroForm一个很好的解释是一本字典,定义哪些可能包含与字段名称相关的某些可选条目。

  • 键'/ T'指定部分名称。在你的问题中,'topmostSubform [0]','Page1 [0]'和Website_Address [0]都表示部分名称。

  • 键'/ 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.GetInfoDoc.SetInfo。另见文件Object Paths

5

我昨天遇到了问题,并在论坛和其他人尝试了答案,但没有取得任何进展。我的代码看起来像这样。

// 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

也许你可以考虑一下:

  • iText的不是免费的,在propietary软件环境(2.1.7它/ s的最后一个“自由'版本)。
  • AbcPDF也不免费。

我不得不说,我们有AbcPDF许可证,而我们使用的iText 2.1.7过我们的Java项目...所以我可以说,我以前的答案一致,但是,它不能使用/买这个产品,你可以尝试更换名字变成纯粹的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”这是放新名字的地方。

+0

这一次得手,但后来我加了检查盒子,单选按钮和一个下拉列表,看看它是否适用于这些。在保存pdf并在记事本++中查看原始文本后,我不能再在原始文本中标识任何字段名称。找不到任何东西。虽然这是一个伟大的想法......这个问题困扰了我,毫不夸张地说,几年。 – jason 2017-08-22 14:34:25

0

下面是书中发现,“iText的在行动”

这是从他们的源代码示例采取这本书,与此相同的问题,极大地帮助了我的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(); 
} 
2

尽管您不能使用javascript重命名字段,但您可以添加新字段并删除现有字段。您也可以剪切和粘贴文件。所以...

One。制定重命名脚本,例如:

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领域的秩序,所以得到这些第一。
一组单选按钮是一个字段(getField(“Groupname”)),要在同一组中使用getField(“Groupname.n”)获得第n个,则需要这些位置矩形。适用于所有的属性可以设置为enmase。
激活addField参数是:字段名,字段类型,页面,位置矩形)
在该实例中有9个单选按钮每组

两个英寸将要重命名的字段剪切并粘贴为空白pdf(我假设上面有一页)。运行脚本。剪下并粘贴回来。

您可能需要更改app.activeDocs [0]到app.activeDocs [1]或更换“DOC”和“本”,如果保留两个打开的文档运行脚本时

1

最好的办法是存储领域RECT,然后创建所需的名称和存储位置RECT的新领域,新领域将是相同的位置,老油田,ただ:) 这里是代码:

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 
+1

OP的问题是关于通过API编辑字段名称。即使你的答案是有效的,发布代码示例也不失为一件好事。 – 2018-01-19 22:10:36

+0

对于迟到的回复,我表示歉意。我还花了很长时间来改变字段的名称,最后我意识到最好记录下我想重命名的字段的位置,然后擦除它,并放置一个新字段,其中包含所需的名称在同一个地方。我通过使用java脚本,但通过excel vba实现了这一点。 – 2018-01-26 21:10:54

相关问题