Googleフォームで、ラジオボタン、プルダウン、チェックボックスといった選択肢に対して、定員(人数制限)を設定できる機能があると便利です。
例えば、「松の会」「竹の会」「梅の会」のような選択肢があり、それぞれに定員数が設定されている場合、定員に達した「松の会」が選択肢から自動的に消えることで、以降の申し込みを制限することができます。
このような定員制限機能は、イベントの申し込みなど、人数管理が重要な場面では必須と言えるでしょう。しかし、現在のGoogleフォームには、この機能が標準で搭載されていません。
そこでGAS(Google Apps Script)でうまく対応できないかと考えて、スクリプトを組んでみました。スプレッドシートの関数と組み合わせることで、とても応用の効くものができましたので、ここに投稿します。
それではテストのフォームを作りながら、このGASの使用方法を説明していきます。
テストのフォームとスプレッドシートを作る
フォーム
まず、以下のようなフォームを作ります。

とりあえずラジオボタンの質問を作ってください。
①質問、②選択肢、③説明で覚えてください。
スプレッドシート
フォームをスプレッドシートにリンクしてください。

リンクしたスプレッドシートに2枚目のシート(左から2番目のタブ)を作ります。このシートをGASが参照します。

①フォームの質問
②フォームの選択肢
③フォームの説明
④参照セル~ゼロ"0"より大きい任意の数値
①、②、③は、フォームと同じにしてください。
GAS
次にフォームからGAS(updateItems)を登録します。

次のGASをフォームのエディタにコピペしてください。
- function updateItems(SheetNo){
- //アクティブフォーム
- const form = FormApp.getActiveForm();
- //選択肢シート:SheetNoは必要なら変更する(一番左のシートが0、2番目が1、3番目が2…)
- if(!(SheetNo>1)) SheetNo = 1;
- const itemsSheet = SpreadsheetApp.openById(form.getDestinationId()).getSheets()[SheetNo];
- //シートの選択肢、説明などを配列で取得する
- const lastRow = itemsSheet.getLastRow();
- const itemsList = itemsSheet.getRange(1,1,lastRow,3).getDisplayValues();
- //変数宣言
- let newItems = []; let countItems = 0;
- //説明1を取得
- let helpText = itemsList[0][1];
- for (let i = 1; i < lastRow; i++) {
- //参照セルがゼロでない選択肢を取得する
- if (itemsList[i][2] > 0) {
- newItems[countItems++] = itemsList[i][0];
- }
- // 追加の説明2〜を取得する
- if (itemsList[i][1] != "") {
- helpText += "\n" + itemsList[i][1];
- }
- }
- if (countItems > 0) {
- //フォームの質問、説明、選択肢などを取得する
- const items = form.getItems();
- for (let i = 0; i < items.length; i++) {
- //対象の質問を探して見つけたら…
- if (items[i].getTitle() === itemsList[0][0]) {
- //選択肢のタイプ(ラジオボタン or プルダウン or チェックボックス)を選んで…
- switch (items[i].getType()) {
- //ラジオボタンの選択肢と説明を更新する
- case FormApp.ItemType.MULTIPLE_CHOICE:
- items[i].asMultipleChoiceItem().setChoiceValues(newItems).setHelpText(helpText); break;
- //プルダウンの選択肢と説明を更新する
- case FormApp.ItemType.LIST:
- items[i].asListItem().setChoiceValues(newItems).setHelpText(helpText); break;
- //チェックボックスの選択肢と説明を更新する
- case FormApp.ItemType.CHECKBOX:
- items[i].asCheckboxItem().setChoiceValues(newItems).setHelpText(helpText); break;
- }
- break;
- }
- }
- }
- //選択肢の参照セルが全てゼロなので回答受付を終了する
- else {
- if(form.isAcceptingResponses()) { //UpdateItemsを同じフォームで複数使うための対策
- form.setAcceptingResponses(false);
- //回答受付終了をメールで知らせる
- const formName = form.getTitle();
- const formUrl = form.getEditUrl() + "#responses";
- const mailAdd = Session.getActiveUser().getEmail();
- const mailTitle = "フォーム<" + formName + ">が受付終了になりました。";
- const mailText = "フォーム<" + formName + ">が受付終了になりました。\n" + formUrl;
- GmailApp.sendEmail(mailAdd, mailTitle, mailText);
- }
- }
- return countItems;
- } //Ver1.5.7 for maintenance
↓ ↓ コピペ ↓ ↓ (コピペ後は保存をしてください。)

トリガー
つぎにトリガーを追加します。

イベントの種類の選択は、「フォーム送信時」を選びます。

※承認を求められたら、「Advanced」(あるいは、「詳細」)→「Go to ~~(Unsafe)」(あるいは、「~~に移動」)→「Allow」(あるいは、「許可」)

ここまでで準備ができました。
動作テスト
作成したシート(2枚目)の数値(参照セル:C3)をゼロ"0"にしてください。

フォームを実行(プレビュー)します。

回答後、送信してください。

再度、フォームをプレビューしてください。

