Изменить порядок AcroFields в существующих PDF с помощью iText?

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

Например, у меня есть текстовое поле с именем "number_field", которое находится под вторым текстовым полем с именем "name_field". Когда я устанавливаю значение для этих полей через iText (то есть, 10 для number_field и "John" для name_field), число_field теперь находится над name_field.

Как изменить порядок на странице этих полей с помощью iText? Является ли это возможным?

Ссылка на пример PDF: https://freecompany.sharefile.com/d-s84f6d63e7d04fe79

1 ответ

Решение

Я сделал следующий билет в трекере проблем в iText Group:

Проблема вызвана тем, что iText считывает элементы поля в HashMap следовательно, нет никакого способа предсказать, в каком порядке они будут сплющены. Обычно это не проблема. Я не думаю, что эта проблема возникает в том случае, если вы не выравниваете PDF, потому что в этом случае внешний вид сохраняется в аннотациях виджета, и программа просмотра PDF должна решить, какое поле покрывает другое в случае перекрывающихся полей,

Однако если поля формы перекрываются, вы не можете предсказать, какое поле будет покрыто при выравнивании.

Предположим, что мы будем использовать TreeMap вместо HashMap это решит проблему? Не совсем, потому что Comparator мы будем использовать? Иногда порядок табуляции определяется, но не всегда. Если это не определено, должны ли мы упорядочить поля в том порядке, в котором они появляются в /Fields массив? Или имеет смысл упорядочить их по порядку аннотаций виджетов в /Annots массив? Другой вариант - заказать их в зависимости от их положения на странице. Короче говоря, это не решение, которое должен принять iText.

Однако, если кто-то хотел бы решить эту проблему, мы могли бы создать Comparator переменная-член для PdfStamperImp, Если такой Comparator предоставляется (мы могли бы даже предоставить некоторые реализации), тогда процесс выравнивания будет выполняться в порядке, определенном Comparator,

Этот билет получил очень низкий приоритет (я предполагаю, что вы не являетесь клиентом одной из компаний iText Software), но при написании этого билета у меня была другая идея.

Я уже ссылался на подчеркивающую часть текста, используя iTextSharp в комментариях. В этом случае вы получите все позиции на местах (используя getFieldPositions() метод) и нарисуйте все содержимое в правильном порядке, используя ColumnText, У этого подхода есть несколько недостатков: чтобы шрифт, размер шрифта и цвет шрифта были правильными, вам необходимо изучить поля. Это требует некоторого программирования.

Сейчас я публикую это как ответ, потому что у меня есть гораздо лучшая альтернатива: заполните форму в два прохода! Это показано в примере FillFormFieldOrder. Заполняем форму src в результате чего сплющенная форма dest как это:

public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
    go2(go1(src), dest);
}

Как видите, мы выполняем go1() Метод первый:

public byte[] go1(String src) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    PdfStamper stamper = new PdfStamper(reader, baos);
    AcroFields form = stamper.getAcroFields();
    form.setField("sunday_1", "1");
    form.setField("sunday_2", "2");
    form.setField("sunday_3", "3");
    form.setField("sunday_4", "4");
    form.setField("sunday_5", "5");
    form.setField("sunday_6", "6");
    stamper.setFormFlattening(true);
    stamper.partialFormFlattening("sunday_1");
    stamper.partialFormFlattening("sunday_2");
    stamper.partialFormFlattening("sunday_3");
    stamper.partialFormFlattening("sunday_4");
    stamper.partialFormFlattening("sunday_5");
    stamper.partialFormFlattening("sunday_6");
    stamper.close();
    reader.close();
    return baos.toByteArray();
}

Это заполняет все sunday_x поля и использует частичное выравнивание формы, чтобы сгладить только эти поля. go1() метод занимает src в качестве параметра и возвращает byte[] будет частично сплющенная форма.

byte[] будет использоваться в качестве параметра для go2() метод, который требует dest как его второй параметр. Теперь мы собираемся заполнить sunday_x_notes поля:

public void go2(byte[] src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    AcroFields form = stamper.getAcroFields();
    form.setField("sunday_1_notes", "It's Sunday today, let's go to the sea");
    form.setField("sunday_2_notes", "It's Sunday today, let's go to the park");
    form.setField("sunday_3_notes", "It's Sunday today, let's go to the beach");
    form.setField("sunday_4_notes", "It's Sunday today, let's go to the woods");
    form.setField("sunday_5_notes", "It's Sunday today, let's go to the lake");
    form.setField("sunday_6_notes", "It's Sunday today, let's go to the river");
    stamper.setFormFlattening(true);
    stamper.close();
    reader.close();
}

Как видите, теперь мы сглаживаем все поля. Результат выглядит так:

Теперь вам больше не нужно беспокоиться о порядке полей, а не в /Fields массив, а не в /Annots массив. Поля заполняются в том порядке, в котором вы хотите. Примечания теперь охватывают даты, а не наоборот.

Другие вопросы по тегам