【GASで自動化】Googleカレンダーの予定変更・未完了タスクをGmailに自動で知らせる方法

自動化事例

「今日の夕方までに終わらせるはずだった、あのタスク、どうなった?」
「急な打ち合わせで開始時間が変更になったこと、チーム全員に伝わったかな?」

チームで仕事を進めていると、このようなタスクの進捗確認やスケジュールの変更連絡が頻繁に発生します。口頭での確認や手動での連絡は、抜け漏れや伝達ミスの原因となり、業務の遅延につながることも少なくありません。

もし、未完了のタスクスケジュールの変更を自動で検知し、関係者に通知してくれる仕組みがあれば、これらの課題を解決し、より重要な業務に集中できるのではないでしょうか。

この記事では、多くの企業で利用されているGoogleのツール(スプレッドシート、カレンダー、Gmail)と、簡単なプログラムであるGAS(Google Apps Script)を連携させ、追加コストなしで実現できる「自動通知システム」の構築方法を、専門知識がない方でも実践できるように解説します。

はじめに:自動通知で目指すゴール

この記事では、2つのステップに分けて自動通知の仕組みを構築します。

  1. 【基本編】未完了タスクの通知:まず、多くの方に共通する課題である「タスクのやり忘れ」を防ぐため、1日の終わり(例えば、毎日17時)に、その日完了すべきタスクがスプレッドシート上で「未完了」のままだった場合、指定したメールアドレスに通知する仕組みを作ります。
  2. 【発展編】スケジュール変更の通知:次に、チーム内の情報共有を円滑にするため、Googleカレンダーの予定が変更・更新された際に、その変更内容をメールで通知する機能を追加します。

これらの仕組みを導入することで、タスクのやり忘れを防ぎ、スケジュール変更の共有漏れをなくし、チーム全体の生産性向上に貢献します。

準備するもの

この仕組みを構築するために、特別なツールや有料サービスは必要ありません。必要なのは以下の4つだけです。

  • Googleアカウント
  • Googleスプレッドシート(タスク管理用)
  • Gmail(通知の受信・確認用)
  • Googleカレンダー(スケジュール管理用)※【発展編】で利用します。

普段お使いのGoogleアカウントがあれば、すぐに始めることができます。

タスク管理用のスプレッドシートを作成する

まず、チームのタスクを管理するためのGoogleスプレッドシートを用意します。

A1セルから右に向かって、以下のような項目を作成してください。すでにタスク管理シートを運用している場合は、それを活用しても構いません。

A列B列C列D列E列
タスクIDタスク内容担当者期限ステータス

【各項目の説明】

  • タスクID:各タスクを一意に識別するための番号です。「T-001」「T-002」のように、重複しない値を入力します。このIDが、後でカレンダーと連携する際の「キー」になります。
  • タスク内容:「〇〇社向け提案資料作成」など、具体的なタスクの内容を記載します。
  • 担当者:そのタスクを担当する人の名前を記載します。
  • 期限:タスクの完了期限となる日付を記載します。
  • ステータス:「未着手」「作業中」「完了」など、タスクの進捗状況がわかるように記載します。

ステータスは入力規則でプルダウンリストを作成する

「ステータス」列は、入力規則の機能を使ってプルダウンリストにすると、入力が楽になり、表記の揺れも防げるため便利です。

  1. ステータス列(E列)を選択します。
  2. メニューの「データ」>「データの入力規則」をクリックします。
  3. 「ルールを追加」をクリックし、「条件」で「プルダウン」を選択します。
  4. 「未着手」「作業中」「完了」といった選択肢を1つずつ入力し、「完了」をクリックします。

【基本編】未完了タスクを定時に通知する

ここから、いよいよ自動化の仕組みを構築していきます。使用するのはGoogle Apps Script(略称:GAS)です。

GASは、Googleの各種サービスを連携・自動化できるプログラミング言語です。プログラミングと聞くと難しく感じるかもしれませんが、今回はコピー&ペーストで実装できるようにコードを用意しましたので、ご安心ください。

GASを初めて利用する方へ

GASの基本的な使い方(スクリプトエディタの開き方、コードの保存方法、プログラムの実行を予約する「トリガー」の設定方法など)については、こちらの入門記事で詳しく解説しています。

コードをコピー&ペーストする

タスク管理スプレッドシートのメニュー「拡張機能」>「Apps Script」からスクリプトエディタを開き、以下のコードをすべてコピーして貼り付けてください。

// =============================================================
//【設定項目】 ここから
// =============================================================

// 通知を送信したいGmailアドレス
const NOTIFY_EMAIL_ADDRESS = 'your-email@example.com';

// タスクを管理しているスプレッドシートのID
const SPREADSHEET_ID = 'ここにシートIDを貼り付け';

// タスク一覧が記載されているシート名
const SHEET_NAME = 'シート1';

// =============================================================
//【設定項目】 ここまで
// =============================================================


/**
 * メインの処理:期限日の未完了タスクをメールで通知する
 */
