PR

【GAS】Googleフォームでラジオボタン・プルダウン・チェックボックスの選択肢に定員(人数制限)を設定

Google Workspace

googleフォームを活用していると、ラジオボタンプルダウン、およびチェックボックスの選択項目に対して、定員のような人数制限があると助かります。

例えば、選択肢に「松の会」、「竹の会」、「梅の会」などの項目があって、それぞれに定員数があるとします。定員に達した「松の会」が選択肢から消せたら「松の会」にこれ以上申し込めません。つまり定員という制限がかけられます。

このような機能は必須に思えますが、googleフォームの機能に含まれていません。

そこでGAS(Google Apps Script)でうまく対応できないかと考えて、スクリプトを組んでみました。スプレッドシートの関数と組み合わせることで、とても応用の効くものができましたので、ここに投稿します

それではテストのフォームを作りながら、このGASの使用方法を説明していきます。

スポンサーリンク

テストのフォームとスプレッドシートを作る

フォーム

まず、以下のようなフォームを作ります。

とりあえずラジオボタンの質問を作ってください。
質問選択肢説明で覚えてください。

スプレッドシート

フォームをスプレッドシートにリンクしてください。

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

フォームの質問
フォームの選択肢
フォームの説明
参照セル~ゼロ"0"より大きい任意の数値

は、フォームと同じにしてください

GAS

次にフォームからGAS(updateItems)を登録します。

次のGASをフォームのエディタにコピペしてください。

  1. function updateItems(SheetNo){
  2.   //アクティブフォーム
  3.   const form = FormApp.getActiveForm();
  4.   //選択肢シート:SheetNoは必要なら変更する(一番左のシートが0、2番目が1、3番目が2、、、)
  5.   if(!(SheetNo>1)) SheetNo = 1;
  6.   const itemsSheet = SpreadsheetApp.openById(form.getDestinationId()).getSheets()[SheetNo];
  7.   //シートの選択肢、説明などを配列で取得する
  8.   const lastRow = itemsSheet.getLastRow();
  9.   const itemsList = itemsSheet.getRange(1,1,lastRow,3).getDisplayValues();
  10.   //
  11.   let newItems = [];
  12.   let count = 0;
  13.   //説明1を取得
  14.   let helpText = itemsList[0][1];
  15.   for (let i = 1; i < lastRow; i++) {
  16.     //参照セルがゼロでない選択肢を取得する
  17.     if (itemsList[i][2] > 0) {
  18.       newItems[count++] = itemsList[i][0];
  19.     }
  20.     // 追加の説明2〜を取得する
  21.     if (itemsList[i][1] != "") {
  22.       helpText += "\n" + itemsList[i][1];
  23.     }
  24.   }
  25.   if (count > 0) {
  26.     //フォームの質問、説明、選択肢などの取得
  27.     const items = form.getItems();
  28.     for (let i = 0; i < items.length; i++) {
  29.       //対象の質問を探して見つけたら、、、
  30.       if (items[i].getTitle() === itemsList[0][0]) {
  31.         //選択肢のタイプを選んで、、、(ラジオボタン or プルダウン or チェックボックス)
  32.         switch (items[i].getType()) {
  33.           //ラジオボタンの選択肢を更新する
  34.           case FormApp.ItemType.MULTIPLE_CHOICE:
  35.             items[i].asMultipleChoiceItem().setChoiceValues(newItems); break;
  36.           //プルダウンの選択肢を更新する
  37.           case FormApp.ItemType.LIST:
  38.             items[i].asListItem().setChoiceValues(newItems); break;
  39.           //チェックボックスの選択肢を更新する
  40.           case FormApp.ItemType.CHECKBOX:
  41.             items[i].asCheckboxItem().setChoiceValues(newItems); break;
  42.         }
  43.         //説明を更新する
  44.         items[i].setHelpText(helpText); break;
  45.       }
  46.     }
  47.   }
  48.   //選択肢の参照セルが全てゼロなので回答受付終了
  49.   else {
  50.     if(form.isAcceptingResponses()) { //UpdateItemsを複数同時に使うための対策
  51.       form.setAcceptingResponses(false);
  52.       //回答受付終了をメールで知らせる
  53.       const formName = form.getTitle();
  54.       const formUrl = form.getEditUrl() + "#responses";
  55.       const mailAdd = Session.getActiveUser();
  56.       const title = "フォーム<" + formName + ">が受付終了になりました。";
  57.       const text = "フォーム<" + formName + ">が受付終了になりました。\n" + formUrl;
  58.       //メールを送る
  59.       GmailApp.sendEmail(mailAdd, title, text);
  60.     }
  61.   }
  62. } //Ver1.4.5 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は単純にフォーム全体の回答者数に制限が設けられます。さらに、返信メールにも対応していますので、簡単なフォームであればこれで十分かもしれません。

