質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google フォーム

Google フォームは、 Google社が提供しているアンケートフォーム作成および集計ができる無料のツール。Googleアカウントがあれば利用が可能です。集計データは、スプレッドシートに収集され、データ分析もできます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1148閲覧

Googleフォームのチェックボックスの集計をGASで行いたい

gretsch

総合スコア1

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google フォーム

Google フォームは、 Google社が提供しているアンケートフォーム作成および集計ができる無料のツール。Googleアカウントがあれば利用が可能です。集計データは、スプレッドシートに収集され、データ分析もできます。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

0クリップ

投稿2022/12/27 10:28

編集2022/12/28 09:15

前提

イベントの申し込みフォームをGoogleフォームを使用して作成したいと考えています。
そこで、Googleフォームのチェックボックスの集計をGASで行いたいのですが、方法が分かりません。
ネットで見つけたサイト様のコードが大変参考になったので、そのコードを参考に試行錯誤しており、そのコード内ではラジオボタンの集計が実装されています。
その集計部分をラジオボタンのコードからチェックボックス向けに変更すれば良いとは思うのですが、実際にはチェックボックスが複数選択された場合などもあり、どこを修正してよいかわかりません。

ちなみに、プログラミングについての知識は乏しく、業務の一環として今回このようなプログラミングを行うことになり期限も迫っているため困っています。

実現したいこと

ここに実現したいことを箇条書きで書いてください。

  • ▲▲機能を動作するようにする

イベントの日程(2日間)について参加申し込みを募り、それぞれの日で50名に達したところで申し込みフォームの当該日の選択をできないようにしたいです。
その際、申し込みフォーム上に、残り人数を表示させたいです。
なお、両日参加の方を想定して、両方の日を選択できるようにしたいです。

該当のソースコード

Google

1const form = FormApp.getActiveForm(); 2const spreadSheet = SpreadsheetApp.openById("*************************"); 3const reserveSheet = spreadSheet.getSheetByName("予約"); 4const listSheet = spreadSheet.getSheetByName("日程"); 5 6// *--------------------* 7// フォーム送信時の処理 8// *--------------------* 9function receivedApplication(e) { 10 11 // フォームの送信内容 12 const email = e.response.getRespondentEmail(); 13 const items = e.response.getItemResponses(); 14 const preferredDate = ( items[0].getItem().getTitle() === "参加希望日" ? items[0].getResponse() : "" ); 15 let result = ""; 16 17 if ( preferredDate ){ 18 // 日程シートチェック&更新 19 result = checkAvailability(preferredDate); 20 // 予約シートに申込内容を書き込み 21 if ( result = "OK" ){ reserveSheet.appendRow([email, preferredDate]); } 22 // フォームを更新 23 editForm(); 24 } else { 25 result = "NG"; 26 } 27 28 // メール送信 29 sendEmail(email, preferredDate, result); 30 31} 32 33// *---------------------* 34// 予約状況をチェックする 35// *---------------------* 36function checkAvailability(preferredDate){ 37 38 // 日程シートを配列に格納 39 const list = listSheet.getDataRange().getValues(); 40 list.shift(); 41 42 // リストから予約日を探し、定員を確認する 43 for ( let i = 0; i < list.length; i++ ){ 44 if ( list[i][0] == preferredDate ){ 45 // 予約済 < 定員であればOK 46 if ( list[i][2] < list[i][1] ){ 47 listSheet.getRange(i + 2, 3).setValue( list[i][2] + 1); 48 return "OK"; 49 } else { 50 return "NG"; 51 } 52 } 53 } 54 55 // 希望日がリストに存在しなかった場合はNG 56 return "NG"; 57 58} 59 60// *----------------------* 61// 予約結果をメール送信する 62// *----------------------* 63function sendEmail(email, preferredDate, result){ 64 65 const mailTitle = "予約結果について"; 66 let mailBody; 67 68 if ( result == "OK" ){ 69 mailBody = "予約が完了しました。\n" 70 + `予約日:${preferredDate}` 71 } else { 72 mailBody = "定員超過のため予約できませんでした。\n" 73 + "下記のフォームから再度申請してください\n" 74 + form.getPublishedUrl(); 75 } 76 77 // 結果メール送信 78 GmailApp.sendEmail(email, mailTitle, mailBody); 79 80} 81 82// *-----------------* 83// フォームを更新する 84// *-----------------* 85function editForm(){ 86 87 let infoText = ""; // 「空き状況」部分のテキスト 88 let choiceValues = []; // 「参加希望日」部分の選択肢 89 90 // 日程シートを配列に格納 91 const list = listSheet.getDataRange().getValues(); 92 list.shift(); 93 94 // 日程シートのデータからフォームの内容を作成する 95 for ( const record of list ){ 96 if ( record[2] < record[1] ){ 97 // 空きがある日程は「空き状況」に記載+選択肢として設定 98 infoText += `${record[0]} : 残り ${record[1] - record[2]} 名\n`; 99 choiceValues.push(record[0]); 100 } else { 101 // 空きがない日程は「空き状況」に満員を記載+選択肢にはしない 102 infoText += `${record[0]} : 満員(申込不可)\n`; 103 } 104 } 105 106 // 選択肢が1つもない場合、選択肢は「全日程申込不可」としフォームをクローズ 107 if ( !choiceValues.length ) { 108 choiceValues.push("全日程申込不可"); 109 form.setAcceptingResponses(false); 110 } 111 112 // フォームに変更を反映 113 const items = form.getItems(); 114 items[0].setHelpText(infoText); 115 items[1].asMultipleChoiceItem().setChoiceValues(choiceValues); 116 117} 118