参照セルをゼロ"0"にした選択肢の項目が消えていたら、成功です。
実践編
ここまでが、GAS(updateItems)を追加したフォームの基本動作です。
この基本動作をもとに、自分で作るフォームに応用していきます。
既存のフォームを修正変更し、改めて回答を募集する際は、過去のデータが混ざらないよう、リンクしたスプレッドシートとフォームの回答を全削除してください。(以下の①②の作業)
①回答シートの回答行を削除する。

②フォームの回答を削除する

応用例その1
次に、このテストフォームを使った応用例を示してみます。
選択肢シート(2枚目のシート)に、新たな項目と関数を加えています。
(数式で表示:[Ctrl]+@)

テストのフォームよりの回答・送信を(15回)繰り返しました。その時の回答シートです。

この時の選択肢シート(2枚目のシート)には、次のように表示されています。

① =COUNTIF('フォームの回答' !C:C, A2)
フォームとリンクしている"フォームの回答"シートに記録されている"お茶の会"のカウント数(参加者数)
② =E2-D2
定員数(任意)から参加者数を引いた残りの席数
③ =if(C2>0, "", A2 & "は定員に達しました")
残りの席数が"0"以下のとき、"お茶の会は定員に達しました"と表示
この時のフォームのプレビューです。

お分かりでしょうか?
回答の選択項目をカウントして、定員数に達した項目が選択肢から消えています。
また、その消えた項目の旨を説明にて表示しています。
このように、選択肢シート(2枚目のシート)に関数と組み合わせることで、自分の作るフォームの質問の選択肢に応用の幅が広がります。
その他、説明
すべての項目が定員に達したら...
選択肢の参照セル(④C列のセル)がすべてゼロ"0"以下の値になると、強制的に回答受付終了となるようにGASに組まれています。同時に、フォームのオーナーへ回答受付終了のメールを送ります。


選択肢のタイプ
選択肢のタイプは、ラジオボタン、プルダウン、チェックボックスの3種類があります。
GASで自動的にタイプを判断しますので、自由に選んでください。
選択肢の項目が多い場合は、プルダウンの方が見た目も使い勝手も良いですね。
シートタブの位置
選択肢シートのタブの位置(左から2番目)を替えたいときは、UpdateItems(SheetNo)の引数を使ってください。引数SheetNoは、タブの位置が3番目は"2"、4番目は"3"…です。
その他、応用例
updateItemsを使った応用例を作ってあります。
ご参考になりましたら幸いです。
既存のフォームを修正変更し、改めて回答を募集する際は、過去のデータが混ざらないよう、リンクしたスプレッドシートとフォームの回答を全削除してください。(以下の①②の作業)
①回答シートの回答行を削除する。

②フォームの回答を削除する

応用例その2(残席数をフォームに表示する)
応用例その3(残席数をフォームの選択肢に表示する)

