【有料級】Googleフォームの回答内容をGASで取得し、Googleドキュメント内の本文を書き換え&PDF化してメールを自動送信しよう!

近年、Googleフォームの回答内容を活用した業務効率化のニーズは非常に高まっています

そこで、本記事ではGoogleフォームの回答内容をGoogle Apps Script(GAS)を用いて取得し、それを元にGoogleドキュメントを自動生成&PDF化してメール送信する手法について解説します

本記事の内容
  • Googleフォームの回答内容をGASで取得して、Googleドキュメントで作成したテンプレートに取得した値を落とし込む
  • 自動作成したGoogleドキュメントをPDF変換する
  • 変換したPDFを添付ファイルとして相手先にメールを送信する
こーすけ先生

私が過去に実際に扱った案件をベースに記事を書いています
正直、有料級の情報だと思います!

この記事を読めば、Googleフォームの回答データを取得し、Googleドキュメント内に反映する方法を学ぶことができます!めちゃくちゃ便利なので、是非読んでいってください!

この記事の執筆者について
  • GASの人
  • ITベンダSEとして12年勤務する中で民間、金融、官公庁の現場を一通り経験済
  • 現在は公務員をやりながら起業に向けて着々と準備中
GASなら任せろ!

​GASを極めたい方や、業務の効率化を図りたい方は、ぜひこの記事を読んください!
難しいことはGASに任せて、我々人間は楽しちゃいましょう!

こーすけ先生

当ブログでは実際に仕事でGASを扱っている私が、GASの魅力について徹底的に取り上げていきます!

目次

事前準備

本記事で取り組む演習
  • Googleフォームを作成&回答
  • Googleドキュメントで、欠席届のテンプレートを作成する
  • PDFを保存するためのフォルダを作成
こーすけ先生

本記事は初心者の方向けに丁寧に解説しているので、事前準備を飛ばして先に進みたい!という方はここをクリックして、【お題:Googleフォームの各項目を取得し、Googleドキュメントに反映後、PDF変換してメール送信する】までジャンプしてください

【事前準備①】Googleフォームを作成する

スクロールできます
項目名 タイプ必須
氏名を選択してくださいプルダウン
欠席日を入力してください日付
連日にまたがって欠席する場合は、欠席期間の終了日を入力してください日付
届出理由を選択してくださいラジオボタン
こーすけ先生

参考に私が作成したフォームは以下となります!

がすぴょん

フォームを作成したら回答してみてね!
回答0件だとエラーになってしまうよ

【事前準備②】Googleドキュメントを作成する

こーすけ先生

それでは、次にGoogleドキュメントで欠席届テンプレートを作成しましょう!

どんな様式でも構いませんが上記フォームの値をマッピングさせるため、それを意識して作成してみて下さい!

こーすけ先生

今回、こちらの「(練習)欠席届」を使って演習します!
必要に応じてコピーして使ってください!

{{}}(可変文字部)について

がすぴょん

この{{date}}みたいに波括弧で囲んであるのは何なの?

こーすけ先生

波括弧の部分は「可変文字部」といって、{{}}内を入力内容に書き換える魔法のような存在なんだ!詳しくは、以前の記事で説明しているよ!
是非読んでみてね!

【事前準備③】PDF出力場所の作成

こーすけ先生

Googleフォームの回答をGoogleドキュメントに反映し、PDFに変換するため、その出力先を作成しておきましょう!

Googleフォームはコンテナバインド型で開くため、IDは不要ですが、注文書テンプレートPDF出力場所のIDは事前に取得しておきましょう!

がすぴょん

IDは緑色の四角で囲った部分だよ!

【お題】Googleフォームの各項目を取得し、Googleドキュメントに反映後、PDF変換してメール送信する

ひとつひとつのサービスをつなぎ合わせるイメージ
本記事で取り組む演習
  • Googleフォームの回答内容をGASで取得して、Googleドキュメントで作成したテンプレートに取得した値を落とし込む
  • GoogleドキュメントをPDF変換する
  • 変換したPDFを添付ファイルとして相手先にメールを送信する
こーすけ先生

Googleフォームの方で1件、回答しておくのを忘れないようにしてくださいね!
(回答がないとエラーになってしまうため)

