【GASを使って業務効率化入門】定型メールを正規表現でスプレッドシートに転記する

#みなさん業務効率化していますか

業務効率化、といいつつも自動化のお話です。

皆さんの職場では様々な業務があることと思いますが、その様々な業務の中には、

1. すでに定常化している業務
1. 工夫すれば定常化できる業務
1. 定常化できない業務

この３つになるかと思います。
この中で最も集中すべきところはどこでしょうか。
当然、3.定常化できない業務でしょう

逆にいうと定常化できてしまう業務というのは、可能な限り自動化した方が仕事の生産性は高まっていきます。
雑務は新人がやる、みたいな状況も仕事を覚えるという建前もありますが、よりパフォーマンスの高い人が遺憾なく発揮するため、という点でも合理的ではあります。（それをよしとするかは別問題として）

ということで、業務効率化もとい業務自動化のお話です。

#メールを自動でスプレッドシートに入力できるようにした。

業種は様々あるでしょうが、資料請求や予約、申込などをするとみなさんのメールに定型のフォーマットに沿ったメールが届くかと思います。

全然関係のない余談ですが、先日とある新築マンションの資料請求を軽い気持ちでしたところ、1日に電話が3回なり、資料を担当者が自宅まで持参する(しかも希望していた間取りとは全く違う間取りばかりの資料 :dizzy_face:)、という奇妙な出来事にあいました。気安く資料請求するのはやめようと思いました。

さて、そんなメールが到着するとどの職場でもスプレッドシートやエクセルに落とし込んで管理したり営業を行ったりするかと思います。

今回は、Gmailに到着した定型メールをスプレッドシートに書き込む、そんなプログラムを紹介したいと思います。

#使うもの
使うものは全部で３つ

- Gmail
- スプレッドシート
- トリガー

この3つです。

手順は大きく、

1. GASを書く
1. トリガーを設定する

の2工程です。
コード紹介の前に定型メールの内容を紹介しましょう。

今回は、ホテルの新規予約情報で例えたいと思います。
全く知らない業界でのたとえなので、ホテルの予約でこんな情報は入力されない、等は目をつぶっていただければと思います。


#参考メール
`plaintext:件名：ABCホテルに新規予約が入りました
新規予約が入りました。
以下はその情報です。

【予約番号】
12345678

【チェックイン日時】
2021年1月1日

【チェックアウト日時】
2021年1月3日

【大人】
2名

【子供】
2名

【部屋】
和室

【顧客氏名】
田中太郎

【顧客住所】
東京都千代田区千代田１−１−１

【顧客電話番号】
090-1234-5678

以上です。
`

ありがちですね。
これに基づいて、GASを書いていきます。

#ソースコード
`javascript:collection_Gmail_yoyaku
function collection_Gmail_yoyaku(){
  //startーmaxの件数を数える。
  var start =  0;
  var max   = 10;
  var thds = GmailApp.search("ABCホテルに新規予約が入りました", start, max);
  var messe = GmailApp.getMessagesForThreads(thds);

  //空の配列を用意。受信した新着メールを格納するために使う
  var values = [];
  //メール受信後に既存メールかどうかを判定するための準備
  //idsは過去に受信したメールのidの一覧となる
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var yoyaku_sheet = sheet.getSheetByName('予約情報');
  var LastRow = yoyaku_sheet.getLastRow();
  var ids = yoyaku_sheet.getRange(2, 16, LastRow).getValues().flat();

  for(var i = 0; i < messe.length; i++){
    for(var j = 0; j < messe[i].length; j++){
      //1日に複数件同じ件名、受信元になるとスレッドになる。
      //スレッド内は2次元配列になっているので、変数iとjを定義して、2次元配列にも対応できるようにする
      //idはgmail一つずつに割り当てられる個別のID、bodyはメールの本文
      const id = messe[i][j].getId();
      var body = messe[i][j].getPlainBody()


      //body（本文）内の２つのフレーズの間にある文言を抽出する。
      //例えば、IDの場合、参考メール内の【予約番号】と【チェックイン日時】の間にある文言を抽出する。
      //抽出の処理は下部にあるfunction RegExpBodをつかう
        var ReciveID = RegExpBody(body,'【予約番号】','【チェックイン日時】');
        var CheckIn = RegExpBody(body,'【チェックイン日時】','【チェックアウト日時】');
        var CheckOut = RegExpBody(body,'【チェックアウト日時】','【大人】');
        var Adult = RegExpBody(body,'【大人】','【子供】');
        var Child = RegExpBody(body,'【子供】' ,'【部屋】');
        var Room = RegExpBody(body,'【部屋】','【顧客氏名】');
        var Name = RegExpBody(body,'【顧客氏名】','【顧客住所】');
        var Address = RegExpBody(body,'【顧客住所】','【顧客電話番号】');
        var Tel = RegExpBody(body,'【顧客電話番号】','以上です');


        //毎度メールを追記すると何件も重複がでてくるので、新着メールのみを書き込むようにすrつ
        //これまでのメールをidsに入れておき、idsに含まされいない＝新着メールのみリストに追加する
        if(!ids.includes(id)){
          const record = [
            ReciveID,CheckIn,CheckOut,Adult,Child,Room,Name,Address,Tel,id
          ];
          values.push(record);
        }
      }

      //リストの内容をスプレッドシートに記載する
      if(values.length > 0){
        yoyaku_sheet.getRange(LastRow + 1, 1, values.length, values[0].length).setValues(values);
        LastRow = LastRow + 1;
      }
    }
  }
}

//２つのフレーズの間にある文言を正規表現で抽出する。
//regだと2つのフレーズも含めて抽出してしまうので、replaceを使って、不要なものを取り除く
//なお、未入力項目がある場合にエラーを出さないよう、strが未入力以外で実行するようにしている
function RegExpBody(str,front,back){
  console.log(front,back);
  var reg = new RegExp(front + '[\\s\\S]*?'+ back);
  if(str.match(reg)[0] !== ""){
    var data = str.match(reg)[0].replace('\r', '').replace(front, '').replace(back, '').replace(/\r?\n/g, '');
  }else{var data = ""}
  return data;
}
`

解説についてはコメントアウトを読んでください。


#　トリガーを設定する

あとはトリガーをつけて、N分置きに実行するようにすればOKです。

注意すべきこととして、検索回数があります。
GmailApp.searchは1日2万回の制限があります。今回のものだと10件の取得となりますので、1日2000回のトリガー実行が上限となります。
1日は1440分なので毎分実行しても実行できますが、こういうのは複数実行するかと思いますので、1日あたりの検索数を意識して回数やトリガーの周期を決めていくべきです。

#メールの抽出って地味に面倒
普段、こういうメール情報の抽出って手動コピーだったり、CSVインポートだったりするかと思いますが、それだけでもいくつかの工程を挟む必要があります。
1工程で終わらない単純作業はただの苦痛にしかならないので、早々に取り除くべきです。

こういう簡単にできる自動化を増やしていき、僕たちが人間として人間らしい生産性のある仕事に注力できるよう、がんばっていきたいですね。