LoginSignup
0
0

【GAS】時間割をカレンダーに流し込む

Last updated at Posted at 2023-03-19

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);
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0