function checkIncompleteTasks() {
  const today = new Date();
  
  // スプレッドシートからタスク一覧を取得
  const tasks = getTasksFromSheet();
  if (tasks.length === 0) {
    console.log('シートからタスク情報を取得できませんでした。');
    return;
  }
  
  // 今日の日付に該当する未完了タスクを抽出
  const incompleteTasks = tasks.filter(task => {
    const dueDate = new Date(task.dueDate);
    return isSameDate(today, dueDate) && task.status !== '完了';
  });
  
  // 未完了タスクがなければ処理を終了
  if (incompleteTasks.length === 0) {
    console.log('本日期限の未完了タスクはありません。');
    return;
  }

  // 通知メールを作成して送信
  sendIncompleteTaskNotification(incompleteTasks);
}

/**
 * スプレッドシートからタスク一覧を取得する関数
 * @return {Array} タスク情報の配列
 */
function getTasksFromSheet() {
  try {
    const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
    // 2行目から最終行までのデータを取得
    const data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 5).getValues();
    
    // 扱いやすいようにオブジェクトの配列に変換
    const tasks = data.map(row => ({
      taskId: row[0],
      taskName: row[1],
      assignee: row[2],
      dueDate: row[3],
      status: row[4]
    }));
    return tasks;
  } catch (e) {
    console.error('スプレッドシートの取得に失敗しました: ' + e.toString());
    return [];
  }
}

/**
 * 2つの日付が同じ日かどうかを判定する関数
 * @param {Date} date1 - 比較する日付1
 * @param {Date} date2 - 比較する日付2
 * @return {boolean} 同じ日付であればtrue
 */
function isSameDate(date1, date2) {
  return date1.getFullYear() === date2.getFullYear() &&
         date1.getMonth() === date2.getMonth() &&
         date1.getDate() === date2.getDate();
}

/**
 * 未完了タスクの通知メールを送信する関数
 * @param {Array} tasks - 未完了タスクの配列
 */
function sendIncompleteTaskNotification(tasks) {
  const subject = '【要対応】本日期限の未完了タスクのお知らせ';
  let body = '本日が期限の未完了タスクがあります。\n\n';
  
  tasks.forEach(task => {
    body += '----------------------------------------\n';
    body += `タスク名: ${task.taskName}\n`;
    body += `担当者: ${task.assignee}\n`;
    body += `期限: ${new Date(task.dueDate).toLocaleDateString()}\n`;
    body += '----------------------------------------\n\n';
  });
  
  body += '速やかに対応をお願いします。';

  try {
    GmailApp.sendEmail(NOTIFY_EMAIL_ADDRESS, subject, body);
    console.log('未完了タスクの通知メールを送信しました。');
  } catch (e) {
    console.error('メールの送信に失敗しました: ' + e.toString());
  }
}

コード内の設定項目を編集する

貼り付けたコードの冒頭部分にある【設定項目】を、ご自身の環境に合わせて書き換えてください。

  1. NOTIFY_EMAIL_ADDRESS: 通知を受け取りたいご自身のGmailアドレスを入力します。
  2. SPREADSHEET_ID: タスク管理スプレッドシートのURLに含まれる、
    「https://docs.google.com/spreadsheets/d/XXXXXXXXXXXXXXXXXXXX/edit」
    の文字部分をコピーして貼り付けます。
  3. SHEET_NAME: タスク一覧が書かれているシート名を入力します。デフォルトでは「シート1」です。

トリガーを設定して自動実行する

コードの準備ができたら、最後に「トリガー」を設定して、プログラムを定時に自動実行するようにします。

トリガー設定画面を開き、以下の内容で設定・保存してください。

  • 実行する関数:checkIncompleteTasks
  • イベントのソース:時間主導型
  • トリガーのタイプ:日付ベースのタイマー
  • 時刻:午後5時~6時(など、業務の終業時間帯に設定)

これで【基本編】の設定は完了です!毎日、設定した時間にプログラムが自動実行され、条件に合う未完了タスクがあればメールで通知が届きます。

【発展編】スケジュールの変更を検知して通知する

次に、Googleカレンダーの予定が変更された際に通知する仕組みを作ります。

準備:Googleカレンダーにタスクの予定を登録する

発展編の仕組みを実装するにあたり、まずGoogleカレンダーにタスクを実行する時間を「予定」として登録します。

このとき、スプレッドシートの「タスクID」を予定の説明欄に記載するのが重要なポイントです。

【登録例】

  • 予定のタイトル:サンプル社向け提案資料作成
  • 日時:2025/9/16(火) 14:00〜16:00
  • 説明:タスクID: T-001

これにより、プログラムが「このカレンダーの予定は、スプレッドシートのどのタスクに対応しているのか」を正確に判断できるようになります。

コードに設定を追加する

発展編の機能で必要となる「カレンダーのID」を、スクリプトエディタの【設定項目】部分に追記します。SHEET_NAMEの下に、以下の1行を追加してください。

// カレンダーのID(通常はご自身のメールアドレス)
const CALENDAR_ID = 'your-email@example.com';

「your-email@example.com」は、ご自身のGmailアドレスなどに書き換えてください。

