今までの記事一覧
Googleフォーム×GASで実現する業務自動化シリーズ全記事まとめ目次
前提
この記事は、フォーム回答を保存しているスプレッドシート側のGASを前提にしています。
トリガーは以下を設定してください。
- 実行する関数:
onFormSubmit - イベントのソース:スプレッドシートから
- イベントの種類:フォーム送信時
おさらい
前回は、Googleフォームの事前入力URLの作成方法として、toPrefilledUrl() と、文字列結合方式を比較し、用途によって適宜使い分けをしたほうがいいということがわかりました。
前回の記事を書き進めるうちに、文字列結合方式の entry.xxxxx はどうなっているのか興味が出てきたため、今回はいろいろな実験をしてみたいと思います。
※フォームの選択肢や回答を日本語にすると、エンコードされた %E5%90%8D%E5%89%8D のような暗号になってしまい分かりづらいため、今回、フォームの選択肢と回答を英語にします。
質問タイプ別 &entry.xxxxx の生成パターン
- URLの前半部分
&entry.xxxxxより前の部分はこうなっています。
このベースURLの末尾に、以降で解説する&entry.xxxxxが続きます。
https://docs.google.com/forms/d/e/1FA************/viewform?usp=pp_url
記述式(短文)の場合
&entry.423554781=Grilled+Fish
423554781 は質問ID。
半角スペースは + で表現されるようですね。
試しに回答内容を「Grilled+Fish」のように + を含む文字列にしてみたところ、
&entry.423554781=Grilled%2BFish
文字としての + は、URLエンコードのルールに従って %2B として表現されるようです。
記述式(段落)の場合
&entry.423554781=Grilled+Fish%0AMakunouchi
改行は %0A (改行コード)に変換されるようです。
ラジオボタンの場合
&entry.423554781=Grilled+Fish
記述式(短文)と同じ構造ですね。
ここまでは、一番シンプルな &entry.質問ID=回答の文言 という基本ルールが成り立っています。
ここで「その他」を選んで内容を入力してみると、
&entry.423554781=__other_option__
&entry.423554781.other_option_response=Noriben
2行になりました。
1行目で「その他」が指定され、2行目で「記述内容」が入るというわけですね。
ちなみに、「その他」にチェックを入れただけで中身を空欄にしたままリンクを生成すると、
https://docs.google.com/forms/d/e/1FA************/viewform?usp=pp_url
&entry 以降のパラメータ自体が作成されません。これをそのまま開くと、当然空欄のフォームが開きます。
※ブラウザ側に前回の下書きデータが一時保存されている場合は、その下書きが優先して開くことがあります。
チェックボックスの場合
&entry.423554781=Hamburger+Steak
&entry.423554781=Grilled+Fish
&entry.423554781=__other_option__
&entry.423554781.other_option_response=Noriben
選択した項目ごとに &entry.質問ID=回答 が追加されます。
「その他」を選択した場合は、選択肢本体と入力内容の2行が追加されます。
ここで、実験として「Grilled Fish」にチェックを入れ、さらに「その他」にもチェックを入れた状態で、中身の記述欄を空欄にしてURLを作成してみると・・・