まずは全体のコードを確認

// 欠席届テンプレートファイル
const DOC_TEMPLATE = DriveApp.getFileById('〇〇〇〇〇〇(自分のドキュメントID)');
// PDF出力先
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇(自分のフォルダID)');

function gaslog_formSubmit(e) {
  let itemResponses;
  // フォームの回答をイベントオブジェクトまたはフォーム自身から取得する。
  if (e !== undefined) {
    itemResponses = e.response.getItemResponses();
  } else {
    const wFormRes = FormApp.getActiveForm().getResponses();
    itemResponses =  wFormRes[wFormRes.length-1].getItemResponses();
  }

  // 回答をもとに欠席届を作成する 
  let wFileRtn = createGDoc(itemResponses);
  // PDF変換してファイルIDを取得する
  let wPdfId = createPdf(wFileRtn[0], wFileRtn[1]);
  // PDF変換したあとは元ファイルを削除する
  DriveApp.getFileById(wFileRtn[0]).setTrashed(true);
  
  // 今回はPDFファイルを添付してメールを送信する
  sendEmailEx(
    '***************@gmail.com'
    , '【自動送信メール】欠席届の送信'
    , `受講生より欠席届が送信されました。`
    , {attachments: DriveApp.getFileById(wPdfId).getBlob()}
  );
}

function createGDoc(itemResponses) {
  // テンプレートファイルをコピーする
  const wCopyFile = DOC_TEMPLATE.makeCopy()
        , wCopyFileId = wCopyFile.getId()
        , wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
  let wCopyDocBody = wCopyDoc.getBody()                 // Googleドキュメント内の本文を取得する
      , today = dayjs.dayjs();
  // 本日の日付を設定する
  wCopyDocBody = wCopyDocBody.replaceText(`{{date}}`, today.format('YYYY年MM月DD日'));
  // 以降はGoogleフォームの回答をマッピングする
  itemResponses.forEach(function(itemResponse){
    switch (itemResponse.getItem().getTitle()) {
      case '氏名を選択してください。':
        wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
        break;

      case '欠席日を入力してください。':
        dateF = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        break;

      case '連日にまたがって欠席する場合は、欠席期間の終了日を入力してください。': // 欠席の場合のみ対応
        if ( itemResponse.getResponse()!='' ) {
          dateT = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        } else {
          dateT = dateF;
        }
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydatefrom}}`, dateF);
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydateto}}`, dateT);
        break;

      case '届出理由を選択してください。':
        wCopyDocBody = wCopyDocBody.replaceText(`{{reason}}`, itemResponse.getResponse());
        break;

      default:
        break;
    }
  });
  wCopyDoc.saveAndClose();
  // ファイル名を変更する
  let fileName = '欠席届_'+today.format('YYYYMMDD');
  wCopyFile.setName(fileName);
  // コピーしたファイルIDとファイル名を返却する(あとでこのIDをもとにPDFに変換するため)
  return [wCopyFileId, fileName];
}

function createPdf(docId, fileName){
  // PDF変換するためのベースURLを作成する
  let wUrl = `https://docs.google.com/document/d/${docId}/export?exportFormat=pdf`;

  // headersにアクセストークンを格納する
  let wOtions = {
    headers: {
      'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
    }
  }; 
  // PDFを作成する
  let wBlob = UrlFetchApp.fetch(wUrl, wOtions).getBlob().setName(fileName + '.pdf');

  //PDFを指定したフォルダに保存する
  return PDF_OUTDIR.createFile(wBlob).getId();
}

function sendEmailEx(_recipient, _subject, _body, _option) {
  // 引数の内容でメールを下書き保存する
  const mailDraft = GmailApp.createDraft(_recipient, _subject, _body, _option);
  // 下書き保存したメールIDから下書きを取得し、メール送信を依頼する
  GmailApp.getDraft(mailDraft.getId()).send();
}
こーすけ先生

順を追って解説していきますね!

【STEP1】Googleフォームのフォーム項目をGASで取得する

がすぴょん

作成したGoogleフォームの「︙」をクリックして「〈〉スクリプトエディタ」から、コンテナバインド型でエディタを開こう!

