PR

【GAS】Googleフォームから自動で返信メール~合計金額など好きな値を追加できる自由度の高い返信メール

Google Workspace

ここで紹介するGAS(diyReplay)とスプレッドシートの関数を使って、Googleフォームの回答以外の値を、返信メールの文面に簡単に表示できます

例えば、回答項目を使って計算した合計金額などを、返信メールの文章に加えることができます

スポンサーリンク

準備

テストのフォームとスプレッドシートを作りながら、作成したGAS(diyReply)の機能を説明します。

フォーム

次のようなフォームを作ります。

返信メールの件名
返信メールの本文
返信メールの宛先

スプレッドシート

スプレッドシートにリンクします。

シートを追加して、返信メールに必要なシート(ここでは、シート1)を作ります

  • 1行目(C1~E1)には、質問項目の①②③を入れます。
  • 2行目(B2~E2)には、フォームからの回答が入ります。
  • B3OFF(半角)を入れるとメールを送りません。(文章作成時のテスト時に使えます。)
  • B4返信メールの件名を入れます。ここでは、=C2を入れます。
  • B5返信メールの本文を入れます。ここでは、=D2を入れます。
  • B6返信メールの宛先を入れます。ここでは、=E2を入れます。
  • B7:必要なら、CC:を入れます。複数の場合は、aaa@gmail.com, bbb@gmail.comのように,で区切ってください。
  • B8:必要なら、BCC:を入れます。複数の場合は、aaa@gmail.com, bbb@gmail.comのように,で区切ってください。
  • B9:必要なら、送信元(自分)の表示名を入れます。
  • B10:必要なら、返信先アドレスを入れます。
  • B11(New!):必要なら、送信元アドレスを入れます。
    送信元アドレスには、Googleアカウント(Gmailアドレス)のエイリアスをご利用ください。
    (※権限のないメールアドレスでは、送信できませんのでご注意ください。)
  • B12(New!):ON(半角)を入れるとC12に回答編集用のURLを表示します。

GAS

GAS(diyReply)を登録します。スクリプトエディタを開きます。

次のGAS(diyReplay)をエディタへコピペします。

  1. function diyReply(SheetNo) {
  2.   // アクティブなフォームとスプレッドシート
  3.   const form = FormApp.getActiveForm();
  4.   if (!(SheetNo > 1)) SheetNo = 1; // SheetNoは必要なら変更する(一番左のシートが0、2番目が1、3番目が2…)
  5.   const ss = SpreadsheetApp.openById(form.getDestinationId());
  6.   // 回答シートとメール用シートを取得
  7.   const answerSheet = ss.getSheets()[0];
  8.   const mailSheet = ss.getSheets()[SheetNo];
  9.   // フォームのすべての回答を取得し、最後の(最新の)タイムスタンプを取得
  10.   const formResponses = form.getResponses();
  11.   const lastResponse = formResponses[formResponses.length - 1];
  12.   const formTimestamp = lastResponse.getTimestamp();
  13.   // 回答シートのA列(タイムスタンプ)から、最新のフォーム送信と一致する行を探す
  14.   const sheetTimestamp = answerSheet.getRange(2, 1, answerSheet.getLastRow() - 1).getValues();
  15.   let targetRow = -1;
  16.   for (let i = 0; i < sheetTimestamp.length; i++) {
  17.     if (sheetTimestamp[i][0] instanceof Date && sheetTimestamp[i][0].getTime() === formTimestamp.getTime()) {
  18.       targetRow = i + 2; // 実際の行番号
  19.       break;
  20.     }
  21.   }
  22.   if (targetRow === -1) {
  23.     Logger.log("回答が見つかりませんでした。");
  24.     return;
  25.   }
  26.   // 見つけた行の回答内容をメール用シートに転記
  27.   const lastCol = answerSheet.getLastColumn(); // 最大列数を取得
  28.   mailSheet.getRange(2, 2, 1, lastCol).setValues(answerSheet.getRange(targetRow, 1, 1, lastCol).getDisplayValues());
  29.   SpreadsheetApp.flush(); // sync;sync;syncのおまじない(省略可)
  30.   // B12セルが"ON"の場合、C12に編集リンクを出力
  31.   mailSheet.getRange('C12').setValue(mailSheet.getRange('B12').getValue() === 'ON' ? lastResponse.getEditResponseUrl() : "");
  32.   // メール用シートの項目(B3-B11)を配列に取得
  33.   const mailTbl = mailSheet.getRange('B3:B11').getDisplayValues().map(elm => elm[0]);
  34.   // FROM:(B11)が未設定ならアクティブユーザーのメールアドレスを使用
  35.   if (!mailTbl[8]) mailTbl[8] = Session.getActiveUser().getEmail();
  36.   // "OFF"でなければメール送信
  37.   if (mailTbl[0] !== 'OFF') {
  38.     GmailApp.sendEmail(mailTbl[3],mailTbl[1],mailTbl[2],{from:mailTbl[8],cc:mailTbl[4],bcc:mailTbl[5],name:mailTbl[6],replyTo:mailTbl[7]});
  39.   }
  40. } //Ver4.0.0 for maintenance
