PythonとGoogleスクリプトを使用したテンプレートからPDFファイルを作成する

多くの場合、PythonスクリプトからPDFファイルを作成すると便利です。 請求書、手紙、レポート、または多くの書式設定の繰り返しが、動的なコンテンツのほんの少しを含む他の文書を作成しているかどうか、いくつかの自動化を追加すると、あなたに多くの時間を節約することができます。

これにはいくつかのオプションがあります。 通常のものは次のとおりです:

  1. reportlabのようなPDFライブラリを使用してPDFファイルを直接生成します(例: https://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/)
  2. Jinja2のようなHTMLテンプレートライブラリを使用し、HTMLからPDFに変換します(例:http://pbpython.com/pdf-reports.html)
  3. https://pdfgeneratorapi.com/のようなサードパーティのAPIを使用します。

オプション1では、Pythonの内部から直接Pdfを生成すると、書式設定が非常に困難になることがあります。 コードを使用して要素ごとに必要なものを描画する必要があり、テンプレートが必要なように見えるようになったとしても、維持するのは困難です。

オプション2は、多くの場合、より良い動作することができますが、あなたはまだ神社のHTML定型文を構築する必要があり、時にはHTMLからPDFへの変換は、

オプション3では、最初にオンラインサービスのwebインターフェイスを使用してテンプレートを構築する必要があります。 あなたはドラッグアンドドロップインターフェイスを取得しますが、それはあなたが望むようにあなたのテンプレートの外観を作るために非常に不格好 通常、あなたはまた、サービスを使用するために支払う必要があります。

上記のオプションのいずれかがうまくいくかもしれませんが、それらのいずれかが気に入らない場合は、Googleドライブに基づいたドキュメント生成APIを一緒にハックすることもできます。 あなたは無料のAPIを取得し、あなたは非常に強力であり、請求書、手紙、およびCvのようなもののための多くの既存のテンプレートを持っているあなたのテ

私はオンラインで見つけた請求書テンプレートから始めました。 これは次のようになります:

Google Docs請求書テンプレート

このチュートリアルでは、これらの請求書を生成し、外部Pythonスクリプトから請求書番号をプログラムで挿入できるAPIを作 実際には、他の多くのフィールドでも同じことを行う必要がありますが、デモの理由から簡単な例から始めます。

数行のGoogle App Scriptコードと数行のPythonコードを記述します。

テンプレートドキュメントの作成

組み込みのGoogleドキュメントテンプレートのいずれかを使用するか、ニーズに合ったものをオンラインで検索するか、docs.google.com(Googleアカウントが必要です)。

動的な情報が必要な場所にプレースホルダを追加します。 以下の例では、元の文書にあった「456」idの代わりに請求書番号{invoice_id}を追加しました。 この構文について特別なことは何もありません-私たちは、実際の情報のためにこれを交換するために、後で基本的な検索と置換関数を使用しますので、実際に最終的な文書に表示されることはほとんどありません何かを使用しています。

URLバーで強調表示されている部分であるドキュメントidをメモしてください。

プレースホルダー付き請求書テンプレート

カスタムGoogleスクリプトの設定

Googleドライブに移動し、左上隅の”新規”を押します。 「その他」の下で、利用可能な場合は「Google Apps Script」を選択し、表示されない場合は「その他のアプリを接続」を選択します。

複数のアプリを接続する

“apps script”を検索して接続することを選択します。 あなた自身を信頼するかどうかを尋ねるいくつかの警告メッセージが表示される場合があります。 あなたがそうすると言います。

アプリスクリプトの追加

新しいアプリスクリプトを作成すると、次のようなデフォルトの空白スクリプトが表示されます。

空白のGoogle Apps Script

そこに表示されているコードを削除し、次のように見える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行目で、テンプレート化されたGoogleドキュメントのURLバーからコピーしたドキュメントIDでTEMPLATE_IDを切り替えます。

このコードは、テンプレート化されたドキュメントを検索し、そのコピーを作成し、ファイル名を”Invoice”に加えて、渡したinvoice_idに設定します。 その後、DocumentAppを介して新しいファイルを開きます(ドライブアプリではなく、実際にファイルの内容を取得して編集できるようにします)。 追加したプレースホルダ({invoice_id})をdocで検索し、関数が入力として受け取る実際のinvoice_idに置き換えます。 次に、ドキュメントをパブリックにアクセスできるように設定し、そのドキュメントのPDFエクスポートに直接移動するURLを返します。

この関数の下に、doGetという別の関数を追加します。 前の関数には何でも名前を付けることができますが、doGetはGoogle Apps Scriptsの特別な関数なので、正確にdoGetという名前を付ける必要があります。 この関数は、アプリをデプロイした後に受信したweb要求を処理します。

doGet関数のコードは次のとおりです。 これを前のcreateDocument()関数の下に貼り付けます。

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

これは、urlパラメータとしてinvoice_idを受け取り、これを先ほど作成したcreateDocument関数に渡し、作成したドキュメントのURLをプレーンテキストとして返します。

APIの公開

“公開”メニューから”webアプリとしてデプロイ”を選択します”

webアプリとしてデプロイする

プロジェクトに名前を付けるように求められます。 「PDF API」などの名前を付けます。

プロジェクトに名前を付ける

webアプリをデプロイするためのオプションを設定する新しいメニューが表示されます。

展開オプション

“新規”と表示されている場所の下に”initial deploy”のようなメッセージを追加し、アクセス設定から”Anyone,even anonymous”を選択します。 実行設定は”Me”のままにしておきます。

警告:公共の場所でリンクを共有すると、人々はサービスを悪用し、自動要求でスパムする可能性があります。 これが発生した場合、Googleは不正行為のためにアカウントをロックする可能性がありますので、リンクを安全に保ちます。

デプロイボタンを押して、次のポップアップに表示されるURLをメモします。アプリのURL

追加”?????????????urlの最後にinvoice_id=1″を入力し、ブラウザでそれを訪問します。 それは次のようになります

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

すべてがうまくいった場合は、Googleドキュメントのリンクが表示されます。

ウェブアプリケーションからの応答

URLにアクセスすると、プレースホルダが1で切り替えられた請求書のPDFがダウンロードされます。

アプリケーションの更新

代わりにエラーが表示された場合、または応答が得られない場合は、おそらくコードに間違いがありました。 最初に展開したのと同じ方法で、展開を変更して更新することができます。 更新画面は、展開画面とはわずかに異なります。

更新展開オプション

唯一のトリッキーなことは、あなたが行うすべての変更のバージョンとして”新しい”を選択する必要があるということです。 コードに変更を加えて以前のバージョンを更新した場合、変更は有効になりませんが、これはUIからは明らかではありません。 (あなたはそれが私にこの権利を得るためにいくつかの試みを取った見ることができます。).

Pythonから請求書を作成する

pythonスクリプトから請求書を作成してローカルに保存できるようになりました。 次のコードは、forループで3つの請求書を生成する方法を示しています。

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)

作成とダウンロードのプロセスは非常に遅いため、作成する請求書ごとに数秒かかることに注意してください。

あなたはおそらく、これはPythonの内部からPDFファイルを生成するための非常に”ハックな”解決策であることに気づいたでしょう。 “置換”機能は、適切なテンプレート言語と比較して非常に限られており、get要求を介してデータを渡すことにも制限があります。 請求書IDよりも複雑なものを渡す場合は、最初にデータをURLエンコードします。 これはPythonでurllib.parseモジュールを使用して行うことができます。 より複雑なデータを処理するためのPythonスクリプトの変更例は次のとおりです。

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)

しかし、どのような種類のデータとUrlだけを使用して渡すことができるかにはまだ制限があるため、大量の動的データを送信する場合は、代わりにpost

最初に説明した他の方法と比較してもかなり遅く、Googleにはこの方法で自動的に作成できるファイルの数にいくつかの制限があります。

つまり、Googleドキュメントを使用してテンプレートを生成できることは、迅速かつ強力なことができるので、あなた自身のためにトレードオフを評価する必

また、これは非常に不自然な例であり、Googleのエコシステム内からPythonスクリプトを実行し、他の人がURLを発見した場合に悪用される可能性のある公開用APIを設定する必要を避けることができたことに注意してください。 ただし、Googleでホストされていない既存のPythonアプリケーションがあり、自動生成されたPDFファイルに接続する必要がある場合がありますが、この方法では、PDFを簡単に生成できるGoogleエコシステム内に自己完結型の「マイクロサービス」を設定できます。