• 作成日 : 2025年10月27日

スプレッドシートの条件付き通知を活用して業務を自動化するには?設定方法を徹底解説

Googleスプレッドシートで条件に応じた通知を行うには、標準の「通知ルール」(編集/フォーム送信)に加え、Google Apps Script やアドオンで条件判定・通知処理(メール/Slackなど)を実装します。これにより重要な変化を自動監視でき、編集イベントは即時、計算結果の変化や外部データは分単位の定期チェックなどで把握可能です。運用上は、必要なトリガー種別・頻度・上限を考慮して設計してください。

手動でのデータチェックから解放され、異常値の早期発見、タスクの自動リマインド、チーム間の情報共有が改善されます。

スプレッドシートの条件付き通知とは何か?

条件付き通知は、スプレッドシート内の特定の条件が満たされた時に自動的にメールやチャットツールに通知を送信する機能で、Google Apps Script(GAS)やアドオンを使用して実装でき、業務の自動監視と迅速な対応を可能にします。

この機能により、24時間365日データを監視し、重要な変化を見逃すことがなくなります。

条件付き通知の基本概念と仕組み

条件付き通知は、「トリガー」「条件」「アクション」の3つの要素で構成されています。トリガーはデータの変更や時間経過などのイベント、条件は通知を送るかどうかを判断する基準、アクションは実際の通知送信処理を指します。

例えば、在庫管理システムでは、商品の在庫数が変更された時(トリガー)、在庫が10個以下になった場合(条件)、管理者にメールを送信する(アクション)という流れで動作します。この一連の処理は完全に自動化され、人の介入なしに実行されます。

Googleスプレッドシートでは、標準機能として「通知ルール」が用意されていますが、より高度な条件付き通知を実現するには、Google Apps Scriptを使用したカスタム実装が必要になります。GASを使用することで、複雑な条件設定、複数の通知先への同時送信、外部サービスとの連携など、柔軟な通知システムを構築できます。

標準の通知機能とカスタム通知の違い

Googleスプレッドシートの標準通知機能は、「ツール」→「通知ルール」から設定でき、ユーザーがシートを編集した時やフォームが送信された時に通知を送ることができます。しかし、この機能は単純な変更通知に限定され、特定の値や条件に基づく通知はできません。

一方、Google Apps Scriptを使用したカスタム通知では、セルの値が特定の範囲を超えた時、複数の条件を組み合わせた複雑な判定、時間帯を考慮した通知制御、通知内容のカスタマイズなど、業務要件に合わせた細かい制御が可能です。

標準機能とカスタム通知の使い分けとして、単純な編集通知なら標準機能で十分ですが、ビジネスロジックを含む通知が必要な場合はGASでの実装が推奨されます。

条件付き通知で実現できる自動化

条件付き通知により、以下のような業務自動化が実現できます。

在庫管理では、最小在庫数を下回った際の自動発注通知、賞味期限が近い商品のアラート、異常な在庫変動の検知を行えます。売上管理では、目標達成時の祝福メッセージ送信、前日比で大きな変動があった場合の通知、月末の自動集計レポート送信が可能です。

プロジェクト管理においては、タスクの期限前リマインダー、進捗率に基づくステータス更新通知、担当者変更時の自動連絡を実装できます。これらの自動化により、手動でのチェック作業が不要になり、業務効率が大幅に向上します。

通知先と連携可能なサービス

条件付き通知の送信先は、メールだけでなく様々なサービスと連携できます。

主要な通知先として、Gmail(個人・グループアドレス)、Slack(チャンネル・ダイレクトメッセージ)、Microsoft Teams、LINE Notify、Discord、Chatworkなどがあります。また、Webhookを使用することで、独自のシステムやAPIとも連携可能です。

複数の通知先を組み合わせることで、緊急度に応じた通知の使い分けも可能です。例えば、重要度が高い通知はメールとSlackの両方に送信し、定期的な報告はSlackのみに送信するといった運用ができます。

条件付き通知のメリットと効果

条件付き通知を導入することで得られる主なメリットは以下のとおりです。

編集イベントは即時通知が可能で、計算結果の変化や外部データの監視は分単位などの定期チェックで早期検知できます。これにより、問題の早期発見と迅速な対応を実現します。自動化により、人的ミスの削減と作業時間の大幅な短縮を実現します。可視化により、チーム全体での情報共有が改善され、意思決定スピードが向上します。

