面倒なカレンダー登録はGASにやらせる

# GASを使ってカレンダー登録

毎月の勤務シフトなど不定期な予定をGoogleカレンダーへ
GASを使って半自動的に登録していきます。

## 1. スプレッドシートへ予定表を作成

カレンダーに入力する元データは手動です。
ぽちぽち作っていきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317674/963ceaca-f350-a46a-f9a0-1d902f79d675.png" width="50%">

> 画像はフィクションです。実在の人物や団体などとは関係ありません。
> [フィクションとは -Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)

”早”の時間は 9時から17時まで
”遅”の時間は 17時から24時まで
空欄は休日9時から24時までの設定とします。

## 2. テストスクリプトの作成

GASからカレンダー登録用のテストスクリプトを作成します

### エディタを開く

「1.」で作ったスプレッドシートから[ツール]→[スクリプト エディタ]をクリック。
スクリプトの作成できるページが表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317674/4f703210-cf3f-7cee-ba9c-56aa142b86b9.png" width="50%">

### スクリプトを作成

デフォルトで入力されているコードは削除し以下のコードを入力します。

```javascript
function createEvents() {
  let calendar = CalendarApp.getDefaultCalendar();
  let title = 'GASテスト';
  let startTime = new Date('2021/1/1 10:00:00');
  let endTime = new Date('2021/1/1 12:00:00');
  let option = {
    description: 'discription',
    location: 'location'
  }

  calendar.createEvent(title, startTime, endTime, option);
}
```

`let calendar = CalendarApp.getDefaultCalendar();`でカレンダーを読み込み
`calendar.createEvent(title, startTime, endTime, option);`でカレンダー登録します。

`let startTime = new Date('2021/1/1 10:00:00');`はカレンダーの開始時間
`let endTime = new Date('2021/1/1 12:00:00');`はカレンダーの終了時間

### スクリプトを動かす

入力ができたら「▶︎」のボタンを押して実行
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317674/ff20cc87-0e42-4b14-9e43-47328b695b67.png" width="50%">

するとアクセス許可のダイアログが開くので問題なければ承認をポチポチ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317674/ae033508-f2a6-24b0-5054-0de6558fde39.png" width="50%">

承認できたら、カレンダーが登録されているか確認します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317674/8279ca69-a942-4292-0c3c-04bedec12208.png" width="50%">

こんな感じに登録されているはずです。

```javascript
let option = {
    description: 'discription',
    location: 'location'
}
```

optionはカレンダー詳細の内容です。
descriptionは説明、
locationは場所の登録内容
今回の記事では不要ですので後のコードからは省略します。

## 3. スプレッドシートのデータを読み込む

### スケジュールパターンを設定

```javascript
const scheduleTime = {
  'asa' : {'title' : '早番','startTime' :  '9:00:00','endTime' : '17:00:00'},
  'yoru'  : {'title' : '遅番','startTime' : '16:00:00','endTime' : '24:00:00'},
  'yasumi'  : {'title' : 'シフト休み','startTime' : '10:00:00','endTime' : '18:30:00'}
};
function setTimes(scr){
  if(scr === ''){
    return scheduleTime.yasumi;
  }else if(scr === '早'){
    return scheduleTime.asa;
  }else{
    return scheduleTime.yoru;
  };
};
```

”早”の時間は 9時から17時まで
”遅”の時間は 16時から24時まで
空欄は休日（9時から24時まで）の設定とします。

### データ読み込み用のスクリプトを作成

```javascript
let sheet = SpreadsheetApp.getActiveSheet();
function getSource() {
    let range = sheet.getRange('A1:C31');
    let source = range.getValues();
    let datas = [];
    source.forEach(function (elem, index) {
        datas[index] = {
            "data": "",
            "schedule": ""
        };
        datas[index].data = elem[0].getFullYear() + '/' + (elem[0].getMonth() + 1) + '/' + elem[0].getDate();
        datas[index].schedule = setTimes(elem[2]);
    });
    return datas;
}
```

