Поля в PDF-файлах имеют необычное свойство: все поля с одинаковым именем 1002 * являются одинаковыми полем .Они разделяют ценность.Это удобно, когда форма относится к одному и тому же человеку, и у вас есть хорошая схема именования для всех форм.Это не удобно, если вы хотите поместить 20 экземпляров одной формы в один файл PDF.
Это затрудняет объединение нескольких форм, если не сказать больше.Наиболее распространенный вариант (благодаря iText) - это выравнивание форм перед их объединением, после чего вы больше не объединяете формы, и проблема уходит.
Другой вариант - переименовать вашполя до слияния их.Это может впоследствии затруднить извлечение данных, нарушить работу сценариев и обычно является PITA.Вот почему сглаживание намного популярнее.
В iText есть класс с именем PdfCopyFields
, и он будет правильно копировать поля из одного документа в другой ... он также объединит поля с тем же именем правильно , так что они действительно разделяют одно значение, и Acrobat / Reader не нужно выполнять кучу дополнительной работы с файлом, чтобы получить его таким образом, прежде чем отобразить его пользователю.
Однако PdfCopyFields
не будет переименовывать поля для вас.Для этого вам нужно получить объект AcroFields
у рассматриваемого PdfReader
и вызвать renameField(String, String)
в каждом поле перед каждым объединением документов с PdfCopyFields
.
Все этодля PDF-форм на основе AcroForm.Если вы имеете дело с формами XFA (формами из LiveCycle Designer), все ставки отменены.Вам придётся разбираться с XML, много.
И небеса помогут вам, если вам придется комбинировать формы из обоих.
Настолько, что вы работаете сПоля AcroForm, код может выглядеть примерно так (простите за Java):
public void mergeForms(String outpath, String inPaths[]) {
PdfCopyFields copier = new PdfCopyFields(new FileOutputStream(outpath) );
for (String curInPath : inPaths) {
PdfReader reader = new PdfReader(curInPath);
renameFields(reader.getAcroFields());
copier.addDocument(reader);
}
copier.close();
}
private static int counter = 0;
private void renameFields(AcroFields fields) {
Set<String> fieldNames = fields.getFields().keySet();
String prepend = String.format("_%d.", counter++);
for(String fieldName : fieldNames) {
fields.rename(fieldName, prepend + fieldName);
}
}
В идеале renameFields
также создаст объект общего поля с именем prepend's-value и сделает все остальные поля в документеэто дети.Это облегчит жизнь Acrobat / Reader и позволит избежать ненужных «сохранения изменений»?запрашивать при закрытии полученного PDF от Acrobat.
Да, именно поэтому Acrobat иногда просит вас сохранить изменения, когда вы ничего не сделали!Acrobat сделал что-то за кадром.