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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Google Apps Script

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

Q&A

解決済

2回答

3551閲覧

【GAS】メール本文内で、複数回出現する特定の文字列以降を、繰り返しスプレッドシートに転記

cardamon

総合スコア19

Google Apps Script

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

0グッド

2クリップ

投稿2021/12/27 02:45

編集2022/01/10 11:11

前提・実現したいこと

テイクアウト注文メールが自動転記される、スプレッドシート予約表を作りたいです。

▼注文メール
イメージ説明

▼理想のスプレッドシート
![イメージ説明

困っていること

G列の、商品名を正確に取得することができません。

###試したこと

①matchを使用したら、
1つ目の商品名しか取得できませんでした。
イメージ説明

②ご教示いただいたmatchALLをそのまま貼り付けたら、
やり方が悪いのか、エラーが出ました。

③本屋さんで見つけた、splitを使用したら、
なぜか2文字目の一文字しか取得できませんでした。
イメージ説明

###実際のコード
②splitを使用したコードを記載します。

Google

1function myFunction() { 2 // 検索条件に該当するスレッド一覧を取得 3 var threads = GmailApp.search('subject: 新規注文番号 -label:転記済'); 4 5 // スレッドを一つずつ取り出す 6 threads.forEach(function(thread) { 7 // スレッド内のメール一覧を取得 8 var messages = thread.getMessages(); 9 10 // メールを一つずつ取り出す 11 messages.forEach(function(message) { 12 // メール本文を取得 13 var plainBody = message.getPlainBody(); 14 15 // 来店場所を取り出す 16 var basyo = plainBody.match(/来店地を選ぶ↓:(.*)/); 17 18 // 来店日付を取り出す 19 var hiduke = plainBody.match(/来店日を選ぶ↓(.*)/); 20 21 // 来店時間を取り出す 22 var jikan = plainBody.match(/来店時間を選ぶ↓(.*)/); 23 24 // 番号を取り出す 25 var bangou = plainBody.match(/新しい注文:#(.*)/); 26 27 // 氏名を取り出す 28 var shimei = plainBody.match(/(.*)様/); 29 30 // 合計を取り出す 31 var goukei = plainBody.match(/合計金額:(.*)/); 32 33 // 商品名を取り出す 34 var syohin = plainBody.split('】')[1] 35 .split('==========')[0]; 36 37 38 // 書き込むシートを取得 39 var sheet = SpreadsheetApp.getActive().getSheetByName('自動予約表2'); 40 41 // 最終行を取得 42 var lastRow = sheet.getLastRow() + 1; 43 44 // セルを取得して値を転記 45 sheet.getRange(lastRow, 1).setValue(basyo[1]); 46 sheet.getRange(lastRow, 2).setValue(hiduke[1]); 47 sheet.getRange(lastRow, 3).setValue(jikan[1]); 48 sheet.getRange(lastRow, 4).setValue(bangou[1]); 49 sheet.getRange(lastRow, 5).setValue(shimei[1]); 50 sheet.getRange(lastRow, 6).setValue(goukei[1]); 51 sheet.getRange(lastRow, 7).setValue(syohin[1]); 52 }); 53 54 // スレッドに転記済ラベルを付ける 55 var label = GmailApp.getUserLabelByName('転記済'); 56 thread.addLabel(label); 57 }); 58}

###以下は、過去の質問ログです。
(papinianusさんが、以下の質問に対応したコードを回答くださっており、どなたかの参考になるかもしれないので、念のためログとして残しております)

注文メールの中身が、1種類だけの時は処理できるのですが、2種類以上の商品だと、2種類目以降が取得されません。

注文メール↓
イメージ説明

実際の予約表↓
イメージ説明

該当のソースコード

function myFunction() { // 検索条件に該当するスレッド一覧を取得 var threads = GmailApp.search('subject: 新規注文番号 -label:転記済'); // スレッドを一つずつ取り出す threads.forEach(function(thread) { // スレッド内のメール一覧を取得 var messages = thread.getMessages(); // メールを一つずつ取り出す messages.forEach(function(message) { // メール本文を取得 var plainBody = message.getPlainBody(); // 来店場所を取り出す var basyo = plainBody.match(/来店地を選ぶ↓:(.*)/); // 来店日付を取り出す var hiduke = plainBody.match(/来店日を選ぶ↓(.*)/); // 来店時間を取り出す var jikan = plainBody.match(/来店時間を選ぶ↓(.*)/); // 氏名を取り出す var shimei = plainBody.match(/(.*)様/); // 商品名を取り出す var syohin = plainBody.match(/】(.*)/); // 個数を取り出す var kosuu = plainBody.match(/X (.*)/); // オプションを取り出す var hukusai = plainBody.match(/オプション↓: (.*)/); // 書き込むシートを取得 var sheet = SpreadsheetApp.getActive().getSheetByName('自動予約表'); // 最終行を取得 var lastRow = sheet.getLastRow() + 1; // セルを取得して値を転記 sheet.getRange(lastRow, 1).setValue(basyo[1]); sheet.getRange(lastRow, 2).setValue(hiduke[1]); sheet.getRange(lastRow, 3).setValue(jikan[1]); sheet.getRange(lastRow, 4).setValue(shimei[1]); sheet.getRange(lastRow, 5).setValue(syohin[1]); sheet.getRange(lastRow, 6).setValue(kosuu[1]); sheet.getRange(lastRow, 7).setValue(hukusai[1]); }); // スレッドに転記済ラベルを付ける var label = GmailApp.getUserLabelByName('転記済'); thread.addLabel(label); }); }

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

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

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

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

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

papinianus

2021/12/29 09:05

このコードで実行すると、A 列の連番が維持できないですよね。 メールのテキストもコピペできないです。 希望する回答が提供される質問になっているか今一度ご確認ください。 今のところ、やりかたさえ分かれば自分で 0 から書けるってことで理解してます。
cardamon

2022/01/10 10:45

ご返信ありがとうございます。 A列の連番は、手作業で振ってしまっていました。紛らわしく申し訳ありません。このあと質問をわかりやすく修正します。 また、当方プログラムも書いたことがなく、以下コードを見よう見まねで書き換えました。 https://valmore.work/how-to-copy-gmail-message-to-spreadsheet/ このteratailという場所も、お店のお客さんに教えてもらって初投稿したリテラシーレベルです。(ということを初期の投稿では書いていたのですが、回答がゼロ件だった時、質問の再編集をするようteratailさんに提案され、この辺りの補足情報は蛇足かと考え、丸々削除してしまいました。情報不足で申し訳ありません。)
guest

回答2

0

以下は単なる趣味であり、余談です。動作確認してないです。

javascript

1const q375701 = () => { 2 // 検索条件に該当するスレッド一覧を取得 3 const threads = GmailApp.search('subject: 新規注文番号 -label:転記済'); 4 const label = GmailApp.getUserLabelByName('転記済'); 5 6 // スレッドを一つずつ取り出す 7 threads.forEach(thread => { 8 // スレッド内のメール一覧を取得 9 const messages = thread.getMessages(); 10 11 // メールを一つずつ取り出す 12 messages.forEach(message => { 13 // メール本文を取得 14 const plainBody = message.getPlainBody(); 15 16 // 来店場所を取り出す 17 const basyo = plainBody.match(/来店地を選ぶ↓:(.*)/); 18 19 // 来店日付を取り出す 20 const hiduke = plainBody.match(/来店日を選ぶ↓(.*)/); 21 22 // 来店時間を取り出す 23 const jikan = plainBody.match(/来店時間を選ぶ↓(.*)/); 24 25 // 氏名を取り出す 26 const shimei = plainBody.match(/(.*)様/); 27 28 // 商品名を取り出す 29 const syohin = plainBody.matchAll(/】(.*)/); 30 31 // 個数を取り出す 32 const kosuu = plainBody.matchAll(/X (.*)/); 33 34 // オプションを取り出す 35 const hukusai = plainBody.matchAll(/オプション↓: (.*)/); 36 37 // 書き込むシートを取得 38 const sheet = SpreadsheetApp.getActive().getSheetByName('自動予約表'); 39 40 // 最終行を取得 41 const lastRow = sheet.getLastRow() + 1; 42 43 // セルを取得して値を転記 44 const row = makeRow(basyo,hiduke,jikan,shimei,syohin,kosuu,hukusai); 45 sheet.getRange(lastRow, 1, 1, row.length).setValue(row); 46 }); 47 48 // スレッドに転記済ラベルを付ける 49 thread.addLabel(label); 50 }); 51} 52const makeRow = (c1,c2,c3,c4,c5s,c6s,c7s) => { 53 const length = c5s.length; 54 let result = [c1,c2,c3,c4]; 55 for(let i = 0; i < length; i++) { 56 result.push(c5s[i]); 57 result.push(c6s[i]); 58 result.push(c7s[i]); 59 } 60 return result; 61}

投稿2021/12/29 09:08

papinianus

総合スコア12705

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

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

cardamon

2022/01/10 10:52

アドバイスありがとうございます。そのままペタッと貼ってみたところ ーーー TypeError: String.prototype.matchAll called with a non-global RegExp argument (匿名) @ 新コード.gs:29 (匿名) @ 新コード.gs:12 q375701 @ 新コード.gs:7 ーーー というエラーが出ました。書いていただいたコードを自分なりに理解しようと、ネットで調べたり書店にも赴いたのですが、活かせず、せっかくアドバイスいただいたのに、申し訳ありません。
guest

0

自己解決

・splitを使い
・受信メールの件名・本文をカスタムし
希望に近い動作ができるようになりました。

▼注文メールのサンプル
イメージ説明

▼転記スプレッドシートサンプル
イメージ説明

まったくの素人のため、補足(コメントアウト?)が多く恐縮ですが、コードも載せます。

Google

1 2const yoyakuMessage = () => { 3 const condition = 'subject:(新規注文番号) -label:(転記済)'; 4 5 const start = 0; const max = 500; 6 const threads = GmailApp.search(condition, start, max); 7 const messages = GmailApp.getMessagesForThreads(threads); 8 9 const label = GmailApp.getUserLabelByName('転記済'); 10 11 const data = messages.map(message => { 12 const body = message[0].getPlainBody(); 13 14 const date = message[0].getDate(); 15 16 //メール件名から"新規注文番号"という文字列を削除 17 const subject = message[0].getSubject().replace('新規注文番号', ''); 18 19 //合計金額を探す(改行を含まず、"合計金額:"〜改行手前まで) 20 const goukei = body.split('合計金額:')[1].split('\n')[0]; 21 22 //商品名を探す(改行も含め、"日)"〜"=========="まで) 23 const test = body.split('日)')[1].replace(/[\s\t\n]/g, "") 24 .split('==========')[0].trim(); 25 26 /*: ↑replaceは指定文字列の置換(削除) 27     \t=タブ文字削除、\n=改行削除、\s=空白、g=2個目以降もの意 28   trim=前後の空白・改行を削除 */ 29 30 // 場所、日付、時間を探す(改行の手前まで) 31 const basyo = body.split('1)場所↓:')[1].split('\n')[0]; 32 const hiduke = body.split('2)日付↓')[1].split('\n')[0]; 33 const jikan = body.split('3)時間↓')[1].split('\n')[0]; 34 35 const datum = [date, subject, goukei, test, basyo, hiduke, jikan]; 36 return datum; 37 }); 38 const ss = SpreadsheetApp.getActiveSpreadsheet(); 39 const sheet = ss.getSheetByName('シート名'); 40 41 // 記入可能な行(最終行の次の行) 42 const lastRow = sheet.getLastRow() + 1; 43 44 // 最終行の次の行を、A列から、入力 45 sheet.getRange(lastRow, 1, messages.length, data[0].length).setValues(data); 46 47 // 転記済ラベルをつける 48 threads.forEach(thread => thread.addLabel(label)); 49}

varとconstの違いもまだあまりよくわかっておらず、書店に通ったり動画で初歩の勉強をしはじめたところですが、こちらでアドバイス頂いたコードは、とてもスッキリと洗練されたコードだったのではないか、と感じております。(初学者の自分にはすぐには活用できませんでしたが、ひとつずつ意味を理解していこうと思います。)

この度は、親身な回答アドバイスいただきありがとうございます。

投稿2022/01/11 15:06

cardamon

総合スコア19

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問