akiratakeyama91
@akiratakeyama91 (akira)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

GASを用いてGmailから特定の情報を抽出してスプレッドシートへ転記したい

解決したいこと

Gmailから注文内容を読み取って、スプレッドシートへ必要な情報を転記したいです。

メール内容
[  ポイント利用  ] 0
[獲得予定ポイント合計] 0
[ 受付番号 ] AAAAA
[  品番  ] BBBBB
[  商品名  ] CCCCC
[メーカー品番] DDDDD
[ 注文点数 ] 5点
[ 注文単価 ] \1,267

発生している問題・エラー

match関数を用いて、抽出しようとしているのですが、メール文章のスペースが原因なのか上手く情報を拾えません。

order_id:Array(2)
0: "  ポイント利用  ] 0"
1: "ポイント利用  ] 0"
が返されてしまいます。

本来はorder_idでAAAAAを返して欲しいです。

また、注文単価は\を除いた、1,267を
注文点数の部分は、5点
ではなく、5を返すようにする方法もご教示いただけますと幸いです。

該当するソースコード


function getemessage2() {


//Gmailから購入メールスレッドを抽出 
  const query = 'subject:ご注文内容控え newer_than:2d'
  //const start = 0 //検索範囲の開始地点
  //const end = 5 //検索範囲の終了地点
  const threads = GmailApp.search(query);
  const messagesForThreads = GmailApp.getMessagesForThreads(threads);

    // 書き込むシートを取得、クリア
      var sheet = SpreadsheetApp.getActive().getSheetByName('注文転記用');
      sheet.clear();
       // 見出し
        sheet.getRange('a1').setValue("受付番号"); 
        sheet.getRange('b1').setValue("品番");          
        sheet.getRange('c1').setValue("商品名"); 
        sheet.getRange('d1').setValue("注文数"); 
        sheet.getRange('e1').setValue("注文単価");

      
   for (var thread of messagesForThreads){
    for (var message of thread){
    //新規注文メール本文を取得
    var message_body = message.getPlainBody()
    console.log('%s', message_body);

    //商品数をカウント
    const amount_items = message_body.match(/品番.*/g);
    console.log('%s', amount_items.length);
    for(let j = 0;j<amount_items.length;j++){
    // 最終行を取得
     var lastRow = sheet.getLastRow() + 1;
    //情報取得
      var order_id = message_body.match(/[ 受付番号 ] (.*)/); // 受付番号
      console.log('%s', order_id);
      var product_id = message_body.match(/[  品番  ] (.*)/); // 品番
      console.log('%s', product_id);
      var product_name = message_body.match(/[  商品名  ] (.*)/); // 商品名
      console.log('%s', product_name);
      var pcs = message_body.match(/[ 注文点数 ] (.*)/); // 注文点数
      console.log('%s', pcs);
      var price = message_body.match(/[ 注文単価 ] (.*)/); // 注文単価
      console.log('%s', price);


      sheet.getRange("a"+lastRow).setValue(order_id);
      sheet.getRange("b"+lastRow).setValue(product_id);
      sheet.getRange("c"+lastRow).setValue(product_name);
      sheet.getRange("d"+lastRow).setValue(pcs);
      sheet.getRange("e"+lastRow).setValue(price);
    }
    }
   }
}

自分で試したこと

matchのワードはメールからコピーしています。半角スペースの正規表現を入れてみたりしましたが、ダメでした。

var order_id = message_body.match(/受付番号(.*)/); // 受付番号
にすると
order_id:Array(2)
0: "受付番号 ] AAAAAA"
1: " ] AAAAA"
を返します。

0

1Answer

受付番号を抽出しようとしている正規表現 /[ 受付番号 ] (.*)/ は以下のように解釈されます。

  • [ 受付番号 ]文字クラスを表し、簡単にいえば角カッコ内の文字のいずれか1個とマッチする。つまり「受」「付」「番」「号」「(全角スペース)」のいずれか1個とマッチする。
  •  (.*) は全角スペース1個に続いて、改行を除く任意の文字0個以上とマッチする。

よって、メール内で最初に現れた全角スペース2個から行末までの   ポイント利用  ] 0 にマッチしています。

受付番号を正しく抽出するには、 message_body.match(/\[ 受付番号 \] (.*)/)[1] のように [ の前にバックスラッシュをつけてエスケープし、文字通りの [ とマッチするようにしてください。また match メソッドの返り値は [正規表現全体にマッチした文字列, 1つめのカッコ内パターンにマッチした部分文字列, 2つめの…] という配列で返ります。番号の部分だけ取り出したいので [1] をつけます。

また、注文単価は\を除いた、1,267を
注文点数の部分は、5点ではなく、5を

(.*) の代わりに \\([0-9,]+)([0-9,]+)点 と書いてください。

0Like

Comments

  1. ありがとうございます。すみません、色々試していてお返事が遅くなりました。

          var lastRow = sheet.getLastRow() + 1;
          var order_id = message_body.match(/\[ 受付番号 \] (.*)/)[1]; // 受付番号
          console.log('%s', order_id);
          var product_id = message_body.match(/\[  品番  \] (.*)/)[1] // 品番
          console.log('%s', product_id);
          var product_name = message_body.match(/\[  商品名  \] (.*)/)[1]; // 商品名
          console.log('%s', product_name);
          var pcs = message_body.match(/\[ 注文点数 \] ([0-9,]+)点/)[1]; // 注文点数
          console.log('%s', pcs);
          var price = message_body.match(/\[ 注文単価 ] \\([0-9,]+)/)[1]; // 注文単価
          console.log('%s', price);
    

    の様に書き換えたところ、受付番号、注文点数、注文単価は上手く拾えました。
    ただ、品番と商品名がnullとなり、ヒットせずでした。
    何か考えられる原因ありますでしょうか。

    また、こちらは冒頭で記載していなかったのですが、実際は一つのメールにいくつか商品があり、それらを全て記載したいです。
    書き換えた内容だと、同じ商品を何度も返してきてしまっています。
    配列の部分に変数がないからと推測しますが、こちらもご教示をいただけると幸いです。

  2. 品番と商品名がnullとなり、ヒットせずでした。

    例示のメール本文では角カッコの中に半角スペースと全角スペースが混ざっているようですが、実際のメールと正規表現でスペースの使い分けや個数は一致していますか?

    実際は一つのメールにいくつか商品があり、それらを全て記載したいです。

    match メソッドは最初のマッチを返しますが、 matchAll メソッドならすべてのマッチを返すイテレータが得られます。それをスプレッド構文で配列化し、 map で各マッチからカッコ内にマッチした部分だけ取り出せばいいです。以下のように書いてください。

    const order_ids = [...message_body.matchAll(/\[ 受付番号 \] (.*)/g)].map(m => m[1]);
    

    この場合正規表現の後ろの g は必要なので忘れずに。

  3. 早速のご回答ありがとうございます。
    メールをコピーして貼り付けたところ確かに、品番と商品名だけ、全角スペース+半角スペースが使われておりました。
    このまま、走らせてもnullだったので、半角スペースの部分を\sに変えたりしたのですが、ヒットせずでした。
    どのようにすればよいでしょうか。
    スクリーンショット 2024-12-20 162540.jpg
    matchAllのご説明もありがとうございます。

  4. 半角か全角のスペースがいくつか入る可能性がある部分のパターンは \s* と書いて、0文字以上の任意のスペース文字にマッチするようにしてみてください。

  5. ありがとうございます!\s*を入れてヒットしました。
    matchAllの方は、もう少しやってみます。
    取り急ぎ御礼申し上げます。

Your answer might help someone💌