見出し画像

スプレッドシートのスケジュールをGASを使ってSlackに通知する

* こちらは VOYAGE GROUP Techlog Advent Calendar 2020 20日目の記事です

こんにちは.クリスマスも近づいてワクワクする時期ですが,いかがお過ごしでしょうか.このまえ人事で面倒だったお仕事をGASで自動化したので,そのhow toを書き残しておきたいと思います.

面接予定リマインダがほしい

人事で地味に大変な仕事の1つに,面接スケジュールの管理運用があります.予定調整からリマインド等々,やってみると意外に大変なんです.特にリマインド作業は「スケジュール確認→メッセージ作成→メンション追加→送信」を毎朝晩行うので,なんとか自動で運用したい気運が高まっていました.さいわいスケジュールはGoogleスプレッドシートで管理していたので,GAS + Slackでいい感じのリマインド機能を作りました.

スプレッドシートのスケジュールをSlackに通知する

今回の記事では実際にリマインド通知機能を実装します.前提として,下記フォーマットのスプレッドシートでスケジュール管理をする事とします.

画像1

まずはSlack側の準備です.
通知するチャンネルにIncoming WebHooksを連携してください.下記からポチポチすればできますが,よく分からない場合は詳しそうな人やGoogleさんに聞いてみてください!

Incoming WebHooksを作成するとURLが発行されるのでメモしておきましょう.

次は,スプレッドシートにGASを書きます.

画像2

スプレッドシートの「ツール」⇒「スクリプトエディタ」でGASのディタを開き,下記のコードを貼り付けてください.

function announce() {
 // getSheetByNameで指定したシートの全行を取得する
 const sheetRows = SpreadsheetApp.getActive().getSheetByName('スケジュール').getDataRange().getValues();
 const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'y-M-d');
 
 // 取得したスプレッドシートの行配列から,メッセージを作成
 // 列はA,B,C,...が0,1,2,...にマップされる
 let message = '';
 sheetRows.forEach(function (row, i) {
   // 1行目はヘッダーなので,除外する
   if (i === 0) {
     return;
   }
   // 対象スケジュールが当日でなければメッセージに追加しない
   if (today !== Utilities.formatDate(new Date(row[0]), 'Asia/Tokyo', 'y-M-d')) {
     return;
   }
   const start = Utilities.formatDate(row[3], 'Asia/Tokyo', 'HH:mm');
   const end = Utilities.formatDate(row[4], 'Asia/Tokyo', 'HH:mm');
   message += `${row[1]}さん:${row[2]} ${start}${end}\n`;
 });
 
 // 通知スケジュールがなかったら終了
 if (message === '') {
   return;
 }
 
 // Slackにリマインドメッセージを送信
 UrlFetchApp.fetch(
   // 先ほどメモしたSlackのWebHook URL
   'https://hooks.slack.com/services/......',
   {
     'method' : 'POST',
     'contentType' : 'application/json',
     'payload' : JSON.stringify({'text': message})
   }
 );
}

「先ほどメモしたSlackのWebHook URL」に,WebHookのURLを記入するのを忘れないでください.

コードを用意したら「デバッグ」の右横にあるプルダウンから「announce」を選択し,「実行」を押してください.(初めて実行するときは権限の許可を求められるので,自分のGoogleアカウントで権限を付与してください)

画像3

シートに実行した当日のスケジュールが記載されていれば,WebHookの連携を行ったSlackチャンネルに通知が飛ぶはずです.もし通知されない場合は,スケジュールの日付が間違っていないか,SlackのWebHook連携は完了しているかを確認してください.(対象チャンネルに連携完了メッセージがあるはずです)

announce関数を定期実行する

Slack通知を確認したら,次は通知を定期的に自動実行する仕掛けを用意します.GASでは「トリガー」と呼ばれるイベントに応じて指定した関数を実行する機能があるので,さっそく使ってみましょう.今回は毎日朝10時に「announce」を実行するトリガーを作成します.

function announce() {
 ...
}

// ↓ 追加コード

// 通知用のトリガーを定期的に作成する
function initializeTrigger() {

 // 対象のプロジェクトに登録されているトリガーを取得
 const triggers = ScriptApp.getProjectTriggers();
 
 triggers.forEach(function(t) {
   // createTriggerトリガーが重複しないように,古いトリガーを削除
   if (t.getHandlerFunction() === 'createTrigger') {
     ScriptApp.deleteTrigger(t);
   }
 });
 
 // 毎朝3時頃にcreateTriggerを実行するトリガーを作成
 ScriptApp.newTrigger('createTrigger').timeBased().atHour(3).everyDays(1).create();
}

// 指定した日時にannounceを実行する
function createTrigger() {
 const triggers = ScriptApp.getProjectTriggers();
 triggers.forEach(function(t) {
   // 使用済み・不要なannounceトリガーを削除
   if (t.getHandlerFunction() === 'announce') {
     ScriptApp.deleteTrigger(t);
   }
 });
 
 const today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'y-M-d');
 const time = '10:00:00';

 // 当日の対象時刻にannounceを実行するトリガーを作成
 ScriptApp.newTrigger('announce').timeBased().at(new Date(`${today} ${time}`)).create();
}

上記コードを書いたら「initializeTrigger」を1回実行してください.トリガー一覧で「createTrigger」が作成されていればOKです.

画像4

これで毎日朝10時に「announce」が呼び出されるようになります.
(図は,「createTrigger」が動いて「announce」のトリガーが作成された状態です)

ちなみにコードを読んでいただくと分かると思いますが,実際の処理はちょっとややこしいです.「毎朝10時に発火するトリガー」ではなく,「毎朝3時に『当日の朝10時に発火するトリガー』を作成するトリガー」を作成しています.実は2020年12月現在のGASだと,毎日定期実行するトリガーに対して厳密な分単位の設定をすることができません.一応「nearMinute」という分を指定する関数がありますが,±15分のゆらぎが発生するためピッタリの時刻に通知することが出来ません.一応,日時指定の1回限りであれば指定時刻ピッタリに発火するトリガーを作成できるので「トリガーを作成するトリガー」という方法をとっています.

まとめ

こういった運用改善は「めちゃくちゃすごいサービス」を購入したり,専用サービスをガッツリ開発することが度々あると思います.でも実はそんなに頑張らなくても,GASを使えば低コストで素早く業務改善につながるツールを作ることができます.みなさんもGASを使って快適なお仕事生活を送ってみてください.メリークリスマス!