契約書や案内状、修了証のような書類を、氏名や日付だけ書き換えて1件ずつ作成し直す作業に時間を取られていないでしょうか。
件数が数件のうちは手作業でも回りますが、対象者が増えるほど書き換え漏れや誤字が起きやすくなります。
Google Apps Script(Googleスプレッドシートに付属するスクリプト環境)でGoogleドキュメントのテンプレートに値を差し込み、書類を一括作成する方法を整理しています。
コード全文と、PDF化までの手順を合わせて紹介する内容です。
Google Apps Scriptでの書類自動作成が向くケース(差し込み印刷アドオンとの使い分け)
この方法が向くのは、契約書や案内状、修了証のように文面の大部分が共通で、氏名や日付など数箇所だけが変わる書類を、月に数件から数十件発行する場面です。
| Google Apps Scriptでの自動作成 | 差し込み印刷アドオン | |
|---|---|---|
| 向く件数 | 月数件〜数十件 | 月数百件以上 |
| 差し込み後の個別編集 | スクリプトの改修が必要 | 管理画面から調整しやすい |
| 追加費用 | かからない | 有料プランが必要な場合がある |
| 既存のテンプレート運用 | そのまま活かせる | テンプレートの作り直しが必要な場合がある |
発行後に文面を個別に手直しすることが多い場合や、社内の承認フローと組み合わせたい場合は、既製のアドオンより自作のスクリプトのほうが融通が利きます。
一方で月に数百件を超えるような発行数になると、専用アドオンの管理画面のほうが運用は楽になります。
Google Apps Scriptでの自動化全体の進め方は、以下で整理しています。

準備するもの:テンプレートドキュメントと差し込みリスト
準備するファイルは2つです。
1つ目は書類のレイアウトを作った『テンプレート』ドキュメントで、差し込みたい箇所に{{customerName}}のような目印の文字列をあらかじめ入れておきます。
2つ目は作成する書類の件数分を1行ずつ並べた『差し込みリスト』シートで、氏名、契約日、金額、担当者名、処理済みフラグの列を用意する構成です。
請求書のPDF自動生成については、以下で扱っています。

