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


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

# サンプルについて

今回は披露宴の出席簿をスプレッドシートで管理しているという設定で、A列に招待客名、B列に出欠、C列にメモを入力しています。
招待客はあらかじめシートにすべて入力されているという前提で、各自の出欠やメモが更新されたら Slack に通知されるようにします。
![披露宴の出席簿をスプレッドシートで作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/e9b0a316-3aeb-6f2f-4935-50bce81691b9.png)

# 準備するもの
- Google スプレッドシート
- Slack
    - 通知を受け取るチャンネルを作成しておく

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

こちらの記事が分かりやすいです。
[Webhookって何？を子どもでもわかるように描いてみた](https://kintone-blog.cybozu.co.jp/developer/000283.html#:~:text=Webhook%E3%81%A8%E3%81%AF%EF%BC%88%E7%95%A5%EF%BC%89%E3%80%81,%E3%81%A7%E9%80%9A%E7%9F%A5%E3%81%99%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A7%E3%81%99%E3%80%82)


# Slack APIの設定

## Create New App
Slackで通知を受け取るために [Slack API](https://api.slack.com/) を利用します。

画面右上の `Your apps` → `Create New App` で Slack App を作成します。

![App Nameと通知を受け取るSlackを設定します](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/d1ae417d-bc65-8526-6af5-a1afef76b13e.png)

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

## Incoming Webhooks を有効にする
Slack App を作成したら、作成した App の `Basic Information` 画面に遷移します。
`Add features and functionality` の `Incoming Webhooks` を選択します。

![Incoming Webhooksを有効にする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/690d0b6d-3b4c-8f64-45d3-141ce4aff14d.png)

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

![Add New Webhook  to Workspaceの設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/977997a4-abca-02ec-8cdb-4e9672f7f5fe.png)


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

![通知を受け取るチャンネルを選択して許可する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/8a522f48-00e2-621d-b339-ef8203ee58f8.png)

許可後に作成される Webhook URL をスプレッドシートで使用します。
![Webhook URLが作成されます](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/bcf55398-d9f5-ee5f-f4a1-79c0893714b4.png)


# スプレッドシートの設定

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

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

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

```javascript:コード.gs

function fetchApp() {
  var webhook = 'ここにWebhookURLを貼り付ける';
  var send = {
    "method": "POST",
    "payload": JSON.stringify({
      "text": 'スプレッドシートが更新されました'
    })
  };
  UrlFetchApp.fetch(webhook, send);
}
```
    
変数 webhook には、先程 Slack App の設定で作成した Webhook URL をペーストします。

## イベントトリガーの設定

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

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

![トリガーの設定で関数をfetchAppを選択、エラー通知設定を今すぐ通知を受け取るにします](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/42ef747b-332e-5375-f2cc-3b5cd9fbe75b.png)

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

## Slackに通知が届く

イベントトリガーを設定したことで、スプレッドシートが編集されると 関数fetchApp が実行され、Slackのチャンネルに通知が届くようになります。
![スクリーンショット 2021-02-21 14.06.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/03febae2-2bbc-04d6-f283-657228a80661.png)


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

## 更新されたセルの値を取得し、Slackに通知する
スプレッドシートのスクリプトエディタを開き、あらかじめ入力していたスクリプトを削除して以下をペーストします。

```javascript:コード.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に通知される](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1055553/d15f86fe-bc1f-e9ae-a786-082026adb164.png)


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

# 参考
 [Google Apps ScriptでSlackのbotを作ってみよう](https://devlog.atlas.jp/2020/03/02/3131)