SpreadSheetの更新内容を任意のタイミングにてwebhook経由でSlackに通知させてみる

GASを用いた通知処理の見直し中に、SpreadSheet上に入力したデータのうち未通知のもののみをSlackに通知する系の需要がそれなりにありそうなGoogleAppScriptを思いつき、こしらえてみました。
2024.05.23

SpreadSheetの更新を元にSlack上で作業開始するフローにて、手順にSlack上の連絡でSpreadSheetから内容のコピーペーストがあるものを時折見かけます。SpreadSheetへ入力した内容がワンクリックでSlackに通知されたら楽ですね。

GASを利用した更新通知の整理中にふと思いつき、動作確認まで完了しました。今後の活用向け備忘録です。

通知の仕組み

以下のプロセスを実行します。

  1. SpreadSheetからGASでデータを取得
  2. Slackワークフローにincoming webhook経由でデータを送信
  3. 指定フォーマットのメッセージとしてチャンネルへ投稿

SpreadSheet上で実行するGAS

ベースはChatGPT製で、想定プロセスと一致するように変更をいれています。

セルからデータを取ってSlackに送信します。送信後は送信した行が次回実行時に対象とならないようにチェックを入れています。

今回は1列目にSlack incoming webhookでの送信対象メールアドレス、2列目に送信済みのサインを入れる想定です。

Slackワークフロー上で細かいメッセージ加工はできないため、GASで必要な加工も行っています。一手間掛けて、対象行が連続している場合に「1,2,3,4,5」といった通知ではなく「1〜5」となるようにしました。

// SlackのWebhook URLを設定
var SLACK_WEBHOOK_URL = 'https://hooks.slack.com/triggers/XXXXXXXXXX/XXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXX';
var data_col = 1
var done_col = 2

function onOpen() {
  var ui = SpreadsheetApp.getUi();           // Uiクラスを取得する
  var menu = ui.createMenu('追加したメニュー');  // Uiクラスからメニューを作成する
  menu.addItem('Slackへ送信', 'sendSelectedRowToSlack');   // メニューにアイテムを追加する
  menu.addToUi();                            // メニューをUiクラスに追加する
}

// メイン関数
function sendSelectedRowToSlack() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var startRow = 2
  var numRows = sheet.getLastRow();

  var target_rows = []
  var target_mails = []
  var data = []
  for (var i = 0; i < numRows; i++) {
    var rowIndex = startRow + i;
    if (sheet.getRange(rowIndex, data_col).isBlank()) continue
    if (!sheet.getRange(rowIndex, done_col).isBlank()) continue
    var mail = sheet.getRange(rowIndex, data_col).getValue();
    if (target_rows.length > 0) {
      if (rowIndex - 1 == target_rows.slice(-1)[0]) {
        target_rows.push("-")
      } else {
        target_rows.push(",")
      }
    }
    target_rows.push(rowIndex)
    target_mails.push(mail)
    data.push({'row': rowIndex, 'mail': mail })
    rowIndex += 1
  }
  var row_index_list = []
  var _split = target_rows.join("").split(",")
  for (var i = 0; i < _split.length; i++) {
    if (_split[i].indexOf("-") > -1) {
      var _range = _split[i].split("-")
      row_index_list.push(_range[0] + "〜" + _range.slice(-1)[0])
    } else {
      row_index_list.push(_split[i])
    }
  }
  if (target_mails.length == 0) return
  sendToSlack({
    'row':  row_index_list.join(row_index_list.length > 1 ? "," : ""),
    'mail': target_mails.join("\n")
  });
  for (var i = 0; i < data.length; i++) {
    sheet.getRange(data[i]["row"], done_col).setValue("済")
  }
}

// Slackにメッセージを送る関数
function sendToSlack(data) {
  var payload = data
  
  var options = {
    "muteHttpExceptions": true,
    'method': 'post',
    "headers":{
      "Content-Type": "application/json"
    },
    'payload': JSON.stringify(payload)
  };
  
  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, options);
}

Slackワークフロー構成

Sandbox環境にて実践です。2ステップです。Webhookのパラメータは行番号とメールアドレスを受け付けます。

実行結果

3行目だけ送信済みの状態で、6行目まで入力してから送信してみました。

あとがき

入力したけど通知はまだいい、という場合は通知済欄に手入力でなにかしらのサインを入れておくことでカバーできます。

SpreadSheet上の更新をSlackに通知するというのはよくあるプロセスですが、送信対象行が大量にあった場合に「1,2,3,4,5,6」となっていると人の目にはなかなかチェックが辛いこともあります。範囲であることがわかるだけでも大分楽になるかもしれません。