質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

967閲覧

【GAS】スプレッドシート更新時のメール自動送信処理_不具合解消法

donguriko

総合スコア30

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2022/08/11 13:48

編集2022/08/12 01:36

前提

スプレッドシート内に全部で3つのシートがあります。
シート1:情報のやりとりをするシート
シート2:メールアドレスのテーブル
シート3:自動送信させるメールの件名、本文等が記載されているシート

複数人で「シート1」を通じて、情報のやりとりをしています。
情報のやりとりは、以下の2種があります。
(往路) 新規投稿(B列~G列に追記)
(復路) 新規投稿へのコメントバック(K列~M列に追記)

<シート1のイメージ>
イメージ説明

実現したいこと

(往路)または(復路)のシート1の内容更新が行われたら、
GASで更新連絡メールを自動送信させたいです。
(往路)と(復路)で宛先、本文が異なるため、
処理をfunction1とfunction2の2つに分け、
それぞれに対しイベントトリガー設定をし、自動で処理が
走るようにしようと思っています。

<function1(往路)> I列がブランクの時のみ処理

  • 1-1 スプレッドシートの情報をもとにメール作成、送信
  • 1-2 シート1のI列に「済」フラグ追記
  • 1-3 シート1のJ列にタイムスタンプ追記

<function2(復路)> I列に「済」があり、o列がブランクの時のみ処理

  • 2-1 スプレッドシートの情報をもとにメール作成、送信
  • 2-2 シート1のO列に「済」フラグ追記
  • 2-3 シート1のP列にタイムスタンプ追記

<トリガー設定>
スプレッドシート_変更時

発生している問題・エラーメッセージ

function1の処理は問題なく走ります。
が、処理2-1のメール宛先の元データのN列を、下のスプレッド
シート上の関数※で補充させている関係で、function1が走った
直後にN列が補充されてしまい、そのタイミングでfunction2の処理が走り、
処理2-2、2-3が行われるため、処理2-1処理の判定で「作成対象外」と
判定されてしまうためか、メール送信ができません。

※(セルN5)の関数
=ArrayFormula(IFERROR(VLOOKUP(D5:D,'メアドシート'!$B$5:$H$8,7,0),""))

どのように回避するのがよいか、アドバイスをいただけないでしょうか?
また、どうしてアドバイスいただいた回避策がよいのかのメリ、
(第三案の場合は、以下a)、b)のデメ)についても教えてください。

<現時点で想像している回避策>

a) (セルN5)の関数を修正する
M列(返信コメント)に記載がない場合は、N列の補充処理がされないよう、 
IFをさらに追加すればよいのでは? と、想像しているものの、どこに
どのようにIF追加すればよいか自力でたどりつけないので、
アドバイスが欲しいです。

b) function2にN列を追記する処理を追加する
E列の内容をキーに、シート2:メールアドレスのテーブルを参照し、
O列ブランクのN列のセルにメアド補充させたらよいのではないかと
推察していますが、どのようにコード記載すればよいかまでは
自力でたどりつけないので、アドバイス欲しいです。

該当のソースコード

以下に現コードを全文記載します。
8/12 下コードの冒頭にfunction1のコードを追記。

GAS

