見出し画像

【GAS】Google Apps Script 活用事例 Googleカレンダーの対象期間中の予定をspreadsheetに全て書き出してみる。

Googleカレンダーの対象期間の予定を全て書き出す事が出来たらなぁと、ふと思い書いてみました。前回の、祝日カレンダーをspreadsheetに書き出すスクリプトはこちら

スクリーンショット 2019-12-28 5.07.08のコピー

※自分の環境だと、カレンダーに予定が入っていない人や、チェックマークが外れていると上手く取得できませんでした。(※取得したい人が多過ぎると、カレンダーが見にくくなる欠点があります。)スクリプトはこちら。

取得対象の全員のカレンダーを書き出すスクリプト

function anotherCal() {

//イベントを取得
var calendars = CalendarApp.getAllCalendars();

var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet       = spreadsheet.getSheetByName('RAW');

//特定の日付
var startTime = sheet.getRange(1, 2).getValue();//Spreadsheet側から欲しい日付の操作が出来る
var endTime   = sheet.getRange(2, 2).getValue();//Spreadsheet側から欲しい日付の操作が出来る

var today = new Date();
today = Utilities.formatDate(today, 'JST', 'yyyy/MM/dd');
Logger.log(today);

var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow = Utilities.formatDate(tomorrow, 'JST', 'yyyy/MM/dd');
Logger.log(tomorrow);


var array      = [['日付','ID','予定','開始時刻','終了時刻']];


for(var i = 0; i < calendars.length; i++){

  var calId     = calendars[i].getId();
  var person    = calendars[i].getName();
  var events    = CalendarApp.getCalendarById(calId).getEvents(startTime,endTime);
  
  for (var j = 0; j < events.length; j++){
    var event = events[j];
    var eventTitle = event.getTitle();
    Logger.log(event.getTitle());
    
    var eventStartDay = event.getStartTime();
    eventStartDay = Utilities.formatDate(eventStartDay, 'JST', 'yyyy/MM/dd');
    Logger.log(eventStartDay);
    
    var eventStartTime = event.getStartTime();
    eventStartTime = Utilities.formatDate(eventStartTime, 'JST', 'HH:mm');
    Logger.log(eventStartTime);
    
    var eventEndTime = event.getEndTime();
    eventEndTime = Utilities.formatDate(eventEndTime, 'JST', 'HH:mm');
    Logger.log(eventEndTime);
    
    array.push([eventStartDay,person,eventTitle,eventStartTime,eventEndTime]);
  }//j
}//i 

var isBlank     = sheet.getRange(4, 1, sheet.getLastRow(), sheet.getLastColumn()).isBlank();
var targetRange = sheet.getRange(4, 1, sheet.getLastRow(), sheet.getLastColumn());
Logger.log(isBlank);

//トリガーを使用する事を前提にして、昨日の予定を消して、今日の予定で、上書きするために
//もし4行目以降に値があれば、全て消す。B1, B2は必要のため消さない。


if( isBlank !== true ){ targetRange.clearContent() }
sheet.getRange(4, 1, array.length, array[0].length).setValues(array);
}//end

CalendarApp.getAllCalendars(); 自分が閲覧できる、他のカレンダーに表示されている全てのカレンダーを取得しています。

var startTime = sheet.getRange(1, 2).getValue();
var endTime   = sheet.getRange(2, 2).getValue();

こうしておくと、GASが分からない人でも対象期間をspreadsheet上で自由に設定しやすくなる事です。TODAY関数EDATE関数(1ヶ月後や1ヶ月前まで)もしくは月初と、EOMONTH関数(月末を求める関数)など入れておくと、汎用性が高くなると思います。あとはトリガーを設定すれば、運用の手間暇がグっと減ります。

 for(var i = 0; i < calendars.length; i++){
   for (var j = 0; j < events.length; j++){

    //具体的な処理 今回の場合はイベント名、日付、開始時刻、終了時刻などを取得。

    }
}

取得する人数分のカレンダーID、予定を取得したいので、for文の1周目でカレンダーIDを取得し、for文の2周目で該当するIDの予定を取得し続けます。

for文を二重で使うケースだと、何が何だか分からなくなってしまう事が多かったのですが、自分のやりたい事を日本語で書いて整理すると良いかもしれません。※CalendarApp.getAllCalendars();からのgetEventsとかで全部のイベント持って来れないのかなぁと思いましたが、出来ない仕様なら仕方ない。

メールの下書き作成の場合は、1次元配列の中に文字列を格納してあげれば、良かったのですが、spreadsheetに読み書きする場合は2次元配列にしてあげないといけません。

var array       = [['日付','ID','予定','開始時刻','終了時刻']];
array.push([eventStartDay,person,eventTitle,eventStartTime,eventEndTime]);

for文jの中に記述があります。
既存の配列に要素を加える時は、pushと覚えておけばOK

スクリーンショット 2019-12-28 5.28.44

配列の初期状態は、日付、ID、予定、開始時刻、終了時刻の5つ。5行目, 6行目, 7行目....と処理が一度で終わらず、繰り返すためにfor文の中に、pushを書くと、取得する人数分のカレンダーID()、予定を全て書き切るまで処理が続きます。

画像3

eventStartDay = Utilities.formatDate(eventStartDay, 'JST', 'yyyy/MM/dd');

yyyy/MM/dd形式で日時などを表示させるための記述です。

最近は、GASを、こう書いたらいいみたいのが段々分かってきて、速くより正確に書けるようになってきました。次回はスプレドシートからカレンダーに登録する事にも挑戦してみたいなと考えています。

