Googleフォームの2つ以上の質問の選択肢に定員(人数制限)を設定できます。
今回は、2つ以上の注文メニューにおいて、在庫数を超える注文個数の選択肢を動的に消すことで、注文数の制限に対応したフォームです。
前の記事で作成したGAS(updateItems)とスプレッドシートの関数を組み合わせて実現しました。
次の記事からの続きです。GASで組んだ関数updateItemsを今回も使います。
応用例その7
デリバリー予約フォーム
このフォームは、在庫数を超える注文数の選択肢をメニューより消すことで選べなくしています。
また、在庫数を表示します。
そして、このフォームの最大の特徴は、メニュー(質問)が2つ(以上)あることです。

①質問、②選択肢、③説明
GASの登録
次の記事に従ってGAS(updateItems)をこのフォームに登録してください。
スプレッドシートの関数
次に、フォームとリンクしたスプレッドシートに2枚のシート(シート1、シート2)を用意しました。
この2枚のシートの内容がGAS(updateItems)で使用されます。


①フォームの質問
②質問の選択肢
③質問の説明~このB列を質問の説明に表示します。
④参照セル~このC列の値がゼロ"0"以下になると、フォームの質問のから選択肢が消えます。(このシートの選択肢は消えません。)
このシートの数式を表示([Ctrl]+@)してみます。


テーブル(コピペ用)で表示します。
タイムスタンプ | ホットコーヒー | 軽食 | お名前(代表者) |
ホットコーヒー | ="あと"&D2&"個、注文できます。" | 注文可能数 | 残数 | 注文数 | 注文上限数 |
注文なし | =N(OR('シート1'!D2,'シート2'!D2)) | =F2-E2 | =SUM('フォームの回答'!B:B) | 50 | |
5 | =INT($D$2/A3) | ||||
10 | =INT($D$2/A4) | ||||
15 | =INT($D$2/A5) | ||||
20 | =INT($D$2/A6) | ||||
25 | =INT($D$2/A7) | ||||
30 | =INT($D$2/A8) | ||||
35 | =INT($D$2/A9) | ||||
40 | =INT($D$2/A10) | ||||
45 | =INT($D$2/A11) | ||||
50 | =INT($D$2/A12) |
軽食 | ="あと"&D2&"個、注文できます。" | 注文可能数 | 残数 | 注文数 | 注文上限数 |
注文なし | =N(OR('シート1'!D2,'シート2'!D2)) | =F2-E2 | =SUM('フォームの回答'!C:C) | 50 | |
5 | =INT($D$2/A3) | ||||
10 | =INT($D$2/A4) | ||||
15 | =INT($D$2/A5) | ||||
20 | =INT($D$2/A6) | ||||
25 | =INT($D$2/A7) | ||||
30 | =INT($D$2/A8) | ||||
35 | =INT($D$2/A9) | ||||
40 | =INT($D$2/A10) | ||||
45 | =INT($D$2/A11) | ||||
50 | =INT($D$2/A12) |
関数自体はそう難しいものはありません。
今回のポイントは、2つの質問(ホットコーヒー、軽食)に対して、それぞれにupdateItemsが使われています。
そのため2枚のシート(シート1、シート2)を作る必要があります。
このとき問題になるのが、受付け終了のタイミングです。
今回は質問(ホットコーヒー、軽食)の残数がゼロの時にフォームの受付けを終了したいのですが、2つあるためどちらかの残数がゼロになっても、もう片方が残数ゼロになるまで待たなくてはなりません。
そのために質問の中に最後まで消えない選択肢が必要です。
今回は「注文なし」を設けました。
2枚のシートの残数がゼロになった時に「注文なし」を消す、つまり受付けを終了にするように「注文なし」のフラグ(セル:C2)を次のようにしています。
=N(OR('シート1'!残数, 'シート2'!残数))
2つの残数がゼロになった時、値がゼロになります。つまりフォームの受付け終了となります。
GASの追加登録とトリガーの設定
今回はupdateItemsを2つの質問に対応させているため、フォームからの1度の送信に対して2つのupdateItemsを実行する必要があります。
そこで、次のようなスクリプトを追加します。
function myFunction() {
updateItems(1);
updateItems(2);
}
ファンクション名は、何でもよいですが、ここでは、myFunctionにしました。
updateItemsの引数の1、2は、スプレッドシートでのタブの位置です。左から、0、1、2、3...になります。
今回の場合は、シート1は引数が1、シート2は引数が2です。当然、フォームの回答は0です。
※タブの位置と引数だけ対応させたら、タブの位置は任意です。念のため、シート名は元々自由です。



