GASで毎朝スプレッドシートの要約をGmailに送る|時間主導トリガーの設定手順

朝いちばんにスプレッドシートを開いて、「今日が期限のタスクはどれだっけ」と上から目で追う。これ、地味に時間を取られますよね。

私も副業のタスクをスプレッドシートで管理していたころ、毎朝この確認から1日を始めていました。しかも忙しい朝に限って開き忘れて、夜になってから「あ、今日が期限だった」と気づく……。そこで、シートの中身を要約して、毎朝メールで届けてもらうことにしました。

💡
この記事で解決すること

スプレッドシートのタスク一覧から「未完了・今日が期限・期限切れ」を数えて、毎朝決まった時間帯にGmailへ要約メールを送るGASを作ります。
宛先のメールアドレスはコードに書かず、スクリプトプロパティから読み込みます。コピペして動かすだけなら、目安は20分ほどです。


この記事の前提

  • Googleアカウントがあり、Googleスプレッドシートを使える
  • GASのエディタを開いて「実行」ボタンを押したことがある(なくても手順どおりで大丈夫です)
  • トリガーそのものの基本は、GASを毎日自動で動かす|時間主導型トリガーの設定手順 でも解説しています。この記事は「何を自動で送るか」の中身づくりが中心です

用語メモ
用語 ざっくりした意味
GAS Google Apps Scriptの略。Googleのサービスを動かせるJavaScriptベースの仕組み
時間主導型トリガー 決めた時間帯に、指定した関数を自動で実行してくれる設定
スクリプトプロパティ スクリプトごとに保存できる「名前と値」のメモ帳。宛先や設定値を入れておける
MailApp GASからメールを送るためのサービス。送信専用

結論:やることは3つだけ

先に全体像です。

  1. シートを読み、未完了・今日が期限・期限切れの件数とタスク名を集める
  2. それをメール本文にまとめて、MailApp.sendEmail で送る
  3. 時間主導型トリガーで、毎朝7時台にこの関数を動かす

「タスク」シートから要約メールが届くまでの流れ

手順1:サンプルのシートを用意する

新しいスプレッドシートを作り、シート名を「タスク」にして、次のダミーデータを入れます。1行目は見出しです。A列は日付として入力してください。

期限 タスク 状態
(今日の日付) ブログ記事の下書きを見直す 未着手
(今日の日付) 請求書のテンプレートを確認する 作業中
(昨日の日付) 画像のサイズをそろえる 未着手
(来週の日付) 次の企画を3つ書き出す 未着手
(昨日の日付) 問い合わせフォームのテスト 完了

日付の列に「2026/11/03」のように入力すると、スプレッドシートが日付として扱ってくれます。テストしやすいように、今日・昨日・来週の日付を混ぜておくのがコツです。


手順2:宛先をスクリプトプロパティに登録する

宛先のメールアドレスは、コードに直接書かずにスクリプトプロパティへ入れておきます。コードを人に見せたり、別のシートにコピーしたりしても、宛先が一緒に出回らないので安心です。

  1. スプレッドシートのメニュー「拡張機能」→「Apps Script」を開く
  2. 左側の「プロジェクト設定」(歯車のアイコン)を開く
  3. 下のほうの「スクリプト プロパティを追加」をクリックする
  4. 「プロパティ」に MAIL_TO、「値」に自分の受け取りたいアドレス(例:[email protected])を入れる
  5. 「スクリプト プロパティを保存」をクリックする

同じ「プロジェクト設定」にタイムゾーンの項目もあります。ここが「(GMT+09:00) 日本標準時」になっているか、ついでに確認しておきましょう。日付の比較やトリガーの時間帯は、このタイムゾーンが基準になります。あわせて、スプレッドシート側の「ファイル」→「設定」にあるタイムゾーンも日本になっているか見ておくと、日付が1日ずれるトラブルを防げます。


手順3:要約メールを送るコードを貼る

エディタに戻り、最初からある function myFunction() {} を消して、次のコードを貼り付けて保存します。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
// ===== 設定 =====
const SHEET_NAME = 'タスク';   // 読み込むシート名
const COL = { DUE: 0, TASK: 1, STATUS: 2 }; // 列の位置(A列=0, B列=1…)
const DONE_LABEL = '完了';      // この状態の行は「済み」として数えない
// ================

