【GAS活用システム③-2】GASデジタル伝票で注文受付・販売管理をする~設定編~
Google Apps Script (GAS)を、もっと身近に、日々の暮らしに。
前回より、【GAS活用システム】の第三弾として、「GASデジタル伝票での注文受付・販売管理」を紹介しています。
前回の【GAS活用システム③-1】は、前置きだけでしたが、今回はがっつりGASデジタル伝票の設定を行っていきます。
設定の全体像
前回の最後に紹介した、「GASデジタル伝票」の設定の全体像です。
繰り返しになりますが、GASは結構長めでも、ほぼほぼコピペでいけますよ。それでは、さっそく「GASデジタル伝票」の設定をしていきましょう。
テンプレートをコピーして保存
これまで紹介したGAS活用システム同様、今回もテンプレートを用意しましたので、まずテンプレートのコピーから行います。
Googleアカウントでログイン後、以下をクリックしてください。
メニューバーが表示されない場合は、ツールバーの一番右の v をクリックすれば、メニューが表示されます。
左上メニューより「ファイル」>「コピーを作成」を選択します(Googleアカウントでログインしていないと選べません)
左上メニューより「ファイル」>「コピーを作成」を選択します(Googleアカウントでログインしていないと選べません)
ファイル名を変えて、自分のドライブ上にコピーします。フォルダをマイドライブ以外に変更することも可能です。
【品目集計表】シートの編集
テンプレートをコピーして保存したら、次は【品目集計表】シートを編集します。
はじめに、セルのA1のタイトル「〇〇町内会イベント模擬店」を変更しましょう。ここで入力するタイトルは、後で自動生成する、フォームのタイトルやファイル名としてそのまま使用されます。
続けて、品目名と単価を入力していきます。
テンプレートにはサンプルとして7つの品目が設定されています。品目と単価を上書きしてください。扱う品目が7つより多ければ、4行目から売上合計の行の間に行を追加します。また、7つより少なければ、空白行は残さず、必ず行を削除してください。
【品目集計表】シートの設定は、タイトル、品目名と単価の設定、これだけだけです。
この後、GASが、この【品目集計表】シートのデータを元にフォームを自動生成したり、集計するための関数を自動設定したりするため、上記以外の部分に行を追加したり、列を追加したり、空白セルに文字を入力したりはしないでください。
スプレッドシートは自動保存です。後ほど、品目や単価を変更することも可能なので、仮の設定で大丈夫です。先に進みましょう。
GAS(スクリプト)のコピペと実行
テンプレートのスプレッドシートにはスクリプトが含まれていません。以下の手順でプロジェクトを作成し、スクリプトを設定します。
今回はスクリプトを2つのファイルに分けて登録していきます。
1つ目のファイル「コード.gs」には、フォームからデータが送信された時に実行される処理を記述します。
2つ目は「フォーム作成更新.gs」という名前にし、フォームを新規に作成したり、品目や単価を変更した時にフォームを更新したりするスクリプトを登録します。
スクリプトをコピペ
スプレッドシートのメニューバーから、拡張機能 > Apps Script を選択します。
無題のプロジェクトが生成され、Apps Scriptのスクリプトエディタが表示されました。ファイル:コード.gsに、「function myFunction」が表示されています。
「function myFunction ( ) { }」のところに、上書きする形で下記のコードをコピぺします。
function submitForm(e) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sh = ss.getSheetByName("注文明細");
//合計金額を計算する数式をセットするセルを取得する
const row = e.range.getRow(); //シートに書き込まれたデータの行番号
const lastCol = sh.getLastColumn(); //シートの最後列
const items = sh.getRange(1,2,1,lastCol-4).getValues().flat();
const prices = sh.getRange(2,2,1,lastCol-4).getDisplayValues().flat();
const desc = "備考";
const adjustmentCell = sh.getRange(row, lastCol-2); //調整金額セル
const totalPriceCell = sh.getRange(row, lastCol-1); //合計金額セル
const messageHeader = "\n"+ e.namedValues[items[0]] +"のご注文内容です";
let messageLine = '';
//注文があった品目と数量のみメッセージとして出力(品目の数だけ繰り返し)
for (let i=1; i < items.length; i++) {
let name = items[i], price = prices[i];
if (e.namedValues[name] != ""){ //注文数が入力されている時のみ
messageLine += "\n" + name + ": " +price +"×"+e.namedValues[name]+"個";
}
}
//備考欄に入力があった場合のみメッセージに追加
if (e.namedValues[desc] != ""){ //備考に入力されている時のみ
messageLine += "\n" + desc+":"+e.namedValues[desc];
}
adjustmentCell.setNumberFormat("[$¥-411]#,##0"); //調整金額セルに通貨書式を指定
//合計金額のセルに合計金額を計算する数式をR1C1形式で入力
totalPriceCell.setFormulaR1C1("SUMPRODUCT(R2C3:R2C[-2],RC3:RC[-2])+RC[-1]")
.setNumberFormat("[$¥-411]#,##0"); //通貨書式を指定
const massageTotal = "\n-------------------\n合計金額は "
+ totalPriceCell.getDisplayValue()+ " です!";
console.log(messageHeader + messageLine + massageTotal);
const token = "★トークンをここに設定★"; //トークンを設定
sendLine(messageHeader + messageLine + messageTotal, token);
}
function sendLine(msg,token){
var options = {
"method": "post",
"Content-Type" : "application/x-www-form-urlencoded",
"payload": "message=" + msg,
"headers":{"Authorization" : "Bearer " + token}
};
UrlFetchApp.fetch("https://notify-api.line.me/api/notify",options);
}
なかなかの長さですが、とりあえず全部コピペしてください。あとで一ヶ所だけ修正します(★~★にトークンを設定)。
次は「フォーム作成更新.gs」です。ツールバーの「+」をクリックして、スクリプトファイルを追加します。
名前に「フォーム作成更新」と入力して、下記のスクリプトをコピペします。
function createUpdateForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ssId = ss.getId(); //スプレッドシートIDを取得
const sh0Name = "注文明細" //フォームに紐づくシート名を指定
//品目集計表シートの品目と単価の範囲の値を二次元配列menuとして取得
const sh = ss.getSheetByName("品目集計表");
const lastRowA = sh.getRange(4,1).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
const lastRowD = sh.getLastRow();
const menu = sh.getRange(4,1,lastRowA-3,2).getDisplayValues();
let OneTo10 = createNumList(10); //1~10の連番リストを生成
let OneTo20 = createNumList(20, "番号:"); //"番号:01"~"番号:20"のリストを生成
if (ss.getFormUrl()) { //フォームが既に連携されている場合
var form = FormApp.openByUrl(ss.getFormUrl()); //連携しているフォームを取得
form.deleteAllResponses(); //フォームの回答をすべて削除する
//フォーム内の全アイテムを一旦すべて削除
const formItems = form.getItems();
for(let i = 0; i < formItems.length; i++){
form.deleteItem(formItems[i]);
}
form.removeDestination(); // スプレッドシートの連携を削除
// 現在の時刻(時:分)を格納
time = Utilities.formatDate(new Date(),'Asia/Tokyo','HH:mm');
//一番左のシートの名前"注文明細"に、bk_時刻(時:分)をつけるように変更
ss.getSheets()[0].setName(sh0Name+"bk_"+time);
SpreadsheetApp.flush();
console.log("フォームの項目・回答を削除し、連携シートをバックアップしました");
}else{ //フォームが連携されていない場合
console.log("フォームを新規に作成します");
const formTitle = sh.getRange("A1").getValue(); //タイトル(A1)の値を取得
var form = FormApp.create(formTitle).setTitle(formTitle); //フォームを作成
//作成したフォームのファイルをマイドライブからスプレッドシートのあるフォルダへ移動する
const sheetFolder = DriveApp.getFileById(ssId).getParents().next();
DriveApp.getFileById(form.getId()).moveTo(sheetFolder);
}
//はじめに番号札アイテムを作成(番号:01~番号:20の選択肢をもつプルダウンで)
form.addListItem().setTitle("番号札").setChoiceValues(OneTo20);
//メニュー品目の数だけアイテム作成(1~10の選択肢をもつプルダウンで)
for(let i = 0; i < menu.length; i++){
form.addListItem().setTitle(menu[i][0])
.setHelpText(menu[i][1]).setChoiceValues(OneTo10);
console.log(i+1+"つ目の項目、"+menu[i][0]+"をフォームに追加しました");
}
//最後に「備考」アイテム作成(記述式で)
form.addParagraphTextItem().setTitle("備考");
//スプレッドIDを指定してフォームと連携
form.setDestination(FormApp.DestinationType.SPREADSHEET, ssId);
//フォーム連携で追加されたシート側の処理
SpreadsheetApp.flush();
let sh0 = ss.getSheets()[0]; //一番左のシート
const lastCol = sh0.getLastColumn(); //この時点の最終列を取得
sh0.setName(sh0Name); //シート名を変更
sh0.insertColumnsBefore(lastCol,2); //最終列の前(左)に2列追加
sh0.getRange(1,lastCol).setValue("調整金額"); //新しい列の見出し設定
sh0.getRange(1,lastCol+1).setValue("合計金額");
sh0.setFrozenRows(2); //最初の2行を固定
sh0.setColumnWidths(2,menu.length+3,120); //2列目から合計金額の列のサイズ(幅)を120に設定
for(let i = 0; i < menu.length; i++){ //単価を2行目にセット
sh0.getRange(2,i+3).setValue(menu[i][1].slice(1)) //先頭の円記号をとって数値としてセット
.setNumberFormat("[$¥-411]#,##0"); //通貨書式を指定
}
//品目集計表シートの集計するための関数を設定
sh.getRange(4,3,menu.length)
.setFormula("SUM(OFFSET("+sh0Name+"!$C$3:$C,0,MATCH(A4,"+sh0Name+"!$C$1:$1,0)-1))");
sh.getRange(4,4,menu.length).setFormulaR1C1("RC[-2]*RC[-1]");
sh.getRange(lastRowD-2, 4).setFormula("SUM(OFFSET("+sh0Name+"!$C$1:$C,0,"+menu.length+"))");
sh.getRange(lastRowD, 4).setFormula("SUM(OFFSET("+sh0Name+"!$C$1:$C,0,"+(menu.length+1)+"))");
}
function createNumList(toNum,char) { //連番リストを作成する関数
let OneToNum = [];
for(let i = 1; i <= toNum; i++){
if (char == undefined){ //2番目のパラメータ(文字)の指定がない場合
OneToNum.push(i); //1から指定された数まで数値の連番を作成
}else{ //文字を前につけて01から指定数までの連番リストを作成
OneToNum.push(char+String(i).padStart(2, "0"));
}
}
return OneToNum;
}
超絶、長いですよね。。。でも大丈夫です。これはコピペで一切変更なしでいけます。最初から最後までまるっとコピーしてペーストするだけです。
「無題のプロジェクト」をクリックして、プロジェクト名を変更しておきます。
ツールバーの保存ボタンでプロジェクトを保存します。
フォーム作成更新のスクリプトを実行
保存後、ファイル作成更新.gsをクリックします。
ファイル作成更新.gsの一番はじめに定義されている関数createUpdateFormが、「デバッグ」と「実行ログ」の間に表示されるのを確認したら、「実行」ボタンをクリックします。
「承認が必要です」と言われます。
新規プロジェクトを実行する時に必要な「実行権限の承認」です。以下の手順で承認しましょう。
→ 「権限を確認」をクリック
→ Googleにログイン画面で、自分のアカウントを選択
→ 「詳細」、「[プロジェクト名](安全ではないページ)に移動」を順番にクリック
→ 「許可」をクリックすることで、実行権限の承認完了
手順が不安な方は、【GAS活用①-3】のページで、画面ショットつきで説明しているので、そちらを参考にしてください。
承認の手順が終わると、createUpdateForm関数が実行されます。実行ログに以下のようなメッセージが表示されることを確認しましょう(いつもより多めに出力しています)。
GAS(スクリプト)の実行後の確認と設定
それでは、createUpdateForm関数の実行により、何が行われたのか、確認をしながら、追加で設定をしていきましょう。
生成されたフォームの確認
まず、createUpdateForm関数が生成されたフォームを確認してみましょう。スプレッドシートを保存しているフォルダを再表示すると、フォームができているはずです。ダブルクリックでフォームを表示します。
ちなみに、スプレッドシートのメニューバーの ツール > フォームを管理 > フォームを編集、と、たどってもフォームを開くことができます。
以下のようなフォームが表示されると思います。
フォームは、以下のようなルールで生成されています。現物を見ながら確認してみましょう。
一番上に、「番号札」のアイテム(質問項目)があり、回答の形式はプルダウンで、選択肢として番号:01~番号:20までの値が設定されます。
続けて【品目集計表】シートで設定した品目の名前が、フォームのアイテムのタイトルに、単価がアイテムの説明に設定されています。回答の形式はプルダウンで1~10の選択肢が設定されます。品目の数だけこの設定が繰り返されます。
最後に、「備考」アイテムが段落形式で設定されます。
「番号札:01~番号札:20」や「1~10」の選択肢を変更したい場合、または、そもそも番号札を使用しない場合の対処方法については次回、説明します。
フォームの編集
今回は基本的にGASにより自動生成されたフォームをそのまま使用しますが、色や画像などの「テーマ」は自由に設定可能です。
フォームの「テーマをカスタマイズ」を選択して、お好みの色やテーマを選びましょう。
ヘッダーの「画像をアップロード」を選択して、「テーマ」の中から画像を選んだり、画像をアップロードすることができます。画像にあわせて、背景などの色も一緒に変更されますが、個別に色を変更することも可能です。
フォームは自動保存なので、自分で保存する必要はありません(保存ボタンがないので明示的に保存することはできません)。
【注文明細】シートの確認と設定
次は、スプレッドシート側に戻り、フォーム作成と同時にGASによって追加された【注文明細】シートを確認してみましょう。
【注文明細】シートはフォームと連携しています。1行目を確認してみましょう。
1列目に「タイムスタンプ」とあり、2列目から「番号札」、その後、品名が続いていきます。最後の品名の次の列に、「調整金額」、「合計金額」と2つ、フォームにない項目があり、最後に「備考」があります。
「調整金額」、「合計金額」の2列は、GASで追加しています。それ以外の列はフォームと連動しています。
2行目には、商品の単価が設定されていると思います。これも自動では表示されないので、GASで設定しています。
上記を確認したら、交互の背景色だけ設定しましょう。5~6行目くらいまでの範囲を選択します。
メニューの 表示形式 > 交互の背景色 で好みの色を選択します。
フォームからデータが追加されると、この背景色を設定された行が間にどんどん挿入されていきます。
【注文明細】シートで設定するのは、この交互の背景色だけです。
【品目集計表】シートの確認
最後に【品目集計表】シートも確認してみましょう。さて、何が変わったのかおわかりでしょうか??
売上数、調整金額合計などに、0と表示されるようになりましたね。売上数と書かれた一つ下、C4のセルにカーソルをおくと、以下のような関数が設定されているのが確認できると思います。
少し複雑な関数で、関数の達人でもない限り、すぐにピンときませんね。。この複雑な関数の詳細については、また次回、解説したいと思います。ここでは、このセルに何を表示させたいのかだけおさえておきましょう。
上記の例の場合、C4セルは、【注文明細】シートの注文データのうち、"やきそば"の売上数を集計したい、ということですよね。そのために、この複雑な関数をGASで自動的に設定したわけです。まだ注文が入っていないので、0が表示されていて正解です。
さて、以上で、フォームを新規作成した場合に、createUpdateForm関数が行ったことのすべてを確認できました。
追加で設定したのは、フォームのテーマと【注文明細】シートの交互の背景色だけでしたね。他はGASがやってくれました。
動作確認(フォームからテストデータを送信)
まだLINE通知の設定はしていませんが、どこまでできたのか確認する意味で、ちょっとフォームからデータを入力・送信してみましょう。
フォームの編集画面を開いて、プレビューボタンをクリックするか、
もしくは、スプレッドシートから、ツール > フォームを管理 > 実際のフォームを開く を選択します。
適当にデータを入力して送信ボタンをクリックします。
フォームの送信が終了したら、スプレッドシートの【注文明細】シートを確認します。
データが無事に登録されていますね。タイムスタンプには送信日時が自動設定され、フォームで選択した数がきちんと保存されています。
ですが、よく見るとなぜか3行目ではなくて、4行目にデータが設定されていますね。。実はこれ、謎なのです。。
今回はGASで【注文明細】シートの2行目にも単価を設定し、2行目まで固定表示させているのですが、、、なぜかそうすると4行目からデータが設定されちゃうんですね。。
調べても原因がわからず、特に害はないので、ここは気にせずにいきましょう。どうしても気になるようなら、3行目を手動で削除しても問題ありません。
続けて後ろの方の列を確認します。
フォームと連動していない「調整金額」と「合計金額」にはまだ何も値が表示されていないことが確認できます。
【品目集計表】シートも確認してみましょう。
こちらはスプレッドシートの関数が設定済みなので、もう売上数と売上金額、合計金額などは表示されていますね。
フォーム送信されたら合計金額を計算してLINE通知
ここまで来たらもう残りの設定もやっつけちゃいましょう。
トークンの取得
次に、LINE通知のための設定手順に入ります。LINE通知の送り先となる、「トークン」を取得します。トークンは送り先を判別するための43文字程度の、かなり長い英数字となります。
送り先は自分自身でもLINEグループ宛でもどちらでもいけます。
今回は注文データをグループで共有したいのであれば、LINEグループのトークンを、自分一人に通知するのであれば、自分自身のトークンを取得する、ということになります。
LINE Nofifyの公式サイトにご自分のLINEアカウントでログインして、通知を送りたいLINEグループ、または自分自身に通知するためのトークンを取得しましょう。
細かい手順は、【GAS活用術①-2】LINEグループへリマインド通知を自動送信・その2で画面ショットつきで書いてありますので、参考にしてください。
スクリプトにトークンを貼り付け
トークンを無事取得出来たら、GASにトークンを貼り付けましょう。Apps Scriptのスクリプトエディタが表示し、コード.gsをクリックします。
40行目を表示します。★トークンをここに設定★と書いてある行です。
40行目の" "の中、★~★までを、LINE通知の送り先のトークンで上書きしてください。
注:トークンは文字列になるので、両端を "(ダブルクォーテーション)で囲む必要があります。" "で囲まれた中(★~★までの間)を変更して、" "は消さないようにしてください。
トークンの貼りつけが終わったら、これでスクリプトの変更は終わりです。ツールバーの保存アイコンで保存するのを忘れずに。
フォーム送信時のトリガーを設定する
続けて、スクリプトエディタの画面左端のメニューバーで「トリガー」を選択します。
「トリガーを追加」をクリックします。
トリガーを追加の画面で、「実行する関数の選択」でsubmitForm、「イベントのソースを選択」でスプレッドシートから、「イベントの種類を選択」でフォーム送信時を選択します。
保存ボタンをクリックしてフォーム送信時のトリガーを保存します。
トリガーの設定は簡単でしたね。
最後に、自分自身に送る場合は不要ですが、グループ宛に送る場合は、【GAS活用術①-6】のLINEグループにLINE Notifyを招待するの手順が必要になります。こちらも難しい手順ではありませんので、ぱぱっとやってしまいましょう。
2度目の動作確認(LINE通知を確認)
トリガーの設定が終わったら、これでもうフォームからデータが送信される度に合計金額が自動計算されて、表示されるはずです。さっそく、二度目の動作確認として、再びフォームからテストデータを入力します。
さて、どうでしょう?今度は以下のようなLINE通知、届いたでしょうか?
念のため、合計金額が正しいか、計算してみてくださいね。
続けて、スプレッドシートの【注文明細】シートも確認しましょう。
LINE通知と同じ合計金額が、合計金額の列に表示されていると思います。
さて、一通り、設定が終了したところで、だいぶ長くなってしまったので、今回はこの辺で。
次回は、品目や単価を変更する場合の手順や、番号札を使用しない場合の変更方法、また使用した関数などについて解説していきます。
この記事が気に入ったらサポートをしてみませんか?