何度かバージョンアップを繰り返してしまい、申し訳ありません。
今回のバージョン(Ver4.0.0)は、これまでにいただいた複数のご指摘をもとに、問題点を徹底的に解消した構成となっています。
回答の位置を、シートとフォームの両方から取得する「ハイブリッド型」の仕組みを採用しており、これまで発生していたすべての問題パターンに、初めて完全に対応できました。

↓ ↓ コピペ ↓ ↓ (保存を忘れずに!)

トリガー

トリガーを追加します。

イベントの種類の選択は、「フォーム送信時」を選びます。

※承認を求められたら、「Advanced」(あるいは、「詳細」)→「Go to ~~(Unsafe)」(あるいは、「~~に移動」)→「Allow」(あるいは、「許可」)

動作テスト

フォームを実行(プレビュー)して、回答、そして送信します。

結果、シート1に次のように表示されています。

結果、宛先(TO:)へ送られてきた返信メールです。

成功しました。

このように、GAS(diyReply)はフォームからの回答をシート1にコピー、シート1の内容をメールするだけです。

つまり、思い通りのメールを送るには、スプレッドシートの関数を駆使して自分で作る必要があります

そして、どのような返信メールも自由自在に作ることができます

実践編

応用例その8

フォームより入力された項目には価格があり、その合計金額をメールに表示したいとします。

注文商品(価格あり)の個数をプルダウンのメニューから選ぶフォームです。

返信メールのためのシート1を次のように作りました。
数式表示[Ctrl]+@しています。

シート1

テーブル(コピペ用)に表示します。

質問タイムスタンプ名前メールアドレス注文商品1(1,500円/個)注文商品2 (2,500円/個)
最新の回答
OFF:
メールを送らない
件名ご注文承りました
本文=C2&" 様、
ご注文をありがとうございます。
-------------------------------
注文商品: "&E1&"×"&E2&"個 "&F1&"×"&F2&"個
合計金額:"&TEXT((1500*E2+2500*F2),"#,##0")&"円
-------------------------------
お支払方法は、~~~

またのご利用をお待ちしております。"
TO:=D2
CC:(省略可)
BCC:(省略可)
NAME:(省略可)〇〇商店
REPLY TO:(省略可)
FROM:(省略可)
ON:
回答編集用のURLを表示
シート1
表計算が得意な人には何でもない関数ですが、セル内に文章を書くのは不慣れな人が多いのではないでしょうか。
"文字列"(ダブルクォーテーションで挟まれた文字列)とセルの数値(C2など)を、&(半角)でつなぎながら文章を書くのは慣れないと少し難しいかもしれません。
コツは最初に"を付けてから、一気に文章を書きあげて最後に"で閉じます。
この時、改行([Ctrl]+[Enter]キー)も気にせずに使います。
それから必要な箇所を"&※※&"に置き換えていきます。(※※は、A1,、B2など)

B5セルに望みの文章が表示出来たら、それがそのままメールの文章になります

実行(プレビュー)します。

シート1

成功です。

合計金額が表示された返信メールが送られてきました

シート1の名前(NAME:)で記した○○商店も表示されています。

この例を参考に、ご自分の思い通りな返信メールをお作り下さい。

応用例その8.5(クレジット決済を追加する)

お支払い方法に銀行振込だけでなくクレジット決済も対応した応用例です。
ご参考までにどうぞ。

クレジット決済のためにGASとは関係のない次の「メールリンク型決済」サービスを使います。

応用例その9

応用例その11(2つのGASを使って署名活動フォームを作る)

応用例の補足(フォームの選択肢に定員設定を追加する)

次のGAS(updateItems)を使って、フォームの選択肢に定員(人数制限)を付けられます
今回のGAS(diyReply)と同時に使うことで、フォームの応用がさらに広がります。

複数のGASの同時使用の応用例が『応用例その11』です。
参考にしてください。

応用例の補足2(フォームの回答者数に定員設定を追加する)

次のmultiReplyは、今回のdiyReplyに"フォームの回答者数に定員設定"ができる機能を追加しました。
「質問の選択肢」毎の定員でなく、「回答者数」の定員でよいのなら、とても有用なスクリプトです。

