Рубрики
Без рубрики

Заполнение PDF формы с Python

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Формы наполнения были частью формата PDF Adobe в течение многих лет. Одним из самых известных примеров заполняемых форм в Соединенных Штатах являются документы из службы внутреннего дохода. Есть много правительственных форм, которые используют заполняемые формы. Существует много разных подходов для заполнения этих форм программно. Самый трудоемкий метод, о котором я слышал, это просто воссоздать форму в ReportLab вручную, а затем заполнить его. Честно говоря, я думаю, что это, вероятно, худшая идея, за исключением случаев, когда ваша компания отвечает за создание самого PDF. Тогда это может быть жизнеспособным вариантом, поскольку у вас есть полный контроль над созданием PDF и входам, которые необходимо зайти в него.

Создание простой формы

Нам нужна простая форма для использования для нашего первого примера. REPORTLAB имеет встроенную поддержку для создания интерактивных форм, поэтому давайте использовать REPORTLAB для создания простой формы. Вот код:

# simple_form.py

from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfform
from reportlab.lib.colors import magenta, pink, blue, green

def create_simple_form():
    c = canvas.Canvas('simple_form.pdf')
    
    c.setFont("Courier", 20)
    c.drawCentredString(300, 700, 'Employment Form')
    c.setFont("Courier", 14)
    form = c.acroForm
    
    c.drawString(10, 650, 'First Name:')
    form.textfield(name='fname', tooltip='First Name',
                   x=110, y=635, borderStyle='inset',
                   borderColor=magenta, fillColor=pink, 
                   width=300,
                   textColor=blue, forceBorder=True)
    
    c.drawString(10, 600, 'Last Name:')
    form.textfield(name='lname', tooltip='Last Name',
                   x=110, y=585, borderStyle='inset',
                   borderColor=green, fillColor=magenta, 
                   width=300,
                   textColor=blue, forceBorder=True)
    
    c.drawString(10, 550, 'Address:')
    form.textfield(name='address', tooltip='Address',
                   x=110, y=535, borderStyle='inset',
                   width=400, forceBorder=True)
    
    c.drawString(10, 500, 'City:')
    form.textfield(name='city', tooltip='City',
                   x=110, y=485, borderStyle='inset',
                   forceBorder=True)
    
    c.drawString(250, 500, 'State:')
    form.textfield(name='state', tooltip='State',
                   x=350, y=485, borderStyle='inset',
                   forceBorder=True)
    
    c.drawString(10, 450, 'Zip Code:')
    form.textfield(name='zip_code', tooltip='Zip Code',
                   x=110, y=435, borderStyle='inset',
                   forceBorder=True)
    
    c.save()
    
if __name__ == '__main__':
    create_simple_form()

Когда вы запускаете этот пример, интерактивная форма PDF выглядит так:

Теперь мы готовы изучить один из способов, которыми мы можем заполнить эту форму!

Объединение наложения

Ян Ченч написал статью о Средний Это содержало несколько различных подходов к этой проблеме заполнения форм в формате PDF. Предложенный первым решением было предложить незаполненную форму в PDF и создать отдельный PDF с использованием REPORTLAB, которая имеет данные, которые мы хотим нам «заполнить» эту форму. Автор затем использовал PDFRW объединить два PDF вместе. Вы можете теоретически использовать PYPDF2 для процесса слияния. Давайте пойдем вперед и посмотрим, как этот подход может работать с помощью PDFRW упаковка.

Давайте начнем с установки PDFRW :

python -m pip install pdfrw

Теперь, когда у нас есть эти установленные, давайте создадим файл под названием fill_by_overlay.py Отказ Мы добавим две функции в этот файл. Первая функция создаст наше наложение. Давайте проверим это:

# fill_by_overlay.py

import pdfrw
from reportlab.pdfgen import canvas


def create_overlay():
    """
    Create the data that will be overlayed on top
    of the form that we want to fill
    """
    c = canvas.Canvas('simple_form_overlay.pdf')
    
    c.drawString(115, 650, 'Mike')
    c.drawString(115, 600, 'Driscoll')
    c.drawString(115, 550, '123 Greenway Road')
    c.drawString(115, 500, 'Everytown')
    c.drawString(355, 500, 'IA')
    c.drawString(115, 450, '55555')
    
    c.save()

Здесь мы импортируем PDFRW пакет, и мы также импортируем холст Подмодуль от ReportLab. Тогда мы создаем функцию под названием create_overlay Это создает простой PDF с использованием ReportLab Холст класс. Мы просто используем Drawstring метод холста. Это займет некоторую пробную и ошибку. К счастью, на Linux и Mac, есть приличные приложения PDF Previewer, которые вы можете использовать, чтобы просто сохранить PDF Open, и они автоматически обновляются с каждым изменением. Это очень полезно для выяснения точных координат, которые вам нужно нарисовать свои строки. Поскольку мы создали оригинальную форму, выяснение смещения для наложения на самом деле довольно легко. Мы уже знали, где на странице элементы формы были, поэтому мы можем сделать хорошие образованные догадки, где можно нарисовать струны.

Следующая часть головоломки фактически объединяет наложение, которое мы создали выше с формой, созданной в предыдущем разделе. Давайте напишем, что функция следующая:

