【GAS】スプレッドシートからGoogle Calendarの予定を一括で登録・確認・削除する

# はじめに
Google Calendarの記事をまとめて追加、確認、削除するスプレッドシートを作りましたので紹介します。
Google Apps Scriptの始め方、Google Calendarの操作は以下の記事を参照してください。

 - [【GAS】Google Apps Script 始め方と簡単なスプレッドシート操作](https://qiita.com/koichi_baseball/items/e4754bd1bd72666ab07b)
 - [【GAS】Google Calendarの予定の取得・追加・削除](https://qiita.com/koichi_baseball/items/7fe97cebe2554a1ba8e0)

# できること
## メニュー一覧
自分で追加した「カレンダー更新」タブのメニューから更新を行うことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/a6129ea9-3abe-8d0c-b76c-8f74bdcbf965.png)


## 予定の一括登録
以下のようなスプレッドシートがあり、「カレンダー更新」タブからカレンダーの予定の追加ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/df6b15e0-c5e0-9432-d5e9-c4ab2200359a.png)

カレンダーに予定が追加された様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/33dbde9d-1993-c6f3-6459-17791ea1ebee.png)

## 予定の一括確認・削除
集計開始日から終了日までの予定を確認でき、B列に1をいれた予定の一括削除も行うことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/c8dec4ce-e4b7-a069-7777-aec009583840.png)

5/5の予定が削除された様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/d1f9a48c-c353-68fd-bd7e-b36258793f15.png)

# 実装
※今回は予定の登録を行うシートを「予定追加用シート」、確認と削除を行うシートを「予定削除用シート」としています。
## メニューの追加
まず、更新メニューを追加したいので、スプレッドシートを開いた際に実行される`onOpen`関数で対応するボタンと関数を定義します。

```Javascript
function onOpen(){
  // メニューの追加
  var menu = [
    {name: '予定の登録', functionName: "createEvent"},
    {name: '予定の確認', functionName: "getCalendarEvent"},
    {name: '予定の削除', functionName: "deleteEventById"}
  ];

  SpreadsheetApp.getActiveSpreadsheet().addMenu("カレンダー更新", menu);
}
```


## 予定の一括登録
[この記事](https://qiita.com/koichi_baseball/items/7fe97cebe2554a1ba8e0)で紹介したように、予定の追加には予定を追加するカレンダーのメールアドレスのほかに、「件名、開始時間、終了時間、説明、ゲスト、場所」があればよいので、スプレッドシートにそれらの項目を用意します。それを2次元配列として読み込んで、イベントごとに追加の処理をします。

予定追加用シート↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/df6b15e0-c5e0-9432-d5e9-c4ab2200359a.png)

```Javascript
function createEvent() {
  var sheet   = SpreadsheetApp.getActive().getSheetByName('予定追加用シート');
  var idRange = sheet.getRange(2,3);
  var id      = idRange.getValue();
  var cal     = CalendarApp.getCalendarById(id);
  var lastRow = sheet.getDataRange().getLastRow();
  var lastCol = sheet.getDataRange().getLastColumn();
  
  var eventRange = sheet.getRange(8,2,lastRow-8,lastCol-2);
  var event      = eventRange.getValues();
  
  // イベントごとに登録
  for (var i = 0; i < event.length; i++){
    var title     = event[i][0];
    var startTime = event[i][3];
    var endTime   = event[i][4];
    
    var guests = event[i][1] + ',' + event[i][2];
    var option = {
      description : event[i][5],
      guests : guests,
      location : event[i][6]
    }
    cal.createEvent(title, startTime, endTime, option);
  }
}
```

