実現したいこと
スプレッドシートに重複無くメールが転記されるようにしたいです。
前提
GASでGmailに来た特定のメールアドレスをスプレッドシートに転記しているのですが、定時でトリガーが作動するたびに重複してしまいます。重複なくメールを転記したいです。
※当方、GASのコードを記述できるわけではなく、ChatGPTに記述してもらった素人です。
発生している問題・エラーメッセージ
メールの転記部分に関しては問題なく出力されるのですが、トリガーが作動するたびに以前転記したメール内容も重複して転記してしまいます。
該当のソースコード
Gmailからスプレッドシートに出力される部分のコードです。
重複なく出力されるようコードを組んでもらったのですが、トリガーが起動するたびに以前転記したメールも重複してスプレッドシートに追加されてしまいます。
GAS
1var existingData = sheet.getDataRange().getValues().slice(1); 2var newData = []; 3 4for (var i = 0; i < threads.length; i++) { 5 var messages = threads[i].getMessages(); 6 for (var j = 0; j < messages.length; j++) { 7 var date = messages[j].getDate(); 8 var htmlBody = messages[j].getBody(); 9 var plainBody = extractPlainTextFromHTML(htmlBody); 10 var trimmedBody = removeUnnecessaryTextAndWhitespace(plainBody); 11 12 var isDuplicate = existingData.some(function (row) { 13 return row[0].getTime() === date.getTime() && row[1] === trimmedBody; 14 }); 15 16 if (!isDuplicate) { 17 newData.push([formatDate(date), trimmedBody]); 18 } 19 } 20} 21
全体のソースコード
GAS
1function myFunction() { 2 var subjectToSearch = "在庫数低下"; 3 var sheetName = "販売履歴メタ"; 4 5 var threads = GmailApp.search("subject:" + subjectToSearch); 6 var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); 7 8 if (!sheet) { 9 sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName); 10 sheet.appendRow(["販売日", "本文"]); 11 } 12 13 threads.sort(function (a, b) { 14 return a.getLastMessageDate() - b.getLastMessageDate(); 15 }); 16 17 var existingData = sheet.getDataRange().getValues().slice(1); 18 var newData = []; 19 20 for (var i = 0; i < threads.length; i++) { 21 var messages = threads[i].getMessages(); 22 for (var j = 0; j < messages.length; j++) { 23 var date = messages[j].getDate(); 24 var htmlBody = messages[j].getBody(); 25 var plainBody = extractPlainTextFromHTML(htmlBody); 26 var trimmedBody = removeUnnecessaryTextAndWhitespace(plainBody); 27 28 var isDuplicate = existingData.some(function (row) { 29 return row[0].getTime() === date.getTime() && row[1] === trimmedBody; 30 }); 31 32 if (!isDuplicate) { 33 newData.push([formatDate(date), trimmedBody]); 34 } 35 } 36 } 37 38 if (newData.length > 0) { 39 newData.sort(function(a, b) { 40 return new Date(a[0]) - new Date(b[0]); 41 }); 42 43 sheet.getRange(sheet.getLastRow() + 1, 1, newData.length, newData[0].length).setValues(newData); 44 } 45} 46 47function extractPlainTextFromHTML(html) { 48 var plainText = html.replace(/<[^>]+>/g, ''); 49 return plainText; 50} 51 52function removeUnnecessaryTextAndWhitespace(text) { 53 var productIndex = text.indexOf("商品情報"); 54 var recentIndex = text.indexOf("直近"); 55 56 if (productIndex !== -1 && recentIndex !== -1 && productIndex < recentIndex) { 57 return text.substring(productIndex + 4, recentIndex).replace(/\s+/g, ''); 58 } else if (productIndex !== -1) { 59 return text.substring(productIndex + 4).replace(/\s+/g, ''); 60 } else if (recentIndex !== -1) { 61 return text.substring(0, recentIndex).replace(/\s+/g, ''); 62 } else { 63 return text.replace(/\s+/g, ''); 64 } 65} 66 67function formatDate(date) { 68 var year = date.getFullYear(); 69 var month = ("0" + (date.getMonth() + 1)).slice(-2); 70 var day = ("0" + date.getDate()).slice(-2); 71 return year + "/" + month + "/" + day; 72}
補足情報(コードの説明)
- subjectToSearch変数に検索するメールの件名("在庫数低下")を指定します。
- sheetName変数にスプレッドシートのシート名("販売履歴メタ")を指定します。
- GmailApp.searchを使用して、指定された件名を持つメールをGmailから検索します。検索結果はthreadsに格納されます。
- SpreadsheetApp.getActiveSpreadsheet()を使用して、アクティブなスプレッドシートを取得します。
- SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName)を使用して、指定されたシート名のスプレッドシートを取得します。もし存在しない場合は、新しいシートを作成してsheetに格納します。その際、ヘッダー行(["販売日", "本文"])を追加します。
- threadsのメールを送信日時でソートします。
- sheet.getDataRange().getValues().slice(1)を使用して、既存のスプレッドシートのデータ("販売日"と"本文"のペア)を取得します。slice(1)はヘッダー行を除外するための処理です。
- 重複を避けるために、新しいメールのデータと既存のデータを比較します。重複しない場合、newDataに新しいデータ("販売日"と"本文"のペア)を追加します。
- もしnewDataにデータが存在する場合、newDataを日付でソートします。
- sheet.getRange(sheet.getLastRow() + 1, 1, newData.length, newData[0].length)を使用して、スプレッドシートの最後の行に新しいデータを追加します。
回答1件
あなたの回答
tips
プレビュー