function sendDailySummary() {
  // 宛先はスクリプトプロパティから読む(コードに直書きしない)
  const to = PropertiesService.getScriptProperties().getProperty('MAIL_TO');
  if (!to) throw new Error('スクリプトプロパティ MAIL_TO が設定されていません');

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName(SHEET_NAME);
  if (!sheet) throw new Error(`シート「${SHEET_NAME}」が見つかりません`);

  // 見出し行を除き、タスク名が空の行は無視する
  const rows = sheet.getDataRange().getValues().slice(1)
    .filter(r => String(r[COL.TASK]).trim() !== '');

  const tz = Session.getScriptTimeZone();
  const fmt = d => Utilities.formatDate(d, tz, 'yyyy/MM/dd');
  const today = fmt(new Date());

  const notDone = rows.filter(r => r[COL.STATUS] !== DONE_LABEL);
  const hasDate = r => r[COL.DUE] instanceof Date;
  const dueToday = notDone.filter(r => hasDate(r) && fmt(r[COL.DUE]) === today);
  const overdue = notDone.filter(r => hasDate(r) && fmt(r[COL.DUE]) < today);

  const lines = [
    `${today} のタスク要約です。`,
    '',
    `■ 未完了:${notDone.length}件`,
    '',
    `■ 今日が期限:${dueToday.length}件`,
    ...dueToday.map(r => `・${r[COL.TASK]}(${r[COL.STATUS]})`),
    '',
    `■ 期限切れ:${overdue.length}件`,
    ...overdue.map(r => `・${r[COL.TASK]}(期限 ${fmt(r[COL.DUE])})`),
    '',
    `シートを開く:${ss.getUrl()}`,
  ];

  const subject = `【毎朝の要約】${today} 今日が期限 ${dueToday.length}件 / 期限切れ ${overdue.length}件`;
  MailApp.sendEmail(to, subject, lines.join('\n'));

  console.log(`送信しました。今日あと送れる宛先数の目安:${MailApp.getRemainingDailyQuota()}`);
}

ポイントは3つです。

  • Session.getScriptTimeZone() で、プロジェクト設定のタイムゾーンに合わせて日付を文字にしています。日付を yyyy/MM/dd の形にそろえると、文字のまま大小を比べられるので「今日より前=期限切れ」が簡単に判定できます
  • 状態が「完了」の行は数えません。自分のシートで「済」などを使っているなら、DONE_LABEL を書き換えてください
  • MailApp.getRemainingDailyQuota() は、その日にあと何人の宛先へ送れるかを返します。ログで確認できるようにしておくと、送りすぎに気づけます

保存したら、関数の選択欄で sendDailySummary を選び、「実行」を押します。初回は承認(=スクリプトがシートやメールを使ってよいかの確認)の画面が出るので、自分のアカウントを選んで許可してください。途中で「Googleがこのアプリを確認していない」という趣旨の警告が出た場合は、「詳細」を開き、自分のプロジェクト名へ進むリンクから許可します(自分で作ったスクリプトなので心配はいりません)。受信箱に要約メールが届けば成功です。

本文をもっと見やすくしたい、列の並びが違う、といったときは、AIに次のように頼むと早いです。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
次のGoogle Apps Scriptは、スプレッドシートの「タスク」シートから
未完了・今日が期限・期限切れのタスクを集めて、MailAppで要約メールを送るものです。

【やりたいこと】
- 私のシートは A列=タスク、B列=担当、C列=期限、D列=状態 です。列の位置を合わせてください
- 期限が「3日以内」のタスクも別の見出しで一覧に入れてください
- 宛先はスクリプトプロパティ MAIL_TO から読む書き方は変えないでください

【今のコード】
(ここに sendDailySummary のコードを貼る)

手順4:毎朝7時台に動くトリガーを付ける

