GAS Googleカレンダー 自動登録でダブルブッキングを防ぐ|承認の瞬間にもう一度確認する理由

「GAS Googleカレンダー 自動登録でダブルブッキングを防ぐ|承認の瞬間にもう一度確認する理由」「第191話」というテキストと、青い作業着姿の男性がノートパソコンとカレンダーが表示されたモニターを見ながらスケジュール確認をしているイラストのアイキャッチ画像。机の上には卓上カレンダーも置かれている。 Uncategorized

皆さんこんにちは、横浜で清掃業をしているヤスです。

お客様から「10月3日の午前中でお願いします」と返信メールが届く。メールを読み、カレンダーを開いて、その日に別の予定が入っていないか確かめる。空いていれば予定を入力し、案件の管理表にも工事予定日を書き写す。

このシリーズの第7話では、未整理のPDFを中身で判定して、正しい名前で案件フォルダへ振り分けました。今回は、返信メールから日程を読み取って、Googleカレンダーに予定を入れる仕組みを作りました。

先に核心を書くと、今回の軸は「決められないものは、決めない」です。AIが返すのは「10月3日の午前」まで。それを9:00〜12:00に直すのはGAS(Googleのサービスを自動で動かすためのプログラム)です。そして、承認の瞬間にもう一度カレンダーを確認して、予定が重なっていれば予定を作りません。

※この記事に登場する会社名・人名・住所・案件番号は、すべて練習用に作った架空のダミーです。実在のお客様や実際の取引の話ではありません。

完成形:メールから日時を読み取り、人が承認したら予定を作る

Gmailの「日程連絡」ラベルのメールを読む
  ↓
AIが日付・時間帯・場所を読み取る(時刻の計算はさせない)
  ↓
GASが開始時刻と終了時刻を決める
  ↓
カレンダーに重なる予定がないか確認する
  ↓
「日程調整(確認待ち)」シートに書き出す
  ↓
人が「承認」を選ぶ
  ↓
もう一度、重なりを確認して、Googleカレンダーに予定を作る
案件管理シートの工事予定日を更新する

使ったのは、GAS、Gmail、Googleカレンダー、OpenAI API(プログラムからAIを呼び出すための窓口)、Googleスプレッドシートです。

Googleスプレッドシートの画面。GASによるGoogleカレンダーへの自動登録処理の結果、「予定が重なるため」登録できなかった重複案件が赤色で警告され、正常に「カレンダーに登録」できた案件が緑色でハイライトされている。顧客名や開始日時、判定結果が一覧で分かりやすく整理されている様子。

きっかけはこれまでと同じ、クラウドワークスで見た設備工事会社のバックオフィス効率化の募集です。稼働条件が合わず応募は見送りましたが、書かれていた業務を練習教材として1つずつ作ってきました。今回は「メール・日程調整」の章にあたります。この章のうち「日程調整メールの下書き作成」は第2話で作っていたので、今回は「返信内容から候補日時を抽出」と「Googleカレンダーや管理表への反映」の部分です。

判定は5種類に分けた

メールを読んだ結果は、次の5つのどれかにしました。

判定意味
確認待ち日時が1つに決まり、重なりもない
候補が複数「3日か4日」のように候補が2つ以上。人が選ぶ
予定が重なる既にカレンダーに予定がある
時間帯が不明日付は分かったが、午前・午後・時刻のどれも書かれていない
日時を特定できず日付そのものが決まらない

「決められないもの」に、名前を付けたことになります。うまく読めなかったメールを黙って捨てず、どこで決められなかったのかを判定として残すためです。

作り方①:時刻の計算はAIにさせない

第4話で、見積書の「金額の計算はAIにやらせない」と決めました。今回はその考え方を日時にも当てはめています。

AIに答えさせるのは、日付と、午前・午後・時刻といった時間帯までです。「2026-10-03 の午前」のように返してもらい、それを9:00〜12:00に変換するのはGASの役目にしました。対応関係は、固定のルールとして決めています。

AIが返す時間帯GASが決める時間
午前9:00〜12:00
午後13:00〜17:00
時刻の指定ありその時刻から2時間
終日9:00〜17:00

作業内容ごとの所要時間(エアコン1台なら1時間、など)を使う案もありました。ただ、それをやるには単価マスタに手を入れることになり、見積書の仕組みに影響します。今回は切り離しました。

