googleフォームから返信メールを送るGASをいくつか組んで考えました。
フォームのエディタで組むべきか、スプレッドシートのエディタで組むべきか。
ここでは、フォームから質問と回答を得て、それをメールするGASを3通りのパターンで組みながら考察しています。
3つのパターン
パターン1:
フォームのエディタから登録したGASで直接フォームから回答を取得、メールする。
(GASはフォームと紐づき、回答をフォームから取得)
パターン2:
フォームとリンクしたスプレッドシートのエディタから登録したGASでスプレッドシートから回答を取得、メールする。
(GASはスプレッドシートと紐づき、回答をスプレッドシートから取得)
パターン3:
フォームのエディタから登録したGASでリンクしたスプレッドシートから回答を取得、メールする。
(GASはフォームと紐づき、回答をスプレッドシートから取得)
実際にGASを組んで比較してみます。
テストのためのフォームを作りました。
質問が「名前」「メールアドレス」「選択」の3つだけです。
パターン1:フォームのGASでフォームから直接取得の場合
実際にフォームのエディタから、回答をメールで送るだけの簡単なスクリプトを組んでみました。
- function fromFormNoSheet(e) {
- //全ての質問と回答の取得
- const items=e.response.getItemResponses();
- const questionItem=[],answerItem=[];
- for(let i=0;i<items.length;i++) {
- //質問の取得
- questionItem[i]=items[i].getItem().getTitle();
- //回答の取得
- answerItem[i]=items[i].getResponse();
- }
- //メール送信
- GmailApp.sendEmail(answerItem[1],"fromFormNoSheet:フォームから取得",answerItem[0]+"\n"+answerItem[2]);
- }
↓ ↓ コピペ ↓ ↓
フォーム送信時にメールを送るようにGASをトリガーに追加します。
所感
このパターンの最大の利点は、回答などフォームのデータをすべて引数eで得られます。
リンクしたスプレッドシートが必要ないのは、素晴らしい利点だと思います。
ですが最大の欠点は、引数eからデータを得るので、エディタ上での[▷実行]でテストできないことです。
実際にトリガーの追加を行い、フォームからのプレビューまで行わないと結果が分からないのは、難しいスクリプトを組むのには致命的な欠点なのかもしれません。
一応、私は回避方法を持っています。私独自かもしれませんが説明します。
回避法、今回の場合
エディタから実行すると当然引数eには何も入っておらず、undefinedとなります。
そのため、実際にフォーム→トリガー→GASと値が引き渡されるまで、引数eは使えません。
そこで、変数itemsに全ての質問、回答などを渡す箇所をコメントアウトして、
//const items=e.response.getItemResponses();
代わりに、次のようにします。
const E=FormApp.getActiveForm().getResponses();
const items=E[E.length-1].getItemResponses();
- //const items=e.response.getItemResponses();
- const E=FormApp.getActiveForm().getResponses();
- const items=E[E.length-1].getItemResponses();
これでエディタの[▷実行]が使えますから、テストして問題がなければアンコメントして最初に戻します。
パターン2:スプレッドシートのGASでスプレッドシートから取得の場合
フォームとリンクしたスプレッドシートのエディタからスクリプトを組みます。
- function fromSheet() {
- //フォームとリンクしている回答シート
- const answerSheet = SpreadsheetApp.getActiveSheet();
- //回答シートの最終行列
- const lastRow = answerSheet.getLastRow();
- const lastCol = answerSheet.getLastColumn();
- //1行目の取得〜質問(タイムスタンプを除外)
- const questionItem = answerSheet.getRange(1,2,1,lastCol-1).getValues()[0]
- //最終行の取得〜新しい回答(タイムスタンプを除外)
- const answerItem = answerSheet.getRange(lastRow,2,1,lastCol-1).getValues()[0];
- //メール送信
- GmailApp.sendEmail(answerItem[1],"fromSheet:シート紐付きシートから取得",answerItem[0]+"\n"+answerItem[2]);
- }
↓ ↓ コピペ ↓ ↓
フォーム送信時にメールを送るようにGASをトリガーに追加します。
所感
このパターンの最大の利点は、シートのセルから値を得るので、スクリプトを組むのがイメージし易いことでしょうか。
GASで扱う値がこのシートにある質問と回答だけなら、セルの値を配列に取り込めるので複雑な計算式を扱うのが容易です。
ややこしい計算式、条件式などが必要なら、間違いなく私はこちらを選びます。
逆に欠点は、フォームとリンクしたスプレッドシートが必要なことでしょうか。
フォームだけで完結させたい人には必要ないパターンです。
パターン3:フォームのGASでスプレッドシートから取得の場合
フォームのエディタからスクリプトを組みます。
- function fromFormViaSheet() {
- //フォームとリンクしている回答シート
- const answerSheet = SpreadsheetApp.openById(FormApp.getActiveForm().getDestinationId()).getActiveSheet();
- //回答シートの最終行列
- const lastRow = answerSheet.getLastRow();
- const lastCol = answerSheet.getLastColumn();
- //1行目の取得〜質問(タイムスタンプを除外)
- const questionItem = answerSheet.getRange(1,2,1,lastCol-1).getValues()[0]
- //最終行の取得〜新しい回答(タイムスタンプを除外)
- const answerItem = answerSheet.getRange(lastRow,2,1,lastCol-1).getValues()[0];
- //メール送信
- GmailApp.sendEmail(answerItem[1],"fromFormViaSheet:フォーム紐付きシートから取得",answerItem[0]+"\n"+answerItem[2]);
- }
↓ ↓ コピペ ↓ ↓
フォーム送信時にメールを送るようにGASをトリガーに追加します。
所感
利点は、パターン2と同じで、質問と回答の値を取り扱いやすいことでしょうか。
欠点は、リンクしたスプレッドシートが必要なことです。
簡単なスクリプトならパターン1が良いと思います。
ではなぜ、このパターンも取り上げたかというと、フォームに関してのGASが複数ある時は、できたらフォームのエディタで開発した方がよいと感じたからです。
まず第一にGASがフォームとスプレッドシートで分かれてしまうと、管理がややこしくなります。
次にGAS間で引数と戻り値の交換が必要なことが起こった時のためです。
実行
結果
3つのパターンは「フォーム送信時」にトリガーを登録してあるので、同時に3通のメールが届きました。
パターン1のメール:
パターン2のメール:
パターン3のメール:
問題なくメールが送られてきました。
総評
質問や回答だけでなくフォームの説明や選択肢の操作が必要な時は、間違いなくパターン1、また簡単なGASの時もパターン1がよいと思います。
回答を使っての複雑な計算式や条件式が必要な時は、パターン2かパターン3ですが、それに質問や回答以外のフォームへの操作が必要なら、パターン3がよいと思います。
複数のGASが混在する時もパターン3にまとめるのがよいと思います。
おわりに
いかがでしょうか。
もしGoogleフォームの開発で、GASを組むのにフォームのエディタか?スプレッドシートのエディタか?で悩まれていて、この記事が少しでも参考なりましたら幸いです。
実は私個人では、スタンドアローン型でGASを使っています。スクリプトが増えてくると管理するのが楽なんですね。
ですが他の人にフォームを渡すときは、やはりフォームかスプレッドシートにGASを貼り付けます。
フォームを運用するのにパターン1が相手も楽みたいですね。
それではまた、
コメント