GASでGoogleフォームの回答を自動処理する方法10選|業務時間を月30時間削減する方法
2026年4月
目次
- GASでGoogleフォーム回答を自動処理すべき理由
- GAS連携の事前準備と基本設定
- 方法1:回答をSlack・Chatworkに即時通知する
- 方法2:スプレッドシートに自動整形して転記する
- 方法3:回答者に自動返信メールを送る
- 方法4:条件分岐で担当者に振り分け通知する
- 方法5:回答データをGoogleカレンダーに自動登録する
- 方法6:重複回答を自動チェック・除外する
- 方法7:回答内容からPDFを自動生成する
- 方法8:Googleドライブにファイルを自動保存する
- 方法9:回答データを集計してダッシュボードを自動更新する
- 方法10:外部API連携で他システムに自動データ送信する
- GAS自動処理で失敗しないための3つの注意点
Googleフォームは無料で使えるアンケート・申込みツールとして、多くの企業で使われています。しかし、フォームの回答が溜まっていくだけで、手動でスプレッドシートを開いて確認し、転記し、返信している方も多いのではないでしょうか。
回答が1日に数件程度なら問題ないかもしれません。しかし、月に100件、200件と増えてくると、確認・転記・返信だけで月に20時間以上を費やしている計算になります。これは明らかに人がやるべき仕事ではありません。
Google Apps Script(GAS)を使えば、Googleフォームの回答データを自動で処理できます。プログラミング未経験でも、Googleアカウントさえあれば無料で始められるのがGASの強みです。
この記事では、GASでGoogleフォームの回答を自動処理する具体的な方法を10個、コード付きで解説します。すべて実務で使える内容に絞っていますので、自社の業務に合うものから試してみてください。
GASでGoogleフォーム回答を自動処理すべき理由
Googleフォームの回答処理を手動で行うと、以下のような作業が繰り返し発生します。
- スプレッドシートを開いて新着回答を目視で確認する
- 回答内容を別のシートや社内システムにコピー&ペーストする
- 回答者にお礼や確認のメールを手動で送る
- 内容に応じて担当者に手動で転送する
- 回答データを集計し、報告用資料にまとめる
これらの作業を1件あたり5分としても、月100件の回答で500分(約8時間)が消えます。回答数が増えるほど、この時間は線形に増加していきます。
GASを使えば、これらの作業を「フォーム送信」のタイミングで自動実行できます。GASにはフォーム送信をトリガーにして関数を実行する仕組み(onFormSubmitトリガー)があり、回答が届いた瞬間に処理が走ります。
GASを選ぶ3つの技術的な理由
業務自動化のツールは他にもありますが、Googleフォームの回答処理についてはGASが最適解になるケースが大半です。
第一に、Googleフォームとの親和性です。GASはGoogle Workspace内のサービスとネイティブに連携するため、フォームの回答データに直接アクセスできます。外部ツールのようにAPI認証の設定やWebhookの構築が不要で、数行のコードで回答データを取得できます。
第二に、コストです。GASはGoogleアカウントがあれば無料で利用できます。外部の自動化ツール(Zapierなど)を使う場合、月額数千円から数万円のコストが発生しますが、GASならゼロです。
第三に、カスタマイズ性です。ノーコードツールでは「あと一歩」のところで手が届かないケースがありますが、GASはJavaScriptベースのスクリプト言語なので、条件分岐やループ、外部API連携など、自由度の高い処理が可能です。
GAS連携の事前準備と基本設定
10の方法を試す前に、共通の準備を済ませておきましょう。所要時間は5分程度です。
この領域でつまずきやすいのは、ツール選定よりも「業務の中のどこに組み込むか」の設計です。BoostXの業務自動化サービスは、業務ヒアリングから設計・定着支援までをサービス対応範囲としてカバーできる領域です。
スクリプトエディタを開く
Googleフォームの編集画面から、右上の三点メニューをクリックし「スクリプトエディタ」を選択します。これでApps Scriptの編集画面が開きます。
なお、Googleスプレッドシート側の「拡張機能」メニューからもスクリプトエディタを開けますが、フォーム送信トリガーを使う場合はフォーム側から開く方が設定がスムーズです。
onFormSubmitトリガーの設定方法
スクリプトエディタ左側の時計アイコン(トリガー)をクリックし、「トリガーを追加」を選択します。以下の設定で保存してください。
- 実行する関数:自分が作成した関数名(例:onFormSubmit)
- イベントのソース:「フォームから」を選択
- イベントの種類:「フォーム送信時」を選択
初回のトリガー設定時にGoogleアカウントの認証許可を求められます。「詳細」をクリックしてから「(プロジェクト名)に移動」をクリックし、必要な権限を許可してください。
イベントオブジェクトの基本構造
フォーム送信時にトリガーされる関数には、引数としてイベントオブジェクト(e)が渡されます。このオブジェクトから回答データにアクセスします。
function onFormSubmit(e) {
// フォームの回答を取得
var responses = e.response.getItemResponses();
// 各項目の回答をループで取得
for (var i = 0; i < responses.length; i++) {
var question = responses[i].getItem().getTitle();
var answer = responses[i].getResponse();
Logger.log(question + ': ' + answer);
}
}
スプレッドシート側のonFormSubmitトリガーを使う場合は、e.namedValuesでカラム名をキーにした連想配列として回答データを取得できます。用途に応じて使い分けてください。
方法1:回答をSlack・Chatworkに即時通知する
フォームの回答が届いたらすぐに知りたい、という場面は多くあります。問い合わせフォーム、採用エントリー、クレーム報告など、対応スピードが求められるフォームは特にそうです。
GASを使えば、フォーム送信の瞬間にSlackやChatworkに通知を飛ばせます。メールでの通知と違い、チャットツールならチーム全員がリアルタイムで確認できます。
Slack通知のコード例
function notifySlack(e) {
var webhookUrl = 'https://hooks.slack.com/services/XXXXX/XXXXX/XXXXX';
var responses = e.response.getItemResponses();
var message = '--- 新しいフォーム回答 ---\n';
for (var i = 0; i < responses.length; i++) {
message += responses[i].getItem().getTitle() + ': '
+ responses[i].getResponse() + '\n';
}
var options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ text: message })
};
UrlFetchApp.fetch(webhookUrl, options);
}
Slack Incoming Webhookの設定は、Slackの「App管理」画面から「Incoming Webhooks」アプリを追加し、投稿先チャンネルを指定するだけで完了します。取得したWebhook URLをコード内のwebhookUrl変数に設定してください。
Chatwork通知への応用
Chatworkの場合は、APIトークンとルームIDを使ってメッセージを送信します。UrlFetchAppのURLをChatwork APIのエンドポイント(https://api.chatwork.com/v2/rooms/{ルームID}/messages)に変更し、ヘッダーにX-ChatWorkTokenを追加するだけで対応できます。
方法2:スプレッドシートに自動整形して転記する
Googleフォームの回答は自動的にスプレッドシートに記録されますが、そのままでは使いにくいケースがあります。たとえば、日付のフォーマットを統一したい、姓名を結合したい、別シートの管理台帳に転記したい、といった場合です。
function formatAndTransfer(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var targetSheet = ss.getSheetByName('管理台帳');
var values = e.namedValues;
var name = values['姓'][0] + ' ' + values['名'][0];
var email = values['メールアドレス'][0];
var date = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd');
var status = '未対応';
targetSheet.appendRow([date, name, email, status]);
}
この方法は、フォームの回答シートをそのまま使うのではなく、業務に合わせたフォーマットの管理台帳を別途用意する場合に適しています。ステータス管理の列を追加しておけば、対応状況の把握も容易になります。
方法3:回答者に自動返信メールを送る
フォーム送信後に「受付完了しました」というメールを返すのは、回答者への最低限の礼儀です。Googleフォームの標準機能でも「回答のコピーを送信」は可能ですが、カスタマイズ性が限られています。GASを使えば、回答内容に基づいたパーソナライズされた返信を自動送信できます。
function sendAutoReply(e) {
var responses = e.response.getItemResponses();
var email = '';
var name = '';
for (var i = 0; i < responses.length; i++) {
var title = responses[i].getItem().getTitle();
if (title === 'メールアドレス') {
email = responses[i].getResponse();
}
if (title === 'お名前') {
name = responses[i].getResponse();
}
}
var subject = '【受付完了】お問い合わせありがとうございます';
var body = name + ' 様\n\n'
+ 'お問い合わせいただき、ありがとうございます。\n'
+ '内容を確認のうえ、2営業日以内にご連絡いたします。\n\n'
+ '株式会社○○ お問い合わせ窓口';
GmailApp.sendEmail(email, subject, body);
}
GmailApp.sendEmailの1日あたりの送信上限は、無料のGoogleアカウントで100件、Google Workspaceで1,500件です。大量送信が想定される場合は事前に上限を確認しておいてください。
HTML形式のメールを送る場合
テキストメールではなくHTML形式で見栄えの良いメールを送りたい場合は、GmailApp.sendEmailの第4引数にhtmlBodyオプションを指定します。ロゴ画像の挿入やボタンの配置など、ブランドイメージに合ったメールデザインが可能です。
方法4:条件分岐で担当者に振り分け通知する
「お問い合わせの種類」で「営業に関する質問」を選んだら営業部に、「技術的な質問」を選んだらサポート部に通知する、という振り分け処理です。手動で内容を読んで転送する作業を完全になくせます。
function routeByCategory(e) {
var responses = e.response.getItemResponses();
var category = '';
var message = '';
for (var i = 0; i < responses.length; i++) {
var title = responses[i].getItem().getTitle();
var answer = responses[i].getResponse();
message += title + ': ' + answer + '\n';
if (title === 'お問い合わせの種類') {
category = answer;
}
}
var routingMap = {
'営業に関する質問': 'sales@example.com',
'技術的な質問': 'support@example.com',
'採用について': 'hr@example.com',
'その他': 'info@example.com'
};
var to = routingMap[category] || 'info@example.com';
GmailApp.sendEmail(to, '【フォーム回答】' + category, message);
}
振り分け先のメールアドレスはコード内にハードコードせず、別のスプレッドシートのシートに「カテゴリ名」と「メールアドレス」の対応表を作り、そこから読み込む設計にしておくと、振り分けルールの変更時にコードを触らずに済みます。
方法5:回答データをGoogleカレンダーに自動登録する
セミナー申込みフォーム、面談予約フォーム、施設予約フォームなど、日時を含む回答はカレンダーへの登録作業が必ず発生します。手動でカレンダーを開いてイベントを作成する作業は、GASで完全に自動化できます。
function createCalendarEvent(e) {
var responses = e.response.getItemResponses();
var eventName = '';
var eventDate = '';
var attendeeEmail = '';
for (var i = 0; i < responses.length; i++) {
var title = responses[i].getItem().getTitle();
var answer = responses[i].getResponse();
if (title === 'イベント名') eventName = answer;
if (title === '希望日時') eventDate = answer;
if (title === 'メールアドレス') attendeeEmail = answer;
}
var startTime = new Date(eventDate);
var endTime = new Date(startTime.getTime() + 60 * 60 * 1000);
var calendar = CalendarApp.getDefaultCalendar();
var event = calendar.createEvent(eventName, startTime, endTime);
event.addGuest(attendeeEmail);
}
CalendarApp.createEventの第1引数がイベント名、第2・第3引数が開始・終了日時です。addGuestで参加者のメールアドレスを追加すると、自動でカレンダー招待が送られます。
方法6:重複回答を自動チェック・除外する
同じ人が複数回フォームを送信してしまうケースは珍しくありません。アンケートの回答が重複していると集計結果が歪みますし、申込みの二重登録はオペレーションの混乱を招きます。
GASで過去の回答データと照合し、重複があればフラグを立てる、あるいは処理をスキップする仕組みを作れます。
function checkDuplicate(e) {
var responses = e.response.getItemResponses();
var email = '';
for (var i = 0; i < responses.length; i++) {
if (responses[i].getItem().getTitle() === 'メールアドレス') {
email = responses[i].getResponse();
}
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('回答一覧');
var data = sheet.getDataRange().getValues();
var isDuplicate = false;
for (var j = 1; j < data.length - 1; j++) {
if (data[j][2] === email) {
isDuplicate = true;
break;
}
}
if (isDuplicate) {
// 重複フラグを管理シートに記録
var logSheet = ss.getSheetByName('重複ログ');
logSheet.appendRow([new Date(), email, '重複']);
} else {
// 通常処理を実行
processNewResponse(e);
}
}
メールアドレスでの重複チェックが最も一般的ですが、電話番号や会社名など、フォームの内容に応じてキーとなる項目を変更してください。複数項目の組み合わせで判定する方が精度は上がります。
方法7:回答内容からPDFを自動生成する
申請書や見積依頼書、受付票など、フォーム回答をもとに書類を発行する必要がある業務で威力を発揮します。Googleドキュメントのテンプレートに回答データを差し込み、PDF化する流れです。
function generatePdf(e) {
var responses = e.response.getItemResponses();
var data = {};
for (var i = 0; i < responses.length; i++) {
var title = responses[i].getItem().getTitle();
data[title] = responses[i].getResponse();
}
// テンプレートドキュメントをコピー
var templateId = 'テンプレートのドキュメントID';
var copy = DriveApp.getFileById(templateId).makeCopy('受付票_' + data['お名前']);
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
// プレースホルダーを回答で置換
body.replaceText('{{お名前}}', data['お名前'] || '');
body.replaceText('{{会社名}}', data['会社名'] || '');
body.replaceText('{{日付}}', Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd'));
doc.saveAndClose();
// PDFに変換
var pdf = DriveApp.getFileById(copy.getId()).getAs('application/pdf');
var pdfFile = DriveApp.createFile(pdf);
// メールで送信
GmailApp.sendEmail(data['メールアドレス'], '受付票をお送りします', '',
{ attachments: [pdf] });
// テンプレートのコピーを削除
DriveApp.getFileById(copy.getId()).setTrashed(true);
}
テンプレートのGoogleドキュメント内に{{お名前}}、{{会社名}}のようなプレースホルダーを配置しておけば、replaceTextで自動的に差し替わります。フォームの設問名とプレースホルダーの名前を一致させておくと管理が楽です。
方法8:Googleドライブにファイルを自動保存する
フォームには「ファイルのアップロード」機能があります。履歴書、見積書、写真など、回答と一緒にファイルが添付されるケースです。これらのファイルをGoogleドライブの特定フォルダに自動で整理保存できます。
function organizeFiles(e) {
var responses = e.response.getItemResponses();
var applicantName = '';
var fileIds = [];
for (var i = 0; i < responses.length; i++) {
var title = responses[i].getItem().getTitle();
var answer = responses[i].getResponse();
if (title === 'お名前') applicantName = answer;
if (title === '添付ファイル') fileIds = answer;
}
// 保存先フォルダを取得(なければ作成)
var parentFolder = DriveApp.getFolderById('保存先フォルダのID');
var folderName = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMMdd') + '_' + applicantName;
var folder = parentFolder.createFolder(folderName);
// アップロードされたファイルを移動
if (fileIds && fileIds.length > 0) {
for (var j = 0; j < fileIds.length; j++) {
var file = DriveApp.getFileById(fileIds[j]);
file.moveTo(folder);
}
}
}
ファイルアップロード形式の回答は、アップロードされたファイルのIDが配列で返されます。このIDを使ってDriveApp.getFileByIdでファイルオブジェクトを取得し、任意のフォルダに移動します。日付と回答者名でフォルダを作っておけば、後から探す時にも迷いません。
方法9:回答データを集計してダッシュボードを自動更新する
アンケート結果や申込み状況を定期的に確認したい場合、回答のたびにスプレッドシート上のダッシュボードを自動更新する仕組みが便利です。
function updateDashboard(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var responseSheet = ss.getSheetByName('フォームの回答');
var dashboardSheet = ss.getSheetByName('ダッシュボード');
var data = responseSheet.getDataRange().getValues();
var totalCount = data.length - 1; // ヘッダー除外
// カテゴリ別集計
var categoryCounts = {};
for (var i = 1; i < data.length; i++) {
var category = data[i][3]; // 4列目がカテゴリの場合
categoryCounts[category] = (categoryCounts[category] || 0) + 1;
}
// ダッシュボードに書き込み
dashboardSheet.getRange('B2').setValue(totalCount);
dashboardSheet.getRange('B3').setValue(Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd HH:mm'));
var row = 6;
for (var cat in categoryCounts) {
dashboardSheet.getRange(row, 1).setValue(cat);
dashboardSheet.getRange(row, 2).setValue(categoryCounts[cat]);
row++;
}
}
このコードでは回答のたびにダッシュボードシートの数値を更新しています。Googleスプレッドシートのグラフ機能と組み合わせれば、リアルタイムでグラフが更新されるダッシュボードを構築できます。共有設定を行えば、チーム全員がブラウザから最新の集計結果を確認できます。
方法10:外部API連携で他システムに自動データ送信する
フォーム回答データを社内のCRM、プロジェクト管理ツール、基幹システムに自動連携するケースです。UrlFetchAppを使えば、HTTP通信で外部APIにデータを送信できます。
HubSpot CRMへの自動登録例
function sendToHubSpot(e) {
var responses = e.response.getItemResponses();
var data = {};
for (var i = 0; i < responses.length; i++) {
var title = responses[i].getItem().getTitle();
data[title] = responses[i].getResponse();
}
var apiKey = PropertiesService.getScriptProperties().getProperty('HUBSPOT_API_KEY');
var payload = {
properties: {
email: data['メールアドレス'],
firstname: data['お名前'],
company: data['会社名'],
phone: data['電話番号']
}
};
var options = {
method: 'post',
contentType: 'application/json',
headers: { 'Authorization': 'Bearer ' + apiKey },
payload: JSON.stringify(payload)
};
UrlFetchApp.fetch('https://api.hubapi.com/crm/v3/objects/contacts', options);
}
APIキーはコード内に直接書かず、PropertiesService.getScriptProperties()に保存するのがセキュリティ上の鉄則です。スクリプトエディタの「プロジェクトの設定」からスクリプトプロパティを追加できます。
kintone・Salesforce・Notionなどへの連携
基本的な仕組みは同じです。各サービスのREST APIのエンドポイントに対して、UrlFetchAppでPOSTリクエストを送信します。リクエストボディのJSON構造は各サービスのAPIリファレンスを参照してください。
特にkintoneはREST APIが充実しており、レコード登録・更新・一覧取得がシンプルなAPIで実行できるため、GASとの相性が良好です。
GAS自動処理で失敗しないための3つの注意点
注意点1:実行時間の制限を把握する
GASには1回の実行で6分間(360秒)という時間制限があります。大量のデータ処理や外部API呼び出しを含むスクリプトでは、この制限に引っかかることがあります。処理が6分を超える場合は、タイムベースのトリガーで分割処理する設計にしてください。
注意点2:エラーハンドリングを必ず入れる
フォーム送信のトリガーで動くスクリプトがエラーで止まると、回答者に返信が届かない、データが保存されない、といった実害が出ます。try-catch文でエラーを捕捉し、エラー時にはメールやチャットで管理者に通知する仕組みを入れておくことを推奨します。
function safeOnFormSubmit(e) {
try {
// メイン処理
processFormResponse(e);
} catch (error) {
// エラー通知
GmailApp.sendEmail('admin@example.com',
'【エラー】フォーム自動処理が失敗しました',
'エラー内容: ' + error.message + '\n' + error.stack);
}
}
注意点3:日次のクォータに注意する
GASには1日あたりのサービス利用上限があります。メール送信は無料アカウントで100件/日、Google Workspaceで1,500件/日です。UrlFetchAppの呼び出しは20,000件/日が上限です。大量の回答が想定される場合は、事前にクォータを確認し、上限に達した場合のフォールバック処理を設計してください。
各クォータの最新値は、Googleの公式ドキュメント「Apps Script quotas」のページで確認できます。
よくある質問
Q. プログラミング未経験でもGASは使えますか?
GASはJavaScriptベースの言語で、Web上に学習リソースが豊富にあります。この記事のコードをそのままコピーして使うだけでも動作します。まずはSlack通知(方法1)や自動返信メール(方法3)のように、シンプルな処理から始めてみてください。慣れてきたら条件分岐やAPI連携に進むのがスムーズです。
Q. GASの利用に費用はかかりますか?
GASはGoogleアカウントがあれば無料で利用できます。Google Workspace(旧G Suite)を契約している企業であれば、クォータ(日次の利用上限)がより大きくなりますが、基本機能に差はありません。
Q. 1つのフォームに複数のGASスクリプトを設定できますか?
はい、可能です。1つのフォームに対して複数のonFormSubmitトリガーを設定できます。ただし、処理順序は保証されないため、処理間に依存関係がある場合は1つの関数内で順番に呼び出す設計にしてください。
Q. スクリプトが動かない場合はどうすればいいですか?
まず、スクリプトエディタの「実行ログ」で実行履歴とエラーメッセージを確認してください。よくある原因は、Googleアカウントの認証許可がされていない、トリガーの設定が間違っている、変数名やシート名のタイプミスの3つです。Logger.logを使って処理の途中経過を出力し、どの段階でエラーが発生しているかを特定するのが効率的です。
Q. 回答データのセキュリティは大丈夫ですか?
GASはGoogleのインフラ上で動作するため、通信の暗号化やデータの保管はGoogleのセキュリティ基準に準拠しています。ただし、APIキーやWebhook URLなどの機密情報はPropertiesServiceに保存し、コード内にハードコードしないでください。また、スクリプトの共有設定にも注意が必要です。
まとめ
- GASでGoogleフォーム回答を自動処理すべき理由
- GAS連携の事前準備と基本設定
- 方法1:回答をSlack・Chatworkに即時通知する
- 方法2:スプレッドシートに自動整形して転記する
- 方法3:回答者に自動返信メールを送る
- 方法4:条件分岐で担当者に振り分け通知する
- 方法5:回答データをGoogleカレンダーに自動登録する
- 方法6:重複回答を自動チェック・除外する
業務自動化で手が止まっているなら
最初の一歩の順番を、一緒に整理するところから始められます
GASやAPI連携で業務を楽にしたい、でも「どの業務から自動化すべきか」の判断が難しい——ここで手が止まってしまうケースがあります。先にツールを触るより、自動化する順番を整理しておくほうが、結果的に早く楽になります。BoostXの業務自動化サービスは、この順番づくりから、設計、運用の定着まで並走する内容です。どこから始めるべきか、まずは無料相談でご相談ください。