📌

Google スプレッドシートから日付を読み込んでSlackに通知するGASを作成する

2022/05/20に公開
1

概要

普段、スプレッドシートを使って、勉強会の進捗管理をまとめています。
Slack に勉強予定の内容を通知する便利に思い、GAS を使って実装することにしました。

実装方法

実装は以下の 3 ステップで完了します。

  1. Incoming Webhook を追加
  2. スプレッドシートの GAS を記述
  3. トリガを設定

Incoming Webhook を追加

Slack に通知を送る Slack アプリケーションは複数個ありますが、自分は Incoming Webhook を使用しています。

Slack のアプリケーションで「Incoming Webhook」を検索し、以下の「設定」ボタンを押下すると、ブラウザが開きます。

incoming_webhook_screenshost
Slack の画面

ブラウザが開かれたら、「Slack に追加」を押下します。

incoming_webhook_screenshost
IncomingWebhook の追加画面

次に、投稿先チャンネルが表示されるので選択します(画像では「情報セキュリティマネジメント試験」)。
その後、「Incoming Webhook インテグレーションの追加」を押下します。

incoming_webhook_channel_screenshost
IncomingWebhook のチャンネル先の設定画面

Webhook URL が設定されるので、コピーします。

incoming_webhook_ur_screenshost
IncomingWebhook の Webhook URL

下にスクロールすると、名前やアイコンできる項目があります。
以下は変更例です。

incoming_webhook_icon_name_screenshost
IncomingWebhook のアイコンと名前

以上で、Webhook の基本的な設定方法は完了です。

スプレッドシートの GAS を記述

続いて、Google スプレッドシートで、バッチ処理を作成します。

メッセージ作成・通知処理の作成

今回は、以下の進捗管理のためのシートを作成しました。
画面上部のメニューバーの「拡張機能」を押下した後「App Script」を押下します。

spreadsheet_screenshost
スプレッドシートで作成した進捗管理表

Apps Scirpt の編集画面が表示されるので、バッチ用の処理を記述します。

gas_edit

画像には以下の処理が記述されています。

postMessagecreateMessageという 2 つの関数で構成されます。
postMessageでメッセージを Slack に通知します。
createMessageは、スプレッドシートを読み込み、メッセージを作成する処理をしています。
詳しく処理をみていきます。

function postMessage() {
  const postUrl = "Webhook URL"; // Webhook URL を記述
  const message = createMessage();
  if (message === "") {
    return;
  }
  const jsonData = {
    text: message,
  };
  const payload = JSON.stringify(jsonData);
  const options = {
    method: "post",
    contentType: "application/json",
    payload: payload,
  };
  UrlFetchApp.fetch(postUrl, options);
  return;
}

function createMessage() {
  const dayOfWeekStr = ["日", "月", "火", "水", "木", "金", "土"];
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1");
  const lastRow = sheet.getLastRow();
  const now = new Date();
  const nowMonth = now.getMonth() + 1;
  const nowDay = now.getDate();

  let sheetMonth, sheetDay, sheetDayOfWeek;
  for (let i = 2; i <= lastRow; i++) {
    const sheetDate = sheet.getRange(i, 2);
    sheetMonth = sheetDate.getValue().getMonth() + 1;
    sheetDay = sheetDate.getValue().getDate();
    sheetDayOfWeek = dayOfWeekStr[sheetDate.getValue().getDay()];

    Logger.log(`sheetMonth ${sheetMonth}, sheetDay ${sheetDay}`);
    const chapter = sheet.getRange(i, 3).getValue();
    const title = sheet.getRange(i, 4).getValue();
    if (sheetMonth === nowMonth && sheetDay === nowDay) {
      return `<!here> \n ${sheetMonth.toString()}${sheetDay.toString()}日(${sheetDayOfWeek}) ${chapter}${title} \n チャット欄`;
    }
  }
  return "";
}

postMessage()の定数postUrlに Webhook URL を記入します。
createMessage()でメッセージを作成したあと、json に変換したり、post するための設定などを記述します。
message が空だった場合は、実行を途中で終了します。

postMessage()
function postMessage() {
  const postUrl = "Webhook URL"; // Webhook URL を記述
  const message = createMessage();
  if (message === "") {
    return;
  }
  const jsonData = {
    text: message,
  };
  const payload = JSON.stringify(jsonData);
  const options = {
    method: "post",
    contentType: "application/json",
    payload: payload,
  };
  UrlFetchApp.fetch(postUrl, options);
  return;
}

createMessage()でメッセージを作成します。ハードコードな実装になっています。
「シート 1」を読み込み最終行までの長さを読み込みます。
最終行の長さまで for 文を実行し、shee.getRange(i, 2)日付のセルを読み込みます
その後、読み込んだセルから日付と曜日を算出します
章のセルとタイトルのセルを読み込み日付のセルとバッチの実行日が同じだったときメッセージを return します。
何にも一致しなければ空文字列を return します。

