Googleスプレッドシート上に作成した時間割をGoogleカレンダーに流し込むGASです。
2020年に作成したプロトタイプを安藤先生がUIとかも含めて改変、ご自身のYouTubeチャンネル「GIGAch」で紹介して下さって以降、ともかつさんの「ともかつのノート」上でさらにカスタマイズし、使いやすくして下さいました。
そこで、2020年当初の設計思想を確認し、それを元に機能を制限してコード全体を整理し直したものを公開しておきます。細かい使い方は、ベースとなっている「ともかつのノート」を参照して下さい。
設計思想
- 時間割は基本的に年間を通して変わらないため、一括でカレンダーに流し込みたい。
- 行事や祝祭日がイレギュラーで入るため、期間を区切って流し込む必要がある。
- 各時限の開始、終了時間は可変とすることで汎用性を持たせる。
これを出発点に種々の目的に応じた活用の場が想定され、それに応じた改良が加えられていったのが面白い。起点はシンプルな方が余白が多くあって、それ以降多様な観点からの作り込みを促しやすいのかもしれない。
ver3.0での変更点(改悪含)
- 10限まで使うことがなく6限に戻し、イベントを登録するだけの単純なものへ
- 繰り返しイベントとして登録しないコードへと変更されたことを踏まえ、開始日、終了日のみの設定で動作するように
- その他、コード全体を見直して整理
ver3.3での変更点
- コードの最適化
「(配布用)時間割toカレンダーver3.3」をクリックし、コピーをドライブ上へ作成して使用して下さい。
コード.gs
function onOpen() {
let ui = SpreadsheetApp.getUi();
let menu = ui.createMenu('時間割');
menu.addItem('作成', 'createSchedule');
menu.addItem('削除', 'deleteSchedule');
menu.addToUi();
}
function createSchedule() {
const sheet = SpreadsheetApp.getActiveSheet();
const startDate = new Date(sheet.getRange('A4').getValue());
const endDate = new Date(sheet.getRange('A6').getValue());
let result = Browser.msgBox(`${Utilities.formatDate(startDate, 'JST', 'yyyy-MM-dd')} ~ ${Utilities.formatDate(endDate, 'JST', 'yyyy-MM-dd')} の期間に対して、この時間割を Goolgeカレンダーに作成して良いですか?\\n 【注意】 この操作は取り消せません!`, Browser.Buttons.OK_CANCEL);
if (result == "ok") {
try {
const CALENDAR_ID = sheet.getRange('B2').getValue();
let calendar = CALENDAR_ID ? CalendarApp.getCalendarById(CALENDAR_ID) : CalendarApp.getDefaultCalendar();
const time_schedule = sheet.getRange('C4:D9').getValues();
const schedule = sheet.getRange('E4:K9').getValues();
// Compute interval in days using date objects
const interval = Math.floor((endDate - startDate) / (1000 * 60 * 60 * 24));
for (let i = 0; i <= interval; i++) {
let targetDay = new Date(startDate);
targetDay.setDate(targetDay.getDate() + i);
let weekDay = targetDay.getDay();
if (weekDay == 0) {
continue;
}
weekDay--;
for (let j = 0; j < 6; j++) {
if (schedule[j][weekDay] == '')
continue;
let startTime = new Date(targetDay);
startTime.setHours(time_schedule[j][0].getHours());
startTime.setMinutes(time_schedule[j][0].getMinutes());
let endTime = new Date(targetDay);
endTime.setHours(time_schedule[j][1].getHours());
endTime.setMinutes(time_schedule[j][1].getMinutes());
calendar.createEvent(schedule[j][weekDay], startTime, endTime);
}
}
} catch (e) {
Browser.msgBox('エラーが発生しました: ' + e.message);
}
}
}
function deleteSchedule() {
const sheet = SpreadsheetApp.getActiveSheet();
let startDate = new Date(sheet.getRange('A4').getValue());
let endDate = new Date(sheet.getRange('A6').getValue());
endDate.setHours(23);
endDate.setMinutes(59);
let result = Browser.msgBox(`設定されている期間 ${Utilities.formatDate(startDate, 'JST', 'yyyy-MM-dd')} ~ ${Utilities.formatDate(endDate, 'JST', 'yyyy-MM-dd')} の予定を削除しても良いですか?\\n 【注意】 この操作は取り消せません!`, Browser.Buttons.OK_CANCEL);
if (result == "ok") {
const CALENDAR_ID = sheet.getRange('B2').getValue();
let calendar = CALENDAR_ID ? CalendarApp.getCalendarById(CALENDAR_ID) : CalendarApp.getDefaultCalendar();
let events = calendar.getEvents(startDate, endDate);
events.forEach(function (event) {
event.deleteEvent();
});
}
}
/**
* 取得したカレンダー情報のクリア
*/
function checkClear() {
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('カレンダー情報');
// 一旦、範囲をすべて削除
sheet.clearContents();
// 先頭行の見出しを再設定
let headers = [
{cell: 'A1', value: "実行アカウント"},
{cell: 'A4', value: "登録されているカレンダーの数"},
{cell: 'A7', value: "※このシートの"},
{cell: 'A8', value: " シート名は変更しない!"},
{cell: 'C1', value: "登録されているカレンダーの ID"},
{cell: 'D1', value: "名称"},
{cell: 'E1', value: "isHidden"},
{cell: 'F1', value: "isMyPrimaryCalendar"},
{cell: 'G1', value: "isOwnedByMe"},
{cell: 'H1', value: "isSelected"},
{cell: 'I1', value: "Timezone"}
];
headers.forEach(header => {
sheet.getRange(header.cell).setValue(header.value);
});
}
/**
* カレンダー一覧の取得
*/
function getMyCalendars() {
let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('カレンダー情報');
checkClear();
// 現在の実行アカウントを確認
let eMailID = Session.getActiveUser().getUserLoginId();
sheet.getRange('A2').setValue(eMailID);
// ユーザーが所有またはサブスクライブしているすべてのカレンダーを取得します。
let calendars = CalendarApp.getAllCalendars();
sheet.getRange('A5').setValue(calendars.length); // カレンダーの総数
let calendarData = calendars.map((calendar, i) => {
return [
i + 1,
calendar.getId(), // C
calendar.getName(), // D
calendar.isHidden(), // E
calendar.isMyPrimaryCalendar(), // F
calendar.isOwnedByMe(), // G
calendar.isSelected(), // H
calendar.getTimeZone() // I
];
});
// 書き込み位置の開始行を定義
let startRow = 2;
// 全データを一度に書き込む
sheet.getRange(startRow, 2, calendarData.length, calendarData[0].length).setValues(calendarData);
}