時間主導トリガーを用いて24時間体制の定期監視(例:1分〜数十分間隔)を低コストで構築できます。上限や遅延の可能性を考慮し、重要通知には冗長ルートや再試行・障害通知を設けると安心です。通知の送信履歴は、Apps Scriptでログを記録(例:ログ用シート・BigQuery・外部ログ基盤)することで、後からの確認・分析が可能になります。

これらの効果により、業務品質の向上とコスト削減を同時に達成できます。

スプレッドシートで条件付き通知を設定する方法は?

条件付き通知の設定には、Google Apps Scriptでの基本実装、トリガーの設定、条件式の記述、通知内容のカスタマイズという4つのステップがあり、段階的に実装することで確実に動作する通知システムを構築できます。

適切な設定により、業務要件に完全に合致した通知システムを実現できます。

Google Apps Scriptでの基本的な実装

条件付き通知を実装するには、まずGoogle Apps Scriptエディタを開きます。スプレッドシートから「拡張機能」→「Apps Script」を選択し、スクリプトエディタを起動します。

基本的な条件付き通知の実装例:

function checkConditionAndNotify() {

// 対象シートを明示(シート名は実データに合わせて変更)

const ss = SpreadsheetApp.getActiveSpreadsheet();

const sheet = ss.getSheetByName(‘在庫’) || ss.getActiveSheet();

const values = sheet.getDataRange().getValues(); // 1行目はヘッダー

for (let i = 1; i < values.length; i++) {

const [itemName, stockRaw, thresholdRaw, notified] = values[i];

// すでに通知済みならスキップ

if (String(notified).trim() === ‘通知済’) continue;

// 数値化して判定(未入力や非数値は除外)

const stock = Number(stockRaw);

const threshold = Number(thresholdRaw);

if (!Number.isFinite(stock) || !Number.isFinite(threshold)) continue;

// 条件チェック:在庫が最小在庫数を下回った場合

if (stock >= 0 && stock < threshold) {

sendNotification(itemName, stock, threshold);

// 通知済みフラグ(D列)を設定

const rowIndex = i + 1; // 行番号(1始まり)

sheet.getRange(rowIndex, 4).setValue(‘通知済’);

sheet.getRange(rowIndex, 4).setBackground(‘#ffcccc’);  }}}

function sendNotification(itemName, currentStock, minStock) {

const recipient = ‘[email protected]’;

const subject = `【在庫アラート】${itemName}の在庫が少なくなっています`;

const body = `

${itemName}の在庫が最小在庫数を下回りました。

現在の在庫数:${currentStock}個

最小在庫数:${minStock}個

早急に発注を検討してください。

スプレッドシート:${SpreadsheetApp.getActiveSpreadsheet().getUrl()}  `;

MailApp.sendEmail(recipient, subject, body);

console.log(`通知送信: ${itemName} – 在庫: ${currentStock}`);}

トリガーの種類と設定方法

Google Apps Scriptでは、様々なトリガーを設定して条件付き通知を自動実行できます。

主要なトリガーの種類
  • 時間ベーストリガー:定期的な実行(毎時、毎日、毎週など)
  • 編集時トリガー:セルが編集された時に実行
  • フォーム送信時トリガー:Googleフォームから回答が送信された時
  • 変更時トリガー:シートの構造が変更された時
  • カスタムメニュートリガー:メニューから手動実行

トリガーの設定方法:

function setupTriggers() {

// 既存の「この関数向け」のトリガーのみ削除(安全)

ScriptApp.getProjectTriggers()

.filter(t => t.getHandlerFunction() === ‘checkConditionAndNotify’ || t.getHandlerFunction() === ‘onEditNotification’)

.forEach(t => ScriptApp.deleteTrigger(t));

// 時間ベーストリガー(毎日午前9時に実行)

ScriptApp.newTrigger(‘checkConditionAndNotify’)

.timeBased()

.atHour(9)

.everyDays(1)

.create();

// 編集時トリガー

ScriptApp.newTrigger(‘onEditNotification’)

.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet().getId()) // IDを渡す

.onEdit()

.create();

// 編集時の条件付き通知

function onEditNotification(e) {

const range = e.range;

const value = e.value;

const sheet = range.getSheet();

// 特定の列が編集された場合のみ処理

if (range.getColumn() === 2) { // B列(在庫数)が編集された場合

const row = range.getRow();

const itemName = sheet.getRange(row, 1).getValue();

const threshold = sheet.getRange(row, 3).getValue();

const stockNum = Number(value);

const thresholdNum = Number(threshold);

if (Number.isFinite(stockNum) && Number.isFinite(thresholdNum) && stockNum < thresholdNum) {

sendNotification(itemName, stockNum, thresholdNum);}}}

複雑な条件式の実装方法

実際の業務では、単純な比較だけでなく、複数の条件を組み合わせた複雑な判定が必要になることがあります。

複雑な条件式の実装例:

function checkWarningConditions(row) {

// B列: 現在在庫, C列: 最大/基準在庫, F列: 期限日

const stock = Number(row[1]);

const capacity = Number(row[2]);

const expiry = toDate(row[5]);

// 数値・日付の妥当性チェック

const stockRatio = (Number.isFinite(stock) && Number.isFinite(capacity) && capacity > 0)

? stock / capacity

: NaN;

const daysUntilExpiry = (expiry instanceof Date && !isNaN(expiry))

? daysUntil(expiry)

: Infinity; // 期限未設定は警告条件から除外

return (Number.isFinite(stockRatio) && stockRatio <= 0.2) || daysUntilExpiry <= 3;}

// 日付ヘルパー

function toDate(v) {

// Date型ならそのまま、文字列はDateに変換、数値(シリアル)にも対応

if (v instanceof Date) return v;

if (typeof v === ‘number’) return new Date(Math.round((v – 25569) * 86400 * 1000)); // スプレッドシート序数対応

if (typeof v === ‘string’) return new Date(v);

return new Date(‘Invalid’);}

function daysUntil(d) {

const today = new Date();

// 時刻の影響を避けるため日付丸め

today.setHours(0,0,0,0);

const target = new Date(d.getFullYear(), d.getMonth(), d.getDate());

return Math.ceil((target – today) / 86400000);}

function checkUrgentConditions(row) {

// 緊急条件:在庫0 AND 注文あり

const stock = Number(row[1]);   // 在庫

const orders = Number(row[4]);  // 未出荷注文数など

return Number.isFinite(stock) && Number.isFinite(orders) && stock === 0 && orders > 0;}

function checkInfoConditions(row) {

// 情報条件:在庫が50%以下

const stock = Number(row[1]);

const capacity = Number(row[2]);

if (!Number.isFinite(stock) || !Number.isFinite(capacity) || capacity <= 0) return false;

const stockRatio = stock / capacity;

return stockRatio <= 0.5;}

function complexConditionCheck() {

const ss = SpreadsheetApp.getActiveSpreadsheet();

const sheet = ss.getSheetByName(‘在庫’) || ss.getActiveSheet(); // シート名は実データに合わせて変更

const data = sheet.getDataRange().getValues();

// …}

通知内容のカスタマイズ

通知メッセージを受信者にとって分かりやすく、アクション可能な内容にカスタマイズします。

高度な通知カスタマイズの実装:

function createCustomNotification(data, type) {

const sheetUrl = SpreadsheetApp.getActiveSpreadsheet().getUrl();

// データは念のためエスケープ

const safe = {

itemName: escapeHtml(String(data.itemName ?? ”)),

currentValue: escapeHtml(String(data.currentValue ?? ”)),

threshold: escapeHtml(String(data.threshold ?? ”))};

const htmlBody = `

<div style=”font-family: Arial, sans-serif; max-width: 600px;”>

<div style=”background-color: ${getColorByType(type)}; color: white; padding: 10px;”>

<h2 style=”margin:0;”>${escapeHtml(getHeaderByType(type))}</h2>

</div>

<div style=”padding: 20px; background-color: #f9f9f9;”>

<h3>詳細情報</h3>

<table style=”width: 100%; border-collapse: collapse;”>

<tr>

<td style=”padding: 8px; border: 1px solid #ddd;”><strong>項目名</strong></td>

<td style=”padding: 8px; border: 1px solid #ddd;”>${safe.itemName}</td>

</tr>

<tr>

<td style=”padding: 8px; border: 1px solid #ddd;”><strong>現在値</strong></td>

<td style=”padding: 8px; border: 1px solid #ddd;”>${safe.currentValue}</td>

</tr>

<tr>

<td style=”padding: 8px; border: 1px solid #ddd;”><strong>基準値</strong></td>

<td style=”padding: 8px; border: 1px solid #ddd;”>${safe.threshold}</td>

</tr>

<tr>

<td style=”padding: 8px; border: 1px solid #ddd;”><strong>推奨アクション</strong></td>

<td style=”padding: 8px; border: 1px solid #ddd;”>${escapeHtml(getRecommendedAction(data, type))}</td>

</tr>

</table>

<p style=”margin-top: 20px;”>

<a href=”${sheetUrl}” style=”background-color: #4CAF50; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;”>

スプレッドシートを開く

</a>

</p>

</div>

</div>

`;

return htmlBody;}

function getColorByType(type) {

const colors = { urgent: ‘#ff4444’, warning: ‘#ffaa00’, info: ‘#4444ff’ };

return colors[type] || ‘#888888’;}

function getHeaderByType(type) {

switch (type) {

case ‘urgent’:  return ‘【至急対応】重要アラート’;

case ‘warning’: return ‘【注意】警告通知’;

case ‘info’:    return ‘情報通知’;

default:        return ‘通知’;}}

function getRecommendedAction(data, type) {

// 例:在庫アラート想定

const stock = Number(data.currentValue);

const threshold = Number(data.threshold);

if (type === ‘urgent’) return ‘至急、補充または代替案を検討してください。’;

if (type === ‘warning’) {

if (Number.isFinite(stock) && Number.isFinite(threshold) && stock < threshold)

return ‘補充発注を行ってください。’;

return ‘状況を確認してください。’;}

return ‘状況を共有し、必要に応じて対応してください。’;}

function escapeHtml(s) {

return s

.replace(/&/g,’&amp;’)

.replace(/</g,’&lt;’)

.replace(/>/g,’&gt;’)

.replace(/”/g,’&quot;’)

.replace(/’/g,’&#39;’);}

Slack連携での通知実装

メールだけでなく、Slackへの通知も実装できます。

Slack通知の実装例:

function sendSlackNotification(message/* , channel */) {

const webhookUrl = PropertiesService.getScriptProperties().getProperty(‘SLACK_WEBHOOK_URL’); // 推奨:プロパティに保存

if (!webhookUrl) throw new Error(‘SLACK_WEBHOOK_URL が未設定です’);

const payload = {

// channel は省略(多くの Incoming Webhook では無視されるため)

username: ‘スプレッドシート通知Bot’,

icon_emoji: ‘:bar_chart:’,

attachments: [{

color: message.color || ‘warning’, // ‘good’ | ‘warning’ | ‘danger’ | ‘#RRGGBB’

title: message.title,

text: message.text,

fields: message.fields || [],

footer: ‘Google Sheets’,

ts: Math.floor(Date.now() / 1000) }] };

const options = {

method: ‘post’,

contentType: ‘application/json’,

payload: JSON.stringify(payload),

muteHttpExceptions: true};

const res = UrlFetchApp.fetch(webhookUrl, options);

if (res.getResponseCode() >= 300) {

throw new Error(`Slack webhook error: ${res.getResponseCode()} ${res.getContentText()}`); }}

try {

UrlFetchApp.fetch(webhookUrl, options);

console.log(‘Slack通知送信成功’);

} catch (error) {

console.error(‘Slack通知送信失敗:’, error);

// フォールバックとしてメール送信(定義済みの関数を呼ぶ)

MailApp.sendEmail({

to: ‘[email protected]’,

subject: ‘【障害】Slack通知に失敗しました’,

htmlBody: `

<p>Slack通知の送信に失敗しました。</p>

<pre>${escapeHtml(String(error))}</pre>

<pre>${escapeHtml(JSON.stringify(message))}</pre>  ` });}

※ 複数チャンネルへ送る必要がある場合は、Bot Token + chat.postMessage API の利用を検討してください(Incoming Webhookでは制約があるため)。


※ 掲載している情報は記事更新時点のものです。

※本サイトは、法律的またはその他のアドバイスの提供を目的としたものではありません。当社は本サイトの記載内容(テンプレートを含む)の正確性、妥当性の確保に努めておりますが、ご利用にあたっては、個別の事情を適宜専門家にご相談いただくなど、ご自身の判断でご利用ください。

関連記事