def merge_pdfs(form_pdf, overlay_pdf, output):
    """
    Merge the specified fillable form PDF with the 
    overlay PDF and save the output
    """
    form = pdfrw.PdfReader(form_pdf)
    olay = pdfrw.PdfReader(overlay_pdf)
    
    for form_page, overlay_page in zip(form.pages, olay.pages):
        merge_obj = pdfrw.PageMerge()
        overlay = merge_obj.add(overlay_page)[0]
        pdfrw.PageMerge(form_page).add(overlay).render()
        
    writer = pdfrw.PdfWriter()
    writer.write(output, form)
    
    
if __name__ == '__main__':
    create_overlay()
    merge_pdfs('simple_form.pdf', 
               'simple_form_overlay.pdf', 
               'merged_form.pdf')

Здесь мы открываем как форму, так и наложенные PDF с помощью PDFRW’s Pdwreader классы. Затем мы распилеем на страницы как PDF, и объединяем их вместе, используя Pagemerge Отказ В конце кода мы создаем экземпляр Pdfwriter Что мы используем для записи вновь объединенного PDF. Конечный результат должен выглядеть так:

Примечание. Когда я запустил этот код, я получил некоторые ошибки на STDOUT. Вот пример:

[ERROR] tokens.py:226 stream /Length attribute (171) appears to be too small (size 470) -- adjusting (line=192, col=1)

Как я уже упоминал, это на самом деле не мешает созданию слитого PDF. Но вы можете следить за этим, так как они могут подсказать проблему, если у вас есть какие-либо проблемы.

Другие способы заполнения форм

Я прочитал около нескольких других способов «заполнить» поля в таких видах PDF. Один из них должен был взять PDF и сохранить страницы как серию изображений. Затем нарисуйте прямоугольники в местах, которые вы хотите добавить текст, а затем использовать новое изображение в качестве файла конфигурации для заполнения PDF. Кажется видом дурака и честно говоря, я не хочу идти ко всему этой работе.

Лучший метод будет открывать PDF в редакторе PDF, где вы можете добавить невидимые поля только для чтения. Вы можете отметить поля уникальными именами, а затем получить доступ к ним через метаданные PDF. Цвет по метадате и используйте методы холста ReportLab, чтобы снова создать наложение, а затем объединить его так же, как и раньше.

Я также видел, как многие люди говорят об использовании формата данных форм или FDF. Это формат, который предполагается, что PDFS используют для удержания этих данных, которые должны быть заполнены в PDF. Вы можете использовать Pypdftk и Pdfjinja сделать заполнение формы. Интересно, Pypdftk Не работает с полями изображения, например, где вы можете вставить изображение подписи. Вы можете использовать Pdfjinja Для этого. Однако Pdfjinja Кажется, имеет некоторые ограничения при работе с флажками и радиобоксами.

Вы можете прочитать больше об этих темах по следующим ссылкам:

Использование пакета PDFFRMS

Пакет, который я думаю, удерживает наибольшее количество обещаний в отношении простоты для использования – это новый pdfforms упаковка. Это требует, чтобы вы устанавливаете кроссплатформенную приложение под названием PDFTK хоть. К счастью, PDFTK свободен, так что это не очень проблема.

Вы можете установить pdfforms, используя PIP, как это:

python -m pip install pdfforms

Использовать pdfforms, вы должны сначала у него проверять PDF, который содержит форму, чтобы она знала, как ее заполнить. Вы можете сделать проверку, как это:

pdfforms inspect simple_form.pdf

Если PDFFRMS работает правильно, он создаст «заполненный» PDF в его «тестовой» подпапке. Эта подпапка появляется рядом с тем, где сама pdfforms не так, не там, откуда. Это заполнит форму с номерами в последовательном порядке. Это Полевые номера Отказ

Следующее, что вы делаете, это создать файл CSV, в котором первый столбец и строка содержит имя PDF. Другие строки в первом столбце соответствуют номерам поля. Вы вводите номера полей, которые вы хотите заполнить здесь. Затем вы вводите данные, которые вы хотите заполнить в форме в форме третьего столбца вашего файла CSV. Второй столбец игнорируется, так что вы можете поставить описание здесь. Все столбцы после третьего столбца также игнорируются, поэтому их можно использовать для того, что вы хотите.

Для этого примера ваш файл CSV может выглядеть что-то подобное:

simple_form.pdf,,,
1,first name,Mike
2,last name,Driscoll

После того, как вы заполните CSV, вы можете запустить следующую команду, чтобы фактически заполнить вашу форму с помощью своих пользовательских данных:

pdfforms fill data.csv

Заполненный PDF появится в подпунечной папке заполнены по умолчанию.

Теперь на плохие новости. Я не смог заставить это работать правильно на Windows или Mac. Я получил проверять Шаг для работы на Windows, но на Mac это просто висит. На окнах, когда я бегу на заполнить Команда это просто не удается с ошибкой о неисправности PDF для заполнения.

Я думаю, что когда этот пакет становится менее подверженным ошибкам, это будет действительно удивительно. Единственным основным недостатком, отличным от его возникновения, заключается в том, что вам необходимо установить 3-й Party Tool, который вообще не написан в Python.

Обертывание

Посмотрев на множество различных вариантов, доступных для разработчика Python для заполнения форм PDF, я думаю, что самый прямой метод создает наложение, а затем объединяет его на заполняемую форму PDF, используя инструмент, такой как PDFRW. Хотя это немного похоже на взлом, другие методы, которые я видел, кажется, так же как хаки и как поглощение времени. После того, как у вас есть положение одной из клеток в форме, вы можете разумно рассчитать большинство других на странице.

Дополнительное чтение