【AppSheet】請求書を作ろう~シンプルver.~

目次
はじめに
今回は請求書作成システムの開発を行ないます。
ひとくちに請求書といっても、様々な形式がありますが、今回作るのは『シンプルバージョン』です。
もちろん、シンプルバージョンと言っても、請求書として必要な項目はすべて揃っているのでご安心ください。
では、さっそく解説していきます!
完成イメージ
以下が完成した請求書作成システムのイメージです。
また、作成された請求書は以下です。
テーブルの設定
テーブルは以下の4つです。
①請求ヘッダ
②請求明細
③入金データ
④顧客データ
⑤検索用
以下、ひとつずつ説明していきます。
①請求ヘッダ
請求書の様な合計と明細が必要な書類は、ヘッダと明細の2つに分割します。
見積書や納品書なども同様ですので、これは1つ覚えておきましょう。
青文字はすべてバーチャルカラムです。
・ID
・請求日(Date)
・支払期限(Date)
・ステータス(Enum)
・顧客名(Ref)
・請求書発行回数(Number)
・PDF(File)
・Related 請求明細s(自動生成)
・Related 入金データs(自動生成)
・10%対象金額(Price)
SUM([Related 請求明細s][10%対象])・8%対象金額(Price)
SUM([Related 請求明細s][8%対象])・0%対象金額(Price)
SUM([Related 請求明細s][0%対象])・請求金額(税込)(Price)
[10%対象金額] * 1.1 + [8%対象金額] * 1.08 + [0%対象金額]・請求金額(税抜)(Price)
SUM([Related 請求明細s][金額])・入金金額合計(Price)
SUM([Related 入金データs][入金金額])・請求残高(Price)
[請求金額(税込)]-[入金金額合計]・10%消費税(Price)
[10%対象金額]*0.1・8%消費税(Price)
[8%対象金額]*0.08・消費税合計(Price)
[10%消費税]+[8%消費税]このテーブルのポイントは「消費税」です。
通常であれば、「消費税」というバーチャルカラムを1つ準備し、SELECTなどを使って計算結果を入れるのですが、ここでは各税区分ごとにカラムを作ってます。
理由は、SELECTを使ったバーチャルカラムは、将来的にデータが増えると重くなるためです。
特に、請求書のような数年にわたり保管義務のあるものはデータ量が莫大になるので、今回のような形式にした方が良いでしょう。
②請求明細
ヘッダを作成したら、次に請求明細を作ります。
それぞれの請求明細に請求ヘッダのIDを持たせることで、それぞれの明細を特定の請求ヘッダにまとめることができます。
カラムは以下の通りです。
・ID(Text)
・請求ヘッダ(Number)
・仕様(Text)
・個数(Number)
・単価(Price)
・税率(Enum)
・10%対象(Price)
IF([税率]="10%",[金額],0)・8%対象(Price)
IF([税率]="8%",[金額],0)・0%対象(Price)
IF([税率]="0%",[金額],0)・備考(Text)
・金額(Price)
[個数]*[単価]10%対象、8%対象、0%対象はFOMULAに関数を入力してください。
また、「税率」からむのEnumは「10%、8%、0%」の三つが選択肢です。
ここでとても重要なこととして、
「%」は必ず全角にしてください。
今回、「税率」カラムはテキストとして読み取らせますが、半角の%だと、勝手に百分率に変換されてしまいます。
そのため、%は必ず全角で表記するようにしてください。
③入金データ
・ID(Text)
・請求ヘッダ(Ref)
・入金日(Date)
・入金金額(Price)
・備考(Text)
④顧客データ
・ID(Text)
・顧客名(Text)
・住所(Text)
・担当者(Text)
・Related 請求ヘッダs(自動生成)
・Related 検索用s(自動生成)
⑤検索用
・ID(Text)
・開始日(Date)
・終了日(Date)
・顧客名(Ref)
「検索用」テーブルの使いどころは、次のUIのViewの設定で詳しく解説していきます。
Viewの設定
テーブルの設定が終わったら、次はビューの設定に入ります。
ビューの全体像は以下です(わかりやすくAppSheetの画像を添付します)

REFERENCE VIEWSにある3つのビューは、「ダッシュボード」ビューの構成要素になります。
「ダッシュボード」ビューの全体像と動きは以下です。
「検索」ビューで指定された条件で「請求ヘッダ」ビューがフィルターされ、「請求ヘッダ」ビューをクリックすると、その詳細が「請求ヘッダ詳細」ビューに表示されます。
それでは、REFERENCE VIEWSのビューから解説します。
「検索」ビュー
・View name:検索
・For this data:検索用
・View type:detail
View Optionsの「Quick edit columns」で「Add」をクリックし、開始日、終了日、顧客名を追加します。

