体験会や説明会の申込をGoogleフォームで受けていると、回答は1枚のシートにどんどん溜まっていきます。
「10/20の参加者だけ見たい」と思うたびに、フィルタをかけたり、日程ごとのシートへ手でコピーしたりしていませんか。
この記事では、回答が届いた瞬間に、選ばれた日程と同じ名前のシートへ自動でコピーする仕組みを、コピペだけで作る方法を紹介します。
料金はかかりません(Googleの無料の機能だけで動きます)。
【できるようになること】
・フォームに回答が届くと、「参加希望日」で選ばれた日程のシート(例:10-20(月))に1行追加される
・新しい日程が選ばれたら、そのシートを見出し付きで自動で作る
・元の「フォームの回答 1」シートはそのまま残る(消えたり並び替わったりしない)
・今までの回答も、最初の1回でまとめて振り分ける
日程だけでなく、「コース」「店舗」「担当者」など、選択式の質問ならどれでも振り分けに使えます。
【用意するもの】
・Googleフォームと、その回答先のスプレッドシート(フォームの「回答」タブ →「スプレッドシートにリンク」で作れます)
・振り分けに使う質問(例:「参加希望日」)
【手順(10分ほど)】
1. 回答先のスプレッドシートを開き、メニューの「拡張機能」→「Apps Script」を開きます
2. 最初から書いてある文字を全部消して、下のコードを貼り付け、保存(フロッピーのマーク)します
3. コードの上の方にある SPLIT_HEADER = '参加希望日' の「参加希望日」を、フォームの質問のタイトルと一字一句同じに書き換えて、もう一度保存します
4. 上の関数の選択欄で「setup」を選び、「実行」を押します
5. 「承認が必要です」と出たら「権限を確認」→ 自分のアカウントを選ぶ →「詳細」→「(プロジェクト名)に移動」→「許可」
・自分で作ったスクリプトなので「Googleで確認されていません」と出ても問題ありません
6. スプレッドシートに戻ると、日程ごとのシートができています。以後は回答が届くたびに自動で追加されます
【コード】
/**
* Googleフォームの回答を、選んだ日程(または種類)ごとのシートへ自動で振り分ける
*
* 使い方
* 1. フォームの回答先スプレッドシートを開き、「拡張機能 > Apps Script」を開く
* 2. 最初からある文字を全部消して、このコードを貼り付けて保存
* 3. 下の SPLIT_HEADER を、振り分けに使う質問のタイトルと一字一句同じにする
* 4. 関数「setup」を選んで「実行」→ 画面の案内に沿って許可する(1回だけ)
* 以後、回答が届くたびに「回答の値」と同じ名前のシートへ1行ずつコピーされます。
* 元の「フォームの回答 1」シートはそのまま残ります。
*/
const SPLIT_HEADER = '参加希望日'; // 振り分けに使う質問のタイトル
const MAX_SHEET_NAME = 90; // シート名の長さの上限(Googleの上限は100文字)
/** 1回だけ実行:フォーム送信時に動くように設定し、今までの回答も振り分ける */
function setup() {
const ss = getSS_();
ScriptApp.getProjectTriggers()
.filter(t => t.getHandlerFunction() === 'onFormSubmitSplit')
.forEach(t => ScriptApp.deleteTrigger(t));
ScriptApp.newTrigger('onFormSubmitSplit').forSpreadsheet(ss).onFormSubmit().create();
rebuildAll();
}
/** フォーム送信時に自動で動く */
function onFormSubmitSplit(e) {
const row = e.range.getValues()[0];
const src = e.range.getSheet();
const header = src.getRange(1, 1, 1, src.getLastColumn()).getValues()[0];
appendTo_(header, row);
}
/** 今までの回答をすべて振り分け直す(各シートは作り直し) */
function rebuildAll() {
const src = responseSheet_();
const data = src.getDataRange().getValues();
if (data.length < 2) return;
const header = data[0];
const col = colOf_(header);
const groups = {};
data.slice(1).forEach(r => {
const name = sheetName_(r[col]);
if (!name) return;
(groups[name] = groups[name] || []).push(r);
});
const ss = getSS_();
Object.keys(groups).forEach(name => {
const sh = ss.getSheetByName(name) || ss.insertSheet(name);
sh.clear();
sh.getRange(1, 1, 1, header.length).setValues([header]).setFontWeight('bold');
sh.getRange(2, 1, groups[name].length, header.length).setValues(groups[name]);
});
}
function appendTo_(header, row) {
const name = sheetName_(row[colOf_(header)]);
if (!name) return;
const ss = getSS_();
let sh = ss.getSheetByName(name);
if (!sh) {
sh = ss.insertSheet(name);
sh.getRange(1, 1, 1, header.length).setValues([header]).setFontWeight('bold');
}
sh.appendRow(row);
}
function colOf_(header) {
const i = header.indexOf(SPLIT_HEADER);
if (i < 0) throw new Error(`「${SPLIT_HEADER}」という質問が見つかりません。SPLIT_HEADER をフォームの質問タイトルと同じにしてください。`);
return i;
}
/** シート名に使えない文字を置き換える(日付の回答は「2026-10-20」の形に) */
function sheetName_(v) {
if (v instanceof Date) v = Utilities.formatDate(v, Session.getScriptTimeZone(), 'yyyy-MM-dd');
const s = String(v == null ? '' : v).trim().replace(/[\[\]\*\?\/\\:]/g, '-');
return s.slice(0, MAX_SHEET_NAME);
}
function responseSheet_() {
const ss = getSS_();
return ss.getSheets().find(sh => sh.getFormUrl()) || ss.getSheets()[0];
}
/** 回答先のスプレッドシート(スクリプトをシートから開いた場合はそのシート) */
function getSS_() {
return SpreadsheetApp.getActiveSpreadsheet()
|| SpreadsheetApp.openById(PropertiesService.getScriptProperties().getProperty('SHEET_ID'));
}
【うまく動かないとき】
・「〇〇という質問が見つかりません」と出る:SPLIT_HEADER の文字が、回答シート1行目の見出しと違っています(全角・半角、空白も含めて同じにしてください)
・シートが増えない:手順4の「setup」を実行したか確認してください。フォームの設定で回答先が別のシートになっていないかも確認を
・やり直したい:関数「rebuildAll」を実行すると、日程ごとのシートを作り直します
【自分で設定するのが大変なときは】
「メールで担当者に知らせたい」「定員を超えたら受付を止めたい」など、お店や教室に合わせた形での作成は、こちらのサービスで承っています。お名前などの個人情報は「〇〇」に置き換えた見本で大丈夫です。
▶ Googleフォームの回答をGASで自動集計します(回答のたびにメール通知)