試したこと

115行目の asMultipleChoiceItem は asCheckboxItem にすべきだとは思うのですが、それ以外どこを修正すべきかわからずにいます。

どうぞよろしくお願いいたします。

gretsch👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/12/27 16:25 編集

ひとまず、上記のコードおよびシート周りで、チェックボックスに改造する前の「ラジオボタンバージョン」を自分で組まれたうえで、定員オーバーの場合も含めて正常に動作していることは確認されていますか? ・「イベントの日程(2日間)について参加申し込みを募り」とのことですが、回答者が2日分にチェックを入れて申し込む(=回答ボタンを押す)直前で、その2日のうちいずれか1日が他の人の申し込みによって定員に達した場合、2日とも(=定員に達していない日も)予約しないのでしょうか? それとも、定員に達していない日は予約扱いとし、定員に達していた日だけ予約できなかった旨を案内するのでしょうか?
gretsch

2022/12/27 23:12 編集

アドバイスありがとうございます。 「ラジオボタンバージョン」は想定通りの動きをすることは確認できました。 予約時の挙動につきましては、  ・定員に達していない日は申し込み(予約)OKとし、残りのカウントを減らす  ・定員に達していた日だけ申し込み(予約)できなかった旨をメールで案内する ようにしたいと思っております。 よろしくお願いいたします。
guest

回答1

0

ベストアンサー

Google Form 上のスクリプトエディタに以下のコードを貼り付けて保存し、実行してください。

更に、サイドメニューの「トリガー」の設定から、

  • 実行する関数を選択
    • formStatusCheck
  • イベントのソースを選択
    • フォームから
  • イベントの種類を選択
    • フォーム送信時

として、トリガーを追加してください。

js