`let sheet = SpreadsheetApp.getActiveSheet();`でスプレッドシートを読み込み
`let range = sheet.getRange('A1:C31');`で読み込む範囲を指定
`let source = range.getValues();`で範囲内のデータを読み込み
`source.forEach(function(elem, index) {...});`で読み込んだデータを整理
ここでは取得したData値をyyyy/mm/dd に変換ししています。
「スケジュールパターンを設定」で作った関数setTime()でスケジュールパターンをデータに挿入

これを実行すると以下の値を返します。

```javascript

 [ { data: '2021/1/1',shift: { title: 'シフト休み', startTime: '10:00:00', endTime: '24:00:00' } },
  { data: '2021/1/2',shift: { title: '早番', 'startTime' : '9:00:00','endTime' : '17:00:00' } },
  { data: '2021/1/3',....}
  .
  .
  ....]
```

## 4. スケジュールをカレンダー登録する

カレンダー登録用のスクリプトとスプレッドシート読み込み用のスクリプトができたので実際にカレンダーを登録していきます。

```javascript
function setCalendar() {
    let calendar = CalendarApp.getDefaultCalendar();
    let schedule = getSource();
    schedule.forEach(function (elem, index) {
        let title = elem.schedule.title;
        let startTime = new Date(elem.data + ' ' + elem.schedule.startTime);
        let endTime = new Date(elem.data + ' ' + elem.schedule.endTime);
        calendar.createEvent(title, startTime, endTime);
    });
};
```

カレンダーを読み込み、
「データ読み込み用のスクリプトを作成」で作った関数getSource()でスプレッドシートのデータを取得
`schedule.forEach(function (elem, index) {...});`で各スケジュールをカレンダーへ登録

これを実行すると各日にちごとにスケジュールがカレンダーに登録されているはずです。

### 全コード

```javascript

const scheduleTime = {
  'asa' : {'title' : '早番','startTime' :  '9:00:00','endTime' : '17:00:00'},
  'yoru'  : {'title' : '遅番','startTime' : '16:00:00','endTime' : '24:00:00'},
  'yasumi'  : {'title' : 'シフト休み','startTime' : '10:00:00','endTime' : '18:30:00'}
};
function setTimes(scr){
  if(scr === ''){
    return scheduleTime.yasumi;
  }else if(scr === '早'){
    return scheduleTime.asa;
  }else{
    return scheduleTime.yoru;
  };
};

let sheet = SpreadsheetApp.getActiveSheet();
function getSource() {
    let range = sheet.getRange('A1:C31');
    let source = range.getValues();
    let datas = [];
    source.forEach(function (elem, index) {
        datas[index] = {
            "data": "",
            "schedule": ""
        };
        datas[index].data = elem[0].getFullYear() + '/' + (elem[0].getMonth() + 1) + '/' + elem[0].getDate();
        datas[index].schedule = setTimes(elem[2]);
    });
    return datas;
}

function setCalendar() {
    let calendar = CalendarApp.getDefaultCalendar();
    let schedule = getSource();
    schedule.forEach(function (elem, index) {
        let title = elem.schedule.title;
        let startTime = new Date(elem.data + ' ' + elem.schedule.startTime);
        let endTime = new Date(elem.data + ' ' + elem.schedule.endTime);
        calendar.createEvent(title, startTime, endTime);
    });
};

````


## 参考文献

- [【初心者向けGAS】スプレッドシートのセル・セル範囲とその値を取得する方法](https://tonari-it.com/gas-spreadsheet-range-value-values/)
- [GASでデフォルトのGoogleカレンダーにイベントを追加する簡単なスクリプト](https://tonari-it.com/gas-default-calendar-create-event/)


----
:christmas_tree: [FORK Advent Calendar 2020](https://qiita.com/advent-calendar/2020/fork)
PREV :arrow_left: ４日目 [マテリアルデザインのCSSフレームワーク「Materialize」を触ってみた](https://qiita.com/sk2usa/items/78cc001d14418a098ed0)　@sk2usa さん
NEXT :arrow_right: 7日目 [canvasとJSで、目に優しいオリジナルテトリス](https://qiita.com/yuzukisakioka/items/6c226f619fb12d8902ab)　@yuzukisakioka さん