トリガーにmyFunctionだけ登録できたら準備完了です。

実行(回答)と結果
時短のため注文上限数は、コーヒー、軽食とも20個にしてあります。
実行(プレビュー)します。

ホットコーヒーを10個、軽食を15個選びました。

送信後のプレビューです。
注文可能数がゼロになった選択肢の項目が消えました。残数も更新されています。

ホットコーヒーを5個、軽食を5個選びました。送信後のプレビューです。
軽食の選択肢に「注文なし」が残っています。

最後のホットコーヒーを選びました。
全ての残数がゼロになりましたので、自動で回答の受付けが終了しました。

補足説明
今回のフォームでは、メニュー(選択肢)に「注文なし」があります。
選択条件には「必須」設定をしました。これだとメニューを選ぶ必要がなくても、必ず「注文なし」を選ばなくてはなりません。
少しでも使い易くするためにフォームの「事前入力したURLを取得」で初期値に「注文なし」を使うことをお勧めします。


毎回このリンクへアクセスするなら、すでに「注文なし」が入力されているため使い勝手が良いと思います。
どうぞお試しください。
補足説明2
今回の例では質問が2つのパターンでしたが、質問数を増やして運用したい場合、updateItemsがシーケンシャル(逐次的)に実行されるため、フォーム項目の更新に時間がかかるのが課題です。
例えば、1回の updateItems 実行に最大5秒かかると仮定すると、6回の実行では合計30秒ほどかかることになります。
この間、フォームへのアクセスはできるだけ避けたいですが、現実的にはこの時間を大幅に短縮したいと考えるでしょう。
そこで代替案として、次のように複数のラッパー関数を定義する方法があります。

function mf1() {updateItems(1)}
function mf2() {updateItems(2)}
function mf3() {updateItems(3)}
function mf4() {updateItems(4)}
function mf5() {updateItems(5)}
function mf6() {updateItems(6)}
そして、これらのmf1()〜mf6()という6つの関数それぞれを、同じ条件のトリガーに登録します。