function gaslog_formSubmit(e) {
  let itemResponses;
  // フォームの回答をイベントオブジェクトまたはフォーム自身から取得する。
  if (e !== undefined) {
    itemResponses = e.response.getItemResponses();
  } else {
    const wFormRes = FormApp.getActiveForm().getResponses();
    itemResponses =  wFormRes[wFormRes.length-1].getItemResponses();
  }
  console.log(itemResponses);
}
18:50:29	お知らせ	実行開始
18:50:31	情報	[ { toString: [Function],
    getItem: [Function],
    setFeedback: [Function],
    setScore: [Function],
    getScore: [Function],
    getFeedback: [Function],
    getResponse: [Function] },
…
  { toString: [Function],
    getItem: [Function],
    setFeedback: [Function],
    setScore: [Function],
    getScore: [Function],
    getFeedback: [Function],
    getResponse: [Function] } ]
18:50:30	お知らせ	実行完了
こーすけ先生

オブジェクトがしっかり取得できていることが分かりましたね!

【STEP1】の補足説明

こーすけ先生

補足説明が不要な方は【STEP2】までジャンプしてください!

  if (e !== undefined) {
    itemResponses = e.response.getItemResponses();
  } 

もし 、イベントオブジェクトeundefined でない場合、イベントオブジェクトから回答情報を取得します

e.response はイベントオブジェクト内のフォームの回答に関するプロパティであり、getItemResponses() メソッドは回答に含まれる個々の質問と回答のペアを含むオブジェクトの配列を返します

else {
    const wFormRes = FormApp.getActiveForm().getResponses();
    itemResponses =  wFormRes[wFormRes.length-1].getItemResponses();
  }

eundefined である場合、このブロックが実行されます

こーすけ先生

つまり、直接フォームの回答を取得する必要があります

const wFormRes = FormApp.getActiveForm().getResponses();

フォームの全ての回答を取得し、それを wFormRes という変数に格納しています

itemResponses =  wFormRes[wFormRes.length-1].getItemResponses();

wFormRes 配列の最後の要素(最新の回答)を取得し、その回答に含まれる質問と回答のペアを含むオブジェクトの配列を itemResponses に代入しています

こーすけ先生

この条件分岐を使用することで、送信イベントが発生した場合と、直接回答を取得する場合の2つのケースに対応できます!

イベントオブジェクトが存在する場合は、それから回答情報を取得し、存在しない場合はフォームの全回答から最新の回答を取得しています

【STEP2】Googleドキュメントで作成したテンプレートにSTEP1で取得した値を設定する

// 欠席届テンプレートファイル
const DOC_TEMPLATE = DriveApp.getFileById('〇〇〇〇〇〇(自分のドキュメントID)');
// PDF出力先
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇(自分のフォルダID)');

function gaslog_formSubmit(e) {
  let itemResponses;
  // フォームの回答をイベントオブジェクトまたはフォーム自身から取得する。
  if (e !== undefined) {
    itemResponses = e.response.getItemResponses();
  } else {
    const wFormRes = FormApp.getActiveForm().getResponses();
    itemResponses =  wFormRes[wFormRes.length-1].getItemResponses();
  }
  
  // 回答をもとに欠席届を作成する 
  let wFileRtn = createGDoc(itemResponses);
}

function createGDoc(itemResponses) {
  // テンプレートファイルをコピーする
  const wCopyFile = DOC_TEMPLATE.makeCopy()
        , wCopyFileId = wCopyFile.getId()
        , wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
  let wCopyDocBody = wCopyDoc.getBody()                 // Googleドキュメント内の本文を取得する
      , today = dayjs.dayjs();
  // 本日の日付を設定する
  wCopyDocBody = wCopyDocBody.replaceText(`{{date}}`, today.format('YYYY年MM月DD日'));
  // 以降はGoogleフォームの回答をマッピングする
  itemResponses.forEach(function(itemResponse){
    switch (itemResponse.getItem().getTitle()) {
      case '氏名を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
        break;

      case '欠席日を入力してください':
        dateF = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        break;

      case '連日にまたがって欠席する場合は、欠席期間の終了日を入力してください': // 欠席の場合のみ対応
        if ( itemResponse.getResponse()!='' ) {
          dateT = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        } else {
          dateT = dateF;
        }
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydatefrom}}`, dateF);
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydateto}}`, dateT);
        break;

      case '届出理由を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{reason}}`, itemResponse.getResponse());
        break;

      default:
        break;
    }
  });
  wCopyDoc.saveAndClose();
  // ファイル名を変更する
  let fileName = '欠席届_'+today.format('YYYYMMDD');
  wCopyFile.setName(fileName);
  // コピーしたファイルIDとファイル名を返却する(あとでこのIDをもとにPDFに変換するため)
  return [wCopyFileId, fileName];
}
こーすけ先生

