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

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

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

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

Q&A

解決済

2回答

4893閲覧

【GAS】Gmailとスプレッドシートの連携/自動転記について

ful_a_o

総合スコア13

Google Apps Script

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

0グッド

0クリップ

投稿2019/03/12 01:23

前提・実現したいこと

Gmailで受信している問合せメールの内容の一部を、スプレッドシート/GASを使って下記の流れで自動的に転記できるようにしたいと考えています。

 ・特定のラベル付き+未読状態のメールを取得する
・メール内から該当箇所のみをスプレッドシートに転記する
・取得が終わったメールは既読状態に変更する

■元のメールデータ/例文
下記のようなメールから「問合せNo、問合せ日時、氏名、フリガナ、電話番号」の部分のみを取り出してスプレッドシートに転記したい。
(上記の項目名部分で文字列検索をする?)

XX様

この度はお問い合わせありがとうございます。
確認し、こちらからご連絡させて頂きます。

------問い合わせ日時------
問合せNo   :000000
問合せ日時   :2019/12/31 00:00:00

--------お客様情報--------
氏名     :山田太郎 様
フリガナ   :ヤマダタロウ 様
電話番号   :000-0000-0000

////////////////////////////
株式会社〇〇
住所
電話
メール
///////////////////////////

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

・該当箇所のみをスプレッドシートに転記する
部分をどう記述すればいいかわからない状態です。

当方非プログラマーのため、メソッドの動作などを検索しながらサンプルコードを組み合わせて作成しておりましたが、
文字列のいい検索方法がわかりませんでした。

該当のソースコード

Google