これにより、理論的にはフォームからの送信時に各スクリプトが並行して実行されるため、スクリプト1回分の所要時間で済むことが期待できます。
おわりに
いかがでしたか。フォームの本来ない使い方をぎりぎりまで攻められたのではないでしょうか。
メニューの数を2つ以上に増やしていけば、なんちゃってオーダーシステムができるかもしれませんね。
メニューの項目が消えていく様は、まるでデータベースを使っているようです。
ですがあまり多くするのは、個人的にはお勧めできません。管理するシートの数が増えたらとても面倒です。(体験済)
その時は無理せずデータベースの導入を考えましょうね。
それではまた、
コメント
Kasuga様
アドバイスありがとうございました。
他の投稿の質問欄も拝見し、関数の変更を行いました。
また、フォームとスプレッドシートの説明文の改行の箇所が違いそこを直すと
スリープ関数無しでも正常に作動しました。
何とも初歩的な部分でお恥ずかしいですがすが、もしどなたかの参考になればと思い
コメントさせて頂きました。
いつもご丁寧に対応頂きありがとうございます。
これからも活用させていただきます。
以前、私の方でも管理シートを7枚までテストしたことがありますが、問題なくフォームに変更が反映されました。
ただし、1回の updateItems 実行に3~5秒ほどかかるため、すべての反映が完了するまでに30秒以上かかっていました。
そのため、確認は十分な時間を置いてから行うのが確実です。
また、updateItems(1)~updateItems(5) は一つずつ実行し、それぞれの質問項目にきちんと反映されているか確認することも重要です。
なお、各質問には、たとえば「選択なし」など、最後まで残る選択肢を設けていますか?
失礼しました、スプレッドシート上では反映されていますが、フォーム上で反映されていないの間違いです。
Kasuga様
ご提案ありがとうございました。
そちらの設定も利用し、非表示にすることができました。
スプレッドシートの管理シートが6枚あり、フォーム上ではきちんと反映されているのですが、
フォーム上で3、5、6の管理シートのもののみ反映されません。
他の方の質問回答にあったスリープ関数の部分を追加したのですが、そのままの状態です。
その他にチェックする箇所等ありますでしょうか?
こまめ様、
一人で複数個の回答でしたら、チェックボックスを使われてはいかがでしょうか。
次の記事が参考になるかと思います。
【GAS】Googleフォームの選択肢に定員を設定~チェックボックスでも対応
Kasuga様
前回、自動返信メールの設定では大変お世話になりました。
今回こちらの設定を申込受付に利用したいのですが、個数では無く、時間帯で受け付ける場合も利用可能でしょうか?
選択肢としては1人につき30分の枠×7個ほどで、それが6種類あるので設定用シートが6枚必要かとは思うのですが、、。
どれも定員が一人なのでその時間帯に申し込みがあればその時間帯は非表示にしたいです。
申込者も定員数が1と分かっているのでフォーム上に人数表示は必要無く、時間帯のみ非表示は可能でしょうか?
選択肢の例はこのような形です
10:00~10:30 定員1
10:30~11:00 定員1
11:00~11:30 定員1
そうですか……反映されませんでしたか?
私の方で応用例7を2種から6種へ拡張してみましたが、成功しました。
特にSleepなども使わずに何度かやってみましたが、問題なく反映されていました。
私のテストサンプルはシンプルなので、もっと複雑なパターンも今度テストしてみますね。
ともかさんの方でも何か分かりましたらお知らせいただくと助かります。
ありがとうございます!
やってみましたが、
シート内はやりたいことができていますが、
フォームへの反映はされませんでした…!
やはり6種というのが無謀すぎましたかね…。。
ご丁寧にありがとうございました!!
当ブログをご覧いただきありがとうございます。
フォームの質問を6種も使われているのですか?!勇者ですね!ぜひ成功させていただきたいと思います。
注文フォームは、「応用例その7」をupdateItems(1)~updateItems(6)まで拡張させたものを使われているということでよろしいのでしょうか?
実際にこの応用例7をここまで使っていただいた報告はないので、エラーに関しては推測になります。
確認していただきたいのが、「あと〇点、購入できます。」の表示がシートには正しく表示されているが、フォームに反映されていないことです。
もしシートにも正しく表示されていないのでしたら、シートの関数の問題です。シート1~シート6の関数をもう一度確認してください。特にE列は、=SUM(‘フォームの回答’!B:B)~=SUM(‘フォームの回答’!G:G)のようにシートごとに異なりますので注意してください。
シートに正しく表示されているにも関わらず、フォームに反映されないのでしたら、確かに複数のスクリプトの同時実行による影響かもしれません。
その場合、試しに各スクリプトの実行開始に間隔を開けてみてください。スリープ関数(Utilities.sleep)を使ってみましょう。
例えば次のようにします。2000は2秒間だけスクリプトを止めます。
function myFunction() {
updateItems(1);
Utilities.sleep(2000);
updateItems(2);
Utilities.sleep(2000);
updateItems(3);
Utilities.sleep(2000);
updateItems(4);
Utilities.sleep(2000);
updateItems(5);
Utilities.sleep(2000);
updateItems(6);
Utilities.sleep(2000);
}
少し面倒ですが、お試しいただければ幸いです。
すみません、上記コメント削除お願いできますか?(名前が…)
再コメントさせていただきます。
ーーーーーーーーーーーーーーーーーーーーーーーーー
詳しく説明してくださり、ありがとうございます!
初めてですが、ほぼコピペで希望していた注文フォームをつくることができそうです。
ただ、1点ほど上手くいかない部分があります。
商品説明の「あと〇点、購入できます。」が更新されたり、されなかったりです。
商品によって上手く機能したり、回答が反映されなかったりしています。
初めてGASを使うのですが、コードも初めてで
こちらのコピペと書き換えのみで行っています。
商品の種類が多いことで上手く反映されないのでしょうか?(6種)
他に聞ける方がおらず、こちらに質問させていただきました。
お忙しいこととは思いますが、返信いただけると幸いです。
よろしくお願いいたします。