応用例その4(1~3人の申込みにも定員のある選択肢で対応)
応用例その5(チェックボックスで定員のある選択肢に対応)
応用例その6(定員に申込締切日を追加)
応用例その7(複数の質問の選択肢に定員を設定)
これまでの応用例は一つの質問の選択肢だけの対応ですが、この応用例7を使うことで、複数の質問の選択肢に定員を設定できます。
フォームの回答者数で制限する ~ multiReplyの紹介
updateItemsは、「質問の選択肢」ごとに制限(定員、人数制限)を設けられますが、multiReplyは単純にフォーム全体の回答者数に制限が設けられます。さらに、返信メールにも対応していますので、簡単なフォームであればこれで十分かもしれません。
Googleフォームでとにかく簡単に申し込み人数制限を設定したい方はこちら
おわりに
GASで複雑な処理を行うスクリプトを組むと、様々なフォームに応用させるのが難しくなります。GASの処理は単純で、スプレッドシートの関数で応用できるのが私の好みです。フォームに自分のアイデアを採用するためテストする時、関数はトライ&エラーが簡単ですからね。ちなみに今(執筆時)、選択肢の項目に残数を表示する方法を思いついたので試しています。(済)
以上、このGASが皆様のフォームの開発に役立つことを願いまして、それではまた。
追記、google公式サイトのApps Scriptリファレンスを見ていると、今まで見落としていたgetTypeを見つけました。
これで、ラジオボタンとプルダウンを自動で区別できるようになりました。よかったよかった^o^(Ver.1.3.0)
追記、チェックボックスへの対応も問題ないことが分かりましたので、GAS(updateItems)へチェックボックスも追加しました。(Ver.1.4.0)
追記、UpdateItemsの複数同時使用に対して、複数の終了メールに対策しました。(Ver.1.4.5)
追記、GASの仕様変更によるエラー対応のため、コードに変更を加えました。(Ver.1.5.5)
今までは.setHelpTextはセクション毎に設定できていましたが、
例) Item.setHelpText('文字列');
2024/10月以降のGASのアップデート(?)から、セクションのタイプ毎にキャストする必要があるようです。
例) Item.asMultipleChoiceItem().setHelpText('文字列');
参考) https://support.google.com/docs/thread/300175092?hl=en
情報をいただいた二月様、たくさん様に感謝です。m(_ _)m
バグ等ありましたら、お知らせいただくと幸いです。
コメント
無事に動作したようで何よりです。
私のスクリプトを使ってのGoogleフォームの開発は、GASの勉強よりシートの関数の勉強になるとは思いますが、頑張ってください。
早速のご回答ありがとうございます。
最終的にやりたいのは「応用例その7」に近いものですが、
とりあえず、このページの例をそのままやってみておりました。
あらためてやってみましたら、うまく動作いたしました!
もしかすると、今までトリガーの設定で
「イベントの種類を選択」で「フォーム送信時」にせず
「起動時」のままにしていたかもしれません。
お騒がせいたしました。
とりあえず、練習(勉強)のため作例通りに作成してみて
いずれ「応用例その7」にもチャレンジしてみようと思っております。
このようなサイトを公開していただき、感謝しております。
ありがとうございました。
まずはGASの初心者にも関わらず当記事を試してくださりありがとうございます。
応用例その7は少し複雑なUpdateItemsの使用例なので混乱させてしまったかもしれませんね。
もう少し簡単な説明ができないものかと少しづつ加筆していますが、なにしろエンジニア脳なもので・・・。
さてご質問の件ですが、GoogleフォームのスクリプトエディタでUpdateItemsをコピペした後、
function myFunction() {
updateItems(1);
updateItems(2);
}
をUpdateItemsの後に追加されたでしょうか?
エディタから実行テストするのでしたら、このmyFunctionを実行してください。
またトリガーに追加するのもUpdateItemsでなくmyFunctionですのでお間違えがないでしょうか?
この点を間違えてなくまだエラーが出るようでしたら、再度ご連絡をお願いします。
追記ですが、このUpdateItemsは、プルダウン、ラジオボタン、チェックボックスに対応しますので「注文数を数値で入力」は対象外となっております。ご了承くださいませ。
お世話になります。
GASは意味も分からず、WEBにあるものをコピペして使用している程度です。
今回も検索をして貴サイトにたどり着きました。
私がやりたいことは、ほぼ「応用例その7」と同じもので、
注文数をプルダウンから選択するのではなく、
注文数を数値で入力するものを作成しようと思っております。
まずは、作例そのままでやってみようと思い手順通り進めましたが、
すべての応用例で使用している「updateItems」がエラーになってしまいます。
TypeError: Cannot read properties of null (reading ‘getDestinationId’)
updateItems @ コード.gs:6
デバックをすると6行目で止まってしまいます。
何度かチャレンジしましたが、全く同じで解決できませんでした。
コピペしたのはVer1.4.5です。
大変恐縮ですが、何が原因か、また解決方法等お分かりになりましたらご教示願えますでしょうか。
よろしくお願いいたします。
いいえ、これは私のミスです。ご指摘がありませんでしたら、このまま気づかず被害が拡大していました。
今回はとても助かりました。また何か見つけましたらよろしくお願いします。
余談ですが、もし回答送信後の返信メール機能も追加することになりましたら、
スクリプトのDiyReply(【GAS】Googleフォームから自動で返信メール~合計金額など好きな値を追加できる自由度の高い返信メール)をUpdateItemsと同時使用することをおすすめします。
返信メールがいくつかあって混乱するそうです(今は2つだけにしていますが)。
何度もご対応ありがとうございます。
素人な物で半角全角に違いに気づかずコピペのみで作業していました。
おかげさまで無事動作確認も取れ、本番使用したいフォームにも組み込むことができました。
この度はありがとうございました。
度々のバグのご指摘に感謝いたします。
原因は半角の”が全角に変換されていることで私の一方的なミスです。
これはWordPressの仕様なので強制的にこの機能を止めていたのですが、少し前のテーマの変更でこの操作が無効になっていました。
また操作を加えましたので、全角変換は行われないはずです。
ご迷惑をお掛けしました。
お手数ですが、また何か問題が見つかりましたらお知らせください。
早速のご対応ありがとうございます。
無事テストまでたどり着けました。
同様にして選択肢が削除されるところまでは出来ました。
しかし、応用編の様に関数を使用すると、スプレッドシート上で関数エラーが出てしまいます。
他の応用編2~の関数もコピペしてみましたが同様です。
対応策あるでしょうか?御教授ください。
ご報告をありがとうございます。
昨日にリクエストでこのUpdateItemsに少し機能追加を行いました。
そのときにコードをHTMLに変換する際に、ダブルクォーテーション(“”)が正しく変換されなかったようです。^^;
修正し確認をしましたので大丈夫かと思います。再度お試しください。
ご迷惑をお掛けしました。
役に立つ情報ありがとうございます。
この様なスクリプトを探していました。
しかし、コピペで使用してみましたが、
「構文エラー: SyntaxError: Invalid or unexpected token 行: 21 ファイル: コード.gs」
と出てスクリプトが保存出来ず、以降の作業もできません。
ご指示していただければ幸いです、よろしくお願い致します。