【GAS】Googleカレンダーを一括管理したい

Googleカレンダーでスケジュールを一括作成・編集したい

#目次
[0. 構成](#0-構成)
[1. スケジュールの作成](#1-スケジュールの作成)
[2. 既存スケジュールの一覧表示](#2-既存スケジュールの一覧表示)
[3. 既存スケジュールの修正と削除](#3-既存スケジュールの修正と削除)
[4. 参考にしたサイト](#4-参考にしたサイト)

#0. 構成
Apps Scriptのファイル配置はこんな感じ。
![qiita01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643466/7a1ecd91-86eb-c105-7939-b92752f2db5a.png)

スケジュール作成のデータはスプレッドシートから取得する。
テーブルの作り方はこんな感じ。（「makeList」シート）
![qiita02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643466/521b3fdb-1335-7dff-f465-b602e8710f20.png)

既存スケジュールの一覧表示は、スプレッドシートに書き出す。
修正／削除のデータもスプレッドシートから取得。（「editList」シート）
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643466/dde805fa-d2ab-15fb-53c4-56a5987662ee.png)


時刻を扱うので「appscript.json」でタイムゾーンを日本時刻に設定すること。

```appscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}
```

#1. スケジュールの作成

```makeShedule.js
let user = Session.getActiveUser().getUserLoginId()
let calendar = CalendarApp.getCalendarById(user);
let ss = SpreadsheetApp.openById("1cwWIuY5DFzcOk11-B3kGUs35tmVnQjFfE6kT8-g9Tic");

function makeSchedule() {
  let sh = ss.getSheetByName("makeList");
  let lastRow = sh.getRange(sh.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();

  for(let i = 4; i <= lastRow; i++) {
    let shouldMake = sh.getRange(i, 6).getValue();
    let exist = sh.getRange(i, 7).getValue();

    if(shouldMake == true && exist != true) {
      editCalender2Make(sh, i);
    }
  }
}

function editCalender2Make(sh, i) {
  let title = sh.getRange(i, 1).getValue();
  let startTime = sh.getRange(i, 2).getValue();
  let endTime = sh.getRange(i, 3).getValue();  
  let guestsValue = sh.getRange(i, 4).getValue();
  let descValue = sh.getRange(i, 5).getValue();

  calendar.createEvent(title, startTime, endTime, {guests:guestsValue, description:descValue, sendInvites:true});

  flag2MakeList(sh, i);
}

function flag2MakeList(sh, i) {
  sh.getRange(i, 6).setValue(false);
  sh.getRange(i, 7).setValue(true);
}
```

#2-既存スケジュールの一覧表示

```listScheduleExist.js
function listSchedule() {

  clearListedSchedule();

  let sh = ss.getSheetByName("editList");
  
  let startTime = sh.getRange(1, 2).getValue();
  let endTime = sh.getRange(2, 2).getValue();

  let events = calendar.getEvents(startTime, endTime);
  
  for(let i of events){
    let event = events[i];

    let title = i.getTitle();
    let startTime = i.getStartTime();
    let endTime = i.getEndTime();
    let desc = i.getDescription();
    let id = i.getId();

    let guests = i.getGuestList();
    let guestsArray = [];
    for(let j in guests) {
      guestsArray.push(guests[j].getEmail());
      }
    guestList = guestsArray.join();

    let lastRow = sh.getRange(sh.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();

    sh.getRange(lastRow + 1, 1).setValue(title);
    sh.getRange(lastRow + 1, 2).setValue(startTime);
    sh.getRange(lastRow + 1, 3).setValue(endTime);
    sh.getRange(lastRow + 1, 4).setValue(desc);
    sh.getRange(lastRow + 1, 5).setValue(guestList);
    sh.getRange(lastRow + 1, 6).setValue(id);
  }
}
```

#3-既存スケジュールの修正と削除

```editSchedule.js
function editSchedule() {
  let sh = ss.getSheetByName("editList");
  let lastRow = sh.getRange(sh.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();

  let dataStartrow = 5;

  let existGuestsCol = 5
  let eventIdCol = 6;
  let optionCol = 7
  let newTitleCol = 8;
  let newStarttimeCol = newTitleCol + 1;
  let newEndtimeCol = newTitleCol + 2;
  let newDescCol = newTitleCol + 3;
  let newGuestsCol = newTitleCol + 4;

  for(let i = dataStartrow; i <= lastRow; i++) {
    let option = sh.getRange(i, optionCol).getValue();
    if(option === "修正") {
      exeEditSchedule(sh, i, existGuestsCol, eventIdCol, newTitleCol, newStarttimeCol, newEndtimeCol, newDescCol, newGuestsCol);
    } else if(option === "削除") {
      exeDelSchedule(sh, i, eventIdCol);
    }
  }

  clearListedSchedule();
  Browser.msgBox("スケジュールの修正／変更が完了しました。\\n本スプレッドシートの入力値はリセットします。")
}

function exeEditSchedule(sh, i, existGuestsCol, eventIdCol, newTitleCol, newStarttimeCol, newEndtimeCol, newDescCol, newGuestsCol) {
  
  let eventId = sh.getRange(i, eventIdCol).getValue();
  let event = CalendarApp.getEventById(eventId);

  let newTitle = sh.getRange(i, newTitleCol).getValue();
  let newStartTime = sh.getRange(i, newStarttimeCol).getValue();
  let newEndTime = sh.getRange(i, newEndtimeCol).getValue();
  let newDesc = sh.getRange(i, newDescCol).getValue();
  let newGuest = sh.getRange(i, newGuestsCol).getValue();

  if(newTitle !== ""){
    event.setTitle(newTitle);
  }
  if(newStartTime !== ""){
    event.setTime(newStartTime, newEndTime);
  }
  if(newDesc !== ""){
    event.setDescription(newDesc);
  }
  if(newGuest !== ""){
    let arrNewGuest = newGuest.split(",");
    
    let existGuest = sh.getRange(i, existGuestsCol).getValue();
    let arrExistGuest = existGuest.split(",");

    for(let j = 0; j < arrNewGuest.length; j++){
      if(existGuest.indexOf(arrNewGuest[j]) < 0){
        event.addGuest(arrNewGuest[j]);
      }
    }
    for(let j = 0; j < arrExistGuest.length; j++){
      if(newGuest.indexOf(arrExistGuest[j]) < 0){
        event.removeGuest(arrExistGuest[j]);
      }
    }
  }
}

function exeDelSchedule(sh, i, eventIdCol) {
  let eventId = sh.getRange(i, eventIdCol).getValue();
  let event = CalendarApp.getEventById(eventId);
  event.deleteEvent();
}
```

```clearListedSchedule.js
function clearListedSchedule() {

  let sh = ss.getSheetByName("editList");
  let lastRow = sh.getRange(sh.getMaxRows(), 1).getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  let dataStartrow = 5
  
  sh.getRange(dataStartrow, 1, lastRow, sh.getLastColumn()).clearContent();

}
```

#4-参考にしたサイト
二次配列の扱い方は下記サイトを参考にさせていただきました。

https://tonari-it.com/gas-calendar-spreadsheet/