追伸、スプレッドシートにあらかじめ記載しておいたカレンダーIDを読み取り、カレンダーを取得する事に挑戦してみました。この場合も、Googleカレンダー上の他のカレンダーに登録されていないカレンダーを取得する事は出来ませんでした。

カレンダーIDをシートから読み込んで、予定を書き出したい場合は、こんな感じ

スクリーンショット 2019-12-28 5.07.08のコピー

function myFunction() {
 
 var spreadsheet  = SpreadsheetApp.getActiveSpreadsheet();
 var source       = spreadsheet.getSheetByName('LIST');//読み込みをするためのシート
 var sheet        = spreadsheet.getSheetByName('RAW');//書き込みをするためのシート
 
 //特定の日付
 var startTime = sheet.getRange(1, 2).getValue();//Spreadsheet側から欲しい日付の操作が出来る
 var endTime   = sheet.getRange(2, 2).getValue();//Spreadsheet側から欲しい日付の操作が出来る
 
 //見出し行
 var calArray      = [['日付','ID','予定','開始時刻','終了時刻']];
 
 
 //スプレッドシートから読み取ったカレンダーIDを挿入するために一次元配列化
 var calendarsId    = source.getRange(2, 4, source.getLastRow()-1).getValues();
 calendarsId = Array.prototype.concat.apply([], calendarsId);
 Logger.log(calendarsId);
 
 for(var i = 0; i < calendarsId.length; i++){
   
   var calendar  = CalendarApp.getCalendarById(calendarsId[i]);
   Logger.log(calendarsId.length);
   Logger.log(calendarsId[0]);
   Logger.log(calendar);
   
   var events    = calendar.getEvents(startTime, endTime);
   var person    = calendar.getName();
   
   for (var j = 0; j < events.length; j++){
     var event = events[j];
     var eventTitle = event.getTitle();
     Logger.log(event.getTitle());
     
     var eventStartDay = event.getStartTime();
     eventStartDay = Utilities.formatDate(eventStartDay, 'JST', 'yyyy/MM/dd');
     Logger.log(eventStartDay);
     
     var eventStartTime = event.getStartTime();
     eventStartTime = Utilities.formatDate(eventStartTime, 'JST', 'HH:mm');
     Logger.log(eventStartTime);
     
     var eventEndTime = event.getEndTime();
     eventEndTime = Utilities.formatDate(eventEndTime, 'JST', 'HH:mm');
     Logger.log(eventEndTime);
     
     calArray.push([eventStartDay,person,eventTitle,eventStartTime,eventEndTime]);
   }//j
 }//i 
 
 var isBlank     = sheet.getRange(4, 1, sheet.getLastRow(), sheet.getLastColumn()).isBlank();
 var targetRange = sheet.getRange(4, 1, sheet.getLastRow(), calArray[0].length);
 Logger.log(isBlank);
 
 //トリガーを使用する事を前提にして、昨日の予定を消して、今日の予定で、上書きするために
 //もし4行目以降に値があれば、全て消す。B1, B2は必要のため消さない。
 
 
 if( isBlank !== true ){ targetRange.clearContent() }
 sheet.getRange(4, 1, calArray.length, calArray[0].length).setValues(calArray);
}//end

続きあります。スプレッドシートに書き出して、部署名や名前を処理した上で、Slackに飛ばします。

2020/11/05 追記
自分のカレンダーのみをシートに書き出す方法

function getCalEvents() {

 //日付の処理、11/6 - 11/7までを取得する。
 const start  = new Date('2020/11/06');
 const end    = new Date();
 end.setDate(end.getDate() + 1);
 
 //Dateオブジェクトを、文字列に変換する
 const stringDate  = (date, number, format) => {
  date.setDate(date.getDate() + number);
  return Utilities.formatDate(date, 'JST', format);
 }
 
 //自分のカレンダーから、タイトル、日時、開始時刻、終了時刻、内容を取得
 const events = CalendarApp
 .getDefaultCalendar()
 .getEvents(start, end)
 .map(event => ({
   title: event.getTitle(),
   date: stringDate(event.getStartTime(), 0, 'yyyy/MM/dd'),
   start: stringDate(event.getStartTime(), 0, 'HH:mm'),
   end: stringDate(event.getEndTime(), 0, 'HH:mm'),
   description: event.getDescription()
 }));
 
 console.log(events);
 
 //シートに書き出す
 setEventsToSheet_(events);
}



//シート側の処理 最終行直下にカレンダーの内容を書き出す。
function setEventsToSheet_(events) {
 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 const sheet       = spreadsheet.getSheetByName('書き出し');
 const targetRow   = sheet.getLastRow() + 1;
 
 //オブジェクトを、2次元配列にコンバート
 const keys   = Object.keys(events[0]);
 const values = events.map(event => keys.map(key => event[key]));

 console.log(values);
 
 sheet.getRange(targetRow, 1, values.length, values[0].length).setValues(values);

}

下記の記事を読んで、こういう風にオブジェクト使うのかぁーと勉強になりました。変数が多くなってくると、ちょっと読みにくくなるなーとも感じていて、書き方を真似てみました。

きっちり役割ごとに、カレンダーからイベントを取得する関数と、シートに転記する関数分けて書いています。

const events = CalendarApp
.getDefaultCalendar()
.getEvents(start, end);

//[ {}, {}, {} ];

通常だと、[ {}, {}, {} ]; こんな感じで返ってきて、中身を確認しづらいと感じていました。

この記事が気に入ったらサポートをしてみませんか?