## 予定の確認
予定の確認は[この記事](https://qiita.com/koichi_baseball/items/7fe97cebe2554a1ba8e0)で予定の取得方法(`event`)は説明したのでそれをスプレッドシートに入力していきましょう。

以下の関数はGoogle Calendarの`event`を受け取って2次元配列に代入していく関数です。参加者の部分などすこしごちゃごちゃしているのでもっといい方法があるかもしれません。[こちら](https://tonari-it.com/gas-calendar-spreadsheet/)のサイトを参考にさせていただきました。
大事な部分は`getID()`で取得できるカレンダーの予定に紐づいている予定のidです。予定の削除はこのidをもとに行います。

予定削除用シート↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/c8dec4ce-e4b7-a069-7777-aec009583840.png)

```Javascript
function setEventsToSheet(events, sheetName){
  // 招待されている人の処理
  var arrData = [],guestData=[];
  for (var i = 0; i < events.length; i++){
    guestData = [events[i].getCreators()[0]]
    var guests = events[i].getGuestList();
    for(var j=0;j<guests.length;j++){
      var mail = guests[j].getEmail();
      guestData.push(mail);
    }
    // 1次元配列を作る
    tmpCalendarData = 
      [
        i+1, //No
        events[i].getTitle(), 
        events[i].getStartTime(),
        events[i].getEndTime(),
        "=INDIRECT(\"RC[-1]\",FALSE)-INDIRECT(\"RC[-2]\",FALSE)",//所要時間の計算
        events[i].getLocation(),
        events[i].getId(),
        guestData
      ]
    guestData = []
    arrData.push(tmpCalendarData)
  }
  
  // シートに予定を書き込む
  var sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  var row_no = sheet.getDataRange().getLastRow();
  var col_no = sheet.getDataRange().getLastColumn();
  sheet.getRange(7,2,row_no,col_no).clearContent();
  
  var rows = arrData.length;
  var cols = arrData[0].length;
  
  sheet.getRange(7,3,rows,cols).setValues(arrData);
}
```

予定の取得は[前回の記事](https://qiita.com/koichi_baseball/items/7fe97cebe2554a1ba8e0)と同じですね。スプレッドシートの`E3:F3`セルで集計期間を入力してそれをもとにカレンダーの予定を取得します。

```Javascript
function getCalendarEvent(){
  // カレンダーの予定を取得する
  var sheet     = SpreadsheetApp.getActive().getSheetByName('予定削除用シート');
  var idRange   = sheet.getRange(2,3);
  var id        = idRange.getValue();
  var cal       = CalendarApp.getCalendarById(id);
  var dateRange = sheet.getRange("E4:F4");
  var date      = dateRange.getValues();
  var startDate = new Date(date[0][0]);
  var endDate   = new Date(date[0][1]);

  var events    = cal.getEvents(startDate, endDate);

  if(events.length==0) Browser.msgBox("予定はありません");
  else setEventsToSheet(events, '予定削除用シート'); 
}
```

## 予定の一括削除
[この記事](https://qiita.com/koichi_baseball/items/7fe97cebe2554a1ba8e0)では`deleteEvent`メソッドを使って指定した日付のすべての予定を削除していましたが、今回はイベントに紐づくidを`getEventById`で取得し、`deleteEvent`メソッドでイベントごとに削除を行います。
予定の確認の際に使用したシートをそのまま使います。
B列の削除フラグが`event[i][0]`にあたるのでそれが1の場合のidのイベントを削除しています。

予定削除用シート↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426354/c8dec4ce-e4b7-a069-7777-aec009583840.png)

```Javascript
function deleteEventById(){
  var sheet       = SpreadsheetApp.getActive().getSheetByName('予定削除用シート');
  var idRange     = sheet.getRange(2,3);
  var id          = idRange.getValue();
  var cal         = CalendarApp.getCalendarById(id);
   
  var LastRow     = sheet.getDataRange().getLastRow();
  var LastCol     = sheet.getDataRange().getLastColumn();
  
  var eventsRange = sheet.getRange(7,2,LasrRow,LastCol);
  var events      = eventsRange.getValues();
  
  var eventId;
  for(var i=0; i<events.length; i++){
    if(events[i][0]==1){ 
      eventId   = events[i][7];
      var event = cal.getEventById(eventId);
      event.deleteEvent();
    }
  }
}
```

# おわりに
Google Calendarの予定を一括で登録・確認・削除を行うことができました。とても便利なのでぜひ使ってみてください！

# 参考
 - [Google Apps ScriptでGoogleカレンダーの記録をスプレッドシートに出力する](https://tonari-it.com/gas-calendar-spreadsheet/)
 - [今日からGoogleカレンダーで使えるGASのコード一覧](https://google-apps-script.net/instructions/?p=249)
 - [【GAS】Google Apps Script 始め方と簡単なスプレッドシート操作](https://qiita.com/koichi_baseball/items/e4754bd1bd72666ab07b)
 - [【GAS】Google Calendarの予定の取得・追加・削除](https://qiita.com/koichi_baseball/items/7fe97cebe2554a1ba8e0)