はじめに
Googleカレンダーの仕事用とプライベート用を分けて管理している人も多いのではないでしょうか。そして、予定をご友人や恋人と共有したいという方もいらっしゃるのではないでしょうか。
しかし、仕事用のカレンダーはセキュリティの観点やモラルの観点から共有できないこともあります。また、プライベートカレンダーを共有したとしても仕事用の予定はそのアカウントには入っておらず、結局プライベート用のカレンダーに複製しないといけないことになります。
この記事では仕事用のカレンダーに追加・更新された予定を自動でプライベートカレンダーにコピーすることで違うアカウントのカレンダー情報を一言かすることができるようになります。それでは見ていきましょう。
完成はこちら(Google Apps Scriptに貼り付けてください)
function copyWorkEventsToPrivateCalendar() {
  // 仕事用カレンダーとプライベートカレンダーのIDを設定する
  var workCalendarId = '仕事用のメールアドレスを入力してください(コピー元)';
  var privateCalendarId = 'プライベートのメールアドレスを入力してください(コピー先)';
  var workCalendar = CalendarApp.getCalendarById(workCalendarId);
  var privateCalendar = CalendarApp.getCalendarById(privateCalendarId);
  if (workCalendar === null || privateCalendar === null) {
    console.error("Invalid calendar ID(s). Please check your calendar ID settings.");
    return;
  }
  // 仕事用カレンダーの予定を取得する
  var now = new Date();
  var futureDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); // 30日後までの予定を取得
  var workEvents = workCalendar.getEvents(now, futureDate);
  // 仕事用カレンダーの予定をプライベートカレンダーに同期する
  for (var i = 0; i < workEvents.length; i++) {
    var workEvent = workEvents[i];
    var eventId = workEvent.getId();
    // プライベートカレンダーに同じIDの予定があるか確認する
    var privateEvents = privateCalendar.getEvents(workEvent.getStartTime(), workEvent.getEndTime());
    var privateEvent = null;
    
    for (var j = 0; j < privateEvents.length; j++) {
      if (privateEvents[j].getDescription() === eventId) {
        privateEvent = privateEvents[j];
        break;
      }
    }
    if (privateEvent === null) {
      // 新しい予定をプライベートカレンダーに追加する
      privateEvent = privateCalendar.createEvent(workEvent.getTitle(), workEvent.getStartTime(), workEvent.getEndTime());
      privateEvent.setDescription(eventId);
    } else {
      // 既存の予定を更新する
      privateEvent.setTitle(workEvent.getTitle());
      privateEvent.setTime(workEvent.getStartTime(), workEvent.getEndTime());
    }
  }
  // 変更前の予定を削除する
  var privateEvents = privateCalendar.getEvents(now, futureDate);
  for (var i = 0; i < privateEvents.length; i++) {
    var privateEvent = privateEvents[i];
    var eventId = privateEvent.getDescription();
    var workEvent = workCalendar.getEventById(eventId);
    if (workEvent !== null) {
      if (!(workEvent.getTitle() === privateEvent.getTitle() && workEvent.getStartTime().getTime() === privateEvent.getStartTime().getTime() && workEvent.getEndTime().getTime() === privateEvent.getEndTime().getTime())) {
        privateEvent.deleteEvent();
      }
    }
  }
 
}
function syncCalendars() {
  // 仕事用カレンダーとプライベートカレンダーのIDを設定する
  var workCalendarId = '仕事用のメールアドレスを入力してください(コピー元)';
  var privateCalendarId = 'プライベートのメールアドレスを入力してください(コピー先)';
  var workCalendar = CalendarApp.getCalendarById(workCalendarId);
  var privateCalendar = CalendarApp.getCalendarById(privateCalendarId);
  if (workCalendar === null || privateCalendar === null) {
    console.error("Invalid calendar ID(s). Please check your calendar ID settings.");
    return;
  }
  // 仕事用カレンダーの予定を取得する
  var now = new Date();
  var futureDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); // 30日後までの予定を取得
  var workEvents = workCalendar.getEvents(now, futureDate);
  // 仕事用カレンダーの予定をプライベートカレンダーに同期する
  for (var i = 0; i < workEvents.length; i++) {
    var workEvent = workEvents[i];
    var eventId = workEvent.getId();
    // プライベートカレンダーに同じIDの予定があるか確認する
    var privateEvents = privateCalendar.getEvents(workEvent.getStartTime(), workEvent.getEndTime());
    var privateEvent = null;
    
    for (var j = 0; j < privateEvents.length; j++) {
      if (privateEvents[j].getDescription() === eventId) {
        privateEvent = privateEvents[j];
        break;
      }
    }
    if (privateEvent === null) {
      // 新しい予定をプライベートカレンダーに追加する
      privateEvent = privateCalendar.createEvent(workEvent.getTitle(), workEvent.getStartTime(), workEvent.getEndTime());
      privateEvent.setDescription(eventId);
    } else {
      // 既存の予定を更新する
      privateEvent.setTitle(workEvent.getTitle());
      privateEvent.setTime(workEvent.getStartTime(), workEvent.getEndTime());
    }
  }
  // 変更前の予定を削除する
  var privateEvents = privateCalendar.getEvents(now, futureDate);
  for (var i = 0; i < privateEvents.length; i++) {
    var privateEvent = privateEvents[i];
    var eventId = privateEvent.getDescription();
    var workEvent = workCalendar.getEventById(eventId);
    if (workEvent !== null) {
      if (!(workEvent.getTitle() === privateEvent.getTitle() && workEvent.getStartTime().getTime() === privateEvent.getStartTime().getTime() && workEvent.getEndTime().getTime() === privateEvent.getEndTime().getTime())) {
        privateEvent.deleteEvent();
      }
    }
  }
 
}
// トリガーを設定する関数
function createTrigger() {
  ScriptApp.newTrigger('syncCalendars')
    .timeBased()
    .everyMinutes(30) // 30分ごとに実行されるように設定
    .create();
}手順について
ステップ1 カレンダーの共有を設定する
二つのアカウント別に設定する必要があります。
–仕事用カレンダー(コピーしたい予定が入っている)側の設定–
- Googleカレンダーを開きます。
- 右上の設定を開きます。
- 左のメニューバーの「マイカレンダーの設定」からコピーしたいカレンダーを選択して下さい。
- 「ユーザーやグループを追加」を選択して、プライベート用カレンダー(コピー先のカレンダー)のメールアドレスを入力して下さい。