画面から設定する場合は、公式の手順どおり次の流れです。

  1. エディタ左側の「トリガー」(目覚まし時計のアイコン)を開く
  2. 右下の「トリガーを追加」をクリックする
  3. 実行する関数に sendDailySummary、イベントのソースに「時間主導型」、タイプに「日付ベースのタイマー」、時刻に「午前7時~8時」を選ぶ
  4. 「保存」をクリックする

画面の項目名はGoogleの更新で変わることがあります。見つからないときは「関数」「時間主導型」「毎日」「時間帯」の4つを探すつもりで見てみてください。

コードで作りたい場合は、次の関数を1回だけ実行します。同じトリガーが重複しないよう、すでにあるときは作らないようにしています。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
function createMorningTrigger() {
  const exists = ScriptApp.getProjectTriggers()
    .some(t => t.getHandlerFunction() === 'sendDailySummary');
  if (exists) {
    console.log('sendDailySummary のトリガーはすでにあります');
    return;
  }
  // 毎日、午前7時台のどこかで実行(タイムゾーンはプロジェクト設定に従う)
  ScriptApp.newTrigger('sendDailySummary')
    .timeBased()
    .atHour(7)
    .everyDays(1)
    .create();
}

⏰
「7時ちょうど」には届きません

公式ドキュメントによると、時間主導型トリガーの実行時刻は多少ランダムになります。たとえば午前9時のトリガーなら、9時から10時のどこかの時刻が選ばれ、その時刻が毎日続きます(前回からおよそ24時間おきに動きます)。「7時に来ない、壊れた?」と焦らなくて大丈夫です。


つまずきやすい点

私が最初にやらかしたのは、テスト中に createMorningTrigger を何回も実行してしまい、同じメールが朝に3通届いたことです。トリガー画面で重複がないか、ときどき見ておくと安心ですよ。

症状 原因 対処
「MAIL_TO が設定されていません」と出る スクリプトプロパティの名前が違う、または保存していない 「プロジェクト設定」でプロパティ名が MAIL_TO になっているか確認する
今日が期限なのに0件になる A列が日付ではなく文字として入っている 表示形式を「日付」にして入れ直す
日付が1日ずれる プロジェクト、またはスプレッドシートのタイムゾーンが日本になっていない 「プロジェクト設定」と、スプレッドシートの「ファイル」→「設定」でタイムゾーンを確認する
同じメールが何通も届く トリガーが重複している 「トリガー」画面で余分なものを削除する
メールが届かない日がある 1日に送れる宛先数の上限に達した、またはエラーで止まった 左側の「実行数」で失敗がないか確認する

1日に送れるメールの宛先数には上限があり、公式の割り当て表では個人のGoogleアカウント(gmail.com など)で1日100件、Google Workspaceで1日1,500件です。この上限は、その日最初に送ってから24時間でリセットされます。自分宛てに1日1通なら心配いりませんが、宛先を増やすときは意識しておきましょう。

うまく動かないときは、エラー文ごとAIに渡すのが近道です。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
Google Apps Scriptで、スプレッドシートの要約をMailAppで送る関数を
時間主導型トリガーで毎朝動かしています。

【困っていること】
手動で実行するとメールが届くのに、トリガーで動いたときだけ届きません。

【わかっていること】
- 「実行数」画面の状態:(失敗/完了 など)
- エラーメッセージ:(ここに貼る)
- プロジェクト設定のタイムゾーン:(例:日本標準時)

考えられる原因を可能性が高い順に挙げて、確認する場所を教えてください。

まとめ

  • 宛先はスクリプトプロパティ MAIL_TO に入れて、コードには書かない
  • 日付は Utilities.formatDate で文字にそろえると、「今日が期限」「期限切れ」を判定しやすい
  • トリガーは「7時台のどこか」で動く。重複させないように注意する

次の一歩は、自分が毎朝見ているシートを1つ選んで、COL の列番号だけ書き換えて実行してみることです。1通目が届いたら、朝の確認はもうメールを開くだけになりますよ。


関連する本・記事

こうした「毎朝同じものを確認する仕事」をGASでまとめて自動化したい方は、『Google Apps Script × 生成AI 全自動仕事術』も参考になります。生成AIに頼みながら、GASで手作業を減らしていきたい方向けの1冊です。