Google Apps Scriptを使用し、Googleスプレッドシートに格納されたデータをもとに、Googleドキュメントのテンプレートを使用して新しいドキュメントを作成し、最終的にはPDFファイルに出力するものです。GoogleスプレッドシートとGoogleドキュメントを組み合わせて、データに基づくレポートを効率的に作成するためのものです。
一つのデータ毎にドキュメントを作成するのではなく、一つのドキュメントに改ページを加えながら追記していくので、ユーザーのアカウント情報をまとめた用紙を一括作成したり、アンケート結果や成果物をレポートとして一括作成するといった活用が見込まれます。あるいは、フォームと連携したスプレッドシートを用いることで、さらに活用の幅が広がると思います。
「(配布用)テンプレからレポート一括作成」と「(配布用)レポートテンプレ」をコピーして、使用して下さい。なお、スプレッドシートに書かれている情報は、「個人情報テストデータジェネレーター」で生成した動作確認用のダーミーデータです。
主な機能
- Googleスプレッドシートのメニューバーに「レポート作成」という新しいメニューを追加
- 「レポート作成」メニューから「作成」という項目を選択すると、createReportFromTemplate関数が実行されます。
- createReportFromTemplate関数が実行されると、スプレッドシートからデータを取得し、指定されたGoogleドキュメントテンプレートを使用して新しいドキュメントを生成します。テンプレート内のプレースホルダーは、スプレッドシートのデータに置き換えられます。
- 新しく作成されたドキュメントは、スプレッドシートと同じフォルダに保存されます。
- 最後に新しいドキュメントをPDF形式で出力し、スプレッドシートと同じフォルダに保存します。
このツールは、Google スプレッドシートとGoogle ドキュメントを組み合わせて、データに基づくレポートを効率的に作成するためのものです。
注意事項
- テンプレートIDの設定: スクリプト内のTEMPLATE_DOCUMENT_IDを、実際のGoogle ドキュメントテンプレートのIDに置き換える必要があります。これを行わないと、スクリプトは正しく動作しません。
- アクセス許可: スクリプトがGoogle スプレッドシートやGoogle ドキュメントにアクセスするためには、適切なアクセス許可が必要です。初回実行時に、スクリプトがリクエストするアクセス許可を承認してください。
- プレースホルダーの形式: テンプレート内のプレースホルダーは、{}で囲まれた形式である必要があります。例えば、スプレッドシートのヘッダーが「氏名」であれば、テンプレート内のプレースホルダーは{氏名}となります。
- 他の要素タイプへの対応: 現在のスクリプトでは、主要な要素タイプ(段落、リスト項目、テーブル、ページブレーク)に対応していますが、他の要素タイプを含むテンプレートを使用する場合、スクリプト内で適切な処理を追加する必要があります。
- スクリプトの実行時間: Google Apps Scriptには実行時間の制限があります。処理するデータが非常に大量であったり、複雑な処理が必要な場合、スクリプトの実行時間が制限を超える可能性があります。
- エラーハンドリング: 現在のスクリプトでは、エラーハンドリングが最小限になっています。実際に使用する場合、適切なエラーハンドリングを追加して、スクリプトの安定性と堅牢性を向上させることが望ましいです。
お願い
テンプレートに画像を含めたものの開発を最終目標とし様々なコードを試しましたが、先行事例も見当たらず断念しました。アドバイスいただけると幸いです。
スクリプト
function onOpen() {
let ui = SpreadsheetApp.getUi();
let menu = ui.createMenu('レポート作成');
menu.addItem('作成', 'createReportFromTemplate');
menu.addToUi();
}
function createReportFromTemplate() {
// スプレッドシート、テンプレートドキュメントのIDを指定
let spreadsheetId = SpreadsheetApp.getActiveSpreadsheet().getId();
let templateId = 'TEMPLATE_DOCUMENT_ID';
// スプレッドシートからデータを取得
let sheet = SpreadsheetApp.openById(spreadsheetId).getActiveSheet();
let data = sheet.getDataRange().getValues();
// ヘッダー行を削除
data.shift();
// テンプレートドキュメントを開く
let templateDoc = DocumentApp.openById(templateId);
let templateBody = templateDoc.getActiveSection();
// スプレッドシートと同じフォルダに新しいドキュメントを作成
let spreadsheetFile = DriveApp.getFileById(spreadsheetId);
let parentFolder = spreadsheetFile.getParents().next();
let newDoc = DocumentApp.create('New Document');
let newDocumentId = newDoc.getId();
parentFolder.addFile(DriveApp.getFileById(newDocumentId));
// 新しいドキュメントを開く
newDoc = DocumentApp.openById(newDocumentId);
let newDocBody = newDoc.getActiveSection();
// データをテンプレートに当てはめて新しいドキュメントに追記
data.forEach(function(row) {
let tempBody = templateBody.copy();
// テンプレート内のプレースホルダーを置き換える
for (let i = 0; i < row.length; i++) {
let placeholder = '{' + sheet.getRange(1, i+1).getValue() + '}';
tempBody.replaceText(placeholder, row[i]);
}
for (let i = 0; i < tempBody.getNumChildren(); i++) {
let childElement = tempBody.getChild(i).copy();
let childElementType = childElement.getType();
let newDocBody = newDoc.getBody();
// 各要素タイプに基づいて要素を追加
switch (childElementType) {
case DocumentApp.ElementType.PARAGRAPH:
newDocBody.appendParagraph(childElement.asParagraph());
break;
case DocumentApp.ElementType.LIST_ITEM:
newDocBody.appendListItem(childElement.asListItem());
break;
case DocumentApp.ElementType.TABLE:
newDocBody.appendTable(childElement.asTable());
break;
case DocumentApp.ElementType.PAGE_BREAK:
newDocBody.appendPageBreak(childElement.asPageBreak());
break;
// 他の要素タイプがある場合には、ここに追加
default:
break;
}
}
// ページブレークを追加
newDocBody.appendPageBreak();
});
// 変更を保存
newDoc.saveAndClose();
// 新しいドキュメントをPDFファイルとして出力
exportToPdf(newDocumentId, parentFolder);
}
function exportToPdf(documentId, parentFolder) {
// PDFファイル名を指定
let pdfName = 'output.pdf';
// ドキュメントをPDF形式で取得
let pdfBlob = DriveApp.getFileById(documentId).getAs('application/pdf');
// PDFファイル名を設定
pdfBlob.setName(pdfName);
// PDFファイルをスプレッドシートと同じフォルダに保存
parentFolder.createFile(pdfBlob);
}
謝辞
「一つのドキュメントファイルにテンプレートを元に成形されたデータを追記していく」スクリプトの書き方で苦労していましたが、chatGPT(GPT-4)にその解決方法を教えてもらいました。ネット上に多くの知識を蓄積してくださった世界中の皆様、それを集約してくれるchatGPTさん、ありがとうございます。これからも困った時にはサポートをお願いします。