Erstellen von PDF-Dateien aus Vorlagen mit Python und Google Scripts

Oft ist es nützlich, PDF-Dateien aus Ihren Python-Skripten zu erstellen. Unabhängig davon, ob Sie Rechnungen, Briefe, Berichte oder andere Dokumente erstellen, die viel Formatierung, aber nur wenig dynamischen Inhalt enthalten, können Sie durch das Hinzufügen einer gewissen Automatisierung viele Stunden sparen.

Sie haben einige Optionen dafür. Die üblichen sind:

  1. Verwenden Sie eine PDF-Bibliothek wie reportlab, um PDF-Dateien direkt zu generieren (z. https://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/)
  2. Verwenden Sie eine HTML-Vorlagenbibliothek wie Jinja2 und konvertieren Sie von HTML in PDF (z. B. siehe http://pbpython.com/pdf-reports.html)
  3. Verwenden Sie eine Drittanbieter-API wie https://pdfgeneratorapi.com/ .

Bei Option 1 kann das Generieren von PDFs direkt aus Python heraus die Formatierung sehr erschweren. Sie müssen alles, was Sie brauchen, Element für Element mit Code zeichnen, und selbst wenn Sie eine Vorlage haben, die so aussieht, wie Sie es möchten, ist es schwierig zu warten.

Option 2 kann oft besser funktionieren, aber Sie müssen immer noch das Jinja HTML-Boilerplate erstellen, und manchmal kommt die HTML-zu-PDF-Konvertierung nicht ganz so heraus, wie Sie es erwartet haben.

Option 3 erfordert, dass Sie die Vorlage zuerst über die Weboberfläche eines Onlinedienstes erstellen. Obwohl Sie eine Drag-and-Drop-Oberfläche erhalten, ist es ziemlich klobig und schwierig, Ihre Vorlage so aussehen zu lassen, wie Sie möchten. Normalerweise müssen Sie auch bezahlen, um den Service zu nutzen.

Während eine der oben genannten Optionen für Sie funktionieren kann, können Sie, wenn Ihnen keine davon gefällt, auch eine auf Google Drive basierende API zur Dokumentenerstellung zusammenhacken. Sie erhalten eine kostenlose API und können Google Text & Tabellen als Vorlagen-Tool verwenden, das sehr leistungsfähig ist und viele bereits vorhandene Vorlagen für Dinge wie Rechnungen, Briefe und Lebensläufe enthält.

Ich habe mit einer Rechnungsvorlage begonnen, die ich online gefunden habe. Es sieht so aus:

Google Docs-Rechnungsvorlage

In diesem Lernprogramm gehen wir durch das Erstellen einer API, mit der diese Rechnungen generiert werden und mit der Sie die Rechnungsnummer programmgesteuert aus einem externen Python-Skript einfügen können. In Wirklichkeit müssten Sie dasselbe für viele andere Felder tun, aber wir beginnen aus Demonstrationsgründen mit einem einfachen Beispiel.

Wir werden ein paar Zeilen Google App Script-Code und ein paar Zeilen Python-Code schreiben.

Erstellen eines Vorlagendokuments

Verwenden Sie eine der integrierten Google-Dokumentvorlagen, suchen Sie online nach einer, die Ihren Anforderungen entspricht, oder erstellen Sie Ihre eigenen unter docs.google.com . (Sie benötigen ein Google-Konto).

Fügen Sie dort Platzhalter hinzu, wo Sie dynamische Informationen benötigen. Im folgenden Beispiel habe ich INVOICE NO {invoice_id} anstelle der ID „456“ hinzugefügt, die ich im Originaldokument hatte. Es gibt nichts Besonderes an dieser Syntax – wir werden später eine grundlegende Such- und Ersetzungsfunktion verwenden, um dies gegen die tatsächlichen Informationen auszutauschen.

Notieren Sie sich Ihre Dokument-ID, die der hervorgehobene Teil in der URL-Leiste ist.

Rechnungsvorlage mit Platzhalter

Einrichten eines benutzerdefinierten Google-Skripts

Gehen Sie zu Google Drive und drücken Sie oben links auf „Neu“. Wählen Sie unter „Mehr“ „Google Apps Script“, wenn es verfügbar ist, oder „Weitere Apps verbinden“, wenn es nicht angezeigt wird.

Weitere Apps verbinden

Suchen Sie nach „apps script“ und verbinden Sie es. Möglicherweise sehen Sie einige Warnmeldungen, in denen Sie gefragt werden, ob Sie sich selbst vertrauen. Sag, dass du es tust.

Apps-Skript hinzufügen

Sobald Sie ein neues App-Skript erstellen können, wird ein leeres Standardskript angezeigt, das wie folgt aussieht.

Leeres Google Apps Script

Löschen Sie den dort angezeigten Code und ersetzen Sie ihn durch eine createDocument -Funktion, die wie folgt aussieht.

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";}

Schalten Sie in Zeile 2 die TEMPLATE_ID mit der Dokument-ID aus, die Sie aus der URL-Leiste Ihres Google Doc-Templates kopiert haben.

Dieser Code findet das Vorlagendokument, erstellt eine Kopie davon und setzt den Dateinamen auf „Rechnung “ plus das, was wir an invoice_id übergeben. Anschließend wird die neue Datei über die DocumentApp geöffnet (anstelle der Drive-App, damit wir den Inhalt der Datei tatsächlich abrufen und bearbeiten können). Es durchsucht das Dokument nach dem Platzhalter, den wir hinzugefügt haben ({invoice_id} ), und ersetzt ihn durch den tatsächlichen invoice_id, den die Funktion als Eingabe verwendet. Anschließend wird das Dokument als öffentlich zugänglich festgelegt und eine URL zurückgegeben, die direkt zu einem PDF-Export für dieses Dokument führt.

Fügen Sie unterhalb dieser Funktion eine weitere Funktion mit dem Namen doGet hinzu. Während die vorherige Funktion beliebig benannt werden kann, ist doGet eine spezielle Funktion in Google Apps Scripts, daher müssen Sie sie genau doGet . Diese Funktion verarbeitet eingehende Webanforderungen, nachdem wir unsere App bereitgestellt haben.

Der Code für die Funktion doGet lautet wie folgt. Fügen Sie dies unter der vorherigen createDocument() -Funktion ein.

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

Dies nimmt die invoice_id als URL-Parameter auf, übergibt diese an unsere createDocument -Funktion, die wir gerade geschrieben haben, und gibt die URL des erstellten Dokuments als Klartext zurück.

Veröffentlichen unserer API

Wählen Sie im Menü „Veröffentlichen“ die Option „Als Web-App bereitstellen“

 Als Web-App bereitstellen

Sie werden aufgefordert, das Projekt zu benennen. Geben Sie ihm einen Namen wie „PDF API“ oder was auch immer Sie wollen.

Projekt benennen

Sie sehen ein neues Menü, in dem Sie die Optionen für die Bereitstellung Ihrer Web-App festlegen können.

Bereitstellungsoptionen

Fügen Sie eine Nachricht wie „initial deploy“ hinzu, unter der „Neu“ steht, und wählen Sie „Jeder, auch anonym“ aus den Zugriffseinstellungen. Belassen Sie die Ausführungseinstellungen als „Ich“.

Warnung: Wenn Sie den Link an einem öffentlichen Ort teilen, können Personen den Dienst missbrauchen und ihn mit automatischen Anfragen spammen. Google kann Ihr Konto für Missbrauch sperren, wenn dies geschieht, so halten Sie den Link sicher.

Klicken Sie auf die Schaltfläche Bereitstellen und notieren Sie sich die URL, die im nächsten Popup angezeigt wird.

URL Ihrer App

Hinzufügen „?invoice_id=1“ an das Ende der URL und besuchen Sie sie in Ihrem Browser. Es sollte ungefähr so aussehen

https://script.google.com/macros/s/AKfycbxDiKpTGqMijZmU8-0cPj06DBFjDOPYZJ9IFvhcO111GCh8jqxC/exec?invoice_id=1

Wenn alles gut gegangen ist, sollte ein Google Text & Tabellen-Link angezeigt werden.

Antwort aus unserer Webanwendung

Wenn Sie die URL besuchen, sollte ein PDF der Rechnung mit dem mit 1 ausgeschalteten Platzhalter heruntergeladen werden.

Aktualisieren der Anwendung

Wenn Sie stattdessen einen Fehler sehen oder keine Antwort erhalten, haben Sie wahrscheinlich einen Fehler im Code gemacht. Sie können es ändern und die Bereitstellung auf dieselbe Weise aktualisieren, wie Sie sie ursprünglich bereitgestellt haben. Der Aktualisierungsbildschirm unterscheidet sich nur geringfügig vom Bereitstellungsbildschirm.

Update Deployment options

Die einzige knifflige Sache ist, dass Sie für jede Änderung, die Sie vornehmen, „Neu“ als Version auswählen müssen. Wenn Sie Änderungen am Code vornehmen und eine frühere Version aktualisieren, werden die Änderungen nicht wirksam, was auf der Benutzeroberfläche nicht ersichtlich ist. (Sie können sehen, dass ich ein paar Versuche brauchte, um das richtig zu machen.).

Erstellen unserer Rechnungen aus Python

Wir können jetzt Rechnungen erstellen und lokal aus einem Python-Skript speichern. Der folgende Code zeigt, wie drei Rechnungen in einer Schleife for generiert werden.

import requestsurl = "https://script.google.com/macros/s/AKfycbyYL5jhEstkuzZAmZjo0dUIyAmzUc1XL5B-01fHRHx8h63cieXc/exec?invoice_id={}"invoice_ids = 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)

Beachten Sie, dass der Erstellungs- und Downloadvorgang recht langsam ist, sodass jede von Ihnen erstellte Rechnung einige Sekunden dauert.

Sie haben wahrscheinlich bemerkt, dass dies eine ziemlich „hackige“ Lösung ist, um PDF-Dateien aus Python heraus zu generieren. Die „Ersetzen“ -Funktionalität ist im Vergleich zu einer richtigen Vorlagensprache ziemlich begrenzt, und das Übergeben von Daten über eine Get-Anforderung hat auch Einschränkungen. Wenn Sie etwas Komplizierteres als eine Rechnungs-ID durchlaufen, müssen Sie die Daten zuerst URL-codieren. Sie können dies in Python mit dem Modul urllib.parse tun. Eine Beispieländerung des Python-Skripts zum Umgang mit komplizierteren Daten lautet wie folgt.

import requestsimport urllib.parseurl = "https://script.google.com/macros/s/AKfycbyYL5jhEstkuzZAmZjo0dUIyAmzUc1XL5B-01fHRHx8h63cieXc/exec?"invoice_ids = 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)

Es gibt jedoch immer noch Einschränkungen, welche Art von Daten und wie viel Sie nur mithilfe von URLs übergeben können.

Es ist auch ziemlich langsam im Vergleich zu einigen der anderen Methoden, die wir am Anfang besprochen haben, und Google hat einige Einschränkungen, wie viele Dateien Sie auf diese Weise automatisch erstellen können.

Die Möglichkeit, Vorlagen mit Google Text & Tabellen zu generieren, kann jedoch schnell und leistungsstark sein.

Beachten Sie auch, dass dies ein ziemlich erfundenes Beispiel ist, in dem wir das Python-Skript innerhalb des Google-Ökosystems hätten ausführen und vermeiden können, eine öffentlich zugängliche API einzurichten, die möglicherweise missbraucht werden könnte, wenn andere Personen die URL entdecken. Möglicherweise haben Sie jedoch eine vorhandene Python-Anwendung, die nicht bei Google gehostet wird, die Sie mit automatisch generierten PDF-Dateien verbinden müssen, und mit dieser Methode können Sie dennoch einen eigenständigen „Mikroservice“ innerhalb des Google-Ökosystems einrichten, der eine einfache PDF-Generierung ermöglicht.

Fazit