SANANEBLOG
GAS PR

Google カレンダーをスプレッドシートで管理するツールの作成方法【GAS】

記事内に商品プロモーションを含む場合があります

はじめに

今回の記事では、Googleカレンダーとスプレッドシートを連携させ、スプレッドシートでGoogleカレンダーを管理することで、イベントの一括管理や編集が可能となるツールを紹介します。

メリット
  1. 一括管理:月ごとのイベントを一覧で確認し、スプレッドシート上で編集ができます。
  2. 柔軟性:特定の月を指定してイベントをスプレッドシートにエクスポート、またはGoogleカレンダーにインポートできます。
  3. 時短:複数のイベントを一度に編集や追加、さらには自動更新ができます。

これにより、例えばチームのスケジュール調整やプロジェクトの管理など、多くのタスクの効率化が可能になります。

SANANE

GASを触ったことのない方でも簡単に作成可能です。作業時間は15分ほどです。

動作イメージ

SANANE

まずは簡単に本ツールの動作について説明します。

例として次のようなGoogleカレンダーを用意します。10-11時のイベントや、終日のイベント等が入っています。

カレンダーからスプレッドシートへのエクスポート

スプレッドシートは以下画像のようになっています。

スプレッドシートのA2セルとB2セルに取得したい年月を入力し、[カレンダーツール]の[カレンダーからエクスポート]をクリックします。

対象月のGoogleカレンダー上に記載があった3件のイベントが一括で出力されます。

出力される内容は以下のとおりです。

イベントのタイトル

イベントの開始日時

イベントの終了日時

場所

説明

終日(終日であれば「はい」が出力される)

公開設定

通知時間(分)

イベントID

カレンダーへのインポート

スプレッドシート上でイベントの追加や削除、編集を行った後、「カレンダーへインポート」をクリックします。

編集した内容がGoogleカレンダーへ反映されます。

作成方法

まず、Google スプレッドシートにアクセスします。

アクセスしたら、[新しいスプレッドシートを作成]> [空白]をクリックして新しいスプレッドシートを作成します。

その後、[拡張機能]>[Apps Script]をクリックします。

GASの設定

新しいタブが開きGASが表示されます。

ここから、GAS上でスクリプトを作成します。もともと記載してある以下コードは削除します。

function myFunction() {

}

削除したら、以下コードをコピーしてそのまま貼り付けてくだい。

function setCellFormat() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  // 分のセル範囲の表示方法を変更
  sheet.getRange("C2:C1000").setNumberFormat("00");
  sheet.getRange("D2:D1000").setNumberFormat("00");
  sheet.getRange("F2:F1000").setNumberFormat("00");
  sheet.getRange("G2:G1000").setNumberFormat("00");
}

function exportCalendarToSheet() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  var year = sheet.getRange("A2").getValue();
  var month = sheet.getRange("B2").getValue() - 1;
  
  var calendarId = 'primary'; 
  var calendar = CalendarApp.getCalendarById(calendarId);
  
  var startDate = new Date(year, month, 1); 
  var endDate = new Date(year, month + 1, 0, 23, 59, 59); 
  
  var events = calendar.getEvents(startDate, endDate);
  
  sheet.getRange(5, 1, sheet.getLastRow(), 13).clearContent();
  sheet.getRange("A1").setValue("取得年");
  sheet.getRange("B1").setValue("取得月");
  sheet.getRange(4, 1, 1, 13).setValues([['タイトル', '開始日時', '開始時間', '開始分', '終了日時', '終了時間', '終了分', '場所', '説明', '終日', '公開設定', '通知時間帯', 'ID']]);
  
  for (var i = 0; i < events.length; i++) {
    var event = events[i];
    
    var eventId = event.getId();
    
    var startEventDate = event.getStartTime();
    var endEventDate = event.getEndTime();
    
    var allDay = (startEventDate.getHours() === 0 && startEventDate.getMinutes() === 0 && endEventDate.getHours() === 0 && endEventDate.getMinutes() === 0) ? 'はい' : '';
    
    var startFormattedDate = Utilities.formatDate(startEventDate, Session.getScriptTimeZone(), 'yyyy/MM/dd');
    var startHour = startEventDate.getHours().toString(); // 文字列として取得
    var startMinute = ("0" + startEventDate.getMinutes()).slice(-2);
    
    var endFormattedDate = Utilities.formatDate(endEventDate, Session.getScriptTimeZone(), 'yyyy/MM/dd');
    
    if (allDay === 'はい') {
        endEventDate.setDate(endEventDate.getDate() - 1); // 終日のイベントの終了日を1日減算
        endFormattedDate = Utilities.formatDate(endEventDate, Session.getScriptTimeZone(), 'yyyy/MM/dd');
    }
        
    var endHour = endEventDate.getHours().toString(); // 文字列として取得
    var endMinute = ("0" + endEventDate.getMinutes()).slice(-2);
    
    var title = event.getTitle();
    var location = event.getLocation() || '';
    var description = event.getDescription() || '';
    
    var visibility = event.getVisibility();
    if (visibility === CalendarApp.Visibility.PUBLIC) {
      visibility = '公開';
    } else if (visibility === CalendarApp.Visibility.DEFAULT) {
      visibility = 'デフォルトの公開設定';
    } else {
      visibility = '非公開';
    }
    
    var notifications = event.getPopupReminders();
    var notificationTime = '';

    if (allDay !== 'はい' && notifications && notifications.length > 0) {
        notificationTime = notifications[0];
    } else if (allDay !== 'はい') {
        notificationTime = '30'; // 終日でない場合のデフォルトの通知時間を30分として設定
    }
    
    sheet.getRange(i + 5, 1, 1, 13).setValues([[title, startFormattedDate, startHour, startMinute, endFormattedDate, endHour, endMinute, location, description, allDay, visibility, notificationTime, eventId]]);
  }
}