これを実行すると、作成した欠席届テンプレートと同階層に値が設定された欠席届が作成されます!ゴールはもうすぐそこですね!

がすぴょん

いや、待って!
僕の方はエラーになっちゃうよ

こーすけ先生

ああ「dayjs」か!何気なく使っちゃったけど、
ちゃんと説明するね!

caseブロックにて、自分がGoogleフォームに設定した質問文と1文字でも違うとエラーになってしまうので、一字一句間違えないように気を付けてください!

Day.jsライブラリを追加する

STEP
メニューバーから「+(ライブラリを追加)」をクリック
STEP
出てきたダイアログのスクリプトIDに以下のIDを入力し、「検索」をクリック

1ShsRhHc8tgPy5wGOzUvgEhOedJUQD53m-gd8lG2MOgs-dXC_aCZn9lFB

STEP
「追加」をクリックすると、GAS上で「Day.jsライブラリ」を使用できるようになる
がすぴょん

エラーが消えてちゃんと今日の日付が出るようになった!

こーすけ先生

GASのライブラリは、GASプロジェクト内に直接コードを書くことなく、外部のスクリプトを利用する仕組みなんだ!
便利だからこの機会に覚えておいて!

Google Apps Script (GAS) の「ライブラリ」は、外部のスクリプトやコードをプロジェクトに統合するための機能です。ライブラリを使用すると、他のプロジェクトや外部のスクリプトで共通の関数やクラスを再利用できます。

【STEP2】の補足説明

こーすけ先生

補足説明が不要な方は【STEP3】までジャンプしてください!

// 欠席届テンプレートファイル
const DOC_TEMPLATE = DriveApp.getFileById('〇〇〇〇〇〇(自分のドキュメントID)');
// PDF出力先
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇(自分のフォルダID)');

DOC_TEMPLATE に、欠席届のテンプレートファイルのGoogleドキュメントIDを指定します
PDF_OUTDIR に、PDF出力先のフォルダのGoogleドライブIDを指定します

こーすけ先生

欠席届のテンプレートファイルとPDF出力先を指定してあげています!
後に、この元ファイルをコピーする時に使います!

function createGDoc(itemResponses) {
  // テンプレートファイルをコピーする
  const wCopyFile = DOC_TEMPLATE.makeCopy()
        , wCopyFileId = wCopyFile.getId()
        , wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
   ︙
   ︙
   ︙
    }
  });

このcreateGDoc関数は、Google Apps Scriptを使用して欠席届を作成する際に、指定されたテンプレートファイルをコピーし、Googleドキュメント本文中の{{可変文字部}}部分を、Googleフォームの回答内容を置き換えて新しいファイルを生成するためのものです

  const wCopyFile = DOC_TEMPLATE.makeCopy()
        , wCopyFileId = wCopyFile.getId()
        , wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
  let wCopyDocBody = wCopyDoc.getBody()                 // Googleドキュメント内の本文を取得する
      , today = dayjs.dayjs();
  // 本日の日付を設定する
  wCopyDocBody = wCopyDocBody.replaceText(`{{date}}`, today.format('YYYY年MM月DD日'));

DOC_TEMPLATEから取得したテンプレートファイルをmakeCopy()メソッドを使用してコピーしています

その後、コピーされたファイルのIDを取得し、DocumentApp.openById()メソッドを使用して、コピーしたファイルをGoogleドキュメントとして開きます

コピーしたファイルの本文を取得し、本日の日付をdayjsライブラリを使用して取得し、テンプレート内の{{date}}という変数に置き換えています

がすぴょん

Day.jsすごすぎるね!

