Googleスプレッドシートの変更をGASを使ってDiscordに通知する
この記事は2024/02/01に作成されました。
皆さんはGoogleスプレッドシートやGoogleドキュメントの共有機能を使ったことはありますか?
頻繁に自分がみて更新を確認している分にはいいのですが、長期間使用するもので1週間に数回しか更新されないスプレッドシートなど、わざわざ更新されているか確認しにいくのも面倒だなぁと思ったので、今回は更新があるとDiscordに通知してくれるbotを作っていこうと思います!
とはいえ更新の都度通知が飛ぶと鬱陶しくなってしまうので「更新があった日に、何時ごろにどんな更新をしたか、決まった時間に通知」してくれる設定にしようと思います。
過去にbot作成に必要なウェブフックは作ってあるので、そちらを流用して作っていきます。
スプレッドシートのメニューバーから「拡張機能」>「Apps Script」を選択してGASの画面を開きます。
コード.gsに下記のコードを貼り付けていきます。
// 編集されたら自動的に発火
function onEdit(e) {
//シート名を入力 *シート名が違う場合、適宜変更してください
if (e.source.getSheetName() != 'シート1') {
return;
}
//変更時刻 -> onEditが実行されたタイミングを取得
const timeSet = new Date();
const time = Utilities.formatDate(timeSet, 'JST', 'yyyy-MM-dd HH:mm');
//削除や範囲編集されたセルの対応
const setItem = e.value;
if(setItem == undefined) {
item = '削除されました';
if(e.range.getA1Notation().includes(':')){
item = '範囲変更がありました';
}
}else{
item = setItem;
}
//変更があったセルと、更新された内容を格納
const message = [e.range.getA1Notation(), item]; //onEditでないと取得できない場合があるので注意
// 変更があったことをスクリプトプロパティに追加
const script_property = PropertiesService.getScriptProperties();
script_property.setProperty(time, JSON.stringify(message)); //
}
//時間になったら下記を発火
function timeNotify(e) {
// スクリプトプロパティの変更をチェック。
const script_property = PropertiesService.getScriptProperties();
const properties = script_property.getProperties();
const array = Object.entries(properties);
if (array.length == 0) {
console.log('変更なし'); //
return;
}
const count = array.length; //変更があった場合変更された件数を取得
//DiscordのWebhookを登録
const webhook_url = 'https://discord.com/api/webhooks/XXXXXXXXXX/XXXXXXXXXX'; //DiscordのWebhook URLを貼り付け
// メッセージを作成
let message_body = count + '件の変更がありました!\n';
let embeds = {
fields: [],
};
array.forEach((prop) => {
const key = prop[0]; //時間の抽出
const val = JSON.parse(prop[1]); //変更があったセルと、更新された内容を抽出
console.log(key, val);
embeds.fields.push({
name: '変更時間:' + key,
value: '変更されたセル:' + val[0] + '\n変更内容:' + val[1],
});
});
const messageData = {
'content': message_body,
'embeds': [embeds],
}
UrlFetchApp.fetch(webhook_url, {{
'method': 'post',
'contentType': ''application/json',
'payload': JSON.stringify(messageData)
});
//送信が完了したら、プロパティの中身を削除する
script_property.deleteAllProperties();
}
onEdit() はユーザーがトリガーを設定しなくても、スプレッドシートに変更があると自動で発火してくれるものになります。
しかしながら、仕様上の問題があり「入力、コピー&ペースト、削除」などはきちんと取得できるのですが、「マウスドラッグによる連続コピー、連続したセル範囲へのコピー&ペースト」は発火はするものの情報の取得ができません。
今回は少し無理やりかもしれないですが、変更内容が取得できなかった場合、範囲変更なのか削除なのか分岐をかけてテキストとして出力する方法にしてみました。
ここまで設定できたらtimeNotify() のトリガー設定をしていきます。
右メニューのタイマーのアイコンから「トリガーを追加」ボタンをクリック
実行する関数を「timeNotify」、イベントのソースを「時間主導型」、時間ベースのトリガーのタイプを「日付ベースのタイマー」に設定して、お好みの時刻に変更し保存するとその時刻目安にイベントが発火されるようになります。これで完成です!
おまけ
今回初めて Discordの「embeds」を使ってみたのですがこちらはDiscord Bot専用の「埋め込み機能」になります。
「embeds」の中身は通知には表示されず、スッキリな見た目になるため活用できる場所はかなり多そうだと思いました。
またデザインのカスタマイズがそこそこできるみたいなのですが、今回は初めての使用だったので触らないでいたのですが次回使うときは少し触れられたらなと思います!
エンジニア/O.H