function importToCalendar() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var calendarId = 'primary';
  var calendar = CalendarApp.getCalendarById(calendarId);
  
  var lastRow = sheet.getLastRow();
  
  var year = sheet.getRange("A2").getValue();
  var month = sheet.getRange("B2").getValue() - 1;
  var startDate = new Date(year, month, 1); 
  var endDate = new Date(year, month + 1, 0, 23, 59, 59); 

  // カレンダーから指定期間のイベントを取得
  var eventsInCalendar = calendar.getEvents(startDate, endDate);
  
  // スプレッドシートに記載されているイベントIDを取得
  var eventIdsInSheet = [];
  for (var i = 5; i <= lastRow; i++) {
    var eventId = sheet.getRange(i, 13).getValue();
    if (eventId) {
      eventIdsInSheet.push(eventId);
    }
  }

  // カレンダーのイベントIDがスプレッドシートに存在しない場合、イベントを削除
  for (var j = 0; j < eventsInCalendar.length; j++) {
    var eventInCalendar = eventsInCalendar[j];
    if (eventIdsInSheet.indexOf(eventInCalendar.getId()) === -1) {
      eventInCalendar.deleteEvent();
    }
  }  

  for (var i = 5; i <= lastRow; i++) {
    var title = sheet.getRange(i, 1).getValue();
    var startFormattedDate = sheet.getRange(i, 2).getValue();
    var startHour = sheet.getRange(i, 3).getValue();
    var startMinute = sheet.getRange(i, 4).getValue();
    var endFormattedDate = sheet.getRange(i, 5).getValue();
    var endHour = sheet.getRange(i, 6).getValue();
    var endMinute = sheet.getRange(i, 7).getValue();
    var location = sheet.getRange(i, 8).getValue();
    var description = sheet.getRange(i, 9).getValue();
    var allDay = sheet.getRange(i, 10).getValue();
    var eventId = sheet.getRange(i, 13).getValue();
    
    var startDate = new Date(startFormattedDate);
    var endDate = new Date(endFormattedDate);

    if (allDay === 'はい') {
        endDate.setDate(endDate.getDate() + 1); // 終日イベントの終了日は次の日の0時に設定
        if (eventId) {
            var event = calendar.getEventById(eventId);
            if (event) {
                event.setTitle(title);
                event.setLocation(location);
                event.setDescription(description);
                event.setAllDayDates(startDate, endDate);
            }
        } else {
            var newEvent = calendar.createAllDayEvent(title, startDate, endDate, {
                location: location,
                description: description
            });
            sheet.getRange(i, 13).setValue(newEvent.getId());
        }
    } else {
        startDate.setHours(startHour, startMinute);
        endDate.setHours(endHour, endMinute);
        if (eventId) {
            var event = calendar.getEventById(eventId);
            if (event) {
                event.setTitle(title);
                event.setLocation(location);
                event.setDescription(description);
                event.setTime(startDate, endDate);
            }
        } else {
            var newEvent = calendar.createEvent(title, startDate, endDate, {
                location: location,
                description: description
            });
            sheet.getRange(i, 13).setValue(newEvent.getId());
        }
    }
  }
}

function onOpen() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var menuItems = [
    {name: 'カレンダーからエクスポート', functionName: 'exportCalendarToSheet'},
    {name: 'カレンダーへインポート', functionName: 'importToCalendar'}
  ];
  spreadsheet.addMenu('カレンダーツール', menuItems);
}

アプリIDとスプレッドシートIDの記入が完了したら、[Ctrl+S]かApps Script 上部バーの[プロジェクトを保存]をクリックして保存します。

Calendar APIの追加

Apps Scriptのエディタの左サイドバーにある「サービス」をクリックします。

「+ サービスを追加」をクリックし、””を検索して追加します。

GASの実行

Google Apps Script 上部バーの[デバック]の右となりにある[実行する関数選択]で[setCellFormat]を選択します。

[▶実行]をクリックします。最初のスクリプトの実行には権限が必要となるため、[承認が必要です]というモーダルが表示されたら、

[権限を確認]>[表示されているGoogleアカウント]>[詳細]>[無題のプロジェクト(安全ではないページ)に移動]>[許可]まで移動します。クリック後GASが実行されます。

ツールの利用方法

A2セルとB2セルに取得したい年と月を入力します。下のイベント一覧のヘッダーはGAS実行後表示されます。

上部メニューの「カレンダーツール」から、「カレンダーからエクスポート」をクリックするとGoogleカレンダーからイベント情報をスプレッドシートに出力します。

「カレンダーへインポート」をクリックすると、スプレッドシート上で行ったイベント情報の修正や新規作成のイベント内容がGoogleカレンダーへ反映されます。

注意点

通知時間は、最初の通知の時間のみ表示されます。単位は分です。

今回のツールは公開設定のインポートには対応しておりません。K列に非公開を入力しても実際のカレンダーへは反映されません。

GASおすすめ本

GASをもっと勉強したい!ほかにも自分で何か作成したい!という方には以下がおすすめです。仕事で使えるアイデアなども得ることができます。