maak PDF-bestanden van sjablonen met Python-en Google-Scripts

vaak is het handig om PDF-bestanden te maken van uw Python-scripts. Of u nu facturen, brieven, rapporten of andere documenten maakt die veel opmaakherhaling bevatten, maar slechts een klein beetje dynamische inhoud, het toevoegen van wat automatisering kan u vele uren besparen.

u hebt hiervoor een paar opties. De gebruikelijke zijn::

  1. gebruik een PDF-bibliotheek zoals reportlab om PDF-bestanden direct te genereren (bijv. https://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/)
  2. gebruik een HTML templating bibliotheek zoals Jinja2 en converteren van HTML naar PDF (bijv. zie http://pbpython.com/pdf-reports.html)
  3. gebruik een API van derden zoals https://pdfgeneratorapi.com/.

Voor Optie 1 kan het genereren van PDF ‘ s rechtstreeks vanuit Python het formatteren erg moeilijk maken. Je moet alles tekenen wat je nodig hebt element voor element, met behulp van code, en zelfs als je eenmaal hebt een sjabloon op zoek naar de manier waarop u het wilt, het is moeilijk te onderhouden.

Optie 2 kan vaak beter werken, maar je moet nog steeds de Jinja HTML boilerplate bouwen, en soms komt de html naar PDF conversie niet helemaal zoals je had verwacht.

optie 3 vereist dat u de sjabloon eerst maakt met behulp van de webinterface van een online service. Hoewel je een drag-and-drop-interface krijgt, is het nogal onhandig en moeilijk om je sjabloon eruit te laten zien zoals je wilt. Meestal moet je ook betalen om de service te gebruiken.

hoewel een van de bovenstaande opties voor u kan werken, kunt u ook samen een API voor het genereren van documenten op basis van Google Drive hacken. Je krijgt een gratis API, en je zult in staat zijn om Google Docs te gebruiken als je templating tool, die is vrij krachtig en heeft veel reeds bestaande sjablonen voor dingen zoals facturen, brieven, en CVs.

ik begon met een factuursjabloon dat ik online vond. Het ziet er zo uit:

Google Docs factuursjabloon

in deze handleiding gaan we door met het maken van een API die deze facturen genereert en waarmee u programmatisch het factuurnummer kunt invoegen vanuit een extern Python-script. In werkelijkheid zou je hetzelfde moeten doen voor veel van de andere velden, maar we beginnen met een eenvoudig voorbeeld voor demonstratie redenen.

we zullen een paar regels Google App Script code schrijven, en een paar regels Python code.

een sjabloondocument maken

gebruik een van de ingebouwde Google-documentsjablonen, zoek online naar een sjabloon die aan uw behoeften voldoet, of bouw uw eigen sjabloon op docs.google.com. (je hebt een Google-Account nodig).

plaatshouders toevoegen waar u dynamische informatie nodig hebt. In het onderstaande voorbeeld heb ik factuur nummer {invoice_id} toegevoegd in plaats van de “456” id die ik op het originele document had. Er is niets speciaals aan deze syntaxis — we zullen later een basis Zoek-en vervang-functie gebruiken om dit uit te wisselen voor de echte informatie, dus gebruik iets dat waarschijnlijk niet in het uiteindelijke document zal verschijnen.

noteer uw document-id, het gemarkeerde deel in de URL-balk.

factuursjabloon met plaatshouder

een aangepast Google-Script instellen

Ga naar Google Drive, druk op “nieuw” in de linkerbovenhoek. Selecteer onder ‘meer ”Google Apps Script’ als het beschikbaar is of ‘meer apps verbinden’ als u het niet ziet.

meer apps verbinden

zoek naar “apps script” en kies om het aan te sluiten. Je zou kunnen zien sommige waarschuwingsberichten vragen of je jezelf vertrouwt. Zeg dat je dat doet.

Apps-Script

toevoegen zodra u een nieuw app-Script kunt maken, ziet u een standaard leeg script dat er als volgt uitziet.

leeg Google Apps Script

verwijder de code die u daar ziet en vervang deze door een createDocument functie die er als volgt uitziet.

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

schakel op Regel 2 de TEMPLATE_ID uit met de document-ID die u hebt gekopieerd van de URL-balk op uw Google-Doc.

deze code vindt de templated doc, maakt er een kopie van en stelt de bestandsnaam in op “factuur” plus wat invoice_id we doorgeven. Het opent vervolgens het nieuwe bestand via de DocumentApp (in plaats van de Drive-App, zodat we daadwerkelijk de inhoud van het bestand kunnen krijgen en bewerken). Het zoekt de doc naar de plaatshouder die we hebben toegevoegd ({invoice_id}) en vervangt deze door de werkelijke invoice_id die de functie als invoer neemt. Het stelt vervolgens het document openbaar toegankelijk te zijn en geeft een URL die rechtstreeks naar een PDF-export voor dat document gaat.

voeg onder deze functie nog een functie toe genaamd doGet. De vorige functie kan van alles worden genoemd, maar doGet is een speciale functie in Google Apps-Scripts, dus u moet deze functie precies doGetnoemen. Deze functie zal inkomende webverzoeken behandelen nadat we onze app hebben geïmplementeerd.

de code voor de functie doGet is als volgt. Plak dit onder de vorige createDocument() functie.

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

dit neemt de invoice_id in als een URL parameter, geeft dit door aan onze createDocument functie die we zojuist hebben geschreven, en geeft de URL van het aangemaakte document terug als platte tekst.

publiceren van onze API

selecteer “implementeren als web-app” in het menu “publiceren””

 implementeren als web app

u wordt gevraagd het project een naam te geven. Geef het een naam als “PDF API” of iets anders dat je wilt.

het project een naam geven

u zult een nieuw menu zien om de opties voor het implementeren van uw web app in te stellen.

implementatieopties

voeg een bericht als ” initial deploy “toe onder waar” New “staat en kies” Anyone, even anonymous ” uit de toegangsinstellingen. Laat de uitvoeringsinstellingen als “mij”staan.

waarschuwing: als u de link op een openbare plaats deelt, kunnen mensen misbruik maken van de service en deze spammen met automatische Verzoeken. Google kan uw account vergrendelen voor misbruik als dit gebeurt, dus houd de link veilig.

druk op de knop implementeren en noteer de URL die u ziet in de volgende pop-up.

de URL van uw app

toevoegen “?invoice_id = 1 ” naar het einde van de URL en bezoek deze in uw browser. Het moet er ongeveer uitzien als

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

als alles goed ging, moet u een Google Docs link weergegeven.

antwoord van onze webapplicatie

als u de URL bezoekt, moet een PDF van de factuur met de placeholder geschakeld met 1 worden gedownload.

het bijwerken van de toepassing

als u in plaats daarvan een fout ziet, of geen antwoord krijgt, dan heeft u waarschijnlijk een fout gemaakt in de code. U kunt het wijzigen en de implementatie bijwerken op dezelfde manier als u het in eerste instantie hebt geïmplementeerd. Het updatescherm verschilt slechts enigszins van het implementatiescherm.

implementatieopties bijwerken

het enige lastige is dat u “nieuw” Als versie moet selecteren voor elke wijziging die u aanbrengt. Als u wijzigingen aanbrengt in de code en een vorige versie bijwerkt, zullen de wijzigingen niet van kracht worden, wat niet duidelijk is in de gebruikersinterface. (Je kunt zien dat het kostte me een paar pogingen om dit goed te krijgen.).

onze facturen maken vanuit Python

we kunnen nu facturen maken en lokaal opslaan vanuit een Python-script. De volgende code laat zien hoe u drie facturen in een lus for kunt genereren.

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)

merk op dat het aanmaken en downloaden proces vrij traag is, dus het zal een paar seconden duren voor elke factuur die u maakt.

u hebt waarschijnlijk gemerkt dat dit een nogal “hacky” oplossing is om PDF-bestanden te genereren vanuit Python. De” replace ” functionaliteit is vrij beperkt in vergelijking met een goede templating taal, en het doorgeven van gegevens via een get request heeft ook beperkingen. Als u door iets ingewikkelder dan een factuur ID, U zult URL coderen van de gegevens eerste. U kunt dit doen in Python met behulp van de urllib.parse module. Een voorbeeld aanpassing van het Python script om te gaan met meer ingewikkelde gegevens is als volgt.

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)

