スプレッドシートの行ごとにGoogleドキュメントの案内状を一括で作りたい
先に結論
ひな形に {{名前}} などの印を書き、Apps Scriptで行ごとにコピーして値に置き換えます。
URLのある行は再実行で飛ばします。
- ひな形に {{見出し}} の印を書く
- 名簿の1行目に「名前」「作成済み」などの見出しを作る
- コードを貼り、1件だけ作って確かめる
- 件数を増やして残りを作る
- ゴミ箱を空にしたファイルは完全に削除される
- 名簿の最後の人までURLが付いたら終わり
※2026年11月時点の情報です。

1ひな形とシートを用意する
{{名前}}佐藤 花子
シートの見出しと同じ語を {{ }} で囲んだ所が、その行の値になる
Googleドキュメントに案内状を書き、差し込む所を {{名前}} にします。置換は最初のタブの本文だけです。
出典:Class Document
2コードを貼って1件だけ作る
- 名簿のシートで「拡張機能」 → 「Apps Script」を開く
- コードを全部消して下を貼り、IDを2か所入れて保存
- 名簿のタブを開いたまま、上のプルダウンで makeDocs を選び「実行」
ひな形IDはURLの /d/ と次の / の間、フォルダは folders/ の後ろです(記事の補足)。
const TEMPLATE_ID = `ここにひな形のID`;
const FOLDER_ID = `ここにフォルダID`;
const LIMIT = 1; // ← 試しは1。全件なら件数より大きい数
function makeDocs() {
const sheet = SpreadsheetApp.getActiveSheet();
const rows = sheet.getDataRange().getDisplayValues();
const head = rows.shift();
const doneCol = head.indexOf(`作成済み`) + 1;
if (!doneCol || !head.includes(`名前`)) throw new Error(`見出しを確認`);
const tpl = DriveApp.getFileById(TEMPLATE_ID);
let row = 1, count = 0;
for (const r of rows) {
row++;
if (count === LIMIT) break;
const v = new Map();
r.forEach((x, c) => v.set(head.at(c), x));
if (v.get(`作成済み`) || !v.get(`名前`)) continue;
const copy = tpl.makeCopy(tpl.getName() + `_` + v.get(`名前`), DriveApp.getFolderById(FOLDER_ID));
const doc = DocumentApp.openById(copy.getId());
v.forEach((x, h) => {
let k = h;
for (const m of `\\.*+?^$|(){}[]`) k = k.split(m).join(`\\` + m);
doc.getBody().replaceText(`\\{\\{` + k + `\\}\\}`, x);
});
doc.saveAndClose();
sheet.getRange(row, doneCol).setValue(copy.getUrl());
SpreadsheetApp.flush();
count++;
}
}
初回の許可で「このアプリは確認されていません」と出たら「詳細」→「(プロジェクト名)に移動(安全ではありません)」へ。会社のアカウントは管理者の承認が要ることがあります。
$ や \ を含む値は公式に置換での扱いの記載が無いため、その行を先頭に置き1件目で確かめます。
出典:コンテナにバインドされたスクリプト / Class Body / Class File / Gmail と Google スプレッドシートでメールへの差し込みを作成する / 自動化のクイックスタート
3件数を増やして残りを作る
1件目に印が残らなければ LIMIT を増やして保存し、再実行します。1回の実行は6分までです。
出典:Google サービスの割り当て
止まったら名前がありURLの無い一番上の行の文書があればゴミ箱へ移して再実行します。作り直す時も同様に移し、その行の作成済みを消して実行します。ゴミ箱を空にすると完全に削除されるので、移すだけにします。
出典:Google ドライブ内のファイルを削除する