この「Quick edit columns」、今回の検索機能で重要になります。
ここで選択した項目が、検索時に任意で値を変更できる箇所です。
「請求ヘッダ」ビュー
・View name:請求ヘッダ
・For this data:ダッシュボード請求ヘッダ
※スライスで新規につくります
・View type:deck
View Optionsの「Group by」は「請求日」の「Descending」とします。
スライスの作成
請求ヘッダビューでは、先で作成した「検索」ビューに応じて、表示内容をフィルターさせる必要があります。
このフィルターは、スライスによって制御していきます。
・スライス名:ダッシュボード請求ヘッダ
・Row filter condition
AND(
IF(ISBLANK(検索用[検索用[開始日]]), TRUE, [請求日] >= INDEX(検索用[開始日], 1)),
IF(ISBLANK(検索用[検索用[終了日]]), TRUE, [請求日] <= INDEX(検索用[終了日], 1)),
IF(ISBLANK(検索用[顧客名]), TRUE, IN([顧客名], 検索用[顧客名]))
)まず、ISBLANK()に関しては、未選択の状態を制御しています。
IFを使って、ISBLANK()の場合をTRUEとすることで、選択欄が未選択(空欄)の場合に、すべてのレコードを表示するようにしています。
次に、[請求日] >= INDEX(検索用[開始日], 1)は、開始日より後の請求日の請求ヘッダを表示します。
INDEXを使っている理由は、LIST形式からDate形式に変換するためです。
検索用[開始日]だけだと、List形式となってしまい、Date形式である[請求日]と型が一致しません。
そのため、INDEXを使うことで、List内にある任意の値(今回は[開始日])を抽出し、Date型である[請求日]と比較することができます。
IN()関数については、請求ヘッダの「顧客名」カラムから、検索用の「顧客名」と一致したものにTRUEを返す、という形です。
以上のようなスライスをつくることで、検索による動的な値変換が可能になります。
「請求ヘッダ詳細」ビュー
・View name:請求ヘッダ詳細
・For this data:ダッシュボード請求ヘッダ
・View type:detail
「ダッシュボード」ビュー
・View name:ダッシュボード
・View type:dashboard
View Optionの「View entries」は以下です。
・検索:Tall
・請求ヘッダ:Tall
・請求ヘッダ詳細:Large
また、Interactive modeは必ずONにしてください。
これをONにしておかないと、特定の請求ヘッダをクリックしても、「請求ヘッダ詳細」ビューが動的に動きません。
「顧客データ」
・View name:顧客データ
・For this data:顧客データ
・View type:table
これは顧客データを登録するためのViewなので、自由に設定してください。
以上で、Viewの設定は完了です。
請求書発行の設定
最後に、請求書を発行するための設定を行ないます。
順番としては、まず請求書のテンプレートの作成、次にアクションの設定、最後にBotの設定をしていきます。
テンプレートの作成
テンプレートについては、以下を参考にしてください。
https://docs.google.com/document/d/1vD0_f_zlhNV2MYkiYOCZXwFFV9jwKdBbQyRYZkgi0fE/edit?usp=sharing
テンプレートで重要なのは以下の3つです。
基本的な型(タグの差し込み)
<<[カラム名]>>上記の型は、データの値を入力する際の型になります。
PDFの作成はBotを利用し、そのBotで指定したテーブルの値をPDFに書き込むことが可能です。
その書き込みの際に、上記の型を利用することで、特定の値を書き込むことができます。
例えば、<<[請求金額(税込)]>>となっている場合、この欄には「請求金額(税込)」カラムの値が入力されます。
参照先テーブルの型
<<[ Ref を設定したカラム名].[参照先テーブル内のカラム名 ]>>テンプレートでは<<[顧客名].[顧客名]>>として記載されています。
説明をわかりやすくするため、<<[顧客名].[顧客名]>>と色分けをしてみました。
[顧客名]は、請求ヘッダのカラムです。これには参照先テーブルのIDが入っているため、<<[顧客名]>>とすると、IDが入力されてしまいます。
一方で、[顧客名]は、親テーブルである顧客テーブルの「顧客名」カラムです。
そのため、<<[顧客名].[顧客名]>>とすることによって、参照先の顧客名を取得することができます。
明細行の表示
請求ヘッダテーブルでは、「Related 請求明細s」という形で明細の一覧を取得できます。
AppSheetは便利なことに、以下の形式で書くことで、明細行の数に合わせた表を自動で作成してくれます。
<< Start: [ Related テーブル名s ]>>
<<[列名]>><<[列名]>><<[列名]>>...
<<End>>今回作っているテンプレートであれば、表の最初である<<[仕様]>>にStartタグを含めて、最後の<<[金額]>>にEndタグを入れます。
そして、他の要素はStartタグとEndタグの間に入るように入れていきます。
アクションの設定
次に、アクションを設定していきます。
このアクションはBotを起動するためのアクションです。
Botは行の「追加」「削除」「更新」で起動させることができます。
今回は「更新」によってBotが起動するように設定するので、行を更新するアクションを作成します。
・Action name:請求書発行
・For record of this tabale:請求ヘッダ
・Do this:Data set the value of some columns in this row
・Set these columns:請求書発行回数=[請求書発行回数]+1
・Position :Primary
Do thisには、列を更新するアクションを設定します。
また、Set these columnsには具体的に実行するアクションの挙動を設定しています。
アクションを実行すると、カラム名「請求書発行回数」にある数値に+1されていきます。
これにより、行を更新するアクションができました。

