GASで複数ページのPDFを出力する

個人的な備忘録です

サンプルコードやスクリーンショットはありません

 

なぜGASでやるか

PDFをサーバーサイドで生成するには色々な方法がありますが、最近wkhtmltopdfがアーカイブされて選択肢が一つ減らされた感があります。

代替策としてヘッドレスブラウザを使う方法があるみたいですが、アプリケーションのイメージを重たくしたくなかったのでGASでやることにしました。成果物をドライブにアップロードしても構わないという要件だったので、連携の容易さの面でも良いチョイスだと思います。

ざっくりとした流れ

以下の図のようになります

指での作図は難しいですね。

基本的な戦略は、GASプロジェクトと紐付くスプレッドシートをテンプレートとして運用し、別のシートにコピーして値をはめ込んでいくというものです。

テンプレート用のスプシにシートを追加していってpdf化しても良いのですが、テンプレートは読み取り専用にしたかったという意図があります。

詰まったところ

簡単なようで意外と詰まりました。いくつか紹介します

PDF化のオプションがわからない

PDFダウンロードする時はダウンロードパスからフェッチしてくるのが良いらしいです。ここではURLパラメータで細かいオプションを指定できて大変助かります。

ところがどっこい、このオプションがよく分からず狙ったPDFを出さなかったので、サードパーティの記事に頼りました。ありがたい🙏

https://jidou-ka.com/gas-spreadsheet-export-pdf/

ドキュメントの向きとサイズ、垂直方向のアラインと罫線の非表示などをこの記事を参考に調整しました。

シートへの変更が反映されない

setValueなどのインターフェイスを用いてシートに変更を及ぼした際、後続の処理でPDF化を行なっても内容が変更されませんでした。

調べてわかったのですが、スプレッドシートでは、パフォーマンスのためにシートへの変更が即座に反映されない場合があります。そのように保留された変更を一度に反映させるのが SpreadsheetApp.flush() です

https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app?hl=ja

シートに変更を与える処理の後でこのメソッドを呼び出すことで解決できました。

Driveにアップロードされたファイルの版管理ができない

PDFファイルが変更された場合、ドライブ上でバージョンを追跡できるようにしたかったのですが、Drive Appにそのようなインターフェイスは見つかりませんでした。そこで、Drive APIという拡張を使います。

https://developers.google.com/apps-script/advanced/drive?hl=ja

Drive.files.updateというメソッドが新しい版のアップロードを可能にします

https://developers.google.com/drive/api/reference/rest/v2/files/update?hl=ja