10分で定員付きの Google フォームを作ろう<コピペ可>
投稿: 2021年9月16日 (最終更新: 2023年12月10日) • 12 分 で読了 • 5,971 語定員に達したらフォームを閉じるだけじゃない
Google フォームで、「先着何人」というフォームを作りたい場面で使えるプログラムを作りました。
定員付きのフォームの作り方は他のサイトでも紹介されていますが、私が作ったものは、
といった特徴があり、非常に便利なものになっています。
では、早速作っていきましょう!
まずは、Google フォーム を開いてください。
フォームは、既存のものでも、新規のものでも構いません。
この記事では、適当に作ったこのフォームを使って説明していきます。
ただし、いくつか設定して欲しい箇所があります。
まず、上のバーより「回答」をクリックしてください。
次に、「回答を受付中」の右のスイッチをクリックし、「回答を受け付けていません」の状態にしてください。
そして、「回答者へのメッセージ」と書いてある下のテキストボックスに、任意のメッセージを入力してください。これは、定員に達してフォームの受付が終了した際に、ユーザーに表示されるものです(下の画像を参照)。
回答者へのメッセージを入力し終えたら、必要に応じて「回答を受け付けていません」の右のスイッチをクリックして「回答を受付中」に戻してください。
それでは、2番の設定を始めます。
上のバーから「設定」をクリックしてください。
その後、「別の回答を送信するためのリンクを表示」をオフ、もしくは「回答を1回に制限する」をオンにします。
後者はGoogleアカウントを使用して回答を1回に制限するため、回答者が Google アカウントを所持している必要があります。そのため、学校や会社などで Google Workspaces を利用している場合などに最適です。
一方、前者は厳格に回答を1回に制限することはできないものの、Google アカウントへのログインが必要ありません。
以下の手順に従って、どちらか一方、もしくは両方の設定を行ってください。
設定画面を開いたら、表示設定>「別の回答を送信するためのリンクを表示」の右側のスイッチをオフ のように操作してください。
設定画面を開いたら、回答>「回答を 1 回に制限する」の右側のスイッチをオフ のように操作してください。
これら以外の設定は、ご自由にどうぞ。
まず、右上の縦に3つ並んでいるドットをクリックし、「スクリプトエディタ」をクリックしてください。
※「現在、ファイルを開くことができません。」と表示された場合は、一旦ログインしているすべての Google アカウントからログアウトし、その後フォームを作成した Google アカウントだけログインし直してみてください。
このような画面が表示されたら、すでに記述されているもの(function myFunction() { ~
の部分)をすべて消してください。
その後、以下のコードをすべてコピペしてください。
`use strict`
const propaty_display_limit = PropertiesService.getScriptProperties().getProperty("DISPLAY_LIMIT");
const propaty_max = Math.floor(PropertiesService.getScriptProperties().getProperty("MAX"));
const propaty_old = PropertiesService.getScriptProperties().getProperty("old");
let LIMIT_COUNT = propaty_max || propaty_max === 0 ? propaty_max : 5;//定員
let old_dis = propaty_old ? propaty_old : "";//古い定員の残り人数通知
let display_limit = Math.floor(propaty_display_limit || propaty_display_limit === 0 ? formatLimit(propaty_display_limit) : -1);//残りの枠を表示するしきい値
const kaigyo = "\n\n---------------------------------\n\n";//残り枠数のあとに追加される文字列
function endFormCheck(changed) {
const form = FormApp.getActiveForm();//アクティブなフォーム
const remaining = LIMIT_COUNT - form.getResponses().length;//残り人数
const displayRemaining = remaining < 0 ? 0 : remaining;//残り人数が負の場合は0にする
if ((display_limit === -1 || remaining <= display_limit) && Number(display_limit !== 0)) {
const description = `定員${LIMIT_COUNT}名のところ、これまでに${form.getResponses().length}名が申し込みました。\n残りは${displayRemaining}枠です。` + (remaining < 0 ? `(超過${form.getResponses().length - LIMIT_COUNT})` : "");//定員があと何人か
if (old_dis && form.getDescription().indexOf(old_dis) !== -1) {
form.setDescription(form.getDescription().replace(old_dis, description));//概要文を書き換え
} else {
form.setDescription(description + kaigyo + form.getDescription());//新規
}
PropertiesService.getScriptProperties().setProperty("old", description);
} else if (old_dis && form.getDescription().indexOf(old_dis) !== -1) {
form.setDescription(form.getDescription().replace(old_dis + kaigyo, ""));//概要文を書き換え
}
if (form.getResponses().length >= LIMIT_COUNT) {
if (changed === "changed" && form.isAcceptingResponses()) {
FormApp.getUi().alert(`回答を締め切りました。\n現在の定員は${LIMIT_COUNT}名です`);//定員の変更によってフォームが閉鎖された場合に、ポップアップで通知
}
form.setAcceptingResponses(false);
} else if (changed === "changed") {
if (!form.isAcceptingResponses()) {
/* 定員に余裕がある場合には、回答の収集を再開することを提案 */
const ui = FormApp.getUi();
const alert = ui.alert("回答の収集を再開", `回答の収集を再開しますか?\n現在の定員は${LIMIT_COUNT}人、残りは${remaining}枠です。`, ui.ButtonSet.YES_NO);
if (alert === ui.Button.YES) {
form.setAcceptingResponses(true);
}
} else if ((display_limit !== -1 && remaining > display_limit) || display_limit === 0) {
/*フォームの説明欄に残りの人数が記述されない場合は、ポップアップでお知らせ*/
FormApp.getUi().alert(`定員${LIMIT_COUNT}名\n残り${LIMIT_COUNT - form.getResponses().length}枠`);
}
}
}
function onOpen() {
const ui = FormApp.getUi(); // Uiクラスを取得する
const menu = ui.createMenu('定員制御'); // Uiクラスからメニューを作成する
menu.addItem('定員を変更', 'setMax'); // メニューにアイテムを追加する
menu.addItem('残りの枠数を表示するしきい値を変更', 'setDisplayLimit');
menu.addItem('最新の状態に更新', 'refresh'); // メニューにアイテムを追加する
menu.addToUi();// メニューをUiクラスに追加する
}
function refresh() {
endFormCheck("changed");//更新用
}
function setMax() {
/* 定員を変更 */
const form = FormApp.getActiveForm();//アクティブなフォーム
const ui = FormApp.getUi();
const title = '定員の設定';
const body = `半角数字で定員を入力してください。\n現在の定員は${LIMIT_COUNT}人で、残りは${LIMIT_COUNT - form.getResponses().length}枠です。`
const prompt = ui.prompt(title, body, ui.ButtonSet.OK_CANCEL);//プロンプトを表示
const text = prompt.getResponseText();
if (prompt.getSelectedButton() === ui.Button.OK) {
if (!isNaN(text) && Number(text) >= 0) {
/*数字であることが確認された場合の処理*/
if (!text) return;//空欄だった場合
LIMIT_COUNT = Math.floor(Number(text));
PropertiesService.getScriptProperties().setProperty("MAX", Math.floor(Number(text)));
display_limit = Math.floor(propaty_display_limit || propaty_display_limit === 0 ? formatLimit(propaty_display_limit) : 0);
refresh();
return;
} else {
/* 数字じゃなかったら */
const ui2 = FormApp.getUi();
const title2 = 'むむ?';
const body2 = Number(text) < 0 ? '0以上の数を半角で入力してください。' : '半角数字で入力してください。'
const alert2 = ui2.alert(title2, body2, ui2.ButtonSet.OK);
if (alert2 === ui2.Button.OK) setMax();
}
}
}
function setDisplayLimit() {
/* しきい値を変更 */
const form = FormApp.getActiveForm();//アクティブなフォーム
const ui = FormApp.getUi();
const title = '残りの枠数を表示するしきい値を設定';
const body = `残りの枠数がいくつ以下になったら、回答者数・残りの枠数をフォームの概要文に表示するかを半角数字で入力してください。\n例)定員が100人で、残り5枠以下になったら残りの枠数をフォームの概要文に表示したい場合→「5」と入力する\n\nまた、残りの枠数が定員の○%以下になったら、というように設定することもできます。\n例)残りの枠数が定員の20%以下になったら残りの枠数をフォームの概要文に表示したい場合→「20%」と入力する\n\n概要文に常に残りの枠数を表示したい場合は、「-1」と入力してください。\n概要文に残りの枠数を表示させない場合は、「0」と入力してください。\n\n現在の設定は「${/%/.test(propaty_display_limit) ? propaty_display_limit : Math.floor(Number(propaty_display_limit))}」です。\n現在の定員は${LIMIT_COUNT}人、残りは${LIMIT_COUNT - form.getResponses().length}枠です。\n\n`;
const prompt = ui.prompt(title, body, ui.ButtonSet.OK_CANCEL);//プロンプトを表示
const text = prompt.getResponseText();
if (prompt.getSelectedButton() === ui.Button.OK) {
if (/%/.test(text)) {
const onlyNum = text.replace("%", "");
if (!isNaN(onlyNum) && Number(onlyNum) >= 0 && Number(onlyNum <= 100)) {
/*パーセントで入力された場合*/
if (!onlyNum) return;
display_limit = formatLimit(text);//しきい値を変更
PropertiesService.getScriptProperties().setProperty("DISPLAY_LIMIT", text);//しきい値を保存
refresh();
return
}
} else if (!isNaN(text) && Number(text) >= -1) {
if (!text) return;//空欄だった場合
display_limit = formatLimit(Number(text));
PropertiesService.getScriptProperties().setProperty("DISPLAY_LIMIT", Math.floor(Number(text)));
endFormCheck();
return;
} else {
/* 数字じゃなかったら */
const ui2 = FormApp.getUi();
const title2 = 'むむ?';
const body2 = "数字または割合(%)を半角で正確に入力してください。"
const alert2 = ui2.alert(title2, body2, ui2.ButtonSet.OK);
if (alert2 === ui2.Button.OK) setDisplayLimit();
}
}
}
function formatLimit(int) {
if (/%/.test(int)) {
/*%を実数に*/
return Math.floor(LIMIT_COUNT * (Number(int.replace("%", "")) / 100));
} else {
/*%でなければ、小数点以下を切り捨てて戻す*/
return Math.floor(int);
}
}
ついでにプロジェクトの名前も変えておきましょう。
左上の「無題のプロジェクト」と書いてある部分をクリックすると表示されるポップアップに、好きな名前を入力してください。
ここまで書いたら、保存してください。
「実行」や「デバッグ」などが並んでいる列のフロッピーディスクのアイコンが保存ボタンです。
キーボードの Ctrl+S でも保存できます。
プログラミングを勉強されている方のために、少し解説します。(とりあえずものが作れればいいという方は読み飛ばしてもらって結構です)
これは、Google Apps Scriptというものです。
JavaScript がベースになっており、Google の色々なサービスを(ときには外部サービスとも)連携させることができます。
このコードでは、フォームの回答数によって、残りの枠数を表示させたり、回答の収集を停止したりしています。
どのコードがどのような動作をしているかはコメントに書いておいたので、是非参考にしてみてください。
トリガーは、「動作を予約する」時に使う機能です。
上記のコードでは、フォームに新たな回答が来ても何も処理が行われないので、フォームに回答が届いたら、定員に達していないかの確認処理・概要文の更新処理を行うようにします。
左側のメニューから、「トリガー」をクリックしてください。
(カーソルを乗せるとメニューが広がります。)
画面が変わったら、右下の「トリガーを追加」をクリックしてください。
このとき、画面左下にこのようなポップアップが表示されたら、先程書いたプログラムが保存されていないということなので、青字の「保存」をクリックしてプログラムを保存してください。
実行する関数→ 「endFormCheck」
実行するデプロイ→「Head」
イベントのソース→「フォームから」
イベントの種類→「フォーム送信時」
を選んで、右下の「保存」をクリックしてください。
少し待つと Google アカウントのログイン画面が表示されます。
自分のアカウントをクリックしてください。
この画面が表示されたら、「許可」をクリックしてください。
「このアプリは確認されていません」との警告が出る場合がありますが、これは普通のことです。
私の環境では再現できなかったのですが(Google に開発者登録をしているからかも)、もしそのような警告が出た場合は、下のサイトの手順通りに対処してください。
※私のコードが信用できないという方は、「安全なページに戻る」をクリックしても構いません。
ここまで終えたら、フォームの編集画面を再読込してください。
すると、右上にパズルのピースのアイコンが表示されたと思います。
「定員付きフォーム」に関する設定は、パズルのアイコン>「定員制御」からすべて行えます。
設定画面はこんな感じです。
まず最初に、「定員を変更」をクリックしてください。
表示されたポップアップに、設定したい定員を半角数字で入力し、「OK」をクリックしてください。
次に、概要文に残りの枠数を表示させるかどうかの設定をします。
先程の設定画面から、「残りの枠数を表示するしきい値を変更」をクリックしてください。
このプログラムでは、フォームの概要文に「あと何枠です」というように表示させることができます。
しかし、あまり枠が埋まっていないことが分かると、申し込む気が失せてしまう人もいるかもしれません。
そこで、枠が残り少なくなってから、「あと何枠です」という表示を開始するように設定できます。
ここでは、「数」か「割合」で設定できます。
まずは、数の場合。これは単純で、「空きが何枠以下になったら、概要文への表示を開始する」ということです。
例えば、空きが10枠以下になったら概要文に「残り○枠です」と表示させたい場合は、ポップアップに「10」と入力してください。
次に、割合の場合。「空き枠が定員の何%以下になったら、概要分への表示を開始する」ということです。
例えば、定員が50人のフォームで、空きが定員の10%の5人以下になった場合に「残り○枠です」と概要文に表示させたい場合は、ポップアップに「10%」と入力してください。
最後に、特殊な場合です。
常に残りの枠数を表示させたい場合は「-1」を、申込数に問わず残りの枠数を表示させたくない場合は「0」を入力してください。
入力し終えたら、「OK」をクリックしてください。もし、「むむ?」という警告が表示された場合は、その数字またはパーセンテージが有効ではないため、「半角で」入力し直してください。
一度設定した内容を変更したい場合も、上記と同じ手順で行えます。
久しぶりのGASだったので色々調べながらの開発でしたが、楽しかったです。
本日紹介したコードは報告不要・クレジット表記不要・商用利用可で使っていただいて構いません。
コードはGitHubでも公開しているので、Star、Issue、プルリク等していただけると幸いです。
関連記事
2021年9月9日 • 4 分 で読了
Google ドライブの動画が再生できないときの対処法
原因は、Chrome のアレ
2021年8月7日 • 3 分 で読了
Chrome 拡張機能を作って公開しよう⑤ 〜権限多すぎ問題を解決〜
1回15分でサクッと開発。今回は「権限多すぎ問題」を解決していきます。
2021年8月4日 • 14 分 で読了
Chrome 拡張機能を作って公開しよう④ 〜コピー機能の実装〜
1回30分でサクッと開発。要となるコピー機能の実装を行います
2021年8月3日 • 6 分 で読了
Chrome 拡張機能を作って公開しよう③ 〜形にする〜
1回15分でサクッと開発。いよいよ形にしていきます!
2021年8月2日 • 5 分 で読了
Chrome 拡張機能を作って公開しよう② 〜ポップアップの作成〜
1回15分でサクッと開発。今回はポップアップの作成。