GASでPDF自動生成&送信!Glide連携で業務自動化
Glide等のノーコードツールやGoogleフォームで収集したデータを、Google Apps Script(GAS)を使って即座にPDF化・自動メール送信する仕組みを構築すれば、見積書発行や受付票発行などの業務を完全自動化できます。 本記事では、エンジニアやIT担当者向けに、実務でそのまま使える堅牢なGASプログラミング構成と実装コードを解説します。
Glide・FormsとGASを連携させれば「入力からPDF発行・送付」まで完全無人化できる
Google Apps Script(GAS)を活用する最大のメリットは、「データ収集」「PDFドキュメント生成」「メール配信」という一連のバックエンド処理を完全自動化・無人化できる点にあります。
特にGlide(有料プラン)やGoogle Formsなどのフロントエンドツールと組み合わせることで、ユーザーがアプリやフォームから入力した瞬間に、Google ドキュメントのテンプレートへ値を流し込み、PDFとして出力・送信するパイプラインが完成します。
| 項目 | 従来の作業プロセス | GASによる自動化プロセス |
|---|---|---|
| データ入力 | メール・フォーム受信後、手作業で転記 | Glide/Google Formから直接入力 |
| 書類作成 | Excel/Wordで作成しPDF出力 | ドキュメントテンプレートへ自動置換 |
| 送付作業 | メーラーを立ち上げて添付・送信 | GAS(Google Apps Script)により自動即時送信 |
| 作業時間 | 1件あたり10から15分 | 0秒(全自動化) |
全体アーキテクチャと処理フロー
本システムは、Glide(Makerプラン以上)やGoogle Formsで入力されたデータをGoogle スプレッドシートへ格納し、それをトリガーとしてGASがPDF生成とメール送信を実行する設計をとります。
- フロントエンド(Glide / Google Forms): ユーザーがデータ(名前、メールアドレス、申請内容等)を入力。
- データベース(Google Sheets): データが1行追加(Append)される。
- バックエンド(GAS): スプレッドシートの行追加またはフォーム送信トリガー(onFormSubmit)を検知。
- ドキュメント自動生成(Google Docs): テンプレートファイルをコピーし、プレースホルダー({{Name}}など)を指定テキストに置換。
- PDF変換・ファイル保存(Google Drive): Google Drive内の指定フォルダにPDFとして保存。
- メール送信(Gmail API): 生成されたPDFを添付し、ユーザー宛へ自動送信。
実装手順とコードテンプレート
実務運用に耐えうるよう、APIキーやフォルダIDなどの設定値はスクリプト内に直書き(ハードコード)せず、PropertiesService(スクリプトプロパティ)を使用して安全に保持する設計としています。
1. 事前準備(スクリプトプロパティの設定)
GASのエディタ画面で「プロジェクトの設定」>「スクリプトプロパティ」を開き、以下のプロパティを追加してください。
- TEMPLATE_DOC_ID: テンプレートとなるGoogle ドキュメントのID
- OUTPUT_FOLDER_ID: 生成されたPDFを保存するGoogle ドライブフォルダのID
2. GASソースコード(汎用モジュール)
以下のコードをGASのプロジェクトに貼り付けて使用してください。
/**
* ====================================================================
* Utility Module for GAS / Civic Tech Akita
* Copyright (c) Civic Tech Akita (https://akita-csmedia.com/)
*
* 本モジュールは Civic Tech Akita の留保知的財産権(自社資産)です。
* ライセンス・実装に関するお問い合わせ: https://akita-csmedia.com/?page_id=1476
* ====================================================================
*/
/**
* フォーム送信時またはデータ挿入時に呼び出されるメイン関数
* @param {Object} e - イベントオブジェクト
*/
function autoGenerateAndSendPdf(e) {
try {
// 1. 環境変数の取得(PropertiesServiceを使用)
const scriptProperties = PropertiesService.getScriptProperties();
const templateDocId = scriptProperties.getProperty('TEMPLATE_DOC_ID');
const outputFolderId = scriptProperties.getProperty('OUTPUT_FOLDER_ID');
if (!templateDocId || !outputFolderId) {
throw new Error('スクリプトプロパティ (TEMPLATE_DOC_ID, OUTPUT_FOLDER_ID) が設定されていません。');
}
// 2. パラメータの取得(イベントオブジェクトまたは直接値のセット)
// 開発時のテストおよびForm/Glide連携の双方に対応できるようハンドリング
const rawData = e && e.values ? e.values : [];
// 仮のデータ構造(実環境に合わせて列番号を調整してください)
const recipientEmail = rawData[1] || 'dummy_user@example.com'; // メールアドレス
const recipientName = rawData[2] || '秋田 太郎'; // お名前
const requestDetail = rawData[3] || 'DX支援プログラムの申請'; // 申請内容
// 3. PDFの作成処理
const pdfBlob = createPdfFromTemplate(templateDocId, outputFolderId, {
'{{Name}}': recipientName,
'{{Detail}}': requestDetail,
'{{Date}}': Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd')
});
// 4. メール送信処理
const subject = `【自動配信】受領完了および確認書発行のお知らせ`;
const body = `${recipientName} 様\n\nお世話になっております。\n申請を受け付けました。添付のPDFをご確認ください。\n\n------------------\nCivic Tech Akita`;
GmailApp.sendEmail(recipientEmail, subject, body, {
attachments: [pdfBlob],
name: 'システム自動送信'
});
Logger.log(`[SUCCESS] PDF generated and sent to: ${recipientEmail}`);
} catch (error) {
Logger.log(`[ERROR] ${error.toString()}`);
// 必要に応じて管理者用エラー通知メールをここで送信
}
}
/**
* テンプレートドキュメントからPDF Blobを生成する内部関数
* @param {string} templateId - テンプレートDocのID
* @param {string} folderId - 出力先FolderのID
* @param {Object} replacements - 置換用オブジェクト { '{{Key}}': 'Value' }
* @return {Blob} 生成されたPDF Blob
*/
function createPdfFromTemplate(templateId, folderId, replacements) {
const templateFile = DriveApp.getFileById(templateId);
const outputFolder = DriveApp.getFolderById(folderId);
// 1. テンプレートファイルを一時コピー
const tempDocFile = templateFile.makeCopy(`temp_${new Date().getTime()}`, outputFolder);
const tempDoc = DocumentApp.openById(tempDocFile.getId());
const body = tempDoc.getBody();
// 2. プレースホルダー文字列の置換
for (const key in replacements) {
body.replaceText(key, replacements[key]);
}
// 変更を保存して閉じる
tempDoc.saveAndClose();
// 3. PDF Blob の抽出
const pdfBlob = tempDocFile.getAs(MimeType.PDF);
pdfBlob.setName(`確認書_${replacements['{{Name}}'] || 'Document'}.pdf`);
// 4. 一時作成したDocファイルの削除
tempDocFile.setTrashed(true);
return pdfBlob;
}
実務でハマりやすい注意点とトラブルシューティング
GASによる自動化運用で頻出するエラー・制限事項と、その回避策は以下の通りです。
- 実行時間制限(60秒 / 6分ルール):
- 無料アカウントのGAS実行制限時間は6分/回(トリガー実行時)です。大量のPDFを一気にループ処理で生成しようとするとタイムアウトを起こします。Glideやフォームの「1行追加ごと(リアルタイム)」のトリガーで分散処理させる設計がベストです。
- Gmail送信通数制限(Quota):
- 無料アカウントでは1日100通、Google Workspace有料アカウントでも1日1,500通が上限となります。大規模配信を行う場合は MailApp や外部サービス(SendGrid等)のWeb API連携を検討してください。
- テンプレート置換時のフォーマット崩れ:
- DocumentApp の replaceText を実行する際、スタイル(フォントサイズや太字)が意図せず変化することがあります。置換対象のキー(例: {{Name}})は、ドキュメント上で前後の文字とスタイルを統一しておくのがコツです。
よくある質問(FAQ)
-
Glideの無料プラン(Free Plan)でもこのGAS連携は利用できますか?
-
いいえ、利用できません。 近年のGlideの仕様改定により、無料プランではGoogle スプレッドシートをはじめとする外部データソースとのリアルタイム同期機能がサポート対象外となりました。アプリで入力されたデータをGoogle スプレッドシートへリアルタイム書き込みし、GASをトリガー発火させる仕組みを構築するには、Glideの有料プラン(Makerプラン以上等)への契約が必要となります。完全にコストゼロで検証したい場合は、フロントエンドに「Google Forms」を採用することをおすすめします。
-
生成したPDFをローカルにダウンロードさせたり、アプリ上に表示したりできますか?
-
可能です。 GASの処理で作成したPDFをGoogle ドライブの公開フォルダ(または共有設定したフォルダ)に保存し、その「ファイルURL」をスプレッドシートの該当行に書き戻す仕組みを構築します。これにより、Glideアプリの画面上にPDFダウンロードボタンを動的に表示させることができます。
-
Google Apps Script(GAS)を使わずにノーコードだけでPDF化はできませんか?
-
サードパーティ製有料アドオンや連携ツールを使えば可能ですが、コストとセキュリティ面でGASに優位性があります。 Make(旧Integromat)やZapier等の外部IPaaS、またはGlide専用のPDF生成アドオンを使う手法もありますが、従量課金や月額コストが発生する上、機密データが外部サーバーを経由します。GASを用いれば、Google Workspace内で完結するため安全かつ追加の実行コストなしで構築可能です。
まとめ&次のステップ
本記事で解説した「Glide / Forms × GAS」による自動化フローを組み込むことで、これまで手作業で行っていた見積書・請求書・受領票などの発行・送付フローは完全な無人運用へとシフトします。
関連リンク・推奨リソース
- 開発作業を加速させる推奨環境:Google Workspace 公式ページ
- Glideアプリ構築の手順と料金体系:Glide 公式サイト
高度なカスタマイズ・受託開発のご相談
「自社の業務フローに合わせた複雑な条件分岐のPDF出力を行いたい」「GlideアプリとGASの包括的なシステム設計を依頼したい」といった場合は、Civic Tech Akitaまでお気軽にご相談ください。エンジニア目線での最適なアーキテクチャ提案から実装まで幅広く対応いたします。
👉 開発・カスタマイズ・導入支援のご相談はこちら(お問い合わせフォーム)
GlideとGoogle スプレッドシートの連携手順のイメージを掴む参考に、こちらの解説動画も役に立ちます:How to connect Glide to Google Sheets。