// 以降はGoogleフォームの回答をマッピングする
  itemResponses.forEach(function(itemResponse){
    switch (itemResponse.getItem().getTitle()) {
      case '氏名を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
        break;

      case '欠席日を入力してください':
        dateF = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        break;

      case '連日にまたがって欠席する場合は、欠席期間の終了日を入力してください': // 欠席の場合のみ対応
        if ( itemResponse.getResponse()!='' ) {
          dateT = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        } else {
          dateT = dateF;
        }
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydatefrom}}`, dateF);
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydateto}}`, dateT);
        break;

      case '届出理由を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{reason}}`, itemResponse.getResponse());
        break;

      default:
        break;
    }
  });
こーすけ先生

この部分は、Googleフォームからの回答(itemResponses)を、Googleドキュメント本文中の{{可変文字部}}部分に置き換える作業をしているよ!

switch文

switch文は以下のように動作します

let fruit = 'apple';

switch (fruit) {
  case 'apple':
    console.log('It is an apple.');
    break;
  case 'banana':
    console.log('It is a banana.');
    break;
  default:
    console.log('It is neither an apple nor a banana.');
}
  • fruitの評価結果に基づいて、対応するcaseブロックが実行されます
  • マッチしたcaseブロックの処理が実行されたら、break文がないと次のcaseブロックも順次実行されます。breakがあるとswitch文から抜け出します
  • expressionがどのcaseにもマッチしない場合は、defaultブロックが実行されます
    defaultは省略可能)
こーすけ先生

この例では、fruitの値が'apple'なので、最初のcaseブロックが実行されます!
breakがあるため、それ以降のcaseは実行されません

// 以降はGoogleフォームの回答をマッピングする
  itemResponses.forEach(function(itemResponse){
    switch (itemResponse.getItem().getTitle()) {
      case '氏名を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
        break;

      case '欠席日を入力してください':
        dateF = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        break;

      case '連日にまたがって欠席する場合は、欠席期間の終了日を入力してください': // 欠席の場合のみ対応
        if ( itemResponse.getResponse()!='' ) {
          dateT = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        } else {
          dateT = dateF;
        }
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydatefrom}}`, dateF);
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydateto}}`, dateT);
        break;

      case '届出理由を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{reason}}`, itemResponse.getResponse());
        break;

      default:
        break;
    }
  });
こーすけ先生

switch文を利用することによって、「〇〇」という質問に対しての回答をGoogleドキュメント本文中の{{可変文字部}}部分に置き換える作業をしているよ!

  wCopyDoc.saveAndClose();
こーすけ先生

コピーして本文を書き換えたGoogleドキュメントを保存して閉じているよ

  // ファイル名を変更する
  let fileName = '欠席届_'+today.format('YYYYMMDD');
  wCopyFile.setName(fileName);
  // コピーしたファイルIDとファイル名を返却する(あとでこのIDをもとにPDFに変換するため)
  return [wCopyFileId, fileName];
こーすけ先生

コピーして本文を書き換えたGoogleドキュメントの名前を「欠席届+日付」にして保存する作業をしているよ!

【STEP3】自動作成したGoogleドキュメントをPDF変換する

function createPdf(docId, fileName){
  // PDF変換するためのベースURLを作成する
  let wUrl = `https://docs.google.com/document/d/${docId}/export?exportFormat=pdf`;

  // headersにアクセストークンを格納する
  let wOtions = {
    headers: {
      'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
    }
  }; 
  // PDFを作成する
  let wBlob = UrlFetchApp.fetch(wUrl, wOtions).getBlob().setName(fileName + '.pdf');

  //PDFを指定したフォルダに保存する
  return PDF_OUTDIR.createFile(wBlob).getId();
}
こーすけ先生

createPdf は、【STEP2】で作成したGoogle ドキュメントを PDF に変換し、指定したフォルダに保存する作業をしてます!

こーすけ先生

PDFじゃなくてWordファイル化したい場合はこちらの記事をご参照ください!

【STEP3】の補足説明

こーすけ先生

補足説明が不要な方は【STEP4】までジャンプしてください!