–プライベート用カレンダー(コピー先)側の設定–
- Googleカレンダーを開きます。
- 右上の設定を開きます。
- 左のメニューバーの「カレンダーを追加」>「カレンダーに登録」を選択して下さい。
- 仕事用カレンダーのメールアドレスを入力してEnterを押して下さい。


ステップ2 コードを編集する
変更が必要な部分は「仕事用のメールアドレス」と「プライベート用のメールアドレス」の二つを変更する場所が計4カ所あります。メールアドレスを変更しておいて下さい。
また、コピーする期間はデフォルトで30日間になっています。基本的には30日間で問題がないと思います。もし変更したい場合copyWorkEventsToPrivateCalendar関数及びsyncCalendars関数の「// 30日後までの予定を取得」の30の部分の数字を任意の数字に変更して下さい。
※基本的は自動化のプログラムを1時間毎に起動基本的には変更する必要はないかと思います。
var futureDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000);ステップ3 Google Apps Scriptのエディターに貼り付ける
こちらを含めると記事が長くなります。Google Apps Scriptのプロジェクトの始め方はこちらの記事をご覧ください。
ステップ4 トリガーを設置する
トリガーとは
Google Apps Scriptのエディタ画面の左のメニューバーにある「トリガー」から設定します。トリガーとはいわば「いつ自動化のシステムを動かしますか」というものです。
トリガーには以下の種類があります。
- 時間主導型
- カレンダー更新型
- フォーム更新型
今回は上二つの「時間主導型」と「カレンダー更新型」を使います。これらを使う理由は以下の通りです。
- 時間主導型・・・仕事用カレンダーがプライベートカレンダーに追加されているのか定期的にチェックする。もし、仕事用カレンダーの予定がプライベートカレンダーに追加されていなければ追加する。
- カレンダー更新型・・・仕事用のカレンダーのタイトルや時間が更新された時にプライベートカレンダーの予定も同様の処理をする。
追加の仕方
- 左のメニューバーの上から3つ目の「トリガー」を選択する。
- 右下の「トリガーを追加」をクリックする。
- copyWorkEventsToPrivateCalendar関数を選択。イベントソースを「時間主導型」。トリガータイプを「時間ベースのタイマー」。時間の間隔を「1時間おき」で設定する。(詳細は下に添付しております画像を参考にして下さい。)
- syncCalendars関数を選択してイベントソースを「カレンダーから」。カレンダーの詳細を入力を「カレンダー更新済み」。オーナーのメールアドレスに「仕事用のメールアドレス」を入力しておいて下さい。(詳細は下に添付しております画像を参考にして下さい。)




注意点
仕事用のカレンダーを削除した際に、プライベートカレンダーは削除されません。そのため、削除の対象を検索する際に「仕事用の予定のタイトル」と「時間」で検索する仕組みになっております。しかし、この精度がGASのみだと低く、他の予定も削除してしまう可能性があります。
仕事用のカレンダーを削除された際にはご自身でプライベート用のカレンダーにコピーされている予定を削除するようにお願い致します。
最後に
いかがだったでしょうか。
今回はGoogle Apps Scriptとカレンダーについてご紹介しました。ぜひ、プロジェクトを実際に作って見て下さい。GASを使ってNotionのコンテンツをLINEに流すなどもできますので、興味のある方はぜひご覧ください。
追記:2024年4月17日
現在、複数のカレンダーの情報を連携させるサービスがすでに作られています。
本記事の作成者である私西坂も現在はこちらを愛用しております。もし、GASがわかりにくいと言う方はぜひこちらも参考にしてください。