1function formStatusCheck() { 2 const form = FormApp.getActiveForm(); 3 const PARTICIPATE_QUESTION_ITEM_ID = 1234567890; 4 const CHOICE_VALUE = ['1日目に参加する', '2日目に参加する']; 5 const HELP_TEXT = ['1日目', '2日目']; 6 const LIMIT = 50; 7 8 // PARTICIPATE_QUESTION_ITEM_ID を調べる 9 function checkItemId() { 10 const questionItems = form.getItems(); 11 console.log('以下から該当する質問の ID をコピーしてください'); 12 for (questionItem of questionItems) { 13 console.log(questionItem.getTitle() + ": " + questionItem.getId()); 14 } 15 } 16 checkItemId(); 17 18 function aggregateAnswers() { 19 const result = {}; 20 for (day of CHOICE_VALUE) { 21 result[day] = 0; 22 } 23 24 // 回答者ごとの回答オブジェクトリスト 25 const responses = form.getResponses(); 26 for (const response of responses) { 27 // 一人の回答者の回答オブジェクトリスト 28 const answerItemResponses = response.getItemResponses(); 29 for (const answerItemResponse of answerItemResponses) { 30 const questionItem = answerItemResponse.getItem(); 31 // 参加日の選択に関する質問の回答情報 32 if (questionItem.getId() === PARTICIPATE_QUESTION_ITEM_ID) { 33 const answerDays = answerItemResponse.getResponse(); 34 for (const answerDay of answerDays) { 35 // 参加日の選択肢をカウントする 36 result[answerDay]++; 37 } 38 } 39 } 40 } 41 42 return result; 43 } 44 45 function updateQuestionItem(answerResult) { 46 const questionItem = form.getItemById(PARTICIPATE_QUESTION_ITEM_ID); 47 if (questionItem == null) return console.error('PARTICIPATE_QUESTION_ITEM_ID をセットしてください'); 48 49 const livingChoices = []; 50 let helpText = ''; 51 CHOICE_VALUE.forEach((day, idx) => { 52 const count = answerResult[day]; 53 const remaining = LIMIT - count; 54 if (helpText !== '') helpText += '、'; 55 helpText += `${HELP_TEXT[idx]}は「残り${remaining}人」`; 56 if (remaining > 0) livingChoices.push(day); 57 }); 58 helpText += 'の申し込み枠が残っています。'; 59 questionItem.setHelpText(helpText); 60 61 // 全ての参加日の参加枠が無くなった場合 62 if (livingChoices.length === 0) { 63 livingChoices.push('参加枠がありません'); 64 // フォームをクローズする 65 form.setAcceptingResponses(false); 66 } 67 questionItem.asCheckboxItem().setChoiceValues(livingChoices); 68 } 69 70 updateQuestionItem(aggregateAnswers()); 71}

投稿2022/12/27 16:45

arcxor

総合スコア2859

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gretsch

2022/12/28 01:49 編集

アドバイスありがとうございます。 提示いただいたコードをそのままGoogleフォームに貼り付けて、3行目のIDのみ変更して実行したところ、以下のエラーが出ました。 構文エラー: SyntaxError: Invalid or unexpected token 行: 3 ファイル: サンプル.gs そこで、IDをダブルクォーテーション”で括って実行したところ、次のエラーが出てしまいます。 エラー Exception: Cannot convert '**************************************' to int. updateQuestionItem @ サンプル.gs:46 formStatusCheck @ サンプル.gs:70 何が悪いのでしょうか。アドバイスいただけますと幸いです。 よろしくお願いいたします。
arcxor

2022/12/28 01:08

どのようなコードを書いたのでしょうか。
gretsch

2022/12/28 01:47

アドバイスいただいたコードをそのままスクリプトエディタに貼り付け、 3行目のID(1234567890)部分のみを、出力したいスプレッドシートのIDに書き換えました。 その状態でコードを実行しました。
arcxor

2022/12/28 01:59

3行目に書くべきはスプレッドシートのIDではありません。よく読んでください。
gretsch

2022/12/28 02:29

アドバイスありがとうございます。 もう一度読み直してチャレンジしてみます。
arcxor

2022/12/28 05:57

3行目のIDには、Google フォームで参加日を選ぶチェックボックスの質問項目を作成した上で、スクリプトエディタ編集画面から「実行」を押したときにログに出力される「質問アイテムのID(参加日を選ぶ質問のアイテムのもの)」を記述してみてください。整数10桁のIDになるはずです。
gretsch

2022/12/28 06:34

さらなるアドバイスをありがとうございます。 ご教示いただいたように、Googleフォームを作成したのち、スクリプトを実行するとconsole logに表示された10桁のIDを3行目の当該部分に上書きしますと、GoogleフォームのIDに該当する項目の表示が変わり、選択したチェックによりリミットの設定値になるまで使用でき、リミットに達した項目については非表示になることを確認することができました! 当初想定していました機能がこんなに早く実現できて、期日にも間に合い大変感謝しております。 改めてお礼申し上げます。 あとはこれにメール送信機能を実装したいと思います。 この度は本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問