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つ以上に増やしていけば、なんちゃってオーダーシステムができるかもしれませんね。
メニューの項目が消えていく様は、まるでデータベースを使っているようです。
ですがあまり多くするのは、個人的にはお勧めできません。管理するシートの数が増えたらとても面倒です。(体験済)
その時は無理せずデータベースの導入を考えましょうね。
それではまた、
コメント
こまめ様、
無事に updateItems の複数使用に成功されたようで、おめでとうございます。
スリープ関数については、以前は念のために試してみたことがありますが、実際には処理時間が長くなるだけですので、使用しないのが正解です。
ご体験されたように複数使用は処理が終わるのに時間がかかります。そのため、一時的に多くのユーザーからの送信には対応しきれない可能性がありますので、どうぞご注意ください。