Google Apps Script (GAS)でGoogleカレンダーにシフト登録する。

## 概要
Googleカレンダーに自分のシフトを一括で登録するGASを実装した際のメモです。

スプレッドシートのコピー版を以下で公開中です。
[シフト管理(公開用)](https://docs.google.com/spreadsheets/d/1AF6ykSd-7CFtHWqVFqXww3Tu-isMm4t6sN9LkMvPlic/edit?usp=sharing)

### 前提

今回はシフトの種類は2交代制(日勤、夜勤、夜勤明け、休日）を想定しています.（スプレッドシートとGASの修正すれば色々なパターンに対応できると思います。


### 使い方の流れ
1. 「Googleカレンダー登録」ボタンを押すと、アプリの許可を求められるので注意事項を読んで許可して下さい。
  ※初回のみ
1. スクリプトプロパティで登録先のGoogleカレンダーID(`CALENDAR_ID`)を設定
  ※初回のみ
1. 「雛形」シートをコピーして、赤セルの年月を更新
1. スプレッドシートで予定を記入
![シフト管理1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708007/bed9bbc4-df8f-b7e7-16d2-18cd262ceee9.png)
1. 「Googleカレンダー登録」ボタンを押すと指定したカレンダーに反映される
![シフト管理2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708007/4147f7fa-3922-0ddf-bbad-1ec821ba10cf.png)


## Googleカレンダーへの登録スクリプト

```javascript
function createScheduleOnGoogleCalendar() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  // 対象となる範囲のセル座標を定義
  var ranges = ['B3:H3', 'B5:H5', 'B7:H7', 'B9:H9', 'B11:H11', 'B13:C13'];
  
  var calendarData = [];
  
  // 各範囲について日付とシフトを取得し、リストに追加
  ranges.forEach(function(rangeStr) {
    var range = sheet.getRange(rangeStr);
    var dates = range.getValues()[0];
    var shiftRow = range.offset(1, 0, 1, range.getNumColumns());
    var shifts = shiftRow.getValues()[0];
    
    for (var i = 0; i < dates.length; i++) {
      var date = dates[i];
      var shift = shifts[i];
      calendarData.push({ date: date, shift: shift });
    }
  });
  
  //スクリプトプロパティに格納したデータベースID、トークンを取得
  const props  = PropertiesService.getScriptProperties();
  const calendarId = props.getProperty('CALENDAR_ID');
  let myCalendar = CalendarApp.getCalendarById(calendarId);


  //シフトの種類、カレンダーで表示する色を設定。デフォルトは、終日での登録になるが、時間をいじることで変更可能
  const SHIFTS = {
    日勤: {
      color: CalendarApp.EventColor.YELLOW,
      startHour: 0,
      endHour: 24
    },
    休み: {
      color: CalendarApp.EventColor.PALE_RED,
      startHour: 0,
      endHour: 24
    },
    夜勤: {
      color: CalendarApp.EventColor.BLUE,
      startHour: 0,
      endHour: 24 // 翌日の朝9時まで
    },
    明け: {
      color: CalendarApp.EventColor.MAUVE,
      startHour: 0,
      endHour: 24
    }
  };

  for (var i = 0; i < calendarData.length; i++) {
    var event = calendarData[i];
    var shift = event.shift;
    var shiftInfo = SHIFTS[shift]; // シフトの種類に対応する情報を取得
    Logger.log(shiftInfo)
    // 開始日時と終了日時を設定
    if (shiftInfo) {
      var startDate = new Date(event.date.getFullYear(), event.date.getMonth(), event.date.getDate(), shiftInfo.startHour, 0, 0);
      var endDate = new Date(event.date.getFullYear(), event.date.getMonth(), event.date.getDate() + (shiftInfo.endHour < shiftInfo.startHour ? 1 : 0), shiftInfo.endHour, 0, 0);

      // イベントを作成
      var createdEvent = myCalendar.createEvent(shift, startDate, endDate);
      createdEvent.setColor(shiftInfo.color);
    }
  }

  var result = Browser.msgBox("完了", Browser.Buttons.OK);
}
```



## スマホからスクリプトを実行したい
図形に割り当てたスクリプトはスマホから起動できないので以下の仕組みを作る。

以下のようなトリガーを作成し、スプレッドシートに変更があった時に`invoke`を実行
![シフト管理3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2708007/699e450e-882d-03b0-1913-d21bba8d97ec.png)

スプレッドシートのチェックボックスがTRUEになっているときだけ、`createScheduleOnGoogleCalendar()`を実行させる。

```javascript
function invoke(){
  //スマホでカレンダー登録するための関数。TRUEになったらカレンダー登録する
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  if (sheet.getRange('J10').getValue()){
    createScheduleOnGoogleCalendar();
    sheet.getRange('J10').setValue(false);
  }
}

```

## まとめ
GASで、スプレッドシートの情報からGoogleカレンダーにシフトを一括登録する方法のご紹介でした。