Botの設定
最後に、Botの設定を行います。
左にあるナビゲーションの「+」をクリックし、「Create a new bot」をクリックします。
トリガーを設定する
「When this EVENT occurs」の「Configure event」をクリックし、「Create new event」を選択します。
・Event name:トリガー
・Table:請求ヘッダ
・Date chane type:Updates
・Condition:
[_THISROW_BEFORE].[請求書発行回数]<>[_THISROW_AFTER].[請求書発行回数]ここで重要なのが、「Date change type」と「Condition」です。
「Date change type」はUpdatesを選択します。
これは、該当する行の値が更新されたときにBotを動かすという指示です。
続いて、「Condition」は更新時の条件を入力します。
今回の条件は、「[請求書発行回数]の前回の値と次回の値が変わったらBotを起動する」というものです。
つまり、[請求書発行回数]が1から2に変わった場合などに発火します。
この関数はBot利用時にはよく使うので、覚えておきましょう。
実行するBotを設定する
「Run this PROSESS」の「Add a step」をクリックします。
「Create new step」を選択したのち「New step」を「請求書発行」に変更します。
右側にある「Settings」では、「Create a new file」を選択します。
以下、その他の設定です。
・HTTP Content Type:PDF
・Template:紙のアイコンをクリックし、先で作ったテンプレートを選択
・File store:Ddeafault
・File Folder Path:
"請求書フォルダ"・File Name Prefix:
[顧客名].[顧客名]&TEXT([請求日],"yyyymmdd")&"-"&[請求書発行回数]・Disable Timestamp?:ON
・Attachment Page Orientation:Portrait
・Attachment Page Size:A4
・Use Custom Margins:OFF
File Folder Pathでは、作成したPDFファイルの保存先を指定できます。
AppSheetのプロジェクトが作られた時点で、デフォルトのファイル保存先が自動で指定されます。
基本的には「/appsheet/data/プロジェクト名」という形になっています。
ご自身のパスを確認したい場合は、「Settings」の「Infomation」にある「App Properties」の最下段を確認してみてください。
File Folder Pathは、このパス以降のフォルダを指定します。
今回の場合は、「請求書フォルダ」というフォルダを作り、そこに保存させたいので、「請求書フォルダ」を指定しています。
File Name Prefixでは、保存時にファイル名の指定ができます。
ポイントは、関数の最後にある[請求書発行回数]です。
AppSheetでファイルを同じ名前で保存した場合、フォルダ上は上書きされます。
しかし、キャッシュが残っているため、AppSheetからPDFファイルを開くと、上書き前のファイルが表示されます。
そのため、[請求書発行回数]をファイル名に含めることで、上書きではなく新規のファイルとして保存します。
これにより、上書き前のファイル表示を防ぐことができます。
PDFのパス名を保存
最後に、PDFのパス名を保存するBotを設定します。
「Add a step」をクリックし、「Create a new step」をクリックします。
「New step」を「PDFパス名保存」とし、「Run a task」を「Run a data action」に変更します。
「Set row values」を選択し、Set these column(s)では、「PDF」を選択します。
関数は以下の通りです。
"請求書フォルダ/"&[顧客名].[顧客名]&TEXT([請求日],"yyyymmdd")&"-"&[請求書発行回数]&".pdf"これにより、カラム名「PDF」にパス名が保存されます。
完成後の動き
では、最後に完成後の動きを見てみましょう。
請求書の作成ができています。
ただ、レイアウトをもっと凝って行いたいという場合は、もう少し工夫が必要になります。
より複雑な請求書の作成方法は、また次回以降の記事で紹介しますので、ぜひ参考にしてみてください。