金額と同じで、日時も「計算のたびに答えが揺れる」ことが困ります。決まった変換は、決まったコードに任せるほうが安心です。

作り方②:重なりの確認は2回やる

一人で現場を回していると、予定の重なりは致命的です。ここが、この仕組みでいちばん大事な部分だと考えています。

重なりの確認は、2回やります。1回目は、メールから日時を抽出したとき。2回目は、人が「承認」を選んだときです。

抽出してから承認するまでには、時間が空きます。その間に、別の予定が入るかもしれません。だから承認の瞬間にもう一度カレンダーを見て、重なっていれば予定を作りません。

同じ日でも、時間帯が違えば重複にはなりません。午前の9:00〜12:00と、午後の13:00〜17:00は、別の枠として扱います。

作り方③:カレンダーに入れる前に、人が承認する

第2話と同じ形にしました。カレンダーに勝手に予定が入ると、他の予定と重なったときに困ります。AIが読み取って、GASが確認して、最後は人が「承認」を選んで初めて予定ができます。

作り方④:「日程連絡」ラベルを別に作った

Gmailには、既存の「案件依頼」ラベルとは別に「日程連絡」ラベルを作りました。

理由は、既存のメール抽出(第2話)と混ざらないようにするためです。同じラベルに入れてしまうと、日程の返信メールが案件の新規依頼として読み取られたり、依頼メールから日程を探しにいったりします。入口を分けておけば、それぞれの仕組みは自分の仕事だけを見ればよくなります。

わざとバラバラに書いたダミーメール5通

日程の書き方を変えた架空の返信メールを5通作り、自分宛てに送りました。

#書き方狙い
①「10月3日の午前中でお願いします」基本形
②「10月3日か10月4日、どちらでも。午後のほうが」候補が複数
③「来週の水曜、14時からで」相対的な日付+時刻
④「再来週以降でしたらいつでも」日付が特定できない
⑤「10月3日の午前中に」(①と同じ日時)ダブルブッキングの検出

結果:5通とも、想定どおりに動いた

③の「来週の水曜」は、正しく変換されました。AIには受信日(9/30・水曜)を渡し、「この日を基準に考えてください」と指示しています。AIの読み取り結果はこうでした。

{"caseNo":"2026-020","customer":null,"place":null,
 "candidates":[{"date":"2026-10-07","period":"時刻","time":"14:00"}]}

JSON(データを決まった形で書き表す書き方)で返ってきています。受信日の翌週の水曜、10月7日になっています。

そして、いちばん見たかったのが④です。「再来週以降でしたらいつでも」では、日付は誰にも決められません。AIの返答はこうでした。

{"caseNo":null,"candidates":[],
 "reason":"再来週以降でしたらいつでもとの記載があり、具体的な日付や時間の指定がないため。"}

candidates が空になり、理由が書かれています。勝手に日付を作りませんでした。この行は「日時を特定できず」として扱われ、開始日時が空欄のまま承認しても、シートには「開始日時または終了日時が入っていません」と表示されます。

承認後の5通の結果をまとめます。

  • ①:カレンダーに登録(10/3 9:00〜12:00)。工事予定日も更新
  • ②:先頭の候補で登録(10/3 13:00〜17:00)。①と同じ日だが時間帯が違うので、重複にならない
  • ③:カレンダーに登録(10/7 14:00〜16:00)。工事予定日も更新
  • ④:開始日時が空欄なので、登録されない
  • ⑤:重複のため中止:2026-018 木村(09:00〜12:00)
GASを利用してGoogleカレンダーに自動登録されたスケジュールの画面。10月3日の予定として、午前に「2026-018 木村(横浜市中区本町〜)」、午後に「2026-019 ミドリ商事」の案件が、作業時間や現場の住所付きで正確にブロック登録されている様子。

つまずき①:テストの順番を間違えて、重複が起きなかった

⑤は、①と同じ日時にして、ダブルブッキングを検出するためのメールでした。

ところが私は、①より先に⑤を承認してしまいました。カレンダーには何も入っていない状態です。当然、そのまま登録されました。

動作としては正しいのです。ただ、テストにはなっていません。カレンダーから予定を消し、①を入れ直してから⑤をやり直したら、今度は上のとおり、ちゃんと止まりました。