1 2function createMailData1() { 3 const ss = SpreadsheetApp.openById('~省略~'); 4 const mySheet1 = ss.getSheetByName('元シート'); 5 const mySheet2 = ss.getSheetByName('メアドシート'); 6 const mailSheet = ss.getSheetByName('メール文シート'); 7 const lastRow = mySheet1.getRange(mySheet1.getMaxRows(), 7).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 8 console.log('lastRow ' + lastRow); //9が出たら正解 9 const targetRows = lastRow - 5 10 console.log('targetRows ' + targetRows); //4が出たら正解 11 12 //▼送信先のメアド 13 //「元シート(mySheet1)」のB列~I列までの値を 14 //getRange.getValuesで二次元配列(myRange)として取得 15 //起点は6行目、3列目(セルB6) 16 //getRange(行,列,●行分,▲列分) 17 const myRange = mySheet1.getRange(6, 2, targetRows, 8).getValues(); 18 console.log('myRange ' + myRange); 19 20 //for ループ 21 //行インデックス0スタートで+1ずつ、lastRowまで繰り返し 22 for (let i = 0; i < targetRows; i++) { 23 let no = myRange[i][0]; // 連番(B列) 24 let recipient = myRange[i][6]; // メアド(H列) 25 let myFlag1 = myRange[i][7]; // 投稿連絡フラグ(I列) 26 console.log('no ' + no); 27 console.log('recipient ' + recipient); 28 console.log('myFlag1 ' + myFlag1); 29 30 //投稿連絡フラグ欄(myFlag1)に「済」ありの時は処理スキップ 31 if (myFlag1 === "済") { 32 continue; 33 } 34 35 //▼メール件名 36 //「メール文シート(mySheet2)」のセルC3から取得 37 //getRange(行,列) 38 const subject1 = mailSheet.getRange(3, 3).getValue(); 39 console.log('subject1 ' + subject1); 40 41 //▼メール本文(body1) 42 //「メール文シート(mySheet2)」のセルC4から取得 43 const body1 = mailSheet.getRange(4, 3).getValue(); 44 console.log('body1 ' + body1); 45 46 const options = { 47 name: '自動送信メール', 48 noReply: true 49 //from:'~省略~' 50 }; 51 GmailApp.sendEmail(recipient,subject1,body1,options); 52 53 //▼元シート(mySheet1)の「投稿連絡メール」欄(I列)に"済"フラグを追記 54 //getRange(行,列,●行分,▲列分) 55 const addFlag = mySheet1.getRange(i +6, 9, 1, 1).setValue("済"); 56 57 //▼元シート(mySheet1)の「投稿連絡送信日」欄(J列)に"済"日時を追記 58 const timeStamp =new Date(); 59 console.log(timeStamp); 60 mySheet1.getRange(i +6, 10, 1, 1).setValue(timeStamp); 61 } 62} 63 64 65 66function createMailData2() { 67 const ss = SpreadsheetApp.openById('~省略~'); 68 const mySheet1 = ss.getSheetByName('元シート'); 69 const mySheet2 = ss.getSheetByName('メアドシート'); 70 const mailSheet = ss.getSheetByName('メール文シート'); 71 const lastRow = mySheet1.getRange(mySheet1.getMaxRows(), 7).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); 72 console.log('lastRow ' + lastRow); //9が出たら正解 73 const targetRows = lastRow - 5 74 console.log('targetRows ' + targetRows); //4が出たら正解 75 76 //▼送信先のメアド 77 //「元シート(mySheet1)」のB列~P列までの値を 78 //getRange.getValuesで二次元配列(myRange2)として取得 79 //getRange(行,列,●行分,▲列分) 80 const myRange2 = mySheet1.getRange(6, 2, targetRows, 16).getValues(); 81 console.log('myRange2 ' + myRange2); 82 83 //for ループ 84 //行インデックス0スタートで+1ずつ、lastRowまで繰り返し 85 for (let i = 0; i < targetRows; i++) { 86 87 //二次元配列名[行インデックス][列インデックス] 88 //起点[0][0]は6行目、3列目(セルB6) 89 let no = myRange2[i][0]; // 連番(B列) 90 let recipient = myRange2[i][12]; // 投稿者メアド(N列) 91 let myFlag1 = myRange2[i][7]; // 投稿連絡フラグ(I列) 92 let myFlag2 = myRange2[i][13]; // 返信連絡フラグ(O列) 93 console.log('no ' + no); 94 console.log('recipient ' + recipient); 95 console.log('myFlag1 ' + myFlag1); 96 console.log('myFlag2 ' + myFlag2); 97 98 //<条件1> 99 //返信連絡フラグ(myFlag2)がブランクの時は処理スキップ 100 if (myFlag2 === "済") { 101 continue; 102 103 //<条件2> 104 //投稿連絡フラグ((myFlag1)が「済」の時はfalse、それ以外はtrue 105 } else if (!(myFlag1 === "済")){ 106 continue; 107 } 108 109 //▼メール件名 110 //「メール文シート(mySheet2)」のセルC7から取得 111 //getRange(行,列) 112 const subject2 = mailSheet.getRange(7, 3).getValue(); 113 console.log('subject2 ' + subject2); 114 115 //▼メール本文(body2) 116 //「メール文シート(mySheet2)」のセルC8から取得 117 const body2 = mailSheet.getRange(8, 3).getValue(); 118 console.log('body2 ' + body2); 119 120 const options = { 121 name: '自動送信メール', 122 noReply: true 123 }; 124 125 GmailApp.createDraft(recipient, subject2, body2, options); 126 //★あとでsendEmailに修正★ 127 //GmailApp.sendEmail(recipient, subject2, body2, options); 128 129 //▼お褒めシート(mySheet1)の「返信連絡フラグ欄(O列)」に"済"フラグを追記 130 //getRange(行,列,●行分,▲列分) 131 const addFlag = mySheet1.getRange(i + 6, 15, 1, 1).setValue("済"); 132 133 //▼お褒めシート(mySheet1)の「返信連絡送信日」欄(P列)に"済"日時を追記 134 const timeStamp = new Date(); 135 console.log(timeStamp); 136 mySheet1.getRange(i + 6, 16, 1, 1).setValue(timeStamp); 137 } 138}

補足情報(FW/ツールのバージョンなど)

次回から、類似のケースは自力解決できるようになりたいので、
回答は遅くなってもかまいませんので、非エンジニア、ビギナーでも
わかるレベルでの回答、解説をいただけると助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2022/08/11 23:01

復路のメールを送る条件を整理してみては? 「N列が変更された時」というのはメール送信条件となるのですか?
退会済みユーザー

退会済みユーザー

2022/08/12 00:50 編集

①トリガーの設定について fucntion1 と function2の両方に、「ファイル変更時」にそれぞれの関数が実行されるようにトリガーを設定している、という理解でよろしいでしょうか。 ②「function1(往路)」でのメールを送信する条件が不明です。function1のコードも質問文に追記してください。
donguriko

2022/08/12 01:38

YAmaGNZさま、qnoirさま コメントありがとうございます。 以下qnoirさまからのコメントに回報します。 ①ご認識いただいているとおりです。 ②大変失礼いたしました。  該当のソースコード欄の冒頭にfunction1のコードを追記させて  いただきました。よろしくお願いいたします。
guest

回答1

0

ベストアンサー

a) (セルN5)の関数を修正する:
M列(返信コメント)に記載がない場合は、N列の補充処理がされないよう、下記のような数式に修正してみてはいかがでしょうか。

=ArrayFormula(IF(ISBLANK(M5:M),"",IFERROR(VLOOKUP(D5:D,'メアドシート'!$B$5:$H$8,7,0),"")))

投稿2022/08/12 07:29

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

donguriko

2022/08/12 09:13

qnoirさま お忙しい中、お手数をおかけいたしました。 ISBLANKの足し方のレクチャーありがとうございます。 関数が沢山続くと、()や カンマが足りているのか、段々わからなくなり、 頭が混乱してしまいます。。。 ご教示いただいた通り修正したら、想定した通りの動きとなりました。 アドバイス本当にありがとうございました!! 大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問