はじめに
今回の記事では、Googleカレンダーとスプレッドシートを連携させ、スプレッドシートでGoogleカレンダーを管理することで、イベントの一括管理や編集が可能となるツールを紹介します。
- 一括管理:月ごとのイベントを一覧で確認し、スプレッドシート上で編集ができます。
- 柔軟性:特定の月を指定してイベントをスプレッドシートにエクスポート、またはGoogleカレンダーにインポートできます。
- 時短:複数のイベントを一度に編集や追加、さらには自動更新ができます。
これにより、例えばチームのスケジュール調整やプロジェクトの管理など、多くのタスクの効率化が可能になります。
GASを触ったことのない方でも簡単に作成可能です。作業時間は15分ほどです。
動作イメージ
まずは簡単に本ツールの動作について説明します。
例として次のような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カレンダーへ反映されます。
注意点
GASおすすめ本
GASをもっと勉強したい!ほかにも自分で何か作成したい!という方には以下がおすすめです。仕事で使えるアイデアなども得ることができます。