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

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

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

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

Q&A

解決済

2回答

10474閲覧

【GAS】複数キーワードの検索ができない

yours

総合スコア13

Google Apps Script

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

0グッド

0クリップ

投稿2019/04/15 06:03

編集2019/04/15 08:37

Gmailを複数ある検索条件に該当するメールを抽出したいのですが、うまく抽出されません。

検索条件はセルB2からB6に5個入力(文字)でき、その文字に該当する物だけを抽出したいのです。

例えば、検索条件としてある時は「B2に【申込書】、B3に【請求書】、B4に【完了】」と入力し、
その入力した文字がSubjectに含まれている物を抽出したいのです。
また、ある時は、「B2に【申請中】、B3に【承認待ち】」と入力して
その入力した文字がSubjectに含まれている物を抽出したいのです。

抽出先は、10行目から下で、A列は受信日、B列は件名、C列は受信者IDになります。

コード function 複数検索メール取得() { /* Gmailから特定条件のスレッドを検索しメールを取り出す */ //1. 現在のスプレッドシートを取得 var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メール'); //2. 指定するセルの範囲(B2,B3,B4,B5,B6)を取得 var kw1 = sh.getRange('B2');//keyword1 var kw2 = sh.getRange('B3');//keyword2 var kw3 = sh.getRange('B4');//keyword3 var kw4 = sh.getRange('B5');//keyword4 var kw5 = sh.getRange('B6');//keyword5 var strTerms = ('Subject:(kw1 kw2 kw3 kw4 kw5 To:(ABC@gmail.com) after:2019/3/1'); var myThreads = GmailApp.search(strTerms, 0, 100); var myMsgs = GmailApp.getMessagesForThreads(myThreads);//二次元配列 GmailApp.getInboxThreads var valMsgs = []; /* 各メールから日時、送信元、件名、内容を取り出す */ for(var i=0;i<myMsgs.length;i++){   for(var j=0;j<myMsgs[i].length;j++){    var msid = myMsgs[i][j].getId();//メッセージIDを取得    //もしメッセージIDがスプレッドシートに存在しなければ    if(!hasId(msid)){     var date = myMsgs[i][j].getDate();     var subj = myMsgs[i][j].getSubject();     valMsgs.push([date,subj,msid]);    }   }  }  /* スプレッドシートに出力 */  if(valMsgs.length>0){//新規メールがある場合、末尾に追加する   var lastRow = sh.getDataRange().getLastRow();   sh.getRange(lastRow+1, 1, valMsgs.length, 3).setValues(valMsgs); var sheet = SpreadsheetApp.getActiveSheet(); var lastRow = sheet.getLastRow(); var lastCol = sheet.getLastColumn(); sheet.getRange(10, 1, lastRow, lastCol).sort(1);  } } function hasId(id){ var data = sh.getRange(1, 3, sh.getLastRow(),1).getValues();//C列(メッセージID)を検索範囲とする var hasId = data.some(function(value,index,data){//コールバック関数 return (value[0] === id); }); return hasId; }

参考にしたスクリプトは下記のものです。

https://tonari-it.com/gas-gmail-messageid/

どなたか、ご教授を宜しくお願いいたします。

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

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

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

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

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

jimbe

2019/04/15 07:13

ご提示のコードは java ではありません. 正しいタグに修正して頂けますか.
yours

2019/04/15 07:25

すみません。超超超初心者で何も分からない状態なんです。手探り状態でやっているので、どんなジャンルになるのかご教授頂けませんでしょうか?
jimbe

2019/04/15 07:34

フッターに'タグ一覧'というのがあると思いますので, そちらからお選びください.
yours

2019/04/15 07:38

jinbe様 ご迷惑おかけいたしました。 ありがとうございます。
macaron_xxx

2019/04/16 00:05

>うまく抽出されません。 とありますが、何が抽出されていますか?なにがうまくいっていないのでしょうか。 それがわからないです。
yours

2019/04/16 01:29

macaron_xxx様 スクリプトを起動させても、何も抽出されず、件数は0(ゼロ)件でした。 ご説明が足りず、大変申し訳ございませんでした。m(__)m
guest

回答2

0

ベストアンサー

次のような修正はいかがでしょうか。

1. 関数名について

今、関数名に2バイト文字(function 複数検索メール取得() {})を使用しておられますが、できれば、function getSrarchedMails() {}など、1バイト文字にしてください。確か2バイト文字で関数名を指定した場合、GASでは動作しなかったように思われます。

2. 検索クエリについて

修正ポイントは次の通りです。

  1. OR検索は、{}を使います。AND検索は()です。
    • 今の場合、"B2:B6"の値をOR検索し、toとafterはAND検索しますので、次のように設定します。
    • 'Subject:{kw1 kw2 kw3 kw4 kw5} To:(ABC@gmail.com) after:2019/3/1'
    • ここで、kw1 kw2 kw3 kw4 kw5はそのまま文字列として扱われてしまいますので、これを変数として使用するように修正します。
  2. "B2:B6"の値を一度に取得するとコストが低くなります。

これらをスクリプトへ反映させるために次のような修正を行ってください。

From

javascript

1var kw1 = sh.getRange('B2');//keyword1 2var kw2 = sh.getRange('B3');//keyword2 3var kw3 = sh.getRange('B4');//keyword3 4var kw4 = sh.getRange('B5');//keyword4 5var kw5 = sh.getRange('B6');//keyword5 6 7var strTerms = ('Subject:(kw1 kw2 kw3 kw4 kw5 To:(ABC@gmail.com) after:2019/3/1');

To

javascript

1var kws = sh.getRange("B2:B6").getValues().map(function(e) {return e[0]}).join(" "); 2var strTerms = 'subject:{' + kws + '} to:ABC@gmail.com after:2019/3/1';

3. 他のエラーについて

おそらく上記の変更を行うと、次はhasId(id)内でエラーが発生すると思われます。原因は、sh.getRange(1, 3, sh.getLastRow(),1).getValues()shが与えられていないためです。そこで、次のような修正をお願いします。

From

javascript

1if(!hasId(msid)){

To

javascript

1if(!hasId(msid, sh)){

これと下記の修正もお願いします。

From

javascript

1function hasId(id){

To

javascript

1function hasId(id, sh){

参考

編集

一番初めにスクリプトの修正をして下さった時に抽出したデータにメッセージに紐づくRe(レス)も抽出されていた為、出来ればファーストメッセージだけを抽出したかっただけです。

上記のコメントにより修正するポイントは下記の通りです。「ファーストメッセージだけを抽出」については、メッセージのインデックス0番目がトップのメッセージを意味します。

From

javascript

1 for(var i=0;i<myMsgs.length;i++){ 2  for(var j=0;j<myMsgs[i].length;j++){ 3   var msid = myMsgs[i][j].getId();//メッセージIDを取得 4   //もしメッセージIDがスプレッドシートに存在しなければ 5   if(!hasId(msid)){ 6    var date = myMsgs[i][j].getDate(); 7    var subj = myMsgs[i][j].getSubject(); 8    valMsgs.push([date,subj,msid]); 9   } 10  } 11 }

To:

javascript

1for(var i=0;i<myMsgs.length;i++){ 2 var msid = myMsgs[i][0].getId(); 3 if(!hasId(msid, sh)){ 4 var date = myMsgs[i][0].getDate(); 5 var subj = myMsgs[i][0].getSubject(); 6 valMsgs.push([date,subj,msid]); 7 } 8}

投稿2019/04/16 00:12

編集2019/04/16 05:56
kisojin

総合スコア899

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

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

yours

2019/04/16 01:20

kisojin様 ご教授ありがとうございます。 検索条件をB2に【申込書】、B3に【請求書】、B4に【完了】と入力し、データが取得できましたが、 しかし、一旦取得したデータをDeleteし、B2に【申請中】、B3に【承認待ち】で再検索すると、 最初に検索した【申込書】、【請求書】【完了】も抽出されてしまいます。 私のご説明が悪かったのだと思います。 検索データは、検索のたびその都度変更いたします。 どうぞ、よろしくお願いいたします。
kisojin

2019/04/16 02:12 編集

私の知識不足のせいでご迷惑をお掛けし大変申し訳ありません。残念ながら "しかし、一旦取得したデータをDeleteし、B2に【申請中】、B3に【承認待ち】で再検索すると、最初に検索した【申込書】、【請求書】【完了】も抽出されてしまいます。" の意味が分かりません。詳細のご説明をお願いしてもよろしいでしょうか。お手間を取らせてしまい申し訳ありません。
kisojin

2019/04/16 03:28

詳細のご説明を有難うございます。コメントへの返事と間違って回答へ投稿をしてしまいました。申し訳ありません。そのため、コメントは当初の回答へ追記させていただきたいと思います。 さて、1回目と2回目の意味について次のように理解しました。 1回目: "メール"のシートの"B2:B6"の値を【申込書】、【請求書】、【完了】にセットしてスクリプトを実行。 2回目: "メール"のシートの"B2:B6"の値を【申請中】、【承認待ち】にセットしてスクリプトを実行。 まず、この理解が正しいのかどうか知りたく思います。 次に、急に「スプレッドシート(A)」、「スプレッドシート(B)」、並びに「因みに、メッセージに紐づくRe(レス)も抽出されてしまいます。出来ればファーストメッセージのみを抽出したいのですが....」と出てきましたが、これはご質問には認められません。ご質問は、タイトルにある「複数キーワードの検索ができない」と理解し、これに基づいて回答させていただきましたが、当初のご質問を変更したいとのお考えで宜しいでしょうか。
yours

2019/04/16 05:10

kosojin様 ご連絡ありがとうございます。 のシートの"B2:B6"の値を【申込書】、【請求書】、【完了】にセットしてスクリプトを実行。 2回目: "メール"のシートの"B2:B6"の値を【申請中】、【承認待ち】にセットしてスクリプトを実行。 で間違いありません。 「スプレッドシート(A)」、「スプレッドシート(B)」にデータを転記は、私の作業なので、今回の問題とは関係ありません。作業内容をお伝えするために記入致しました。 「因みに、メッセージに紐づくRe(レス)も抽出されてしまいます。出来ればファーストメッセージのみを抽出したいのですが....」←は、一番初めにスクリプトの修正をして下さった時に抽出したデータに メッセージに紐づくRe(レス)も抽出されていた為、出来ればファーストメッセージだけを抽出したかっただけです。可能であればご教授頂きたく存じます。 宜しくお願いいたします。
kisojin

2019/04/16 05:59 編集

度々ご迷惑をお掛け致します。1回目、2回目について確認致しました。特に問題は認められませんが、この理解から「しかし、一旦取得したデータをDeleteし、B2に【申請中】、B3に【承認待ち】で再検索すると、最初に検索した【申込書】、【請求書】【完了】も抽出されてしまいます。」との関係が理解できません。これにつきまして、ご説明いただけないでしょうか。スプレッドシートA, Bについては無関係とのことですので、無視させていただきます。また、「ファーストメッセージだけを抽出」について修正させていただきました。お手数ですが、ご確認下さい。
yours

2019/04/16 06:56

kosojin様 度々の修正、ご連絡とありがとうございます。 再度、検証を行ってみますので、結果が出るまでお待ちくださいませ。
yours

2019/04/17 00:17

kosojin様 おはようございます。 検証の結果、文字列の中にスペースがあると、関係ないものまで抽出されてしまうことが分かりました。 お手数お掛けして、大変申し訳ございませんでした。 良い物になったので、感謝しております。 誠に、ありがとうございました。
kisojin

2019/04/18 02:07

無事に解決したとのこと、ご連絡有難うございます。安心しました。私自身、この質問から勉強をさせていただきました。こちらこそありがとうございました。
yours

2019/04/18 05:56 編集

kosojin様 先日はありがとうございました。 またまた、お力をお借りしたいのですが・・・。 検索条件を入力するセルは、出力するシートと同じシートでしたが、 出来れば、同じシートではなく、追加で別シートを作成し、シート名が「検索キーワード」としたいのです。 検索キーワードを入力するセルは、「B2:B101」の100件を予定しております。 どのように変更すればよいのか、ご教授を宜しくお願いいたします。 現在のスクリプトを貼り付けます。 function getSrarchedMails() { //Gmailから特定条件のスレッドを検索しメールを取り出す */ var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メール'); //現在のスプレッドシートを取得 var kws = sh.getRange("B2:B6").getValues().map(function(e) {return e[0]}).join(" "); //指定するセルの範囲(B2:B6)の検索値を取得 var strTerms = 'subject:{' + kws + '} to:ABC@Gmail.com after:2019/3/1'; //検索値、To、2019/3/1以降のデータを検索 var myThreads = GmailApp.search(strTerms, 0, 100); var myMsgs = GmailApp.getMessagesForThreads(myThreads);//二次元配列  var valMsgs = []; for(var i=0;i<myMsgs.length;i++){ // 各メールから日時、件名、IDを取り出す var msid = myMsgs[i][0].getId(); if(!hasId(msid, sh)){ var date = myMsgs[i][0].getDate(); var subj = myMsgs[i][0].getSubject(); valMsgs.push([date,subj,msid]); } }  /* スプレッドシートに出力 */  if(valMsgs.length>0){//新規メールがある場合、末尾に追加する   var lastRow = sh.getDataRange().getLastRow();   sh.getRange(lastRow+1, 1, valMsgs.length, 3).setValues(valMsgs); var sheet = SpreadsheetApp.getActiveSheet(); var lastRow = sheet.getLastRow(); var lastCol = sheet.getLastColumn(); sheet.getRange(10, 1, lastRow, lastCol).sort(1);  } } function hasId(id, sh){ var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メール'); var data = sh.getRange(1, 3, sh.getLastRow(),1).getValues();//C列(メッセージID)を検索範囲とする var hasId = data.some(function(value,index,data){//コールバック関数 return (value[0] === id); }); return hasId; } お騒がせ致しました。 色々とやってみたところ、下記のスクリプトで完成いたしました。 変更点:「sh」を分けました。メール出力シートを「sh1」検索キーワードを「sh2」 スプレッドシートの出力する際、シートの指定 ありがとうございました。 function getSrarchedMails() { //Gmailから特定条件のスレッドを検索しメールを取り出す */ var sh2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('検索キーワード'); //現在のスプレッドシートを取得 var kws = sh2.getRange("B2:B101").getValues().map(function(e) {return e[0]}).join(" "); //指定するセルの範囲(B2:B101)の検索値を取得 var strTerms = 'subject:{' + kws + '} to:ABC@Gmail.com after:2019/3/1'; //検索値、To、2019/3/1以降のデータを検索 var myThreads = GmailApp.search(strTerms, 0, 100); var myMsgs = GmailApp.getMessagesForThreads(myThreads);//二次元配列  var valMsgs = []; for(var i=0;i<myMsgs.length;i++){ // 各メールから日時、件名、IDを取り出す var msid = myMsgs[i][0].getId(); if(!hasId(msid, sh1)){ var date = myMsgs[i][0].getDate(); var subj = myMsgs[i][0].getSubject(); valMsgs.push([date,subj,msid]); } }  /* スプレッドシートに出力 */ var sh1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メール'); if(valMsgs.length>0){//新規メールがある場合、末尾に追加する   var lastRow = sh1.getDataRange().getLastRow();   sh1.getRange(lastRow+1, 1, valMsgs.length, 3).setValues(valMsgs); var sheet = SpreadsheetApp.getActiveSheet(); var lastRow = sheet.getLastRow(); var lastCol = sheet.getLastColumn(); sheet.getRange(5, 1, lastRow, lastCol).sort(1);  } } function hasId(id, sh1){ var sh1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メール'); var data = sh1.getRange(1, 3, sh1.getLastRow(),1).getValues();//C列(メッセージID)を検索範囲とする var hasId = data.some(function(value,index,data){//コールバック関数 return (value[0] === id); }); return hasId; }
guest

0

'Subject:(kw1 kw2 kw3 kw4 kw5 To:(ABC@gmail.com) after:2019/3/1'

この部分が変数になっていないですね。

'Subject:('+kw1+' '+kw2+' '+kw3+' '+kw4+' '+kw5+') To:(ABC@gmail.com) after:2019/3/1'

こんな感じかな?

投稿2019/04/16 00:07

macaron_xxx

総合スコア3191

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

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

yours

2019/04/16 01:23

macaron_xxx様 ご教授ありがとうございます。 検索条件での抽出はできませんでした。 お忙しい中、ご教授頂き、誠にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問