1function getMail(){ 2 var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();    3 var objSheet = objSpreadsheet.getSheetByName("シート1"); //出力先のシートを指定 4 var sheet = SpreadsheetApp.setActiveSheet(objSheet); 5 6 //メールチェック用の変数 7 var start = 0; 8 var max = 500; 9 10 //配列"threads"にラベルが問合せ、状態が未読のスレッドを検索、代入。 11 var threads = GmailApp.search('label:問合せ is:unread',start,max); 12 13 //変数"row"にスプレッドシートの最終行の次行を代入 14 var row = sheet.getLastRow() + 1; 15 16 //オブジェクト"threads"のプロパティ数ループする 17 for(var n in threads){ 18 var thd = threads[n]; 19 var msgs = thd.getMessages(); //未読スレッドに含まれるメッセージを配列として取得 20 21 for(var m in msgs){ 22 var msg = msgs[m]; 23 var body = msg.getBody(); //メール本文を1データの塊として取得する 24 var res = body.split("\n") //取得したメール本文を各改行列ごとに配列に代入 25 26 //indexOfで取得したい文字列が入っている配列のインデックス番号を取得→配列で書き込み?search? 27 //検索したい文字列に空白が含まれているのは正規表現の\sで対応? 28 29 var number = res.indexOf(/問合せNo\s\s\s:/); 30 var date = res.indexOf("問合せ日時  :"); 31 var name = res.indexOf("氏名     :"); 32 var name2 = res.indexOf("フリガナ   :"); 33 var tel = res.indexOf("電話番号   :"); 34 35 36 //セルへの書き込みを行う 37 sheet.getRange(row,1).setValue(number); 38 sheet.getRange(row,2).setValue(res[date]); 39 sheet.getRange(row,3).setValue(res[name]); 40 sheet.getRange(row,4).setValue(res[name2]); 41 sheet.getRange(row,7).setValue(res[tel]); 42 row++ 43 } 44 } 45 //スレッドを既読に変更する 46 thd.markRead(); 47 Utilities.sleep(1000); 48 }

試したこと

・「var res = body.split("\n")」の段階で出力→改行部分でデータ分割はできている。
・セルへの書き込みで「number」そのものを出力すると「-1」が出力される。
→検索ができていない状態でしょうか?

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

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

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

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

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

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

guest

回答2

0

papinianusさんの回答スクリプトが素晴らしく整理されてきれいに書かれているのでご活用されるのが良いと思います。
質問者さんの問題は(indexOfで指定しているワードが対象と一致していることが前提ですが)おそらくvar res = body.split("\n")が配列になっていないからと思われます。(indexOfは一致するものがないときに-1を返しますので)
var resarray = [];
resarray.push(res);
を足せばうまく動きませんか?

投稿2019/03/12 02:31

hiroshi0240

総合スコア640

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

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

papinianus

2019/03/12 02:43

配列になっていると思いますし、配列であるか否が原因ではないと思いますが、おっしゃるように配列になってない(つまり本文全体がデカい一つの文字列である)ときに、resarrayにつっこんでも、-1じゃないでしょうか? Array.prototype.indexOfは`===`での比較しかしない(はず、gasがjavascriptの流儀に乗っていれば)ので、質問者様のように部分文字列や正規表現リテラルを与えても一致させてくれません。 もし仮に部分文字列で一致できたとしても、(resarrayに入れたところで)resをなんとか配列にでも分けてあげないとメール本文全部しか取れないので、部分ごとに分けてシートに書き込みたい目的を達成できない印象を持ちます。
hiroshi0240

2019/03/12 05:33

今、確認しました。おっしゃる通りsplitした時点で配列に格納できてますね。 ということはdate以降のデータは値指定しているので、一致してれば取得できているはずですね。質問者さんのコードのエラーはnumberのindexOf指定に正規表現を使われている部分ですね。 ということは、質問者さんのコードのindexOfをmatchに置き換えればそのまま使えるのかな。
guest

0

ベストアンサー

javascript

1function getMail(){ 2 var objSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();    3 var objSheet = objSpreadsheet.getSheetByName("シート1"); //出力先のシートを指定 4 var sheet = SpreadsheetApp.setActiveSheet(objSheet); 5 6 //メールチェック用の変数 7 var start = 0; 8 var max = 500; 9 10 //配列"threads"にラベルが問合せ、状態が未読のスレッドを検索、代入。 11 var threads = GmailApp.search('label:問合せ is:unread',start,max); 12 13 //オブジェクト"threads"のプロパティ数ループする 14 for(var n in threads){ 15 var thd = threads[n]; 16 var msgs = thd.getMessages(); //未読スレッドに含まれるメッセージを配列として取得 17 18 for(var m in msgs){ 19 var msg = msgs[m]; 20 var body = msg.getBody(); //メール本文を1データの塊として取得する 21 var no = body.match(/^問合せNo\s*?:(.+)$/m)[1]; 22 var dateandtime = body.match(/^問合せ日時\s*?:(.+)$/m)[1]; 23 var name = body.match(/^氏名\s*?:(.+)$/m)[1]; 24 var kana = body.match(/^フリガナ\s*?:(.+)$/m)[1]; 25 var tel = body.match(/^電話番号\s*?:(.+)$/m)[1]; 26 sheet.appendRow([no, dateandtime, name, kana, "", "", tel]); 27 } 28 } 29 //スレッドを既読に変更する 30 thd.markRead(); 31 Utilities.sleep(1000); 32}

投稿2019/03/12 01:55

編集2019/03/13 01:14
papinianus

総合スコア12705

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

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

macaron_xxx

2019/03/13 01:11

これ、たぶん正常に動かないです。 GASではconstでのスコープがグローバルっぽい動き(バグだと思うんですけど)するので、おそらくforの中のconstも再代入されずにずっと1行目のものが追加され続けると思われます。 GASでconstは本当の意味で再代入しない定数以外は使わないほうがいいです。
macaron_xxx

2019/03/13 01:12

function constTest() { var msgs = ["問合せNo   :000000","問合せNo   :000001","問合せNo   :000002"]; for(var m in msgs){ var msg = msgs[m]; Logger.log(msg); const no = msg.match(/^問合せNo\s*?:(.+)$/m)[1]; Logger.log(no); } }
papinianus

2019/03/13 01:18 編集

ありがとうございます。 信用しているので確認を怠って回答を直しました。 盲目的にconstにしていますが、ブロックスコープが働かないのだとすると(javaの影響でしょうかね?)、constにもあまり意味がないですね。 説明変数を持たずに、直接appendRowに変数を渡したほうがいいのかもしれないです。
ful_a_o

2019/03/14 01:43 編集

コメントが遅くなってしまいすみません!回答頂いたコードで動作致しました。 付け焼刃のツギハギな知識でしたので、これを機に改めて基礎から学習していこうと思います。 papinianus様、hiroshi0240様、macaron_xxx様、ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問