Google Apps Scriptで書類をテンプレートから自動作成する手順
テンプレートドキュメントを1件ごとに複製し、複製先の本文にリストの値を差し込んでからPDFへ書き出す流れをスクリプトにします。
処理が終わった行には済みフラグを立てるため、途中で止めても再実行時に重複作成しません。
Step1. プレースホルダーを設計する
テンプレートドキュメントを開き、氏名や日付を入れたい位置に{{customerName}}のような目印の文字列を入力します。
波かっこ2つで挟む書き方にしておくと、Googleドキュメントの自動修正で引用符が変換される影響を受けず、スクリプト側の文字列と確実に一致します。
Step2. コードを貼り付ける(コード全文)
拡張機能からApps Scriptエディタを開き、以下をそのまま貼り付けます。
const TEMPLATE_DOC_ID = 'ここにテンプレートドキュメントのIDを入れる';
const LIST_SHEET_NAME = '差し込みリスト';
const OUTPUT_FOLDER_ID = 'ここにドライブの保存先フォルダIDを入れる';
// 差し込みリストの列(A列から順に0,1,2...)
const LIST_COL = {
customerName: 0,
contractDate: 1,
amount: 2,
managerName: 3,
status: 4,
};
function createDocumentsFromTemplate() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const listSheet = ss.getSheetByName(LIST_SHEET_NAME);
const templateFile = DriveApp.getFileById(TEMPLATE_DOC_ID);
const folder = DriveApp.getFolderById(OUTPUT_FOLDER_ID);
const rows = listSheet.getDataRange().getValues();
for (let i = 1; i < rows.length; i++) {
const row = rows[i];
if (row[LIST_COL.status] === '済') {
continue;
}
generateDocumentForRow(templateFile, folder, row);
listSheet.getRange(i + 1, LIST_COL.status + 1).setValue('済');
}
}
function generateDocumentForRow(templateFile, folder, row) {
const fileName = `${row[LIST_COL.customerName]}様_書類`;
const copiedFile = templateFile.makeCopy(fileName, folder);
const doc = DocumentApp.openById(copiedFile.getId());
const body = doc.getBody();
body.replaceText('{{customerName}}', toText(row[LIST_COL.customerName]));
body.replaceText('{{contractDate}}', toText(row[LIST_COL.contractDate]));
body.replaceText('{{amount}}', toText(row[LIST_COL.amount]));
body.replaceText('{{managerName}}', toText(row[LIST_COL.managerName]));
doc.saveAndClose();
const pdfBlob = DriveApp.getFileById(copiedFile.getId()).getAs('application/pdf');
folder.createFile(pdfBlob).setName(`${fileName}.pdf`);
}
// セルの値を差し込み用の文字列に変換する
// 日付セルはDate型で渡ってくるため yyyy/MM/dd に整形し、数値もそのまま文字列にする
function toText(value) {
if (value instanceof Date) {
return Utilities.formatDate(value, Session.getScriptTimeZone(), 'yyyy/MM/dd');
}
return String(value);
} このコードが何をしているか
createDocumentsFromTemplateが『差し込みリスト』を1行ずつ読み、済みフラグが立っていない行だけを処理します。
generateDocumentForRowがテンプレートを複製してreplaceTextで目印の文字列を実際の値へ置き換え、保存したうえでPDF形式のファイルとして書き出す仕組みです。
差し込む前にtoTextを通しているのは、契約日のような日付や金額のような数値を、そのまま差し込むと書式が崩れたりエラーになったりするためです。
日付はyyyy/MM/ddの形に整えてから差し込みます。
複製したドキュメントとPDFの両方が指定フォルダに残るため、原本を見返したいときは複製側のドキュメントを開けば確認できます。
自分のデータに合わせて変える場所
TEMPLATE_DOC_IDにはテンプレートドキュメントのIDを入れます。
ドキュメントを開いたときのURLの/d/と/editの間の文字列をそのまま貼り付けてください。LIST_COLの各値は『差し込みリスト』の列の並び順です。
A列が0、B列が1というように左から0始まりで数えます。- 目印の文字列は
replaceTextの行を増やせば何個でも追加できます。
テンプレート側の目印とスクリプト側の文字列は1文字も違わず一致させる必要があります。
Step3. 1件でテスト実行する
『差し込みリスト』に1行だけデータを入れた状態で、Apps ScriptエディタからcreateDocumentsFromTemplateを選んで実行します。
初回実行時は権限の承認画面が表示されるので、自分で作成したスクリプトであることを確認したうえで許可します。
実行が終わったら、指定フォルダにドキュメントとPDFが1件ずつ作成されていることを目視で確認する流れです。
Step4. 出来上がったPDFのレイアウトを確認する
テスト実行で問題がなければ、『差し込みリスト』に本番分の行を追加してから再度実行します。
処理済みの行には済みフラグが立つため、翌回以降は新しく追加した行だけが対象になります。
生成したPDFは印刷したときと同じ見た目になっているかを、少なくとも1件は開いて確認してください。
レイアウト崩れの注意点(テンプレート設計で気をつける点)
目印の文字列を表のセルの区切りや改行の途中に置くと、Googleドキュメントが内部でテキストを区切って保存するため、replaceTextが一致しなくなることがあります。
目印は1つのセル、1つの行の中に文字列として続けて入力し、途中で改行や書式の切り替えを挟まないようにしてください。
差し込む値がテンプレートで想定していたより長い場合、表の列幅やページの余白からはみ出すことがあります。
氏名や住所のように長さが一定しない項目は、実際のデータの中で最も長いものを仮に入れてレイアウトを確認しておくと安全です。
テンプレート側で目印にフォントや文字サイズを設定しておくと、複製後に値へ置き換わった後もその書式がそのまま引き継がれます。
逆に目印の前後だけ書式を変えていると、差し込んだ値がそこだけ浮いた見た目になることがあるため、テンプレート作成時に一度PDFへ書き出して確認しておくと安心です。
書類作成の自動化について相談してみませんか?
「テンプレートの目印設計が合っているか自信がない」「契約書ごとに差し込む項目がバラバラで整理できていない」「書類作成から承認まで一括で見直したい」
少しでもお心当たりがあれば、お気軽にご相談ください。
現在、Google Apps Scriptを使った業務自動化のお悩みをお伺いする 無料の個別相談 を実施しています。
よくある質問
Q. プレースホルダーは何個まで設定できますか?
replaceTextの行を増やせば個数の上限はありません。
項目が多くなる場合はLIST_COLと目印の対応が崩れやすくなるため、列の並びと目印の名前を揃えておくと管理しやすくなります。
Q. 一度に何件くらいまで処理できますか?
Google Apps Scriptには1回の実行につき6分までという仕様上の上限があります。
数十件程度なら1回の実行で収まりますが、数百件を超える場合は『差し込みリスト』を分けて複数回に分けて実行してください。
Q. 表の中にプレースホルダーを置いても大丈夫ですか?
置けますが、セルの結合や改行をまたぐ位置に置くとreplaceTextが一致しなくなることがあります。
1つのセルの中で目印の文字列が途切れていないか、テンプレート作成時に確認してください。