業務効率化のためにGASをUdemyで勉強した話

#上司「二人分の仕事してね」「・・・」

稀によくある職場の一場面ですね。
今年春、緊急事態宣言が出る直前に言い渡されたことでした。
※もし、上司が読んで特定されたとき用の言い訳ですが多大なる脚色があります。

投げかけられた仕事は事務業務。
普段の業務に事務業務が乗るわけです。
前任者の異動後もフォローを受けることができましたので、無事軌道に乗り、幸いにも緊急事態宣言が出てリモートワークになったことで通常業務も少なくなり、事務業務もこなすことができました。
しかし、人間一人で二人分、200％の仕事を全集中で維持することなどできるわけもなく、すぐに限界を迎えます。

そこでようやく思い至りました。

#そうだGASしよう→勉強しよう→Udemyだ→ｲﾏｺｺ
私が主に行っていた事務業務とはざっと

・メール対応
・顧客管理シートの管理
・請求処理
・受注処理

あたりとなります。
業務をぼかしているのはご了承ください。
ご覧の通り、スポットで入る定常業務が多く、トリガーさえはっきりしていれば、GASで自動化できるであろうと考えました。

ここまでご覧になられた方はすでに周知のことかと思いますが、私の職場ではG Suiteを使用しております。
そのため、GASをでスプレッドシートの編集やメール送信、フォルダ作成などできると業務効率化が進むと思い至りました。

さて、とはいったものの、過去にVBAを利用経験や、多少のPythonは触った経験はあるものの、GASについては全く存じ上げませんでした。
Qiita等の記事を参考にしようと思いましたが、映像教材の方がわかりやすいだろう、と考えたUdemyを選択しました。

#UdemyでGASの勉強を始めてみて

Udemyでちょうど良い教材はないかと探していたところ以下が見つかりました。
ちょうどセールのタイミングで購入しやすい金額でしたので、スルスルと決済をしました。