function createPdf(docId, fileName){
  // PDF変換するためのベースURLを作成する
  let wUrl = `https://docs.google.com/document/d/${docId}/export?exportFormat=pdf`;

ここでポイントとなるのは、https://docs.google.com/document/d/${docId}/export?exportFormat=pdfのURLとなります

  • https://docs.google.com/document/d/${docId}までが対象のGoogleドキュメントを指しています
  • そのあとのexport?エクスポートを指示しており、GETパラメタへ続きます
  • exportFormat=pdfは読んで字のごとく、エクスポートの形式を指示します
こーすけ先生

${docId} には、新しく作成したGoogleドキュメントファイルのIDが挿入されています!

// headersにアクセストークンを格納する
  let wOtions = {
    headers: {
      'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
    }
  }; 

ScriptApp.getOAuthToken() は Google Apps Script のメソッドで、現在のスクリプトに認証されたユーザーのアクセストークンを取得します
(アクセストークンは、Google サービスへのアクセス許可を持つユーザーを識別し、認証を行います)

こーすけ先生

これにより、認証済みユーザーとして Google ドキュメントに
アクセスし、PDF ファイルを生成できるようになります

このアクセストークンを通じて、スクリプトはユーザーのアカウント権限を利用し、 Google ドキュメントにアクセスできるようになります!

Bearer認証

'Authorization':Bearer〇〇部分は、HTTP リクエストを送信する際、API やウェブサーバーに認証情報を送信する必要がある場合によく使用されます

Bearer認証はアクセストークン認証といい、ログインID・パスワードなどでユーザ認証を行なった後に、サービスから発行されるアクセストークン(GASにおいては、スクリプト自体のアクセストークンgetOAuthToken()を使用) を受け取って、APIのリクエスト時に送信する方式です。

ヘッダー項目を
Authorization: Bearer {アクセストークン}
で設定して、HTTPリクエストを送信します

 // PDFを作成する
let wBlob = UrlFetchApp.fetch(wUrl, wOtions).getBlob().setName(fileName + '.pdf');

//PDFを指定したフォルダに保存する
return PDF_OUTDIR.createFile(wBlob).getId();
こーすけ先生

この関数は Google ドキュメントを PDF に変換し、指定されたフォルダに保存して、その PDF の ID を取得するためのものです

【STEP4】 変換したPDFを添付ファイルとして相手先にメールを送信する

// 欠席届テンプレートファイル
const DOC_TEMPLATE = DriveApp.getFileById('〇〇〇〇〇〇(自分のドキュメントID)');
// PDF出力先
const PDF_OUTDIR = DriveApp.getFolderById('〇〇〇〇〇〇(自分のフォルダID)');

function gaslog_formSubmit(e) {
  let itemResponses;
  // フォームの回答をイベントオブジェクトまたはフォーム自身から取得する。
  if (e !== undefined) {
    itemResponses = e.response.getItemResponses();
  } else {
    const wFormRes = FormApp.getActiveForm().getResponses();
    itemResponses =  wFormRes[wFormRes.length-1].getItemResponses();
  }

  // 回答をもとに欠席届を作成する 
  let wFileRtn = createGDoc(itemResponses);
  // PDF変換してファイルIDを取得する
  let wPdfId = createPdf(wFileRtn[0], wFileRtn[1]);
  // PDF変換したあとは元ファイルを削除する
  DriveApp.getFileById(wFileRtn[0]).setTrashed(true);
  
  //【STEP4】変換したPDFを添付ファイルとして相手先にメールを送信する
  // 今回はPDFファイルを添付してメールを送信する
  sendEmailEx(
    '***************@gmail.com'
    , '【自動送信メール】欠席届の送信'
    , `受講生より欠席届が送信されました。`
    , {attachments: DriveApp.getFileById(wPdfId).getBlob()}
  );
}

function createGDoc(itemResponses) {
  // テンプレートファイルをコピーする
  const wCopyFile = DOC_TEMPLATE.makeCopy()
        , wCopyFileId = wCopyFile.getId()
        , wCopyDoc = DocumentApp.openById(wCopyFileId); // コピーしたファイルをGoogleドキュメントとして開く
  let wCopyDocBody = wCopyDoc.getBody()                 // Googleドキュメント内の本文を取得する
      , today = dayjs.dayjs();
  // 本日の日付を設定する
  wCopyDocBody = wCopyDocBody.replaceText(`{{date}}`, today.format('YYYY年MM月DD日'));
  // 以降はGoogleフォームの回答をマッピングする
  itemResponses.forEach(function(itemResponse){
    switch (itemResponse.getItem().getTitle()) {
      case '氏名を選択してください。':
        wCopyDocBody = wCopyDocBody.replaceText(`{{name}}`, itemResponse.getResponse());
        break;

      case '欠席日を入力してください':
        dateF = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        break;

      case '連日にまたがって欠席する場合は、欠席期間の終了日を入力してください': // 欠席の場合のみ対応
        if ( itemResponse.getResponse()!='' ) {
          dateT = dayjs.dayjs(itemResponse.getResponse()).format('YYYY年MM月DD日');
        } else {
          dateT = dateF;
        }
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydatefrom}}`, dateF);
        wCopyDocBody = wCopyDocBody.replaceText(`{{applydateto}}`, dateT);
        break;

      case '届出理由を選択してください':
        wCopyDocBody = wCopyDocBody.replaceText(`{{reason}}`, itemResponse.getResponse());
        break;

      default:
        break;
    }
  });
  wCopyDoc.saveAndClose();
  // ファイル名を変更する
  let fileName = '欠席届_'+today.format('YYYYMMDD');
  wCopyFile.setName(fileName);
  // コピーしたファイルIDとファイル名を返却する(あとでこのIDをもとにPDFに変換するため)
  return [wCopyFileId, fileName];
}

function createPdf(docId, fileName){
  // PDF変換するためのベースURLを作成する
  let wUrl = `https://docs.google.com/document/d/${docId}/export?exportFormat=pdf`;

  // headersにアクセストークンを格納する
  let wOtions = {
    headers: {
      'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
    }
  }; 
  // PDFを作成する
  let wBlob = UrlFetchApp.fetch(wUrl, wOtions).getBlob().setName(fileName + '.pdf');

  //PDFを指定したフォルダに保存する
  return PDF_OUTDIR.createFile(wBlob).getId();
}

//【STEP4】変換したPDFを添付ファイルとして相手先にメールを送信する
function sendEmailEx(_recipient, _subject, _body, _option) {
  // 引数の内容でメールを下書き保存する
  const mailDraft = GmailApp.createDraft(_recipient, _subject, _body, _option);
  // 下書き保存したメールIDから下書きを取得し、メール送信を依頼する
  GmailApp.getDraft(mailDraft.getId()).send();
}
こーすけ先生

sendEmailEx は、指定された受信者、件名、本文、およびオプションでメールの下書きを作成し、その下書きを取得してメールを送信するものです!

がすぴょん

ちゃんとメールが送られてきた!

こーすけ先生

Googleフォームを用いたドキュメント作成&メール送信はけっこう使えると思うから覚えておこうね!

まとめ

今回は「GASを用いてGoogleフォームの回答を取得し、Googleドキュメント本文を書き換え、PDF化&メール送信を自動化しよう」というテーマで解説を行いました

こーすけ先生

本記事を読んで、「実業務でも使えるのでは…!」と思った方も多いのではないでしょうか

GoogleフォームやGoogleドキュメントなど、単品で考えると「あぁ便利だな」というレベルに過ぎませんが組み合わせると「とんでもなく便利!!!」 となります

ぜひ、皆さんも実業務での活用に取り組んでみてください
引き続き、GASを楽しんでいきましょう!!

「画像も扱いたい!」という方向けの記事もご用意したので、是非チェックしてみてくださいね!

こーすけ先生

X(旧:Twieer)にて、ブログの更新やQiita記事の更新、GAS情報をお届けしますので、是非フォローしてください!

100日後に起業する公務員

こーすけ先生

退職までの漫画をゆるくXにて更新中!
是非フォローしてね!

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

GASの人。ITベンダSEとして12年勤務し、民間、金融、官公庁の現場を一通り経験済。html、css、JavaScript、Java、PHPも分かります。最近は専らGASで小規模アプリケーションを頻繁に作成しています。GASのことなら何でもお任せあれ!現在は公務員として働きながら、起業に向けて着々と準備中です!

コメント

コメントする

CAPTCHA


目次