テストデータに仕込んだ意図は、実行する順番まで含めて意味を持つことがある。

つまずき②:何も起きないのに、エラーも出ない

今回いちばん考えさせられたのは、こちらです。

④の行を選んで承認を実行したら、実行ログが空のまま終わりました。エラーも出ないので、何が起きたのか分かりません。画面を見ても、何も変わっていません。

調べると、シートの反映結果の列に「開始日時または終了日時が入っていません」と書かれていました。コードは正しく動いていて、想定内の結果を返していただけだったのです。

原因は、処理を中止する箇所にログを書いていなかったことでした。中止したことが、どこにも残っていなかったわけです。

第3話と第4話で、私は「エラーが出ないほうが怖い」と書きました。今回はそれが、自分が設計した仕組みの側で起きました。エラーが出ないほうが怖いと分かっていたのに、中止する道のログを書き忘れていたのです。

処理を中止するときは、必ずログに残す。 何も起きないのにエラーも出ない状態が、いちばん分かりにくいと身にしみました。

つまずき③:顧客名が拾えないことがあった

③のカレンダーの予定名が「2026-020 作業」になりました。メールには「伊藤ビルサービスの伊藤です」と書いてあるのに、顧客名としては拾われなかったのです。

顧客名が空のときは「作業」という既定の名前を使う作りにしていたので、予定は作られました。ただ、カレンダーを見たときに、誰の現場か分かりません。

つまずき④:場所が取れたのは1通だけ

場所が取れたのは、①の「横浜市中区本町2-5-1 木村アパート 103号室」だけでした。②の「事務所は2階になります」や、③の「共用部の作業になります」は、場所として拾いませんでした。

これは妥当な判断だと思います。カレンダーの場所欄に「共用部」とだけ入っていても、役に立たないからです。

安全上の注意:最初はテスト用のカレンダーで試す

この仕組みは、実際にGoogleカレンダーに予定を作ります。案件管理シートの工事予定日も書き換えます。

最初は必ず、テスト用のカレンダーで試してください。普段使っているカレンダーで動かすと、間違った予定が入ったときに、本物の予定の中から探して消すことになります。私も今回は、すべて練習用のダミーメールと、ダミーの予定で試しています。

まとめ:決められないものは、決めない

手順をまとめます。

  1. 「日程連絡」ラベルのメールを読む。既存のメール抽出とは入口を分ける
  2. AIには日付・時間帯・場所だけを答えさせる。時刻の計算はさせない
  3. 午前・午後などの時間への変換は、GASの固定ルールで行う
  4. 決められないもの(候補が複数、時間帯が不明、日時を特定できず)は、判定として残す
  5. 承認の瞬間にもう一度、重なりを確認する。重なっていれば予定を作らない
  6. 中止したときは、必ずログに残す

最初の一歩としては、自分に届く日程の返信メールを3通、見返してみることをおすすめします。「来週の水曜」「どちらでも」「いつでも」など、日程の書き方は人によってばらばらです。それを1つの答えに決められるかどうか、自分で考えてみると、決められないものの多さに気づきます。

私の本業の清掃業に置き換えるなら、定期清掃の日程調整メールから、そのままカレンダーに予定を入れるのに使えそうだと考えています。まだ試してはいません。

8本かけて作ったもの

今回で、募集に書かれていた業務は、ひととおり作り終えました。

最初は、人が決めた案件のルールを一覧にするところから始めました。そこにAIでメールを読ませ、人が承認する流れをつなぎ、見積書、発注書、請求、ファイル、日程へと広げてきました。

振り返ると、どの回も同じことを繰り返していたように思います。計算はAIにさせない、判定できないものは動かさない、最後は人が決める。技術より、どこまでを機械に任せて、どこから人が決めるかの線引きのほうが、ずっと大切でした。

GASについて色々と練習してきて、改めてこんなことができるんだと思いました。今まで作っていたものよりもはるかにレベルアップした気がします。これで今回のGASを使った業務自動化シリーズは終了です。

次回は、仕組みが増えて毎朝届くメールが3通になったので、これを1通にまとめる回にします。

関連記事

このシリーズの過去の記事です。

コメント

タイトルとURLをコピーしました