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

Создавайте PDF-файлы из шаблонов с помощью скриптов Python и Google

Этот учебник покажет вам, как создать свой собственный бесплатный генератор шаблонов, который сочетает в себе гибкость Google Docs и мощь Python. Потратьте полчаса на создание собственных шаблонов PDF и заполнение их любыми необходимыми данными.

Автор оригинала: Gareth Dwyer.

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

У вас есть несколько вариантов для этого. Обычные из них:

  1. Используйте библиотеку PDF, такую как reportlab , для непосредственного создания PDF-файлов (например, https://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/)
  2. Используйте библиотеку шаблонов HTML, такую как Jinja2 , и конвертируйте из HTML в PDF (например, см. http://pbpython.com/pdf-reports.html)
  3. Используйте сторонний API,например https://pdfgeneratorapi.com/.

Для варианта 1 создание PDF-файлов непосредственно из Python может очень затруднить форматирование. Вы должны рисовать все, что вам нужно, элемент за элементом, используя код, и даже если у вас есть шаблон, который выглядит так, как вы хотите, его трудно поддерживать.

Вариант 2 часто может работать лучше, но вам все равно придется создавать шаблон Jinja HTML, и иногда преобразование HTML в PDF выходит не совсем так, как вы ожидали.

Вариант 3 требует, чтобы вы сначала создали шаблон с помощью веб-интерфейса онлайн-службы. Хотя вы получаете интерфейс перетаскивания, он довольно неуклюж и трудно заставить ваш шаблон выглядеть так, как вы хотите. Как правило, вы также должны заплатить, чтобы воспользоваться услугой.

Хотя один из вышеперечисленных вариантов может работать для вас, если вам не нравится ни один из них, вы также можете взломать API создания документов на основе Google Диска. Вы получите бесплатный API, и вы сможете использовать Google Docs в качестве инструмента для создания шаблонов, который является довольно мощным и имеет множество уже существующих шаблонов для таких вещей, как счета, письма и резюме.

Я начал с шаблона счета, который нашел в Интернете. Это выглядит так:

Шаблон счета Google Docs

В этом руководстве мы рассмотрим создание API, который генерирует эти счета-фактуры и позволяет программно вставлять номер счета из внешнего скрипта Python. На самом деле вам нужно было бы сделать то же самое для многих других областей, но мы начнем с простого примера для демонстрации.

Мы напишем несколько строк кода скрипта приложения Google и несколько строк кода Python.

Создание шаблона документа

Используйте один из встроенных шаблонов документов Google, найдите в Интернете тот, который соответствует вашим потребностям, или создайте свой собственный docs.google.com. (Вам понадобится учетная запись Google).

Добавьте заполнители, где вам нужна динамическая информация. В приведенном ниже примере я добавил INVOICE NO {invoice_id} вместо идентификатора “456”, который был у меня в исходном документе. В этом синтаксисе нет ничего особенного-позже мы будем использовать базовую функцию поиска и замены, чтобы заменить ее реальной информацией, поэтому используйте что-то, что вряд ли появится в окончательном документе.

Запишите свой идентификатор документа, который является выделенной частью в строке URL-адреса.

Шаблон счета-фактуры с заполнителем

Настройка пользовательского скрипта Google

Перейдите на Google Диск, нажмите “Создать” в левом верхнем углу. В разделе “Дополнительно” выберите “Скрипт Google Apps”, если он доступен, или “Подключить дополнительные приложения”, если вы его не видите.

Подключение дополнительных приложений

Найдите “скрипт приложений” и выберите его для подключения. Вы можете увидеть несколько предупреждающих сообщений, спрашивающих, доверяете ли вы себе. Скажи, что знаешь.

Добавление скрипта приложений

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

Пустой скрипт Google Apps

Удалите код, который вы там видите, и замените его функцией createDocument , которая выглядит следующим образом.

function createDocument(invoice_id) {
  var TEMPLATE_ID = '1Ybq8r_SiWu4Z4-_Z6S0IW1L8FJywfpjPAATPCvvkKk8';  
  var documentId = DriveApp.getFileById(TEMPLATE_ID).makeCopy().getId();
  
  drivedoc = DriveApp.getFileById(documentId);
  drivedoc.setName("Invoice " + invoice_id);
  
  doc = DocumentApp.openById(documentId);
  
  var body = doc.getBody();
  
  body.replaceText('{invoice_id}', invoice_id);
  drivedoc.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT);

  return "https://docs.google.com/document/d/" + documentId + "/export?format=pdf";
}

В строке 2 переключите TEMPLATE_ID с идентификатором документа, который вы скопировали из строки URL-адреса в шаблоне Google Doc.

Этот код находит документ шаблона, создает его копию и устанавливает имя файла в “Счет-фактура” плюс любой invoice_id , который мы передаем. Затем он открывает новый файл через приложение “Документ” (вместо приложения “Диск”, чтобы мы могли получить содержимое файла и отредактировать его). Он ищет в документе добавленный нами заполнитель ( {invoice_id} ) и заменяет его фактическим invoice_id , который функция принимает в качестве входных данных. Затем он устанавливает документ общедоступным и возвращает URL-адрес, который будет напрямую использоваться для экспорта PDF для этого документа.

Под этой функцией добавьте еще одну, называемую doGet . В то время как предыдущая функция может быть названа как угодно, do Get является специальной функцией в скриптах Google Apps, поэтому вам нужно будет назвать ее точно doGet . Эта функция будет обрабатывать входящие веб-запросы после того, как мы развернем наше приложение.

Код для функции doGet выглядит следующим образом. Вставьте это ниже предыдущей функции createDocument () .

function doGet(e) {
  var invoice_id = e.parameter.invoice_id;
  var url = createDocument(invoice_id);
  return ContentService.createTextOutput(url);
}

Это принимает invoice_id в качестве параметра URL, передает его нашей функции createDocument , которую мы только что написали, и возвращает URL-адрес созданного документа в виде обычного текста.

Публикация нашего API

В меню “Опубликовать” выберите “Развернуть как веб-приложение”

Развертывание как веб-приложение

Вас попросят назвать проект. Дайте ему имя, например “PDF API” или что-нибудь еще, что вы хотите.

Наименование проекта

Вы увидите новое меню для настройки параметров развертывания веб-приложения.

Параметры развертывания

Добавьте сообщение типа “начальное развертывание” под надписью “Новое” и выберите “Любой, даже анонимный” в настройках доступа. Оставьте настройки выполнения как “Я”.

Предупреждение : Если вы поделитесь ссылкой в общественном месте, люди могут злоупотреблять сервисом и спамить его автоматическими запросами. Google может заблокировать вашу учетную запись за злоупотребление, если это произойдет, поэтому сохраняйте ссылку в безопасности.

Нажмите кнопку Развернуть и запишите URL-адрес, который вы увидите в следующем всплывающем окне.

URL-адрес вашего приложения

Добавьте” в конец URL-адреса и посетите его в своем браузере. Это должно выглядеть примерно так

Добавьте” в конец URL-адреса и посетите его в своем браузере. Это должно выглядеть примерно так

Если все прошло хорошо, вы должны увидеть ссылку на Google Docs.

Ответ от нашего веб-приложения

Если вы перейдете по URL-адресу, PDF-файл счета-фактуры с заполнителем будет заменен на 1 следует загрузить.

Обновление приложения

Если вместо этого вы видите ошибку или не получаете ответа, вы, вероятно, допустили ошибку в коде. Вы можете изменить его и обновить развертывание таким же образом, как и при первоначальном развертывании. Экран обновления лишь немного отличается от экрана развертывания.

Параметры развертывания обновления

Единственная сложность заключается в том, что вы должны выбрать “Новый” в качестве версии для каждого изменения, которое вы вносите. Если вы внесете изменения в код и обновите предыдущую версию, изменения не вступят в силу, что не очевидно из пользовательского интерфейса. (Вы можете видеть, что мне потребовалось несколько попыток, чтобы сделать это правильно.) .

Создание счетов-фактур из Python

Теперь мы можем создавать счета-фактуры и сохранять их локально из скрипта Python. В следующем коде показано, как создать три счета-фактуры в цикле for .

import requests

url = "https://script.google.com/macros/s/AKfycbyYL5jhEstkuzZAmZjo0dUIyAmzUc1XL5B-01fHRHx8h63cieXc/exec?invoice_id={}"

invoice_ids = ["123", "456", "789"]

for invoice_id in invoice_ids:
    print("processing ", invoice_id)
    response = requests.get(url.format(invoice_id))
    print("file generated")
    response = requests.get(response.content)
    print("file downloaded")
    with open("invoice{}.pdf".format(invoice_id), "wb") as f:
        f.write(response.content)

Обратите внимание, что процесс создания и загрузки довольно медленный, поэтому для каждого создаваемого счета потребуется несколько секунд.

Вы, вероятно, заметили, что это довольно “хакерское” решение для создания PDF-файлов внутри Python. Функциональность “замены” довольно ограничена по сравнению с правильным языком шаблонов, и передача данных через запрос get также имеет ограничения. Если вы проходите через что-то более сложное, чем идентификатор счета-фактуры, сначала вы должны закодировать данные по URL-адресу. Вы можете сделать это в Python, используя модуль urllib.parse . Пример модификации скрипта Python для работы с более сложными данными выглядит следующим образом.

import requests
import urllib.parse

url = "https://script.google.com/macros/s/AKfycbyYL5jhEstkuzZAmZjo0dUIyAmzUc1XL5B-01fHRHx8h63cieXc/exec?"

invoice_ids = ["A longer ID with special characters $% ! --*?+"]

for invoice_id in invoice_ids:
    print("processing ", invoice_id)
    payload = {"invoice_id": invoice_id}
    u = url + urllib.parse.urlencode(payload)
    response = requests.get(u)
    print("file generated")
    response = requests.get(response.content)
    print(response.content)
    print("file downloaded")
    with open("invoice{}.pdf".format(invoice_id), "wb") as f:
        f.write(response.content)

Но все еще существуют ограничения на то, какие данные и сколько вы можете передавать только с помощью URL-адресов, поэтому вам нужно будет изменить сценарий, чтобы вместо этого использовать запросы POST, если вы отправляете много динамических данных.

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

Тем не менее, возможность создавать шаблоны с помощью Google Docs может быть быстрой и мощной, поэтому вам нужно будет самостоятельно оценить компромиссы.

Также обратите внимание, что это довольно надуманный пример, когда мы могли бы запустить скрипт Python из экосистемы Google и избежать необходимости настраивать общедоступный API, который потенциально может быть использован, если другие люди обнаружат URL-адрес. Тем не менее, у вас может быть существующее приложение Python, не размещенное в Google, которое вам нужно подключить к автоматически сгенерированным PDF-файлам, и этот метод по-прежнему позволяет настроить автономный “микросервис” в экосистеме Google, который позволяет легко создавать PDF-файлы.

Вывод

Если у вас возникли какие-либо проблемы с настройкой, вы заметили какие-либо ошибки или знаете лучший способ создания PDF-файлов на Python, пожалуйста, оставьте комментарий ниже или напишите мне в Twitter . Вам также могут понравиться мои другие учебные пособия .