コードをコピー&ペーストする

ここからは、スケジュールの変更を検知する仕組みを実装します。この仕組みでは、PropertiesService(プロパティサービス) という機能を使います。これは、スクリプトが前回の実行内容を覚えておくための「メモ帳」のようなものです。このメモ帳に前回のカレンダー情報を記録しておき、現在のカレンダー情報と比較することで、変更があった予定だけを検出します。

先ほど貼り付けたコードの下に、続けて以下のコードをコピーして貼り付けてください。

/**
 * メインの処理:スケジュールの変更を検知して通知する
 */
function checkCalendarUpdates() {
  const now = new Date();
  // 1時間前から現在までの予定を取得
  const startTime = new Date(now.getTime() - (60 * 60 * 1000));
  const endTime = now;
  
  const calendar = CalendarApp.getCalendarById(CALENDAR_ID);
  const events = calendar.getEvents(startTime, endTime);
  
  // 変更があったイベントを格納する配列
  const updatedEvents = [];
  
  // スクリプトのプロパティ(メモ帳機能)を取得
  const scriptProperties = PropertiesService.getScriptProperties();

  events.forEach(event => {
    const eventId = event.getId();
    const lastUpdated = event.getLastUpdated().toISOString();
    
    // 過去の更新日時をプロパティから取得
    const previousUpdated = scriptProperties.getProperty(eventId);

    // 過去の記録があり、かつ更新日時が異なれば「変更あり」と判断
    if (previousUpdated && previousUpdated !== lastUpdated) {
      updatedEvents.push({
        title: event.getTitle(),
        lastUpdated: lastUpdated,
        startTime: event.getStartTime().toLocaleString('ja-JP'),
        endTime: event.getEndTime().toLocaleString('ja-JP')
      });
    }
    
    // 今回の更新日時をプロパティに保存
    scriptProperties.setProperty(eventId, lastUpdated);
  });
  
  if (updatedEvents.length > 0) {
    sendCalendarUpdateNotification(updatedEvents);
  } else {
    console.log('期間内にスケジュールの更新はありませんでした。');
  }
}

/**
 * スケジュール変更の通知メールを送信する関数
 * @param {Array} events - 更新されたイベントの配列
 */
function sendCalendarUpdateNotification(events) {
  const subject = '【情報共有】スケジュール変更のお知らせ';
  let body = 'Googleカレンダーの予定が変更されました。\n\n';
  
  events.forEach(event => {
    body += '----------------------------------------\n';
    body += `件名: ${event.title}\n`;
    body += `更新後の時間: ${event.startTime} - ${event.endTime}\n`;
    body += '----------------------------------------\n\n';
  });

  body += '内容を確認してください。';
  
  try {
    GmailApp.sendEmail(NOTIFY_EMAIL_ADDRESS, subject, body);
    console.log('スケジュール変更の通知メールを送信しました。');
  } catch(e) {
    console.error('メールの送信に失敗しました: ' + e.toString());
  }
}

トリガーを追加設定する

スケジュール変更はいつ発生するかわからないため、定期的にチェックする必要があります。

先ほどと同様にトリガー設定画面を開き、新しいトリガーを追加します。

  • 実行する関数:checkCalendarUpdates
  • イベントのソース:時間主導型
  • トリガーのタイプ:時間ベースのタイマー
  • 時間の間隔:15分ごと または 30分ごと
    (※頻度を上げすぎると上限に達する可能性があるため、15分以上の間隔を推奨します)

これで、設定した時間間隔でカレンダーの変更がチェックされ、更新があった場合にメールで通知が届くようになります。

もっと便利に!カスタマイズのヒント

今回ご紹介したコードは、ご自身の業務に合わせてさらに便利にカスタマイズすることも可能です。

  • メールの件名や本文を変更する
    GASコード内の sendIncompleteTaskNotification や sendCalendarUpdateNotification といった関数の中にある subject や body の部分を書き換えることで、通知メールの文面を自由に変更できます。
  • 通知先を追加する
    NOTIFY_EMAIL_ADDRESS の設定を ‘user1@example.com, user2@example.com’ のようにカンマ区切りで複数のメールアドレスにすることで、チームのメンバーなど複数人に同時に通知を送ることができます。

まとめ

この記事では、GoogleスプレッドシートとGoogleカレンダーをGASで連携させ、未完了タスクやスケジュールの変更を自動でGmailに通知する仕組みの構築方法を解説しました。

手作業で行っていた進捗確認や変更連絡を自動化することで、ヒューマンエラーを減らし、チーム内の情報共有を円滑にすることができます。何より、これらの定型業務から解放されることで、より創造的で付加価値の高い仕事に時間を使うことができるようになります。

今回ご紹介した方法は、あくまで一例です。GASを使えば、アイデア次第でさらに多様な業務自動化が可能です。ぜひ、この記事をきっかけに、身の回りの業務効率化に取り組んでみてはいかがでしょうか。

※Googleサービスは、Google LLC の商標であり、この記事はGoogleによって承認されたり、Google と提携したりするものではありません。