キャスレーコンサルティング 技術ブログ

Google Apps Scriptでカレンダー連動リマインドのすゝめ

Posted on 04月 20, 2017

こんにちは。 キャスレーコンサルティングのSI(システム・インテグレーション)部のkanemakiと申します。

皆さん、GoogleAppsScriptは好きですか?

これまでも技術ブログでは
Google Apps Script入門
Google Apps Scriptで、心温まる年賀状を作ろう!
Google Apps Scriptとラベルで実現する業務効率化のすゝめ

と過去に取り扱っていますが、今回はGoogleAppsScript(以下GAS)とGoogleCalendarの連携術をご紹介します。

紹介する内容
・カレンダーからスケジュールを引っこ抜け!
・リマインドトリガーを組込もう!
・スプレッドシートから情報を読み込み、自分にリマインドメールを送ろう!

背景

キャスレーではGoogleAppsを利用しております。
Calendarでもリマインダー機能を使いリマインドする事は出来ますが、 「イベントを自動でリマインドしてくれたらな〜」と思うわけです。
(思わない人も話を進めるために、ここでは一旦思うことにしてください。)

リマインダーの為に作業を増やさず、自動化することで当日の会議を忘れない、または会議中に次の会議時間に食い込まない為の リマインダーをGASで実現させましたのでそれを元に[イベントリマインド]をご説明いたします。

GASとは(復習)

次に、本題のGASについてですが、Gmail、Drive、Spreadsheet、Document、Calendar、Mapsなど、 様々なGoogleAppsのアプリケーションに独自の機能を追加するためのスクリプト言語です。

言語仕様はJavaScriptをベースにしており、JavaScript + GoogleAPIというイメージです。
各APIについては、GAS公式に網羅されています。 ※全てEnglishです

カレンダーからスケジュールを引っこ抜け!

処理の流れとして以下のような物を考えています。

『当日のスケジュールを取得し、イベントの○分前にメールを自分に送る』

まずスプレッドシートに、当日のイベントを羅列するシートを以下のように作成します。

part1

次にGASを書いていきましょう。[ツール]から[スクリプトエディタ]を開きます。

part2

エディタにScriptを書いていきます。

まずは、カレンダーから自分のイベント情報を取得します。当日のカレンダー情報を取得するには以下のように記述します。
  var cal = CalendarApp.getCalendarById(ID);//IDはメールアドレスになります。
  var events = cal.getEventsForDay(new Date());

メールで通知したい情報を取得します。私は開始時間とイベント名が分かれば良いのでその2つを取得します。

  var spreadSheet = SpreadsheetApp.openByUrl(this.spreadSheetUrl);
  var sheets = spreadSheet.getSheets();
  var sheet = spreadSheet.getSheetByName('ToDay')

  var pointX = 2;//スプレッドシート上の記入開始行
  var pointY = 1;//スプレッドシート上の記入開始列

  for(var i=0; i < events.length; i++){
    sheet.getRange(i+pointX, pointY).setValue(events[i].getStartTime());//イベント開始時間を取得しスプレッドのセルに転記
    sheet.getRange(i+pointX, pointY + 1).setValue(events[i].getTitle());//イベント名を取得しスプレッドのセルに転記
  }

リマインドトリガーを組込もう!

次にトリガーにリマインドしたいイベントを登録します。
リマインドルールとして、前のイベントの終了時間と次のイベントの開始時間が重なる場合には5分前、それ以外は60分前にリマインドされるようにしました。

  eDateBefore = new Date();

  for(var i=0; i < events.length; i++){
    sDate = events[i].getStartTime();

    //前回の終了時間と今回の開始時間が重なる場合はその5分前にイベントセットする
    if(eDateBefore >= sDate){
      //5分前イベント作成
      sDate.setTime(sDate.getTime() - 5*60*1000);
    }else{
      //60分前イベント作成
      sDate.setHours(sDate.getHours() - 1);
    }

    //新しいトリガーを登録する
    ScriptApp.newTrigger("sendMail").timeBased().at(sDate).create();

    //次回に使う時間
    eDateBefore = events[i].getEndTime();
  }

スプレッドシートから情報を読み込み自分にリマインドメールを送ろう!