maar er zijn nog steeds beperkingen van wat voor soort gegevens en hoeveel u kunt doorgeven met behulp van URL ‘ s, dus u zou het script moeten wijzigen om POSTVERZOEKEN te gebruiken als u veel dynamische gegevens verzendt.

het is ook vrij traag in vergelijking met sommige van de andere methoden die we aan het begin besproken, en Google heeft een aantal beperkingen op hoeveel bestanden u automatisch kunt maken op deze manier.

dat gezegd hebbende, de mogelijkheid om sjablonen te genereren met behulp van Google Docs kan snel en krachtig zijn, dus je moet de afwegingen zelf beoordelen.

merk ook op dat dit een behoorlijk gekunsteld voorbeeld is, waar we het Python-script vanuit het Google-ecosysteem hadden kunnen draaien, en vermeden hadden dat we een API moesten opzetten die mogelijk misbruikt zou kunnen worden als andere mensen de URL ontdekten. Echter, je zou kunnen hebben een bestaande Python applicatie, niet gehost op Google, die u nodig hebt om verbinding te maken met automatisch gegenereerde PDF-bestanden, en deze methode kunt u nog steeds het opzetten van een self-contained “microservice” binnen het Google-ecosysteem dat zorgt voor eenvoudige PDF-generatie.

conclusie