LoginSignup
0
2

More than 1 year has passed since last update.

【GAS】テンプレートを元にレポート一覧を作成

Posted at

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には実行時間の制限があります。処理するデータが非常に大量であったり、複雑な処理が必要な場合、スクリプトの実行時間が制限を超える可能性があります。
  • エラーハンドリング: 現在のスクリプトでは、エラーハンドリングが最小限になっています。実際に使用する場合、適切なエラーハンドリングを追加して、スクリプトの安定性と堅牢性を向上させることが望ましいです。

お願い

テンプレートに画像を含めたものの開発を最終目標とし様々なコードを試しましたが、先行事例も見当たらず断念しました。アドバイスいただけると幸いです。

スクリプト

コード.gs
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さん、ありがとうございます。これからも困った時にはサポートをお願いします。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2