おわりに

GASで複雑な処理を行うスクリプトを組むと、様々なフォームに応用させるのが難しくなります。GASの処理は単純で、スプレッドシートの関数で応用できるのが私の好みです。フォームに自分のアイデアを採用するためテストする時、関数はトライ&エラーが簡単ですからね。
ちなみに今(執筆時)、選択肢の項目に残数を表示する方法を思いついたので試しています。(済)

以上、このGASが皆様のフォームの開発に役立つことを願いまして、それではまた。

追記、google公式サイトのApps Scriptリファレンスを見ていると、今まで見落としていたgetTypeを見つけました。

これで、ラジオボタンとプルダウンを自動で区別できるようになりました。よかったよかった^o^(Ver.1.3.0)
追記、チェックボックスへの対応も問題ないことが分かりましたので、GAS(updateItems)へチェックボックスも追加しました。(Ver.1.4.0)
追記、UpdateItemsの複数同時使用に対して、複数の終了メールに対策しました。(Ver.1.4.5)

バグ等ありましたら、お知らせいただくと幸いです。

コメント

  1. 定員を設定したセミナー時間選択肢を作りたい より:

    役に立つ情報ありがとうございます。
    この様なスクリプトを探していました。

    しかし、コピペで使用してみましたが、
    「構文エラー: SyntaxError: Invalid or unexpected token 行: 21 ファイル: コード.gs」
    と出てスクリプトが保存出来ず、以降の作業もできません。
    ご指示していただければ幸いです、よろしくお願い致します。

    • Kasuga Kasuga より:

      ご報告をありがとうございます。
      昨日にリクエストでこのUpdateItemsに少し機能追加を行いました。
      そのときにコードをHTMLに変換する際に、ダブルクォーテーション(“”)が正しく変換されなかったようです。^^;
      修正し確認をしましたので大丈夫かと思います。再度お試しください。
      ご迷惑をお掛けしました。

    • 定員を設定したセミナー時間選択肢を作りたい より:

      早速のご対応ありがとうございます。
      無事テストまでたどり着けました。
      同様にして選択肢が削除されるところまでは出来ました。

      しかし、応用編の様に関数を使用すると、スプレッドシート上で関数エラーが出てしまいます。
      他の応用編2~の関数もコピペしてみましたが同様です。
      対応策あるでしょうか?御教授ください。

      • Kasuga Kasuga より:

        度々のバグのご指摘に感謝いたします。
        原因は半角の”が全角に変換されていることで私の一方的なミスです。
        これはWordPressの仕様なので強制的にこの機能を止めていたのですが、少し前のテーマの変更でこの操作が無効になっていました。
        また操作を加えましたので、全角変換は行われないはずです。
        ご迷惑をお掛けしました。
        お手数ですが、また何か問題が見つかりましたらお知らせください。

        • 定員を設定したセミナー時間選択肢を作りたい より:

          何度もご対応ありがとうございます。
          素人な物で半角全角に違いに気づかずコピペのみで作業していました。
          おかげさまで無事動作確認も取れ、本番使用したいフォームにも組み込むことができました。
          この度はありがとうございました。

  2. 川村 より:

    お世話になります。
    GASは意味も分からず、WEBにあるものをコピペして使用している程度です。
    今回も検索をして貴サイトにたどり着きました。

    私がやりたいことは、ほぼ「応用例その7」と同じもので、
    注文数をプルダウンから選択するのではなく、
    注文数を数値で入力するものを作成しようと思っております。

    まずは、作例そのままでやってみようと思い手順通り進めましたが、
    すべての応用例で使用している「updateItems」がエラーになってしまいます。

    TypeError: Cannot read properties of null (reading ‘getDestinationId’)
    updateItems @ コード.gs:6

    デバックをすると6行目で止まってしまいます。
    何度かチャレンジしましたが、全く同じで解決できませんでした。
    コピペしたのはVer1.4.5です。

    大変恐縮ですが、何が原因か、また解決方法等お分かりになりましたらご教示願えますでしょうか。
    よろしくお願いいたします。

    • Kasuga Kasuga より:

      まずはGASの初心者にも関わらず当記事を試してくださりありがとうございます。
      応用例その7は少し複雑なUpdateItemsの使用例なので混乱させてしまったかもしれませんね。
      もう少し簡単な説明ができないものかと少しづつ加筆していますが、なにしろエンジニア脳なもので・・・。

      さてご質問の件ですが、GoogleフォームのスクリプトエディタでUpdateItemsをコピペした後、
      function myFunction() {
      updateItems(1);
      updateItems(2);
      }
      をUpdateItemsの後に追加されたでしょうか?
      エディタから実行テストするのでしたら、このmyFunctionを実行してください。
      またトリガーに追加するのもUpdateItemsでなくmyFunctionですのでお間違えがないでしょうか?
      この点を間違えてなくまだエラーが出るようでしたら、再度ご連絡をお願いします。

      追記ですが、このUpdateItemsは、プルダウン、ラジオボタン、チェックボックスに対応しますので「注文数を数値で入力」は対象外となっております。ご了承くださいませ。

  3. 川村 より:

    早速のご回答ありがとうございます。
    最終的にやりたいのは「応用例その7」に近いものですが、
    とりあえず、このページの例をそのままやってみておりました。

    あらためてやってみましたら、うまく動作いたしました!
    もしかすると、今までトリガーの設定で
    「イベントの種類を選択」で「フォーム送信時」にせず
    「起動時」のままにしていたかもしれません。
    お騒がせいたしました。

    とりあえず、練習(勉強)のため作例通りに作成してみて
    いずれ「応用例その7」にもチャレンジしてみようと思っております。

    このようなサイトを公開していただき、感謝しております。
    ありがとうございました。

    • Kasuga Kasuga より:

      無事に動作したようで何よりです。
      私のスクリプトを使ってのGoogleフォームの開発は、GASの勉強よりシートの関数の勉強になるとは思いますが、頑張ってください。

  4. 川村 より:

    ありがとうございました。
    また、わからないところがありましたら、
    ご教示、よろしくお願いいたします。

  5. 西村 より:

    お世話になります。
    GASは意味も分からず、WEBにあるものをコピペして使用している理解度の者です。
    この度、急遽仕事でこのようなフォームの作成が必要でこの方法を探していました。
    大変助かりました。ありがとうございます。
    ただ、一つだけご教授いただけたらと思いましてコメントさせていただきます。
    今回、応用例その7を使わさせていただく予定なのですが、フォームの設定で「回答を1回に制限する」をチェックしますと、フォームからのデータがスプレットシートに反映されないということを確認しました。
    同一者からの2重送信を防ぐためにも設定したいのですが、どうすれば宜しいでしょうか?
    何卒よろしくお願いします。

    • Kasuga Kasuga より:

      当ブログをご覧いただきありがとうございます。
      まず最初に確認したいのですが、「回答を1回に制限する」を使用すると、フォームの回答者がGoogleアカウント所有者であることが必要です。
      もしフォームから回答が不特定多数になるのでしたらこの機能を使うことは現実的ではありません。
      また、Googleアカウント所有者であれば、必ずスプレッドシートに回答は記録されます。確実にフォームとスプレッドシートがリンクされているでしょうか?
      今一度ご確認いただけたらと思います。

  6. パ宮崎 より:

    お世話になっております。

    本記事を参考にフォーム作成を試みております。
    定員に達したら選択肢が消えるところまでは再現できたのですが、
    とある選択肢が消えると他の選択肢に設定した指定のセクションに飛ばす設定が消えてしまいます。

    本件いかように対応したらよろしいでしょうか。
    ご教示いただけますと幸いです。 
    どうぞよろしくお願いします。

    • Kasuga Kasuga より:

      当ブログをご覧いただきありがとうございます。
      セクションをご利用のフォームの質問に当スクリプトをお使いになるとは、勇者ですね。

      簡単なフォームでテストしてみましたが、なるほど確かに選択肢が消えると、セクションへのルートもなくなりますね。
      これは当たり前で、このスクリプトは、シートの情報で選択肢を更新することを送信毎に行っています。
      ですので、選択肢に付けたセクションへの移動情報が消されてしまいます。
      対応方法は、大幅なスクリプトの書き直しになりますし、今考えただけでは汎用性のある方法が思いつきません。
      申し訳ありませんが、選択肢にセクションの移動が付いた場合は、非対応とさせていただきます。
      貴重な情報をいただきありがとうございました。

      • パ宮崎 より:

        ご回答いただき、ありがとうございました。
        質問方法を変えることで対応することができました。

        初めてこういったコードなるものを触る機会でしたが、大変面白かったです。
        貴殿のブログに出会えて良かったです。

        • Kasuga Kasuga より:

          こちらこそ、久しぶりにGASに触れて楽しかったです。
          また何かお気付きになりましたら、お知らせください。

タイトルとURLをコピーしました