サークル出展した際、購入してくれた方から「領収書をもらえますか?」と尋ねられることは少なくありません
紙の領収書を出すのも一つの手ですが、次のお客さんがいる場合、お待たせしてしまうことになります
そこで、今回は「Googleフォームを使って領収書を自動発行する方法」について解説していきたいと思います!
この間、ゲムマや同人イベントに参加している友人からこんな相談を受けたんだよ
最近、イベントに参加した際に「領収書をもらえますか?」と聞かれることが増えた。毎回一人で参加しているため、売り子もおらず、領収書を書く手間が惜しい。お客さんにQRコードを読み取ってもらい、必要項目を入力してもらうことで、領収書をPDF化してメールで送れるようにしたい。
なるほど!
GASを使えば簡単にできるよ!
この記事を読めば、Googleフォームの回答から購入者宛にPDF化した領収書をメール送付することができます!めちゃくちゃ便利なので、是非読んでいってください!
初めての場合、GASで作るのは大変かもしれないけど、一回作ればそれをベースに何度も使えるから頑張って作ってみよう!
GASを極めたい方や、業務の効率化を図りたい方は、ぜひこの記事を読んください!
難しいことはGASに任せて、我々人間は楽しちゃいましょう!
当ブログでは実際に仕事でGASを扱っている私が、GASの魅力について徹底的に取り上げていきます!
事前準備
事前準備の説明が不要な方は【STEP2】までジャンプしてください!
今回は商品が1つだった場合のシンプルな領収書の作り方を説明します!
【事前準備①】Googleフォームを作成する
項目名 | タイプ | 必須 |
---|---|---|
メールアドレス(領収書データの送信先) | テキスト | |
お名前(領収書に記載) | テキスト | |
購入部数 | ラジオボタン |
参考に私が作成したフォームは以下となります!
フォームを作成したら回答してみてね!
回答0件だとエラーになってしまうよ
【事前準備②】Googleドキュメントを作成する
それでは、次にGoogleドキュメントで領収書のテンプレートを作成しましょう!
今回、こちらの「領収書テンプレート」を使って演習します!
必要に応じてコピーして使ってください!
{{}}(可変文字部)について
この{{date}}みたいに波括弧で囲んであるのは何なの?
波括弧の部分は「可変文字部」といって、{{}}内を入力内容に書き換える魔法のような存在なんだ!詳しくは、以前の記事で説明しているよ!
是非読んでみてね!
【事前準備③】PDF出力場所の作成
Googleフォームの回答をGoogleドキュメントに反映し、PDFに変換するため、その出力先を作成しておきましょう!
IDは緑色の四角で囲った部分だよ!
【お題】Googleフォームの回答者に領収書をPDFで自動発行する
Googleフォームの方であらかじめ回答しておくのを忘れないようにしてくださいね!
(回答がないとエラーになってしまうため)
まずは全体のコードを確認
// 欠席届テンプレートファイル
const DOC_TEMPLATE = DriveApp.getFileById('〇〇〇〇〇〇(自分のドキュメントID)');
// PDF出力先
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇(自分のフォルダID)');
function gaslog_formSubmit(e) {
let itemResponses;
// フォームの回答をイベントオブジェクトまたはフォーム自身から取得する。
if (e !== undefined) {
itemResponses = e.response.getItemResponses();
} else {
const wFormRes = FormApp.getActiveForm().getResponses();
itemResponses = wFormRes[wFormRes.length-1].getItemResponses();
}
// 回答をもとに領収書を作成する
let wFileRtn = createGDoc(itemResponses);
// PDF変換してファイルIDを取得する
let wPdfId = createPdf(wFileRtn[0], wFileRtn[1]);
// PDF変換したあとは元ファイルを削除する
DriveApp.getFileById(wFileRtn[0]).setTrashed(true);
// 今回はPDFファイルを添付してメールを送信する
sendEmailEx(
e !== undefined ? itemResponses[0].getResponse() : '〇〇〇〇@gmail.com(自分のメールアドレス)'
, '【自動送信メール】領収書の送信'
, `領収書のPDFを送付致します。`
, {attachments: DriveApp.getFileById(wPdfId).getBlob()}
);
DriveApp.getFileById(wPdfId).setTrashed(true);
}
function createGDoc(itemResponses) {
// テンプレートファイルをコピーする
const wCopyFile = DOC_TEMPLATE.makeCopy()
, wCopyFileId = wCopyFile.getId()
, wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
let wCopyDocBody = wCopyDoc.getBody() // Googleドキュメント内の本文を取得する
, today = dayjs.dayjs();
// 以降はGoogleフォームの回答をマッピングする
itemResponses.forEach(function(itemResponse){
switch (itemResponse.getItem().getTitle()) {
case 'お名前(領収書に記載)':
wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
break;
case '購入部数':
let unitPrice = PropertiesService.getScriptProperties().getProperty('PRODUCT_VALUE')
, quantity = Number(itemResponse.getResponse());
wCopyDocBody = wCopyDocBody.replaceText(`{{price}}`, unitPrice*quantity);
break;
default:
break;
}
});
wCopyDoc.saveAndClose();
// ファイル名を変更する
let fileName = 'イベント領収書:ガスログ_'+today.format('YYYYMMDD');
wCopyFile.setName(fileName);
// コピーしたファイルIDとファイル名を返却する(あとでこのIDをもとにPDFに変換するため)
return [wCopyFileId, fileName];
}
function createPdf(docId, fileName){
// PDF変換するためのベースURLを作成する
let wUrl = `https://docs.google.com/document/d/${docId}/export?exportFormat=pdf`;
// headersにアクセストークンを格納する
let wOtions = {
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
}
};
// PDFを作成する
let wBlob = UrlFetchApp.fetch(wUrl, wOtions).getBlob().setName(fileName + '.pdf');
//PDFを指定したフォルダに保存する
return PDF_OUTDIR.createFile(wBlob).getId();
}
function sendEmailEx(_recipient, _subject, _body, _option) {
// 引数の内容でメールを下書き保存する
const mailDraft = GmailApp.createDraft(_recipient, _subject, _body, _option);
// 下書き保存したメールIDから下書きを取得し、メール送信を依頼する
GmailApp.getDraft(mailDraft.getId()).send();
}
今回は今まで扱ったことがない要素があるので、順を追って解説していきますね!
【STEP1】Googleフォームからコンテナバインド型でスクリプトエディタを開く
スクリプトエディタの開き方が分かる方は【STEP2】にジャンプしてください!
作成したGoogleフォームの「︙」をクリックして「〈〉スクリプトエディタ」から、コンテナバインド型でエディタを開こう!
エディタが表示されたら「▷実行」をクリック!
プロジェクトを開始する時、必ず出てくる画面だよ
「権限を確認」をクリックしよう!
自分のアカウントを選択して…
「詳細」をクリックして、「無題のプロジェクト(安全ではないページ)に移動」をクリックすると…
こんなカンジの画面が出たら「許可」をクリックしよう!
これでGASを書く準備が整ったよ!
早速、試しに色々書いていこう!
【STEP2】GASエディタを開き、「Day.js」をライブラリに追加する
GASのエディタを開くことができたよ!
Day.jsをライブラリに追加する
【STEP2】の補足説明
let today = dayjs.dayjs();
//中略
wCopyDoc.saveAndClose();
let fileName = 'イベント領収書:ガスログ_'+today.format('YYYYMMDD');
wCopyFile.setName(fileName);
dayjs
ライブラリを使って現在の日付を取得し、「イベント領収書:ガスログ_YYYYMMDD(本日の日付)」というファイル名になるようにしています
今回も一時的に保存するGoogleドキュメントのファイル名に日付を自動入力したかったので、「Day.js」を使いました
「Day.jsについて知見を深めたい!」という方はこちらから読んでみてください!
【STEP3】Googleフォームで回答送信時にGASが動くようトリガーを紐づける
左側のメニュー内の「トリガー」をクリック
右下にある「+トリガーを追加」をクリック
トリガーの設定画面において、「イベントのソースを選択」を[フォームから]に、「イベントの種類を選択」を[フォーム送信時]に設定してください
この設定を行うことで、Googleフォームから回答があった際に、回答者宛に自動でメールが送信されるよ!
「もっと詳しく知りたい!」という方はこちらの記事を参考にしてください
【STEP4】「プロジェクトの設定」から金額を設定する※重要
左側のメニュー内にある歯車マーク「プロジェクトの設定」をクリック!
一番下までスクロールし、「プロパティ欄」に金額(単価)を設定します
case '購入部数':
let unitPrice = PropertiesService.getScriptProperties().getProperty('PRODUCT_VALUE')
, quantity = Number(itemResponse.getResponse());
wCopyDocBody = wCopyDocBody.replaceText(`{{price}}`, unitPrice*quantity);
break;
PRODUCT_VALUE
という値を「1000」に設定することでスクリプト内でこの金額が適用されています
スクリプトプロパティから商品の単価(PRODUCT_VALUE
)を取得し、単価と購入数(回答)を掛け合わせて合計金額を計算し、{{price}}
プレースホルダーを置き換えています
購入部数の回答が「1」だと「1,000円」、回答が「2」だと「2,000円」…といったカンジで、スクリプトプロパティから設定した単価を掛けた金額がドキュメントファイルの{{price}}内に反映されるよ
【STEP5】Googleフォームの回答を取得し、ドキュメント内を書き換える
function createGDoc(itemResponses) {
// テンプレートファイルをコピーする
const wCopyFile = DOC_TEMPLATE.makeCopy()
, wCopyFileId = wCopyFile.getId()
, wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
let wCopyDocBody = wCopyDoc.getBody() // Googleドキュメント内の本文を取得する
, today = dayjs.dayjs();
// 以降はGoogleフォームの回答をマッピングする
itemResponses.forEach(function(itemResponse){
switch (itemResponse.getItem().getTitle()) {
case 'お名前(領収書に記載)':
wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
break;
case '購入部数':
let unitPrice = PropertiesService.getScriptProperties().getProperty('PRODUCT_VALUE')
, quantity = Number(itemResponse.getResponse());
wCopyDocBody = wCopyDocBody.replaceText(`{{price}}`, unitPrice*quantity);
break;
default:
break;
}
});
switch文を利用することによって、「〇〇」という質問に対しての回答をGoogleドキュメント本文中の{{可変文字部}}部分に置き換える作業をしているよ!
itemResponses.forEach(function(itemResponse){
switch (itemResponse.getItem().getTitle()) {
case 'お名前(領収書に記載)':
wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
break;
case '購入部数':
let unitPrice = PropertiesService.getScriptProperties().getProperty('PRODUCT_VALUE')
, quantity = Number(itemResponse.getResponse());
wCopyDocBody = wCopyDocBody.replaceText(`{{price}}`, unitPrice*quantity);
break;
default:
break;
}
itemResponse.getResponse()
を用いることで、Googleフォームの回答内容を取得し、テンプレートドキュメント内の{{name}}
や、{{price}}
等の可変文字部をユーザーが回答した内容に置き換えます
今回の例だと、「お名前(領収書に記載)」と「購入部数」の質問に対して、ユーザーが入力した回答内容を取得し、テンプレートドキュメント内の対応する{{可変文字部}}を置き換えます
【STEP6】 PDF化した領収書を添付ファイルとして相手先にメールを送信する
// 欠席届テンプレートファイル
const DOC_TEMPLATE = DriveApp.getFileById('〇〇〇〇〇〇(自分のドキュメントID)');
// PDF出力先
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇(自分のフォルダID)');
function gaslog_formSubmit(e) {
let itemResponses;
// フォームの回答をイベントオブジェクトまたはフォーム自身から取得する。
if (e !== undefined) {
itemResponses = e.response.getItemResponses();
} else {
const wFormRes = FormApp.getActiveForm().getResponses();
itemResponses = wFormRes[wFormRes.length-1].getItemResponses();
}
// 回答をもとに領収書を作成する
let wFileRtn = createGDoc(itemResponses);
// PDF変換してファイルIDを取得する
let wPdfId = createPdf(wFileRtn[0], wFileRtn[1]);
// PDF変換したあとは元ファイルを削除する
DriveApp.getFileById(wFileRtn[0]).setTrashed(true);
// 今回はPDFファイルを添付してメールを送信する
sendEmailEx(
e !== undefined ? itemResponses[0].getResponse() : '〇〇〇〇@gmail.com(自分のメールアドレス)'
, '【自動送信メール】領収書の送信'
, `領収書のPDFを送付致します。`
, {attachments: DriveApp.getFileById(wPdfId).getBlob()}
);
DriveApp.getFileById(wPdfId).setTrashed(true);
}
function createGDoc(itemResponses) {
// テンプレートファイルをコピーする
const wCopyFile = DOC_TEMPLATE.makeCopy()
, wCopyFileId = wCopyFile.getId()
, wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
let wCopyDocBody = wCopyDoc.getBody() // Googleドキュメント内の本文を取得する
, today = dayjs.dayjs();
// 以降はGoogleフォームの回答をマッピングする
itemResponses.forEach(function(itemResponse){
switch (itemResponse.getItem().getTitle()) {
case 'お名前(領収書に記載)':
wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
break;
case '購入部数':
let unitPrice = PropertiesService.getScriptProperties().getProperty('PRODUCT_VALUE')
, quantity = Number(itemResponse.getResponse());
wCopyDocBody = wCopyDocBody.replaceText(`{{price}}`, unitPrice*quantity);
break;
default:
break;
}
});
wCopyDoc.saveAndClose();
// ファイル名を変更する
let fileName = 'イベント領収書:ガスログ_'+today.format('YYYYMMDD');
wCopyFile.setName(fileName);
// コピーしたファイルIDとファイル名を返却する(あとでこのIDをもとにPDFに変換するため)
return [wCopyFileId, fileName];
}
function createPdf(docId, fileName){
// PDF変換するためのベースURLを作成する
let wUrl = `https://docs.google.com/document/d/${docId}/export?exportFormat=pdf`;
// headersにアクセストークンを格納する
let wOtions = {
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
}
};
// PDFを作成する
let wBlob = UrlFetchApp.fetch(wUrl, wOtions).getBlob().setName(fileName + '.pdf');
//PDFを指定したフォルダに保存する
return PDF_OUTDIR.createFile(wBlob).getId();
}
function sendEmailEx(_recipient, _subject, _body, _option) {
// 引数の内容でメールを下書き保存する
const mailDraft = GmailApp.createDraft(_recipient, _subject, _body, _option);
// 下書き保存したメールIDから下書きを取得し、メール送信を依頼する
GmailApp.getDraft(mailDraft.getId()).send();
}
sendEmailEx
は、指定された受信者、件名、本文、およびオプションでメールの下書きを作成し、その下書きを取得してメールを送信するものです!
このような設定を行うことで、Googleフォームの回答者宛に自動で領収書をメール送付することができます
今回はこれでおしまいです!
お疲れ様でした
まとめ
今回は「GASを用いてGoogleフォームの回答を取得し、回答者宛に自動で領収書を送付しよう!」というテーマで解説を行いました
ぜひ、皆さんも実業務での活用に取り組んでみてください
引き続き、GASを楽しんでいきましょう!!
ありがたいことに今年の5月に起業してから忙しくさせてもらっていて技術ブログを更新する時間がまったく取れなかったよ
更新3か月くらい空いちゃったけど、なんだかんだ毎日100人は見に来てくれて本当にありがたいよね
今、「食をDXの力で盛り上げたい」という思いから
テイクアウト専門情報サイトを構築中です!
ひとまずXアカウントを開設したのでフォローしてくれると嬉しいな
「おいしいお店を知りたい!」
— とごなび (@ToGonavi_4u) May 20, 2024
そんな思いからテイクアウト専門の情報サイト「ToGoナビ」を近日リリース予定🧡
地元の人の中では定番のおいしいお店はネットで探せなかったりするので、皆さんのおすすめのお店を知りたい🥺
食べるの大好きなので、DXの力で「食」を応援したいです!#とごなび pic.twitter.com/2uGx7JsWVu
「ToGoナビ」のリリース告知記事はこちら
おかげさまで今年5月に起業しました!
GASやGoogleサービス、プログラミング全般のご相談承ります!
YouTubeでGoogleサービスをより
快適に使う方法をご紹介しています!
見て頂けたらうれしいです
コメント