おわりに

GASを組むことで、フォームやスプレッドシートから得られる質問項目と回答項目を、メール文書に加えるのは簡単です。

しかし、それらにない計算値などをメールに加えるには、GASを特別に組み直さなければいけません。

フォームに対して1対1のGASになってしまい、汎用性が失われてしまします。

また、GASで数式を組んでテストをするのは、なかなかに手間がかかります。

そこで、この負担をスプレッドシートの関数側に持っていくために、GASの機能を削りに削ってできたのが今回のdiyReplyです。

GASでは困難な複雑な数式も、スプレッドシートの関数ならトライ&エラーが簡単に行えるため短時間で完成できます。

diyReplyと組み合わせることで、今回の例では合計金額ですが、関数に詳しい方はいくらでも難しい数式で得た値を、メールに表示できます。

ぜひ、自由自在な返信メールをご活用ください。

それでは、また次の記事でお会いしましょう。

追記(2024.9.25):

このGASを公開して1年以上が経ちますが、今でも日に20~30人の方がご覧になられるようです。
それに伴いこれまで、いくつかの問題点をご指摘いただきました。
特に、フォームとスプレッドシートの回答数が一致しない場合、混乱が生じていたというご指摘を何度か受け、今回の大幅なバージョンアップを行い以下の点を改善いたしました。

  • 従来はスプレッドシートから回答を取得していましたが、新しいバージョン(2.1.0)以降では、フォームに直接記録された回答を取得するように変更いたしました。
    これにより、確実に最後の回答を取得できるようになり、フォームとスプレッドシートの回答数が一致しない場合でも確実に、フォームからの送信者(回答者)の回答を使ったメールが送れます。

次の機能は、より柔軟な対応を可能にするため、追加いたしました。

  • 返信メールの送信者(From:)に、フォームのオーナーのメールアドレスのエイリアスを設定できるようにしました。
  • 回答者が自身の回答を編集するためのURLを表示できるようになりました。

もし使ってみて何か問題点がありましたら、コメントにてお知らせいただけると幸いです。

追記(2025.5.2):

質問セクションについて、バージョン2.1.0以降では、回答をフォームから直接取得する方式のため、対応できていません。旧バージョン(1.3.x以前)では、スプレッドシートから取得するために問題はありません。ただし、最新の回答が必ず回答シートの最終行になるように注意してください。

旧バージョンが必要な方は、このリンク(diyReply-Ver1.3.0)を参照してください。

追記(2025.5.18):

最新バージョン(Ver4.0.0)は、これまでにいただいた複数のご指摘をもとに、問題点を徹底的に解消した構成となっています。
回答の位置をシートとフォームの両方から取得する「ハイブリッド型」の仕組みを採用しており、これまで発生していたあらゆる問題パターンに、今回初めて完全に対応することができました。
特に、回答シートを手動で操作した場合などに発生する、フォームとシートの回答数の不一致によるメールの誤送信にも対応できました。
これにより、より安心してご利用いただけるようになったかと思います。

