AppSheetで申請書等のPDFを生成してみた
AppSheetは様々なビジネス用のアプリケーションを作成可能ですが、ワークフローや請求書などのアプリに付き物である「PDFの生成」もAutomationで実現可能です。
このPDF生成はGoogleドキュメントに仕掛けをしておき、そのテンプレートを元に差し込み印刷のようにPDFを生成する事が可能になっています。欠かせない機能であるため、ここで2パターンのPDF生成をしてみようと思います。今回はGoogle Apps Scriptを利用せずに実装しています。
目次
今回利用するスプレッドシート等
- AppSheetでPDF生成 - AppSheetテンプレート
- PDF出力テスト - Googleスプレッドシート
- 申請書雛形 - Googleドキュメント
- 請求書雛形 - Googleドキュメント
申請書のようなシンプルな1テーブルだけで構成されたファイルの生成と、請求書のように親テーブルとそれにぶら下がる子テーブルの2つで構成されてる場合の2パターンについて、ボタンクリックでPDF生成をしてみようと思います。
ボタンクリックでAutomationを発火させる方法については以下のエントリーで扱っています。
事前準備
テーブル側
今回のアプリは前述でも紹介してる「アクションボタンをクリックしてPDF出力を実行する」ものなので、以下のような準備が必要です。
- 各基準となるスプシのシートに「更新フラグ」用の列を用意する
- この列に対して後述のアクションにて値の書き込みにてUNIQUEID()で生成した値を入力し、Automationを発火させる
- 請求書タイプの場合には明細シートには自身用のID列と連結するための親ID用の請求書ID列を用意する
- Refを利用して親側のIDと子側の請求書IDを連結する
Refで請求明細側の請求書IDに対して親のテーブルを連結してるため、親テーブル側には「Related 請求明細s」というList側のフィールドが自動追加されて連結されます。
図:更新させて発火させる為の列の用意
図:明細側にリレーションを設定する
テンプレート側
申請書タイプ
申請書タイプは1レコードで完結するワークフローなど社内の各種申請で用いることが多いであろうテンプレートです。以下のような手順でGoogleドキュメントで体裁を作成します。
- Googleドキュメントである程度のフォーマットを作成する
- 差し込みたい項目の場所に、AppSheetの列の名前を元に「<<申請日>>」といった文字列を配置します。
- 表などを使ってレイアウト組をして順番に入力内容を配置するように構築しても良いでしょう。
思っているほど難しいものではないのですが、テーブルの列の名前で入れる必要があるため、少しでも誤りがあると挿入されませんので要注意です。
図:挿入文字列を配置していく
請求書タイプ
請求書タイプの場合、前述の申請書タイプに加えて親のレコードにぶら下がる明細レコードが複数存在しており、またその明細の数も不定であるため、前述の記法だけでは不十分です。親のレコード側にある内容は前述の通り入力すればオッケーです。こちらに公式ドキュメントがあります。
請求書の場合は以下のような手順で作成します。
- Googleドキュメントである程度のフォーマットを作成する
- 親レコードにある項目は前述と同様に該当箇所に「<<発行日>>」という形で挿入しておきます。
- また後述の「合計金額や税込金額計算」で用意した合計金額や税込金額などのVirtual Columnの項目も同様に「<<合計金額>>」といった列名で挿入が可能です。
- 問題の明細行ですが、1行分のみを用意しておきます。最初の列の品名がちょっと特殊で以下のような値を入れます
1<< Start: [ Related 請求明細s]>><<品名>>
startから始まり、Related 請求明細sの項目を指定してから品名を入れます。これでループで自動で行追加してくれます。 - 次の数量や単価は通常通りの指定方法で問題ありません。
- 最後の金額欄も品名同様に以下のような指定方法で閉じます。
1<<金額>><<End>> - startからendまでの1行のループで必要な明細分だけ自動で行が拡張されて追加される変わった仕組みになっています。
ただし、これは表形式でなければ旨く動作しないので、例えば箇条書きを実現できるか?といったらPDF出力されませんでした。同一のセル内にStartとEndを一緒にすると1行の中に記述されてしまうので注意。擬似的に箇条書きにしたい場合には以下のように構築します。Endは改行してから配置します。
1 2 3 |
<< Start: [ Related 請求明細s]>> ・<<品名>> <<End>> |
図:請求明細は1行のみだけ用意する
図:実際に出力すると複数行出てくる
実装方法
申請書タイプであれ請求書タイプであれ、アクションボタンからPDF生成までの流れは共通です。以下のような仕組みを構築して出力します。ここでは申請書のビューについて追加する手順として紹介します。同様に請求書側も装備してみましょう。
アクションボタンを追加
AppSheetの開発画面の左サイドバーからActionsという項目にてボタンを追加していきます。
- Add ActionをクリックしてCreate a new actionをクリックする
- Action Nameは適当にセットし、For a record of this tableは「申請書」テーブルを指定する
- Do thisは「Data: set the values of some columns in this row」を指定します。
- set these columnsにて、更新フラグ列にUNIQUEID()を入れる設定を記述します。
- PositionはProminentとして指定する
これでボタンをクリックすると申請書シートの更新フラグ列に値が毎回書き込まれ、それをトリガーにしてAutomationを発火させることが可能になります。
図:これで更新フラグに書き込まれる
図:ボタンクリックで発動します
Automationを設定する
イベントを作成する
前述まででボタンの設置まで用意できました。次に、この更新フラグの書き込みをトリガーにしてPDF発行用の処理を動かし、スプシの申請書シートにはファイルの出力先までのパスを書き込むようにします。
- AppSheetの開発画面の左サイドバーでAutomationをクリックする
- Create a new botのボタンをクリックする。
- ダイアログでCreate a new botをクリックする
- Confiture Eventをクリックする
- Create a new eventをクリックする
- 右サイドバーにてTableは「申請書」を指定する
- Data Change TypeはUpdateのみを選択するようにする
- Conditionでは以下のような数式を構築して更新フラグが変化していたら実行するように仕込む
1[_THISROW_BEFORE].[更新フラグ] <> [_THISROW_AFTER].[更新フラグ] - 右上のSAVEをクリックする
図:更新フラグを元に発火するように仕掛け
PDF生成ステップ
無事に更新フラグを元に発火できるようにしたら、いよいよGoogleドキュメントをテンプレにPDFを生成する仕掛けを作ります。前述のイベントの次より以下の手順でフローを追加します。
- Add a Stepをクリックする
- Run a taskのstepの右サイドバーに於いて、「Create a new file」を選択する
- HTTP Content TypeはPDFを選択する
- Templateのファイルアイコンをクリックして、ドライブから作成しておいた申請書雛形のGoogleドキュメントを指定する
- File Folder Pathは空でも問題ないですが、その場合「/appsheet/data/アプリ名/」以下に「Filesフォルダ」が作成された上で自動でファイルが作られますが、ここで「"雑多なファイル/pdffolder"」と指定すると、「/appsheet/data/アプリ名/雑多なファイル/pdffolder/」以下にファイルが作られるようになります。
- File Name Prefixは自動的につけるPDFのファイル名を指定します。ここでは関数でユニークなファイル名になるようにセットしてみます。
1[請求先] & "-" & TEXT([申請日], "yyyymmdd") & "-" & [更新フラグ] - Disable Timestamp?はスイッチをオンにします(でないとファイル名に勝手にタイムスタンプが追加されてしまう)
- Attachment Page OrientationはPDF出力方向(縦横)およびA4などの出力サイズを指定出来ます。
- 右上のSAVEをクリックする
これで、ドキュメントをテンプレとしてPDFを差し込み印刷的に出力してくれるようになります。
図:テンプレートファイルを指定する
図:ファイル名と出力形式を指定する
出力先パスを書き込む
このステップは特に無くても問題ないですが、出力先のGoogle Drive上のパスを申請書のPDFの場所列(型はFile型を指定する)に対して書き込むことが可能です。以下のようなフローを構築します。
- Add a Stepをクリックする
- Run a data actionを選択する
- 右サイドバーでは「set row values」を選択する
- Set these column(s)では、「PDFの場所」という列名を選択し、関数には以下のような内容を記述する(最後に拡張子の.pdfをつける点が異なるので注意)
1"雑多なファイル/pdffolder" & [アプリ名] & "-" & TEXT([申請日], "yyyymmdd") & "-" & [更新フラグ] & ".pdf"
※前述のフォルダのパスとファイル名を合体させたものを書き込ませます。 - 右上のSAVEをクリックする
図:出力先をスプシに書き込みする
図:書き込み先列はFile型である必要がある
File Not Found問題
前述に於いてFile型の列にPDF出力パスまでを入れています。そうするとAppSheet上にファイルアイコンが出て、クリックするとPDFファイルが開かれるようになります。しかし、実際に開いてみると「not found」とエラーが出て開けないというケースがあります。
Drive上のパスは間違っていないハズだし、ファイル名も正しいハズ。なのに開けない・・・この問題ですが、以下の数点をまず調べましょう。
- File Folder Pathが空の場合は「/appsheet/data/アプリ名/Files」以下にファイルが生成されます。
- 出力先パス書き込みは上記の場合、「"/Files/" & [顧客名] & "-" & TEXT([日付], "yyyymmdd") & "-" & [請求更新フラグ] & ".pdf"」といったように、/Files/から始まりPDFの拡張子付きのもので終わるように書き込みます。
- 最後に重要なのがスプシをソースとしてる場合、「/appsheet/data/アプリ名/」以下にスプシが配置されてる必要があります。別のフォルダの場合だとNGです。
このスプシやPDFのファイルの生成先については、左サイドバーのsettigs→infomation→Default app folderの中にあり、ここを例えば、/プロダクト/車屋管理/PDFと書き換えるとマイドライブ直下から始まるプロダクト以下のディレクトリに変更することができます。変更してる場合も、このケースの場合PDFフォルダ以下にFilesフォルダができて・・・となるので、PDFフォルダ内にスプシを配置しないといけません。
つまり指定のディレクトリからの相対パスで見てる為スプシの置き場が異なるために「not found」となってしまって開けなかったわけです。
図:ファイルアイコンからPDFを開ける
図:ファイルが見つからず開けなかった
図:スプシのあるフォルダにFilesフォルダが有る状態がOK
メールに添付して送信
ここまで来ると生成したPDFをお客様などにお見積りや請求書として添付してメールでそのまま送信する機能が欲しくなります。前述までで対象のPDFのパスはスプシの該当列に書き込まれているので、改めて生成ではなく生成済みPDFをメールに添付して送信するAutomationを作成します。
上記の流れで送信しても良いのですが、内容を確認できずに自動で送信するというのはUX上あまりよろしく無いので、以下の装備を行います。途中まではボタンクリックでGAS発動といった場合の仕掛けと同じものになります。
- スプシにメール送信フラグ列を用意し、Actionを用意しUNIQUEID関数で値を書き込む。
- 値が書き込まれたら、Automationが発動するように用意する。このときのData Change TypeはUpdateのみとし、Conditionでは以下のような数式を入れて、メール送信フラグ列に値が書き込まれた時だけ発火するように仕掛ける。
1[_THISROW_BEFORE].[メール送信フラグ] <> [_THISROW_AFTER].[メール送信フラグ] - Automationの次のプロセスはSend an emailを選択し、Toはお客様メアドの列を指定する。自分の場合メインのテーブルにはお客様メアドが無いけれど、そこからリレーションで参照してる顧客管理テーブルにはあるので、そちらを参照させています。
- Email Subject, Email Bodyを構築。Other ParametersのReply toは自分宛のメアドを入れる(でないとnoreply@appsheet.comがFromで飛んでくるのでお客様は返信ができない)
- 重要なAttachment settingsですが、新規に生成しないのでOther Attachmentsの項目にて生成済みPDFのパスが書かれてる列を指定する(こうすることで自動で添付されます)。
実際にこれでActionのボタンをクリックするとメール送信のAutomationが発火し、生成済みPDFを添付したメールが相手に送られます。GAS無しでここまでの処理を実装可能です。
図:イベントの設定
図:生成済みPDFを指定する
図:送信されたPDF添付のメール
出力した結果
実際にテンプレを元にPDF出力されたファイルを開いてみると以下の図のような形でファイルが生成されていました。色々と調整は必要ではあると思いますが、無事に差し込み印刷のようにPDFが作成されました。
請求書の場合にはあとは手動で電子署名をして相手にメールするといった形で仕事を終えることが可能です。
図:出力されたPDFの事例
図:出力先のパス
合計金額や税込金額計算
この項目は請求書タイプのPDFを生成する上で利用する「明細の合計金額」「消費税額」「税込み金額」の3つを計算する必要があります。今回は請求明細テーブルをRefで連結しているので、それを利用してこれらの値をVirtual Columnとして請求書シートに計算列として追加します。
この列名をGoogleドキュメントの差し込み項目として利用します。
- 請求書テーブルを開き、右上のAdd Virtual Columnをクリックする
- Column Nameを合計金額として、計算式は以下のようなものを入れます。
1SUM([Related 請求明細s][金額]) - 次に同じようにVirtual Columnを追加し、Column Nameは消費税額として計算式は以下のようなものを入れます。2.の列の値をそのまま利用します。
1[合計金額]*0.1 - 次に同じようにVirtual Columnを追加し、Column Nameは税込金額として計算式は以下のようなものを入れます。
1[合計金額]+[消費税額] - 右上のSAVEをクリックして保存する
これで、差し込みで合計欄3種類をそのまま差し込めるようになります。
図:Virtual Columnで計算させます
フォントが気になる点
Google Documentを雛形にして実際にAppSheetでPDFを生成してみると気になる点が1つ。「カスタムなフォントの指示を無視して、中国フォントっぽい表示になる点」。Googleドキュメント上でフォントをいくら指定しても反映されず、こちらのサイトでも指摘されていますが、フォントが固定になります。
このフォントは変更することが現時点でできず、気になる場合にはGASで自前でPDFを生成するロジックを実装する必要があると思います。スプレッドシートを使う手法もあるようですが、こちらは請求明細の生成で課題があります。
図:中国フォントっぽい表示
参考動画
関連リンク
- 月60件超の請求書をAppSheetで自動作成 山喜製陶3代目のDX
- AppSheetからPDFを自動で作成してみよう!
- AppSheet実践編シリーズ⑱~(小ネタ)PDF報告書に画像を表示してみよう!~
- AppSheetでPDF自動出力機能を実装
- AppSheet で請求書アプリ(第7回)Automationで請求書をPDFで発行
- AppSheet で請求書アプリ(第6回)請求書テンプレートを作成する
- AppSheet で PDF帳票出力!Automation 機能を活用しよう!
- AppSheetを用いてデスクレスワーカーの仕事をデジタル化する方法
- Defining the Correct File Path
- 【TIPS】Start 〜 End 構文の使い方
- PDF line breaks
- メールテンプレートの改行の置き換え
- AppSheetでGoogle Driveの共有ドライブを利用しようとしてハマった件
- AppSheetでPDFが開けない!
- File not found
- Appsheet PDF file not found, Html
- AppSheetでファイル作成後にファイル添付メール送信