最初にスプレッドシートに書き込んだ情報、開始時間とイベント名を取得してメールします。
こちらは前回のブログでも利用したsendEmailを使います。

  var spreadSheet = SpreadsheetApp.openByUrl(this.spreadSheetUrl);
  var sheets = spreadSheet.getSheets();
  var sheet = spreadSheet.getSheetByName('ToDay')

  var pointX = 2;//スプレッドシート上の記入開始行
  var pointY = 1;//スプレッドシート上の記入開始列

  var now = new Date();//現在時刻の取得

  while(sheet.getRange(pointX,pointY).getValue() != ''){
    var sDate = new Date(sheet.getRange(pointX, pointY).getValue());
    if (sDate > now){
      var subject = Utilities.formatDate(sDate, "JST", "HH:mm") + '〜'
      + sheet.getRange(pointX,pointY+1).getValue() + '_イベントリマインド[GAS]';

      MailApp.sendEmail(
        '自分自身@casleyconsulting.co.jp',
        subject,
        '',
        { htmlBody: ''}
      );

      break;
    }
    pointX = pointX + 1;
  }

ここではトリガーにより自動起動し、記載されたイベント一覧から適切なイベントを取得しなければなりません。
やり口としてはいくつかあるとは思いますが、今回は起動タイミングより開始時間が先の物を一つだけメールすることで実現しています。

以上で必要な部品は整いました。 最後に実際に作ったコードを、参考までに以下に記載します。

var spreadSheetUrl = 'スプレッドのURL';
//毎朝実行し、イベントを登録する
function setMyEventsToday(){
  // 予定を取得
  var cal = CalendarApp.getCalendarById(ID);
  var events = cal.getEventsForDay(new Date());
  setEventsToSpread(events);
  setEventsToTrigger(events);
}

function setEventsToSpread(events){
  //リマインドしたい内容を記載する。
  //イベント開始時間、イベント情報
  var spreadSheet = SpreadsheetApp.openByUrl(this.spreadSheetUrl);
  var sheets = spreadSheet.getSheets();
  var sheet = spreadSheet.getSheetByName('ToDay')

  var pointX = 2;//スプレッドシート上の記入開始行
  var pointY = 1;//スプレッドシート上の記入開始列

  //初期化
  for(var i=2;i < 1000;i++){
    sheet.getRange(i, pointY).setValue('');
    sheet.getRange(i, pointY + 1).setValue('');
  }

  for(var i=0; i < events.length; i++){
    sheet.getRange(i+pointX, pointY).setValue(events[i].getStartTime());
    sheet.getRange(i+pointX, pointY + 1).setValue(events[i].getTitle());
  }
}

//イベントリマインドのトリガーのセット
function setEventsToTrigger(events) {
  eDateBefore = new Date();

  for(var i=0; i < events.length; i++){
    sDate = events[i].getStartTime();

    //前回の終了時間と今回の開始時間が重なる場合はその5分前にイベントセットする
    if(eDateBefore >= sDate){
      //5分前イベント作成
      sDate.setTime(sDate.getTime() - 5*60*1000);
    }else{
      //60分前イベント作成
      sDate.setHours(sDate.getHours() - 1);
    }

    //新しいトリガーを登録する
    ScriptApp.newTrigger("sendMail").timeBased().at(sDate).create();

    //次回に使う時間
    eDateBefore = events[i].getEndTime();
  }
}

//現在時間からスプレッドシートに記載されたリマインドメールを送る。
function sendMail(){

  var spreadSheet = SpreadsheetApp.openByUrl(this.spreadSheetUrl);
  var sheets = spreadSheet.getSheets();
  var sheet = spreadSheet.getSheetByName('ToDay')

  var pointX = 2;//スプレッドシート上の記入開始行
  var pointY = 1;//スプレッドシート上の記入開始列

  var now = new Date();//現在時刻の取得

  while(sheet.getRange(pointX,pointY).getValue() != ''){
    var sDate = new Date(sheet.getRange(pointX, pointY).getValue());
    if (sDate > now){
      var subject = Utilities.formatDate(sDate, "JST", "HH:mm") + '〜'
      + sheet.getRange(pointX,pointY+1).getValue() + '_イベントリマインド[GAS]';

      MailApp.sendEmail(
        '自分自身@casleyconsulting.co.jp',
        subject,
        '',
        { htmlBody: ''}
      );

      break;
    }
    pointX = pointX + 1;
  }
}

関数setMyEventsTodayを実行し、トリガーイベントが追加されていることを確認します。

part4

あとはsetMyEventsTodayを毎朝実行するようにしてあげれば自動でリマインド設定がされます。
自動実行後にはイベントは以下のように追加されています。
(例として4/9 15:00-16:00,16:00-17:00の2イベントがある場合)

part5

以上です。簡単ですね。

まとめ

今回は、リマインド機能をGASで実現する方法をご紹介いたしました。

ご一読頂き有難うございました。


採用情報

  • Profile
    キャスレーコンサルティングの技術ブログです。
    当社エンジニアが技術面でのTips、技術系イベント等についてご紹介いたします。
  • CSV社長ブログ
  • チーム・キャスレーブログ