createMessage()
function createMessage() {
  const dayOfWeekStr = ["日", "月", "火", "水", "木", "金", "土"];
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1"); // シート1 読み込み
  const lastRow = sheet.getLastRow(); // 最終行までの長さを読み込む
  const now = new Date();
  const nowMonth = now.getMonth() + 1;
  const nowDay = now.getDate();

  let sheetMonth, sheetDay, sheetDayOfWeek;
  for (let i = 2; i <= lastRow; i++) {
    const sheetDate = sheet.getRange(i, 2); // 日付のセルを読み込む
    // 以下3行は、セルから日付と曜日を算出
    sheetMonth = sheetDate.getValue().getMonth() + 1;
    sheetDay = sheetDate.getValue().getDate();
    sheetDayOfWeek = dayOfWeekStr[sheetDate.getValue().getDay()];

    Logger.log(`sheetMonth ${sheetMonth}, sheetDay ${sheetDay}`);
    // 章のセルとタイトルのセルを読み込み
    const chapter = sheet.getRange(i, 3).getValue();
    const title = sheet.getRange(i, 4).getValue();
    // 読み込んだセルの日付が実行日と同じだったとき、メッセージを return する
    if (sheetMonth === nowMonth && sheetDay === nowDay) {
      return `<!here> \n ${sheetMonth.toString()}${sheetDay.toString()}日(${sheetDayOfWeek}) ${chapter}${title} \n チャット欄`;
    }
  }
  // 何もなければ空文字列をreturn
  return "";
}

GAS の記述が完了したら、右上の「デプロイ」を押下し、「新しいデプロイ」を押下するとポップアップが表示されます。
「種類の選択」では「ウェブアプリ」を選択し、ポップアップ右下の「デプロイ」を選択するとデプロイされます。
初回は認可が必要です。

認可手順

authorize
authorize
authorize
authorize

デプロイしたバージョンがナンバリングされ、Head(最新バージョン)も更新されます。

spreadsheet_deploy

以上で処理は完了です。

時刻の設定

バッチの処理自体は完成ですが、時刻がアメリカ時間ですので、日本時刻に設定する必要があります。
左のメニューバーの「プロジェクトの設定」(歯車マーク)をクリックして、プロジェクトの設定画面を開きます。
そして、「『appsscript.json』マニフェスト ファイルをエディタで表示する」にチェックをいれます。

spreadsheet_gas_config

「appssript.json」をエディタで表示し、timeZone を"Asia/Tokyo"にしましょう。

spreadsheet_appsscript

トリガを設定

最後にトリガ(バッチの実行条件を管理)を設定します。
今回の例では、毎日バッチを実行させスプレッドシートのセルの日付が当日の日付と一致したとき、メッセージが送信されるように設定します。
左メニューの「トリガ」(時計マーク)をクリックして、トリガの設定画面を表示します。
右下の「トリガを追加」を押下し、トリガの設定を開きます。

spreadsheet_gas_trigger

トリガの設定では、以下を選択します。
「時間ベースのトリガのタイプを選択」と「時刻を選択」は「イベントのソースを選択」で「時間主導型」を選択すると表示されます。
その後、「保存」を押下します。
この設定は「毎日午前 6 時〜午前 7 時の間にバッチを実行する」になります。
注意点は、「午前 6 時〜午前 7 時の間」です。具体的な時間は決められません。午前 6 時ちょうどだったり、午前 7 時直前の可能性もありますので、余裕を持った実行時間にしましょう。

項目 選択
実行する関数を選択 postMessage
実行するデプロイを選択 実行したいのバージョン(画像だと Head)
イベントのソースを選択 時間主導型
時間ベースのトリガのタイプを選択 日付ベースのタイマー
時刻を選択 任意の時間(画像だと午前 6 時〜7 時)

spreadsheet_gas_trigger_config

以上で設定が完了しました。

動作確認

メッセージが通知されるか確認してみます。トリガの部分の再現は難しいので今日の日付で手動実行できるか確認します
スプレッドシートの「日付」の行に今日の日付を追加します。

spreadsheet_test

そして以下の赤枠の部分で「postMessage」を選択し、「実行」を押下します。

spreadsheet_trigger_test

Slack に通知が来ました。今回は簡単なスクリプトですので、手動で動けば、問題なく動きます。

slack_notify

まとめ

スプレッドシートと GAS で Slack に自動通知する方法を記述しました。
以下の 3 ステップで完了します。

  • IncomingWebhook を設定
  • スプレッドシートと GAS を作成
  • トリガを設定

スプレッドシートだけでも便利ですが、Slack に自動通知できるとさらに便利になります。
GoogleDrive は GAS を使えば今回の通知以外にも自動化ができるので、いろいろ試してみてください。

参考

https://masa-enjoy.com/gas-dateobject-timezone

https://best-cloud.jp/google-apps-script-authentication/

Discussion

Narumi HoriNarumi Hori

知りたかった内容が網羅的に書かれており非常に助かりました!!
ありがとうございます!!

一点だけ質問させてください。
スプレッドシートの日付の列に同じ日付が2つ以上並んでいると、Slackに吐き出されるデータは2つ以上ではなく、1つだけになってしまいます。

同じ日付のデータを全部吐き出させるためにはGASのコードをどのように変更すれば良いでしょうか?

大変お手数ですが、お手隙の際にご教示いただけますと幸いです!
よろしくお願いいたします!