[ビジネスパーソンに贈る業務効率化大全 〜Google Apps Scriptによる業務の自動化〜](https://www.udemy.com/course/gas_for_operational_efficiency/)

こちらの教材ではGASの基本的な書き方を学習した上で、実際に様々な業務に使える事例を紹介しています。

どの実例も業務の中で比較的利用する機会の多いものが紹介されています。
例えば、セクション9のGmailをスプレッドシートに記載する、なんかは実際の業務で頻繁に使用しています。
私の場合はさらに正規表現を使ってメールの内容を取得できるようにしています。
他にも業務でSlackを使っておりますので、Slackに通知するような仕組みを作りました。

ただ、動画を見ながらコードを書くのももちろん勉強にはなるのですが、ちゃんとした血肉にしていくためにも、やり方を理解した上で、改めてググりながらコードを書くことをしていきました。

これが実に大変で、getValues()とgetValue()の違いがわかんない、といったような細かなところで相当苦戦しました。
苦戦したからこそ、今ではなるほどね、と思いコードを書くことができるようになりました。

#例えば何を作ったのか

例えば、以下のやつです。
こちらはとある業務で使っているものを事例として、経費精算をスプレッドシートに書き込んでね、という通知をしてくれるものです。
これをGASで書いてトリガーの設定をすると、指定した日時やタイミングで通知してくれるようになります。
トリガーについてはこちらの記事も見てみるとよいですね。

[【GAS】トリガーの設定](https://qiita.com/kakeru0520sou1/items/a82165446b0932f63c5b)


```JS:Send_Slack
function Send_Slack() {
  //Slackに送信するための設定
  var url = "https://hooks.slack.com/services/hogehoge/";//Incoming Webhook URLです。

  //投稿先と投稿者名、投稿本文を設定
  var payload = {
    'username' : '経費精算確認くん',//投稿先
    'text' : '<!here>\n\
経費精算の時期になりました。シートへの入力をお願いします\n\
スプレッドシートのURL：https://hogehoge',//投稿内容
    'channel' : '#任意のSlackチャンネル名'//投稿するチャンネル
  };

  var options = {
    'method' : 'post',
    'contentype' : 'application/json',
    'payload' : JSON.stringify(payload)  
  };

  //Slackに投稿する。  
  UrlFetchApp.fetch(url,options);
  console.log('sendtoslack完了');
}

```

他にもどの職場でもよく使うのが、メールの送信と受信メールのスプレッドシート転記ですね。
以下はスプレッドシートに記載されている人に上から順番にメール送信をしていくものです。
メール本文自体はGoogleドキュメントに予め記載しておき、名前のような人によって差し替えたいところは{$name}と記載し、for文の中のreplaceTextで差し替えています。結構この差し替えが便利で、例えば、複数回行うセミナーのZoomIDを送る際も同じテクニックを使うことで、簡単に差し替えることができます。
ちなみにメール送信は1日に無料ユーザーならば100件と上限が決められていますので、多くの方に送る場合は有料登録も検討したほうがよいですね。
[GASのメール送信1日100件までの制限について](https://qiita.com/erb_owl/items/b720899b11689903b191#:~:text=GAS%E3%81%A7%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%92%E9%80%81%E4%BF%A1,%E3%82%84%E3%82%84%E5%8E%B3%E3%81%97%E3%81%84%E5%88%B6%E9%99%90%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82)

```JS:Send_Mail
function Send_Mail(){
  // Googleドキュメントからメールの件名と本文を取得
  var doc = DocumentApp.openById('hogehoge');
  //https://docs.google.com/document/d/hogehoge/edit
  //GoogleドキュメントのIDだけだと確認・編集の際に手間になるのでコメントアウトでURLを残してます。
  var subject = doc.getName();
  var text = doc.getBody().getText();
  
  // Googleスプレッドシートからデータ取得
  var spreadsheet = SpreadsheetApp.getActive();
  var sheet = spreadsheet.getSheetByName('顧客名簿');
  
  const FValues = sheet.getRange('A:A').getValues();//E列の値を全て取得
  const LRow = FValues.filter(String).length;//空白の要素を除いた長さを取得
  var LastRow = LRow + 1;  
  
  for(var i = 2; i < LastRow; i++) {
      var name = sheet.getRange(i,6).getValue();
      var mail = sheet.getRange(i,13).getValue();
      var replacedText = text.replace('{$name}', name);
      GmailApp.sendEmail(mail, subject, replacedText,{from:'hogehgoe@gmail.com',name:'株式会社ホゲホゲ',bcc:'sugokueraihito@gmail.com'});
      console.log(name +"様にメール送信しました。")
 }
}
```

また、こちらは受信した特定のメールの情報をスプレッドシートに記載するものです。
ここでは、一例としてとあるセミナ−に申し込んだ人の情報をスプレッドシートに記載するようにしています。
ここでは、Udemyでも学べなかった正規表現について、Qiita等の情報を参考にしながら学習し、一通り動作するものを作り上げました。
正規表現難しいですね。

ちなみに、このメール検索もメール送信同様検索数の上限が決まっているます。
以下のコードではstartとmaxで指定しているように1回の実行で10件の検索を行います。
トリガーを使って、1時間おきに実行するようにすれば、10件☓24時間＝240件が1日で検索されます。
どうやら上限は1日2万件のようなので、たくさんのメールを検索していくるようなコードをたくさん作る場合は、やり方の工夫が必要です。
[Google Apps ScriptにおけるGmailの読み取り件数の制限とその対処法](https://tonari-it.com/gas-gmail-search-limit/)

```JS:join_Seminar
function join_Seminar(){
  //startーmaxの件数を数える。
  var start =  0;
  var max   = 10;
  var thds = GmailApp.search("セミナー申込がありました", start, max);
  var messe = GmailApp.getMessagesForThreads(thds);
  
  //空の配列を用意。受信した新着メールを格納するために使う
  var values = [];
  //メール受信後に既存メールかどうかを判定するための準備
  //idsは過去に受信したメールのidの一覧となる
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var Seminar_sheet = sheet.getSheetByName('セミナー申込者');  
  var LastRow = Seminar_sheet.getLastRow();
  var ids = Seminar_sheet.getRange(2, 16, LastRow).getValues().flat(); 
  
  for(var i = 0; i < messe.length; i++){
    for(var j = 0; j < messe[i].length; j++){
      const id = messe[i][j].getId();
      var body = messe[i][j].getPlainBody()

        //正規表現を使って、二語の間にある情報を変数に入れる
        var mail = RegExpBody(body,'【メールアドレス】','【名前】');
        var name = RegExpBody(body,'【名前】','【フリガナ】');
        var kana = RegExpBody(body,'【フリガナ】','【電話番号】');
        var tel = RegExpBody(body,'【電話番号】','【郵便番号】');
        var post = RegExpBody(body,'【郵便番号】','【住所】');
        var address = RegExpBody(body,'【住所】','--');
        
        //メールの情報がスプレッドシートにない＝新規申込みがあったら、valuesに追加する
        if(!ids.includes(id)){
          const record = [
            mail,
            name,
            kana,
            tel,
            post,
            address,
            messe[i][j].getDate(),
            messe[i][j].getThread().getPermalink(),
            id
          ];
          values.push(record);
        }
      
      //valuesの数だけ、シートに転機していく
      if(values.length > 0){
        Seminar_sheet.getRange(LastRow + 1, 1, values.length, values[0].length).setValues(values);
      }
    }
  }
  //シートの最終行と列を更新する
  var lastRow = Seminar_sheet.getLastRow();
  var lastCol = Seminar_sheet.getLastColumn();
}


//正規表現を使って、メールから抜き出したいワードを抽出する
function RegExpBody(str,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;
}
```

#GASを書いてどれだけ業務効率したのか
みなさんが気にしているであろう、成果について紹介しておきます。
あくまで、一例として認識していただければと思います。

上半期を終え、上司と成果について面談をしたのですが、様々な通知や定常業務を自動化した結果、月28時間の業務削減にできていました。
およそ1日1時間ほどの業務が効率化できたことになります。
この効率化の成果が認められていることもフィードバックしていただけたので、身につけた実力としては一定の成果は満たしているかと思います。

#Udemyの講座でどれだけできるようになるか
はっきりと伝えておきたいのは、<b>Udemyの講座はあくまで入り口と捉えるべき</b>、ということです。
Udemyの講座の中にはもちろん、１から10まで網羅したような優れた教材もあるでしょうが、多くの教材で触れられているのは、汎用性をもたせるためにも基本や応用の一例になってしまいます。
Udemyを通して入門し、Udemy以外にもQiitaやセミナー等への参加、業務に対する見直しなどが必要になってきます。

私も勉強し、できるようになったことは結構ありますが、Udemyは始めるきっかけ＆仕事を面白くするきっかけをくれました。

おそらく、これからも様々な定常業務を見つけたり、定常化できる業務は整理した上で自動化していきます。

自動化することが業務、というわけではありませんが、本業の頭を使った仕事をするためにも、定常業務は早く終わらせたい気持ちがあります。
考える時間を作り、生産的な部分に集中するための時間づくりに過ぎません。

Udemyで得たきっかけが好転につながっておりますので、できれば年収がアップしていってほしいな、と思っております。



#追記
ちなみにこの成果が認められて昇給が決まりました。