Google Apps Script(GAS)に挑戦してみた話

こんにちは。[PLAID Advent Calendar](https://qiita.com/advent-calendar/2018/plaid) 20日目の記事を担当するtaniです。
普段はビジネスサイドのカスタマーサクセスチームでKARTE Journeyのプログラムの設計、運用などを行っています。

今日はシフト作成業務をGoogle Apps Script (GAS) を作って効率化した話を紹介します。

## GASを使ってみようと思った背景
2018年の3~6月の間、私はチャットサポートのプロジェクトに携わっていました。その中で毎月必ず発生する業務でほとんど頭を使わない「シフト作成」という業務がありました。

「シフト作成」では、社員全員のスケジュールをみてスプレッドシートのパズルを完成させ、その内容を元に全員のカレンダーの招待していました。ざっと40人ぐらいのメンバーが対象だったのでシフト作成はまとまった時間で3時間ぐらいを毎回必要としていました。

その中でGoogle Apps Script (GAS) を使えばカレンダーの招待は一発でできるんじゃん？という声をエンジニアからもらい、少しでも効率化するのであればやってみようと思いました！

## なぜ私がやる必要があるのか

正直、私はビジネスサイドの人間なので、エンジニア的なスキルが乏しいです。
そして以前、別のエンジニアが自動でシフト担当者のカレンダー招待まできるGASを作っていることも知っていました。要は頼んだ方が明らかに早いです。

ただ、それだと実際利用するのはビジネスサイドなのに細かなメンテナンスができない。うまく行かなかった時の要因を自分で特定できないので、今回は自分で作ってみようと思いました。

単純にやってみたかった（笑）、というのもあります。

## 作った手順
- GoogleでGASに関する様々な人の記事を検索して、面白そうな内容をそのままコピペして動く喜びを感じる。
- 似たような内容をやっているGASを参照しつつ、中身を読み解き自分用にカスタマイズをする。
- 各ステップの動作を1つずつ確認する。
- 他の人が今後、修正しやすいようにコメントをいれておく。

スクリプトはこのような感じです。

```js

var URL_BOOK = 'https://docs.google.com/spreadsheets/d/XXXXXXXXXXX/edit#gid=XXXXXXX';
var MEMBER_SHEET = '担当者一覧';


function getSheet(bookUrl, sheetName) {
  var book = SpreadsheetApp.openByUrl(bookUrl);
  return book.getSheetByName(sheetName);
}

function getMembers() {
    var sheet = getSheet(URL_BOOK, MEMBER_SHEET);
    var memberObject = sheet.getSheetValues(2, 2, 100, 3);
    return memberObject;
}

function getMemberAccounts(memberObj, memberName) {
    var mail_list = []
    
    for(var a = 0; a < memberName.length; a++){
      for (var i = 0; i < memberObj.length; i++) {
          if (memberObj[i][0] == memberName[a]) {
              mail_list.push(memberObj[i][1])
          }
      }
    }
    return mail_list.toString()
  }

function onOpen() {
    var spreadsheet = SpreadsheetApp.getActive();
    var menuItems = [{
        name: 'csカレンダーに追加',
        functionName: 'create_calender_'
    }];
    spreadsheet.addMenu('CSカレンダー追加（押さないでね）', menuItems);
}

function create_calender_() {

    var members = getMembers();
    // アクティブなスプレッドシートを取得
    var spreadsheet = SpreadsheetApp.getActive();
    // アクティブなシートを取得
    var sheet = spreadsheet.getActiveSheet();
    var values = sheet.getSheetValues(2, 2, 100, 6);
    // 選択されているセルの範囲を取得
    // var range = sheet.getActiveRange();
    // セルの値を取得
    // var values = range.getValues();

    // カレンダーを取得
    var calendar = CalendarApp.getCalendarById('XXXXXXXXXXXXX');

    //var calendar = calendars[0];

    var i;
    for (i = 0; i < values.length; i++) { // 行ごと
        var date = values[i][0];
        var name1 = values[i][2];
        var name2 = values[i][3];
        var name3 = values[i][4];
        var name_array = []
        name_array.push(name1)
        name_array.push(name2)
        name_array.push(name3)
      
        // 空欄を取り除いて '/' 区切りで名前を繋げる ['a', 'b', undefined] => 'a/b'
        var names = [name1, name2, name3].filter(function (name) {
            return name;
        }).join('/');

        // 意図していないフォーマットの行を省く    
        if (!date || !names || !(date instanceof Date)) {
            continue; // 中断して次の行にいく
        }

        // start/endのdateを作る    
        var st = new Date(date.getTime());
        var ed = new Date(date.getTime());
        st.setHours(10, 30, 0); // 10:30:00にセット
        ed.setHours(17, 30, 0); // 17:30:00にセット

        var title = 'チャット担当:' + names; // タイトル

        var options = {
            description: 'チャットシフト担当',
            sendInvites: true
        }; // 詳細セット
        var assigneeAccount = getMemberAccounts(members, name_array);
        if (assigneeAccount == "" || st == null || ed == null) {
          return;
        }
        options.guests = assigneeAccount

        Logger.log(st);
        Logger.log(ed);
        Logger.log(options);
        calendar.createEvent(title, st, ed, options); // カレンダーにイベントを作成    
    }
}
```

## 作ってみた結果

スプレッドシートの**CSカレンダー追加（押さないでね）**を押すと
![スクリーンショット 2018-12-19 18.42.57.png](https://qiita-image-store.s3.amazonaws.com/0/322615/e95e3f13-9ce1-6eee-ac4a-ab47ec9d125b.png)

共有カレンダーに1ヶ月分のスケジュールとタイトルが登録されるようになりました。
![スクリーンショット 2018-12-19 18.44.30.png](https://qiita-image-store.s3.amazonaws.com/0/322615/e6dd3e6f-0a37-90c2-984b-cac8d241249a.png)

今まで1ヶ月分のカレンダー登録と担当者の招待を手動でやっていたのが数秒で完了するようになったのは感動しました。


## 感想
やはり、普段の業務内容と少し異なるので、色々学びがありました。
例えば、アウトプットが固まっていないとスクリプトがバシっとかけないので、エンジニアにプロダクト修正を依頼するときは改めて気をつけよう、という気づき。

1つ1つのステップをテストするのは結構大変なので、スケジュールを決める時はテスト用の時間も意識しようとか。

新しいことを勉強するのは大変だけど、KARTEというプロダクトアウトな製品に関わる一員として、ビジネス側でも少しずつでもこういった所にチャレンジしてエンジニアとの共通言語を習得していきたいと思っています。2019年も頑張るぞ！！