仕事で、Google Calenderを使って月次のミーティングや週次のミーティングを設定することがたまにあります。
定期的な予定を作成する - パソコン - Google カレンダー ヘルプ

繰り返しの設定で毎週、毎月などを選べて便利なのですが、設定後に祝日と被っていないかを確認し、被っていたら前後の日付にずらすという作業を実施していました。
この作業にそれなりの時間がかかっていたので、設定された予定が祝日かどうかスプレッドシートに書き出すGASを作ってみました。
自動でずらすまでは実施できてないのですが、作業時間はそれなりに短縮されたので、作成したものを紹介します。


作成したGAS

const calendarId = 'your_carender_id';
const sheetName = "シート1"
//期間を指定する
const startDate = new Date('2023/01/01 00:00:00'); //取得開始日
const endDate = new Date('2024/01/01 00:00:00'); //取得終了日
// 独自で定義したい祝日
const myCustomHolidays = [{month: 12, day: 29},
                          {month: 12, day: 30},
                          {month: 12, day: 31},
                          {month:  1, day:  2},
                          {month:  1, day:  3},
                          {month:  1, day:  4}];
// 検索時のフィルターに利用するキーワード
const keyword = 'your_keyword';

/* 指定期間のイベントを取得する */
function getEvents() {
  // Add query parameters in optionalArgs
  const optionalArgs = {
    timeMin: startDate.toISOString(),
    timeMax: endDate.toISOString(),
    showDeleted: false,
    singleEvents: true,
    maxResults: 1000,
    orderBy: 'startTime'
    // use other optional query parameter here as needed.
  };
  // call Events.list method to list the calendar events using calendarId optional query parameter
  const response = Calendar.Events.list(calendarId, optionalArgs);
  const events = response.items;

  //対象オブジェクト毎の指定期間内の予定を取得
  const values = [];
  values.push([
    'No',
    'タイトル',
    '開始時刻',
    '終了時刻',
    '休日判定',
    'URL'    
  ]);
  //シートを取得
  let no = 1; //No
  for(const event of events){
    // キーワードを含まない予定の場合は、スプレッドシートへの書き出しをスキップ
    if(!event['summary'].includes(keyword)) continue;

    const record = [
      no++,
      event['summary'],
      _getDateTimeInEvent(event, true),
      _getDateTimeInEvent(event, false),
      _isBusinessDay(new Date(_getDateTimeInEvent(event, true))) ? '平日' : '休日',
      _getCalenderEditUrlFrom(event['htmlLink'])
    ];
    values.push(record);
  }
  SpreadsheetApp.getActiveSheet().getRange(1, 1, values.length, values[0].length).setValues(values);
}

function _getDateTimeInEvent(event, isStart) {
  let startOrEnd = isStart ? 'start' : 'end';
  let result = event[startOrEnd]['dateTime'];
  if(!result) {
    // endのdateも未定義であれば、ブランクを設定
    result = event[startOrEnd]['date'] ?? '';
  }
  return result;
}

function _getCalenderEditUrlFrom(htmlLink) {
  return htmlLink.replace('https://www.google.com/calendar/event?eid=', 'https://calendar.google.com/calendar/u/0/r/eventedit/');
}

function _isBusinessDay(date) {
  console.log(date);
  /* 土日判定 */
  if (date.getDay() % 6 === 0) return false;

  /* 祝日判定 */
  let calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
  let holidays = calendar.getEventsForDay(date);
  if (holidays.length > 0) return false;

  /* 独自のおやすみ */
  let month           = date.getMonth() + 1;
  let day             = date.getDate();

  for (var i = 0; i < myCustomHolidays.length; i++) {
    if (myCustomHolidays[i].month === month && myCustomHolidays[i].day === day) return false;
  }
  return true;
}


使い方

Googleスプレッドシートを作成して、GASのスクリプトエディターを開き、上記のプログラムをコピー&ペーストした値、以下のパラメーターを変更してください。

  • calendarId
    予定取得先のGoogle Carender IDを設定します。
    デフォルトであれば、自分自身のメールアドレスがCarender IDになります。

  • sheetName
    予定の書き出し先となるGoogleスプレッドシートのシート名を入力します。

  • startDateと、endDate
    取得する予定の開始日と終了日を指定してください。
    指定をしない、もしくは、遠い未来日付の場合も、1000件までしか取得できません。

  • keyword
    取得したい予定の件名に含まれる文字列を指定します。
    ブランクの場合は、全件取得となります。

パラメーターの変更後に続き、スクリプトエディターから、Google Calender APIを探して、有効化します。
Image from Gyazo

Image from Gyazo

後は、スクリプトエディターから、getEvents関数を選択し、実行をクリックすると以下のようなイメージで予定を書き出すことができます。

Image from Gyazo


スプレッドシートの値の補足説明

  • 休日、平日判定について
    休日、平日の判定は、予定の開始日を基準に判定しています。
    祝日は、Googleの日本の祝日カレンダーja.japanese#holiday@group.v.calendar.google.comから取得しています。
    休日の場合には、休日が、平日の場合は、平日E列に記載されます。

  • F列について
    F列には、対象行の予定の編集URLが記載されます。
    Google Calender API の戻り値には、編集URLは含まれなかったので、参照URLリンクを置換して編集してURLにしています。
    URLの置換は、_getCalenderEditUrlFrom関数で行っています。

  • カレンダーの設定日付について
    予定の登録の仕方で、date属性、dateTime属性のどちらか一方にしか値が登録されないケースがあったので、dateTime優先で値の取得を行うようにしました。


参考

スクリプトの作成には、以下の記事を参考にしました。

以上です。

コメント