コメント

  1. こまめ より:

    Kssuga様

    各セルに分けて本文で結合とのご提案ありがとうございます。
    その場合例えばH5、Y5 のセルにIF関数を使い設定後に本文に
    =”&H5&”+”&Y5&”の様な入力方法で間違いないでしょうか?

    また、私の質問の仕方があいまいだったのですが宿泊や参加回等にそれぞれ定員を設定する場合も
    ご提案頂いたGASの設定で合っていますでしょうか?

  2. Kasuga Kasuga より:

    こまめさま、
    非表示の完成をおめでとうございます。
    しかし、参加者8件の情報ですから、ものすごく長い関数表記になりますね。
    余っているセルが無限にありますから、参加者情報は、各セルに別けて本文セル(B5)で結合するのもいいかもしれませんね。
    ところで人数制限の設定に関してですが、diyReplyの場合、3分で設定!Googleフォーム 回答数の上限を設定する方法を参考にしていただき、
    function myFunction() {
    diyReply();
    FormApp.getActiveForm().setAcceptingResponses(FormApp.getActiveForm().getResponses().length < 10); }

    のようにしてから、myFunction()をトリガー設定すればよいかと思います。
    或いは、diyReplyの最後の行に、
    form.setAcceptingResponses(form.getResponses().length < 10);
    を追加するのが一番簡単かもしれません。
    お試しください。

    追記、
    【GAS】Googleフォームに定員(人数制限)と返信メール、掲示板などマルチ機能を追加するも試していただけたら、うれしいですね。

  3. こまめ より:

    Kasuga様
    回答ありがとうございます。
    記載頂いた関数を利用し、無事に非表示に出来ました。
    過去のコメントを参考に、自分でも試してみたのですが上手く出来ずに困っていたので大変助かりました。
    重ねての質問で申し訳ないのですが、こちらと人数制限を設定する~のGASは1つのスプレッドシートで利用可能でしょうか?
    可能な場合、使用する際の注意点等ありましたら教えていただきたいです。

  4. Kasuga Kasuga より:

    こまめさま、
    当ブログを御覧いただきありがとうございます。

    質問項目に入力がない場合は、非表示にしたいという質問は何度か受けています。
    その場合、私のアドバイスは、IF関数での対応です。
    次に参考までの関数を書いてみました。IF関数で参加者名が空白の場合は、非表示になるはずです。
    変数は憶測で動作テストはできませんが、イメージは掴めると思います。

    ="参加者名1:"&M2& "
    ~~~
    合計金額:"&TEXT((P3+Q4+R4+S4),"#,##0")&"円
    "&IF(M3="","","参加者名2:"&M3& "
    ~~~
    合計金額:"&TEXT((P4+Q5+R5+S5),"#,##0")&"円
    ")&IF(M4="","","参加者名3:"&M4& "
    ~~~
    合計金額:"&TEXT((P5+Q6+R6+S6),"#,##0")&"円
    ~~~
    ~~~
    ")&IF(M10="","","参加者名8:"&M10& "
    ~~~
    合計金額:"&TEXT((P11+Q12+R12+S12),"#,##0")&"円")

  5. こまめ より:

    いつもフォームを作る際に拝見させて頂いており、大変助かっております。
    今回こちらの方法を参考に申し込みフォームを作成しているのですが
    申し込み人数が1~8人まで選択出来る形式で1人につき複数項目を入力し、自動返信メールには1人につきそれぞれ合計金額を出す形にしたいです。
    1名のみの申し込みの際の本文部分は下記の様にしたのですが、2~8人部分は入力があった人数部分のみ下記項目を表示、入力が無い部分は非表示としたいです。
    お忙しいところ恐縮ですが、ご教授いただければ幸いです。

    参加者名1:”&M2& ”
    携帯電話(参加者名1):”&N2&”
    参加回:”&P2&””&P3&”円
    シャトルバス:”&Q2&”
    “&”バス合計利用回数”&Q3&”
    “&”小計”&Q4&”円
    1日目宿泊:”&R2&”
    2日目宿泊:”&S2&”
    合計金額:”&TEXT((P3+Q4+R4+S4),”#,##0″)&”円

  6. Kasuga Kasuga より:

    rihoi様、
    当ブログをご覧いただき、ありがとうございます。
    GAS(ここでは、diyReply)が突然動作しなくなった場合、何らかの制限に達した可能性があります。
    考えられる制限としては、以下のものが挙げられます。

    ・トリガーの合計実行時間:1日あたり90分
    ・トリガーの登録数:1ユーザーあたり20個まで
    ・Gmailの送信数:1日あたり100通まで
    また、24時間以上経過後に自然に回復したという話も聞いています。

    もしコードを修正された場合は、念のため現在のトリガーを削除し、再度登録することをおすすめします。

    上記の情報が、問題解決の参考になれば幸いです。

  7. rihoi より:

    Google formが新しくなって、初めて試しております。
    今まで、不自由なく使っていたのですが、
    回答はスプレッドシートに反映されますが、自動返信メールとCCやBCC(メール返信機能)が作動しなくなりました。
    コードは新しいものをコピペし直しましたが、メール動作せずでございます。
    ご指導いただけますと幸いです。

  8. Kasuga Kasuga より:

    もう一度、フォーム、スプレッドシート、GASの連携がきちんとできているか見直してみるのがよいと思います。
    再度トリガーを設定されたのでしたら、間違いなく「フォーム送信時」に設定されていますか?
    参考までに、自動返信メールの最短設定方法を次の記事に書いてあります。
    https://terihat.com/gas-howto-reply/
    すぐに返信メールのテストができますから、試してください。
    これでもメールが送れないようでしたら、申し訳ありませんが、私の方では原因はわかりません。

  9. YOSHIZAWA より:

    ご返信ありがとうございます。
    今のところ1日10通にも満たない状態なんですが、他にどんな原因がありますでしょうか?対応策を教えて頂けますと有難いです。
    宜しくお願い致します。

  10. Kasuga Kasuga より:

    GASを使ったGmail送信は、無料アカウントだと1日に100通までに制限されています。
    24時間経って送れるようになるなら、この制限が原因です。

タイトルとURLをコピーしました