はじめに
シフト管理アプリ「シフトボード」の予定をGoogleカレンダーに自動で同期したいと思ったことはありませんか?
この記事では、 Google Apps Script(GAS) を使って、シフトボードからエクスポートしたテキストファイルをGoogleドライブに保存し、それをトリガーで定期的にチェックしてGoogleカレンダーに登録する方法を解説します。
前提として、シフトボードはAPIを公開していないため、データを直接保存するには、iOSカレンダーを一枚噛ませてGoogleカレンダーに同期させる必要があります。この方法でも登録は可能ですが、同期のタイミングが合わず不安定になることがあり、かつ特定の予定のみ限定して登録することもできないため、今回はより確実に登録でき、柔軟に設定できる方法を採用しました。
GAS(Google Apps Script)とは
Google Apps Script(GAS)は、Googleが提供するクラウドベースのスクリプト言語で、Googleのサービス(ドライブ、カレンダー、スプレッドシートなど)を簡単に連携・自動化できます。GASはJavaScriptをベースにしています。
GASを使用するメリット
- 全てGoogleサービス内で完結: 外部サーバーや複雑な環境構築が不要。
- 無料で使える: Googleアカウントがあれば無料枠で十分な機能を利用可能。詳細は公式ドキュメントを参照。
- 簡単なトリガー設定: 時間ベースの自動実行がGUIで設定できる。
- 高い統合性: ドライブやカレンダーとの連携がスムーズ。
プロジェクトのフロー
このプロジェクトの全体像は以下の通りです:
-
登録用ディレクトリの作成
まず、Googleドライブ上にシフト専用のフォルダを作成します。このフォルダが、シフトボードから転送されたデータを一時的に保管する場所となります。 -
シフトボードからGoogleドライブにテキスト形式で保存
シフトボードアプリの「シフトの共有」機能(アプリ上部の共有ボタン)を使用して、シフトデータをテキスト形式でGoogleドライブに保存します。この方法により、シフトデータをクラウド上に保存し、後で処理できるようにします。
2.1 シフトボードのテキスト形式(例)
シフトの共有で保存したファイル内のテキスト形式は以下のようになっています。03/03(月)09:00 - 18:00 - part-time1 03/05(水)09:00 - 14:00 - part-time2
-
GASのトリガー設定による発火とテキスト抽出
Google Apps Script(GAS)のトリガー機能(後述)を活用して、特定の時間ごとにGoogleドライブ上の指定フォルダをチェックします。新しいテキストファイルが追加された場合、GASが自動的に発火し、ファイル内容を抽出します。 -
テキスト解析とGoogleカレンダー用の形式に変換
抽出したテキストから、シフトの日時とタイトルを解析します。この情報を元に、Googleカレンダーで読み込める形式に変換します。たとえば、シフトの開始日時と終了日時、シフト名などを抽出し、カレンダーイベントとして扱えるようにします。 -
Googleカレンダーに送信
最終的に、変換したシフトデータをGoogleカレンダーに登録します。これにより、シフトボードの情報が手動で入力することなく、Googleカレンダーに自動的に反映されるようになります。
プロジェクトの作成
GASプロジェクトの作成
まず、GASプロジェクトを作成します。公式ドキュメントを参考に、プロジェクトを作成してください。
自動生成されたコード.gsを編集していきます。メソッドごとに解説します。
環境変数の取得
function getEnv (key) {
const properties = PropertiesService.getScriptProperties();
return properties.getProperty(key);
}
GASに.envファイルはありません。そのため、スクリプト プロパティとして環境変数を設定します(公式ドキュメント)。スクリプト プロパティはKey-Valueのペア形式になっています。
getScriptProperties()
でアクセスし、getProperty(key)
でValueを返します。
年の取得
function getYear(month) {
const today = new Date();
const currentYear = today.getFullYear();
const currentMonth = today.getMonth() + 1;
if (month < currentMonth) {
const nextYear = currentYear + 1;
return nextYear;
}
return currentYear;
}
元データには年数が書かれていないため、現在の日付から取得する必要があります。today.getMonth() + 1
としているのはgetMonth
の出力が0~11(1月~12月)であるからです。
Googleカレンダー形式に変換
function parseShifts(text) {
const shiftPattern = /(\d{2}\/\d{2})(.)(\d{2}:\d{2}) - (\d{2}:\d{2})\n- (.+)/g;
const events = [];
const currentYear = '2025';
let match;
while ((match = shiftPattern.exec(text)) !== null) {
const [, date, startTime, endTime, calendarTitle] = match;
const [month, day] = date.split('/');
events.push({
title: calendarTitle,
start: { dateTime: `${currentYear}-${month}-${day}T${startTime}:00+09:00` },
end: { dateTime: `${currentYear}-${month}-${day}T${endTime}:00+09:00` },
});
}
return events;
}
これはGoogleカレンダーに登録する際、Googleカレンダーに合った形式へと変換するメソッドです(形式は公式ドキュメント参照)。日付の判定基準はshiftPattern
の正規表現で表しています。前述したように、シフトボードのテキスト形式をshiftPattern
から抽出し、events
に辞書形式で格納していきます。
Googleカレンダーに追加
function processFile(file, calendarId) {
// ファイル内の情報を取得
const text = file.getBlob().getDataAsString();
// Googleカレンダー形式に変換
const events = parseShifts(text);
const calendar = CalendarApp.getCalendarById(calendarId);
events.forEach(event => calendar.createEvent(event.title, new Date(event.start.dateTime), new Date(event.end.dateTime)));
// 処理済みにセット
file.setDescription('processed');
}
これは受け取ったファイルをテキスト形式に変換、さらにGoogleカレンダーに登録できる形へと変換するメソッドです。CalendarApp
でスクリプトがユーザのGoogleカレンダーを読み取り、更新できるようにします(公式ドキュメント)。
crateEvent
で予定の「タイトル」、「開始日(時間)」、「終了日(時間)」をGoogleカレンダーに登録します。その際、ファイルにprocessed
というDescriptionを追加することで、再度同じファイルが読み込まれないようにしています。
エントリーポイント
function syncShiftsToCalendar() {
const folderId = getEnv('FOLDER_ID');
const calendarId = getEnv('CALENDAR_ID');
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFilesByType(MimeType.PLAIN_TEXT);
while (files.hasNext()) {
const file = files.next();
if (!file.getDescription()?.includes('processed')) { // 処理済みチェック
processFile(file, calendarId);
}
}
}
こちらがエントリーポイントとなります。まず、スクリプト プロパティを読み込み、DriveApp
でGoogleドライブの指定したフォルダにアクセスします(公式ドキュメント)。processed
状態を判定し、ファイルがすでに実行されているかを判定します。次に、getFilesByType
により、フォルダー内にある指定したMIMEタイプのファイルを取得します。
(ここで、processed
状態を判定し、Googleカレンダーに登録するかを判断しています)
注意点
1. Googleドライブの権限周り
実行の際、GoogleDriveに関してアクセス権限が制御されることがあります。その際はこちらの記事を参考に許可を行ってください。
2. トリガー設定
定期的にメソッドを実行させるためにトリガー設定を忘れないようにしてください。トリガー設定の詳細はこちらの記事を参照しました。
改善点
- 終了時刻(日付更新)
- バイト等の上がり時間が24時を超える場合は、シフトボードは24時を超える表記になるため、それを考慮する必要がある
-
processed
ではなく削除でもよいのでは?- 登録完了の際、ファイルを削除しても問題ない
- シフトの重複チェック
まとめ
このプロジェクトでは、GASを活用してシフトボードのテキストデータをGoogleドライブ経由でGoogleカレンダーに同期する仕組みを構築しました。特別なサーバーやフロントエンド開発が不要で、Googleサービスだけで完結する点が魅力です。トリガー設定により、定期的に自動更新されるため、手動操作を最小限に抑えられます。
参考