Можно ли изменить имена полей формы 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();
}