【Google Apps Script】スプレッドシートが更新されたらリアルタイムでSlackに通知する


はじめに

スプレッドシートの更新を手動で確認するのが面倒だったので、セルの更新を自動で検知する仕組みを作りたいなと思い調べたところ、Webhook を使って手軽に実現できたのでまとめます。

サンプルについて

今回は披露宴の出席簿をスプレッドシートで管理しているという設定で、A列に招待客名、B列に出欠、C列にメモを入力しています。
招待客はあらかじめシートにすべて入力されているという前提で、各自の出欠やメモが更新されたら Slack に通知されるようにします。

準備するもの

  • Google スプレッドシート
  • Slack
    • 通知を受け取るチャンネルを作成しておく

Webhook とは

Webアプリケーションのイベント発生時に外部のアプリケーションにHTTPリクエストを送信する仕組みです。
今回はスプレッドシートでのイベント発生をSlackに通知するために利用します。

こちらの記事が分かりやすいです。
Webhookって何?を子どもでもわかるように描いてみた

Slack APIの設定

Create New App

Slackで通知を受け取るために Slack API を利用します。

画面右上の Your appsCreate New App で Slack App を作成します。

App name は、Slack での通知名になります。( 後で変更可能です )
Development Slack Workspace で、通知を受け取りたい Workspace を選択します。
Create App で Slack App を作成します。

Incoming Webhooks を有効にする

Slack App を作成したら、作成した App の Basic Information 画面に遷移します。
Add features and functionalityIncoming Webhooks を選択します。

Activate Incoming Webhooks の toggle を ON にします。
Add New Webhook to Workspace をクリックします。

認証画面に遷移したら、通知を受け取るチャンネルを選択し、許可します。

許可後に作成される Webhook URL をスプレッドシートで使用します。

スプレッドシートの設定

Slack API の設定ができたら、スプレッドシートでスクリプトとイベントトリガーを用意します。

Webhookで通知を送信するスクリプトを書く

スプレッドシートのツールからスクリプトエディタを開き、以下をペーストします。

コード.gs

function fetchApp() {
  var webhook = 'ここにWebhookURLを貼り付ける';
  var send = {
    "method": "POST",
    "payload": JSON.stringify({
      "text": 'スプレッドシートが更新されました'
    })
  };
  UrlFetchApp.fetch(webhook, send);
}

変数 webhook には、先程 Slack App の設定で作成した Webhook URL をペーストします。

イベントトリガーの設定

保存したら、時計アイコンをクリックし、トリガーの設定を開き、以下のように設定します。

関数 : fetchApp
イベントのソース : スプレッドシートから
イベントの種類を選択 : 編集時
エラー通知設定 : 今すぐ通知を受け取る

エラー通知設定を 今すぐ通知を受け取る にしておくと、リアルタイムで通知が届くようになります。

Slackに通知が届く

イベントトリガーを設定したことで、スプレッドシートが編集されると 関数fetchApp が実行され、Slackのチャンネルに通知が届くようになります。

更新内容をSlackに通知

せっかくなら更新内容をSlackで受け取りたいので、セルの値が何に変わったのかをSlackに通知するようにします。

更新されたセルの値を取得し、Slackに通知する

スプレッドシートのスクリプトエディタを開き、あらかじめ入力していたスクリプトを削除して以下をペーストします。

コード.gs
function notifySlack() {

  const sheet = SpreadsheetApp.getActiveSheet();
  var cell = sheet.getActiveCell();
  var row = cell.getRow();
  var name = sheet.getRange(row, 1);

  //出欠欄が変更されたとき
  if (cell.getColumn() == 2) {
    //出欠欄が削除されたとき
    if (cell.getValue() == "" ) {
      var message = name.getValue() + 'さんの出欠が削除されました。';
    //出欠欄が変更されたとき
    } else {
      var message = name.getValue() + 'さんの出欠が' + ' ' + cell.getValue() + ' ' + 'に変更されました。';
    }
  //messageをfetchApp()に渡す  
  fetchApp(message)

  //メモ欄が変更されたとき
  } else if (cell.getColumn() == 3) {
    //メモ欄が削除されたとき
    if (cell.getValue() == "" ) {
      var message = name.getValue() + 'さんのメモが削除されました。';
    //メモ欄の内容が変更されたとき
    } else {
      var message = name.getValue() + 'さんのメモが' + ' ' + cell.getValue() + ' ' + 'に変更されました。';
    }
    //messageをfetchApp()に渡す     
    fetchApp(message)

  //出欠欄とメモ欄以外の変更は通知しない  
  } else {
    return
  }
}

//messageを受け取り、Slackに通知
function fetchApp(message) {
  var webhook = 'ここにWebhookURLを貼り付ける';
  var send = {
    "method": "POST",
    "payload": JSON.stringify({
      "text": message
    })
  };
  UrlFetchApp.fetch(webhook, send);
}

今回のシートは、招待客はあらかじめ入力されているという設定なので、出欠欄やメモ欄が更新・削除されたときにだけSlackに通知されるように条件分岐しています。

実行する関数を変更

先述したコードで関数を増やし、notifySlack から fetchApp を呼び出すようにしたので、イベントトリガーで実行する関数を notifySlack に変更します。

セルの内容がSlackにリアルタイム通知される

これで出欠やメモ欄の入力内容の変更が Slack で確認できるようになりました。

今後やりたいこと

セルを編集した人を取得する

誰がセルを編集したのかを Slack で通知できるようにしたかったけど、今回は断念しました。
やり方分かったらまとめようと思います。

参考

Google Apps ScriptでSlackのbotを作ってみよう