値の入っている「Grilled Fish」についてだけ、&entryが作成されました。
&entry.423554781=Grilled+Fish
ブラウザで開くと、中身が空っぽだった「その他」のチェックは自動的に外れた状態でフォームが表示されます。
プルダウンの場合
&entry.423554781=Grilled+Fish
プルダウンの場合は「その他」はないので単純です。
出来上がったURLは記述式(短文)と同じ形式ですね。
均等目盛/評価の場合
&entry.2136749344=4
&entry.487102072=2
これも単純ですね。
&entry.質問ID=数字 の基本パターンです。
選択式(グリッド)の場合
&entry.2136749344=a
&entry.764594397=b
&entry.629157206=c
グリッド形式の場合、ひとつの質問の中に「複数の行」が存在しますが、各行(図の「A」「B」「C」)それぞれに対して個別の質問IDが割り振られていることが分かります。
なお、一部の行だけに入力してURLを作成した場合は、入力があった行のIDだけがURLに組み込まれます。
チェックボックス(グリッド)の場合
&entry.2136749344=a
&entry.764594397=b
&entry.629157206=a
&entry.629157206=c
こちらも、選択式グリッドと同様に、各行(「A」「B」「C」)それぞれに固有の質問IDが割り振られています。その上で、単体のチェックボックスのルールも適用されるため、1つの行の中で複数をチェックした場合は、その行のID(例:629157206)がURL内で何度も繰り返されて結合される仕様になっています。
日付の場合
&entry.160419561=2026-07-01
&entry.xxxxx の中では、2026-07-01というハイフン区切りのシンプルな文字列としてそのまま入っているようです。
フォームの回答を確認すると、下図のようになっているので、内部的には日付データとして格納されているのでしょうか?
試しに以下のGASをフォーム側に仕込んで、回答のタイプを取得します。
日付型なら、2個目のログが true になるはずです。
function myFunction() {
const form = FormApp.getActiveForm();
const responses = form.getResponses();
const lastResponse = responses[responses.length - 1];
const answer = lastResponse.getItemResponses()[0].getResponse();
Logger.log("回答:" + answer);
Logger.log("日付型?:" + (answer instanceof Date)); // Date型ならtrueになる
}
回答:2026-07-01
日付型?:false
あれ? false になった。
ためしにスプレッドシートに連携させて、このコードで送信データ e から直接「回答内容」「回答のデータ型」「回答が日付型かどうか」をログに出力してみます。
function onFormSubmit(e) {
const timestamp = e.values[0]; // タイムスタンプ
const answer = e.values[1]; // 質問1の回答
Logger.log("回答:" + answer);
Logger.log("回答のtype:" + typeof answer);
Logger.log("日付型?:" + (answer instanceof Date));
}
回答:2026/07/01
回答のtype:string
日付型?:false
やっぱり文字列型なのか。意外でした。だとすると、e を使って取得した日付を扱うときは、少し注意が必要かもしれませんね。
ここでさらにしつこく、シートの最終行からデータを取得して実験。
function sheetData() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("フォームの回答 1");
//最終列に日付データが入っているものとします
const data = sheet.getRange(sheet.getLastRow(), sheet.getLastColumn()).getValue();
Logger.log("回答:" + data);
Logger.log("回答のtype:" + typeof data);
Logger.log("日付型?:" + (data instanceof Date));
}
回答:Wed Jul 01 00:00:00 GMT+09:00 2026
回答のtype:object
日付型?:false
セルからとった data そのものは明らかに日付型に見えるのに、Date型 かどうかは false。不思議ですね。
ただ、シート上で日付型として扱うことに問題はないようです。下図のように、シート関数で =ISDATE() するとTRUE になりますし。
脱線してしまいました。これ以上やると長くなりそうなので続きはいつか機会があれば別記事で実験してみたいと思います。
時刻の場合
&entry.160419561=21:37
これも日付と同じパターンで、URL上はコロン区切りのシンプルな文字列として渡される仕様でした。
無効なURLを送ったらどうなる?
さて、無事作成された、事前入力URLですが、もしURLの一部を誤って編集したり、存在しない値を指定した場合はどうなるのでしょうか。
選択肢に存在しない回答を指定した場合
例えば、ラジオボタンの選択肢(正しくは Grilled+Fish)を、以下のように架空の文字列に書き換えてみます。
&entry.423554781=Grilled+Fishhhhhhh
特にエラー画面(400 Bad Request等)が出ることもなく、何も選択しない状態が表示されました。
どうやら、存在しない選択肢はエラーにせず無視されるようです。
「その他」の前提パラメータが欠けていた場合
先ほど確認した通り、本来「その他」に入力させるには以下の2行がセットで必要です。
&entry.423554781=__other_option__
&entry.423554781.other_option_response=noriben
実験として、上の1行目を意図的に削除し、入力内容だけを指定して開いてみます。
&entry.423554781.other_option_response=noriben
これも何も選択されませんでした。「その他」を事前入力する場合は、選択肢本体と入力内容の両方を指定する必要があるようです。
逆に、これだけで後ろの入力内容を省いた場合も、同様に何も選択されませんでした。
&entry.423554781=__other_option__
まったく存在しない「架空の質問ID」を指定した場合
URL内のエントリーIDを、デタラメな数字に書き換えてみます。
&entry.111111111=Grilled+Fish
特にエラーもなく、白紙状態のフォーム(下書きが残っている場合はその下書きの場合あり)になりました。存在しない質問IDは無視されるようです。
ありえない日付(矛盾した日時)を指定した場合
カレンダーに存在しない「2026年7月99日」という無効な日付を送りつけてみます。
entry.1519027078=2026-07-99
日付は事前入力されず、空欄のまま表示されました。ただし、ブラウザに保存された下書きがあれば、その内容が表示されることがあります。

無効URLのまとめ
今回試した範囲では、事前入力URLに無効な値や存在しない質問IDを指定しても、フォーム自体がクラッシュしたりエラー画面になったりすることはありませんでした。
Googleフォームは無効なデータを読み込んだ場合、エラーにするのではなく、その項目を無視してフォームを表示するようです。
選択肢が無効の場合は「現在の下書きで続行しますか?」のメッセージが出るのに対し、質問IDや日時が無効の場合は、下書きがあればその下書きが自動で開くようです。
全体のまとめ
今回は、Googleフォームの事前入力URLを文字列結合で作成する際に使用する entry.xxxxx について、質問タイプごとの生成パターンを調査してみました。
実験の結果、基本的には
&entry.質問ID=回答
というシンプルな構造になっていることが分かりました。
ただし、
- チェックボックスは選択した数だけ
entry.xxxxxが繰り返される - グリッド形式は行ごとに異なる質問IDが割り当てられる
- 「その他」は
__other_option__と入力内容の2つをセットで指定する必要がある
など、質問タイプによって少しずつルールが異なります。
また、存在しない選択肢や誤った質問IDを指定した無効なURLについても試してみましたが、Googleフォームはエラーにするのではなく、その項目を無視してフォームを表示するようでした。
そのため、事前入力URLを文字列結合で作成することは十分実用的ですが、質問IDや選択肢の文字列は正確に指定する必要があります。
今回の実験で、事前入力URLの仕組みがかなり見えてきました。今回調べたルールを利用すれば、toPrefilledUrl() を使わなくても用途によっては柔軟に事前入力URLを生成できそうです。


















