【GAS】Slackで投稿(打刻)時間をGoogleスプレッドシートに反映する

こんにちは、松井です。
普段はスタートアップや事業会社に関わりUIを中心としたデザインに関わりながら、自社サービスなどの開発をしています。

前回、リモートワークで働く方のための勤怠管理（自己管理）ツールを作りました！という内容の記事を投稿しました。

完成物はこちら
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420291/494376e3-10af-aebc-5a16-762483ab85b1.gif)


今回はその続きです。
内容としては、**Slackで打刻時間をスプレッドシート側に反映するところまでです。**
では、早速進めます。

## 仕組みのおさらい
Slackのスラッシュコマンドを利用して開始/終了を投稿。投稿したデータをGoogleのスプレドシートに反映。Googleスプレッドシートをデータベースとして使用。データベースの内容をブラウザ側に反映→ブラウザ側から表示の編集も可能。編集した内容は、スプレッドシートに反映されるというものです。

![Desktop.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420291/427748c7-f245-92b0-0d96-30eea1e1f4e4.jpeg)


## この記事で登場するもの

- GAS(google Apps Script)
- Googleスプレッドシート

## 前提条件
前回、**Slackのスラッシュコマンドを利用して投稿を行い、ボットが投稿したことをSlackでお知らせしてくれる部分まで**を解説していますので、その記事をご確認ください。

https://qiita.com/rubydesign/items/79d3a123a0233a0abb3b

## GASとスプレッドシートを連携させる
まずは、GAS側とスプレッドシート連携させるロジックを学びます。連携させる方法は2つです。

①スプレッドシートのIDを直接紐づける

```javascript:コード.gs
 var sheet = SpreadsheetApp.openById('xxxxxxxxxxxx_xxxxxxxxxxxx');
```

②GAS側からスプレッドシートを新規作成して連携させる

```javascript:コード.gs
 var sheet = spreadsheetApp.getActiveSheet();
```
①のスプレッドシートのIDは、URLから取得できます。例えば以下のような感じです。
https://docs.google.com/spreadsheets/d/この部分がIDとなります/edit#gid=0

②の場合は、使用したいスプレッドシートのメニューから「ツール」→「スクリプトエディタ」を選択します。
選択するとGASのエディタが開くので、このエディタ内で②の方法が利用可能になります。

## 反映させたい内容の処理の実装
では、実際にスプレッドシート側に反映させる時刻などの処理を書いていきます。
いずれもSlackに投稿した時間がスプレッドシートに反映されるイメージです。

まず反映させたい内容を定義します。僕の場合、年/月/日/時/分と細かく分けています。
ブラウザ上に表示させる時の都合で、使い回しが効くように設定しているだけなので、都合に応じて変更してください。

```javascript:コード.gs
 function doPost(e){
   var token = e.parameter.token;
   var name = e.parameter.user_name;  //ユーザーネームの指定
   var date = new Date();  //時間の取得
   var year = Utilities.formatDate(d,'JST','yyyy');  //年の取得
   var month = Utilities.formatDate(d,'JST','MM');  //月の取得
   var date = Utilities.formatDate(d,'JST','dd (E)');  //日の取得
   var time = Utilities.formatDate(d,'JST','HH:mm');  //時間の取得
 }
```

次に、スプレッドシート側に表示させるロジックを書いていきます。

```javascript:コード.gs

var SLACK_ACCESS_TOKEN = 'スラックのトークン';
var KINTAI_CHANNEL =  "チャンネルのID";

  function getSlackApp(){
   return SlackApp.create(SLACK_ACCESS_TOKEN);
  }

  function postMessage(message){
   var slackApp = SlackApp.create(SLACK_ACCESS_TOKEN);
   var result = slackApp.postMessage(KINTAI_CHANNEL, message, null) 
  }

  function getSheet(){
    var ss = SpreadsheetApp.openById('スプレッドシートのID');
    return ss.getSheets()[0];
  }

  function(isGoingToWork(token)){
    doGoingToWorkProcess(name, year, month, date, time)
    var msg = '打刻しました:'+ year + '/' + month + '/' + date;  
  }
  
  function isGoingToWork(token){
    return token === 'スラッシュコマンドのトークン';
  }

  function doGoingToWorkProcess(name, year, month, date, time){
    postMessage( name + "さんが出勤しました！");
    var sheet = getSheet(); //シートの指定(書き方をシンプルにするために、記述を分けています)
    var lastRow = sheet.getLastRow(); 
    var id = lastRow; 
    sheet.appendRow([id, year, month, date, name, time]);
  }

```

## スプレッドシートに反映するとSlack側にメッセージを飛ばす仕組みの解説
上記のコード内ではSlackを投稿すると、スラック側でボットがメッセージを返すという仕組みを作っています。反映されたタイミングでボットがお知らせしてくれれば、わざわざ反映されたかをスプレッドシートで確認する必要がなくなります。

まずスラックトークン箇所については、前回の記事で解説しましたので割愛します。
下記コードで、メッセージの出力を定義しています。

```javascript:コード.gs
function postMessage(message){
  var slackApp = SlackApp.create(SLACK_ACCESS_TOKEN); //スラックのトークンを定義
  var result = slackApp.postMessage(KINTAI_CHANNEL, message, null) //メッセージを投げるチャンネルとメッセージの出力を定義
}

```
そして、スラッシュコマンドのトークンを呼び込み、そのトークンが実行された時にメッセージが飛ぶロジックを書いています。

```javascript:コード.gs
 function(isGoingToWork(token)){
    doGoingToWorkProcess(name, year, month, date, time)
    var msg = '打刻しました:'+ year + '/' + month + '/' + date;  
  }

 function isGoingToWork(token){
    return token === 'スラッシュコマンドのトークン';
  }
```
これで、Slackで設定したスラッシュコマンドのボットがメッセージを返すという仕組みを実現しています。
あとは、ここでもメッセージが飛ぶ仕組みを作っています。

```javascript:コード.gs
  function doGoingToWorkProcess(name, year, month, date, time){
    postMessage( name + "さんが出勤しました！");
    var sheet = getSheet(); //シートの指定(書き方をシンプルにするために、記述を分けています)
    var lastRow = sheet.getLastRow(); //最後の行を定義
    var id = lastRow; //idをlastRowに定義
    sheet.appendRow([id, year, month, date, name, time]); //シートに反映させる記述
  }
```
これは、スラッシュコマンドのメッセージではなく、スラッシュコマンドを実行することにより紐づけられた、スラック側のボットが反応してメッセージを飛ばす仕組みです。

IDは、https://api.slack.com/apps 内にあるVerification Tokenを利用しています。
<img width="747" alt="スクリーンショット 2020-03-12 23.27.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420291/9256640b-2417-e382-5d77-890111575c40.png">

下記画像のように、自分だけにしか見えないメッセージ(これがスラッシュコマンド側のメッセージボット)と、チャンネル内の通常のメッセージに(これがスラック側が反応してメッセージを飛ばすボット)と2つを実装しています。
![スクリーンショット 2020-03-12 23.22.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420291/a07b67e4-f1d6-856f-3ccb-fa968a013c01.png)
以上が実装できれば、完了です。

## 終わりに
ブラウザでの表示が不要であればSlack側での勤怠管理または、自己管理ツールは完了です。条件分岐はいりますが同じ要領で、退勤や休憩、タスクを書き込むロジックを書くことも出来るので、頑張って実装してみてください。

ツイッターなどでもサービスについて、日々考えている事を発信していますので是非[フォロー](https://twitter.com/takuo0327)してください。