無趣味の戯言

三日坊主なので頑張らないように頑張ります

【GAS】特定の予定だけを自動で別カレンダーにコピーさせるスクリプト

Google Apps Scriptとやらで遊んでみたので。


ASCII Art by: AA変換(アスキーアート生成)|Web便利ツール@ツールタロウ

こんばんは、だいちゃんです。

暇だったのでGoogle Apps Script(GAS)の勉強がてら、カレンダーに登録された特定の予定だけを自動で別のカレンダーに転記させてあげるスクリプトを書いてみました。書いた、というと語弊がありそうですね、コピペして組み合わせました←

目次

目的

僕自身、ほぼ全ての予定をGoogleカレンダーで管理しています。暇なので予定が少ないから管理するまでもないんですけど。

Googleカレンダーは共有機能も便利なので、うちの家では、家族で共有のカレンダーをひとつ作って、そこに家族に知らせたい予定は書いてね、っていうことを今年の頭くらいから初めています。これまた結構便利で、父の出張とか、僕&弟のバイトとか一目瞭然で、他の頼み事の予定を組みやすくなりました。お陰で「いついついるだろ?ちょっとアシになってくれ」みたいなお願いもされやすくなりました。

ただ、少し悩みだったのが登録の手間です。

僕のバイトの予定はもちろんすぐにでも共有してくれてもいいのですが、デートの予定とか(無いけど)、そういうプライベートな恥ずかしい予定(無いけど)とかのすべてが共有されては困ります。なので、わざわざ自分のカレンダーと、家族用カレンダーに2度登録する必要が出て来るわけです。

そもそもプライベートなスケジュールだけをプライベートなカレンダーに登録して、(家族内に)公開できる予定は共有カレンダーに書き込む手もありますが、そうすると常に家族全員分の予定がカレンダー上に表示されて邪魔なので(基本的に家族共有カレンダーは非表示にしておきたいので)、やはり自分のカレンダーと家族共有カレンダーの2箇所に予定を登録する方法で解決したいわけです。

ということで作ることにしました。

仕組み

仕組みとしては、

  1. 個人カレンダーから1ヶ月分(正確には「来月の月末」)の予定を取得する
  2. そのなかでタイトルに特定の文字(今回は「*」)が入っている予定だけスプレットシートに吐き出す
  3. 家族共有カレンダーから特定の文字(僕の家では【なまえ】を予定のタイトルに入れる決まりなのでそれ)がタイトルについてる予定を削除する
  4. スプレットシートに吐き出されている予定を登録する(その際、タイトルに【なまえ】を入れる)

という形です。

そのまま家族に共有OKな予定を追加するときは、予定のタイトルに「*」を入れるようにするだけで勝手に拾って家族共有カレンダーに追加してくれます。

スプレットシートに吐き出した段階で過去に登録した予定は消すなり重複チェックをすれば、一度予定を全部消してもう一度全部再登録、みたいな面倒なことにならないのですが、暇な僕は予定が少ないので良しとします。

スクリプト

function myFunction() {
  // カレンダーID
  var fromCalendarID = '*****カレンダーID*****';   // 個人カレンダー(元)
  var toCalendarID = '*****カレンダーID*****'; // 共有カレンダー(先)

  // スプレッドシート:シート名
  var SHEET_NAME = 'EventList';
  // スプレッドシート:開始位置
  var RANGE = 1;

  // シート情報を取得
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
  // シートを初期化
  sheet.clear();
  // 登録元のカレンダー情報を取得
  var calendar = CalendarApp.getCalendarById(fromCalendarID);
  // 登録元カレンダーから翌月末日までの予定を取得
  var today = new Date();
  var schedules = calendar.getEvents(today, new Date(today.getFullYear(), today.getMonth() + 2, 0));

  // 登録元の予定の中で「*」の付いてる予定だけを出力する
  for(var index = 0; index < schedules.length; index++) {
    var range = RANGE + index;
    if(schedules[index].getTitle().indexOf("*") != -1) {
      // 開始時間を出力
      sheet.getRange(range, 3).setValue(schedules[index].getStartTime());
      // 終了時間を出力
      sheet.getRange(range, 4).setValue(schedules[index].getEndTime());
      // 予定名を出力→*を削除
      sheet.getRange(range, 5).setValue(schedules[index].getTitle().replace("*",""));
    }
  }
 
  // 登録先のカレンダー情報を取得
  var tocalendar = CalendarApp.getCalendarById(toCalendarID);
  // 登録先カレンダーから翌月末日までの予定を取得
  var toschedules = tocalendar.getEvents(today, new Date(today.getFullYear(), today.getMonth() + 2, 0));

  // 既に登録されている予定の中で「【なまえ】」が付いてるやつを削除  
  for(var i = 0; i < toschedules.length; i++) {
    var eventname = toschedules[i].getTitle();
    if(eventname.indexOf("【なまえ】") != -1){
      toschedules[i].deleteEvent();
    }
  }

  // 予定を再登録(タイトルに【なまえ】を付ける)
  for(var i = 1; i <= sheet.getLastRow(); i++) {
    var cleateTitle = "【なまえ】" + sheet.getRange(i, 5).getValue();
    var cleateStart = sheet.getRange(i, 3).getValue();
    var cleateEnd = sheet.getRange(i, 4).getValue();
    
    var newevent = tocalendar.createEvent(cleateTitle, cleateStart, cleateEnd);
  }
}

注意点とか疑問点とか

  • カレンダーIDは、デフォルトカレンダーならGmailのメアドでいいみたいです。それ以外はカレンダーの設定画面から見れます。
  • スプレットシートのシート名は「EventList」になってます。スクリプト側とシート側とで一致させてください。
  • 日本語ももとい、英語もダメなのでスペルミスしてるかも。Calender?Calendar?←ググれカス
  • 翌月末日までの予定を取得する設定なのは仕様です。調べてたら使ってみたくなったの。getEventsの中を(today, new Date(today.getFullYear(), today.getMonth() + 1, today.getDate())にすれば1ヶ月分でいけます。31日に実行して翌月に31日がなかったらどうなるんだろ。
  • カウント用に i をいろんなとこでたくさん使ってるけどこれってアリなのかな。
  • 気持ち悪いとこ多々あるかもしれませんがご愛嬌...

参考にしたサイト(というかほぼこの方々のものです)