Можно ли изменить имена полей формы PDF?

вот ситуация. У меня есть PDF с автоматически сгенерированными именами полей формы pdf. Проблема в том, что эти имена не очень удобный. Они выглядят примерно так : topmostSubform[0].Page1[0].Website_Address[0]

Я хочу иметь возможность изменить их так, чтобы они были чем-то вроде WebsiteAddress. У меня есть доступ к ABCPDF, и у меня есть опыт работы с iTextSharp, но я попытался использовать эти API для этого (поля формы доступа и попытаться переименовать), но это не кажется, что это возможно.

есть ли у кого-нибудь опыт, пытающийся сделать это через какой-либо API (предпочтительно с открытым исходным кодом). Код также .Net.

8 ответов


хорошая новость: вы можете изменить имена полей в iTextSharp.

вы не можете редактировать PDF-файл. Вы читаете в существующем PDF-файле, обновляете имена полей в памяти, а затем записываете пересмотренный PDF-файл. Чтобы изменить имя поля называют Сети.Метод 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();
}

теперь плохие новости: появляются ограничения в символах, которые вы можете использовать в переименованных полях.

я протестировал фрагмент выше с вашим именем Поля примера, и это не сработало. Удалите периоды, хотя, и это работает. Я не уверен, что есть обходной путь, но это может быть проблемой для вас,


полное имя поля AcroForm явно не сохраняется в поле. Он фактически получен из иерархии полей, с разделенным точкой списком предков, появляющимся слева.

просто переименование поля из ' topmostSubform[0].Page1[0].Поэтому Website_Address[0] 'to' WebsiteAddress ' вряд ли даст правильный результат.

вы найдете раздел 8.6.2 "словари полей" ссылки PDF дает хорошее объяснение того, как именование полей работает ;-)

в принципе, каждое поле в AcroForm это определить словарь, который может содержать некоторые дополнительные элементы, относящиеся к полю имя.

  • клавиша '/T' указывает частичное имя. В вашем вопросе " topmostSubform[0]", "Page1[0]" и Website_Address[0] все представляют частичные имена.

  • Key '/TU 'указывает альтернативное" удобное " имя для полей, которое может использоваться вместо фактического имени Поля для идентификации полей в пользовательском интерфейсе.

вместо переименования рассматриваемого поля подумайте о добавлении записи a /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" to "/T:text" установит частичное имя поля.

примеры, написанные на C# и VB.NET из используемые функции можно найти здесь: док.GetInfo, Doc.SetInfo. См. также документацию по Путь К Объекту.


У меня была проблема вчера и после того, как я попробовал ответы на форуме и других, но не продвинулся. Мой код выглядел так.

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

и это сделало работу


возможно, вы можете рассмотреть это:

  • iText не является бесплатным, в сдержащих программная среда (2.1.7 it / 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" - это место, где помещается новое имя.


хотя вы не можете переименовать поля с помощью 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, поэтому сначала получите их.
Группа радиобутонов-это одно поле (getField ("Groupname")), чтобы получить n-е в той же группе, используйте getField ("Groupname.н"), вы нужны эти для прямоугольника положения. Свойства, которые применяются ко всем можно установить enmase.
параметры addField: имя поля, тип поля, страница, прямоугольник позиции)
В примере есть 9 радиобутонов в каждой группе

два. Вырезать и вставить поля, которые вы хотите переименовать в пустой pdf (я предположил одну страницу выше). Запустить сценарий. Вырезать и вставить обратно.

вам может потребоваться изменить приложение.activeDocs[0] в приложение.activeDocs[1] или заменить "doc" на "это", если оба документа открыты при запуске скрипта


лучший способ-сохранить поля 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

да, можно переименовать поля формы. У меня нет опыта работы с API исходного кода, который поможет вам в этом, но мои компании PDF SDK может помочь вы делаете это, и из немного поиска кажется, что iText действительно позволит вам переименовать поля формы.


вот пример java, найденный в книге "iText in Action"

это взято из их примера исходного кода для книги и очень помогло мне с этой же проблемой. часть2.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();
}