ノーコードで簡単！超絶強化されたSlackのワークフローでSpreadsheetと連携して業務効率化した話

Slackのワークフローが2020年10月頃に超絶強化されて、Appとの連携ができるようになりました！
![スクリーンショット 2021-05-03 21.22.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/84295334-f405-6e87-200f-b86a3417176f.png)
特にスプレッドシートとの連携（[Google Sheets for Workflow Builder](https://slack.com/apps/A01AWGA48G6-google-sheets-for-workflow-builder)）が激アツで、今までだとできなかった or できてもかなり実装が複雑になっていた自動化が簡単にできて超便利です！

この機能でどんなものを作ったのか、どう作るのかを解説します
通常のワークフローでは使えない、日付を扱うための実用的な裏技も紹介してますので、ぜひ最後まで読んでいってください :bow: 

**:warning:(2021/06/07 追記)**
**Updateをかけることで、関数が固定される裏技ですが、できなくなってしまいました。**
**対応策↓**
**selectで持ってこれる値は文字列になっています。**
**関数を入れているセルに対してselectをかけて**
**持ってきた値でセルを再度更新(update)をしてあげることで、同じことができます。**

# 今までどんなものを作った？
* 出退勤システム
    * 出退勤時間のログをスプレッドシートに記録する
* QAシステム
    * Slack上で行われる質問&回答をスプレッドシートと連携して管理する
* 休憩宣言システム
    * １時間の休憩を取得する際に、戻り時間をSlackに通知する。
* MeetURL作成システム
    * GoogleMeetのURLを生成してSlackに送信する

一つ一つ解説します！

## 出退勤システム
▼作ったワークフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/fc80a073-e657-515e-43e3-e969efe0b782.png)

1. 入力用のフォームを開く
1. フォームの入力内容でスプレッドシートに行を追加(Add row)
1. 内容を固定するため行を更新(Update row)
1. 内容をSlackに送信

と処理します。

▼出力先のスプレッドシート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/cf71d15e-5414-715d-bb4d-c6251236360a.png)


### 入力用のフォームを開く
「区分」で出勤 or 退勤　を選ばせて
「備考」でその日の作業詳細や「早退します」などの、出退勤の関連情報を入力してもらいます。
一日の予定を出勤の備考にいれても良いかもしれないですね。

▼画面表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/7f540a37-260f-66a4-16f7-8a3a8d1db952.png)


### フォームの入力内容でスプレッドシートに行を追加(Add row)
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/f58f4fb8-7957-15f0-5ece-c5b753553bf7.png)

日付はスプレッドシートの[NOW関数](https://support.google.com/docs/answer/3092981?hl=ja)をValueに指定します。
このままだとNOW関数が入力されているだけなので、現在時刻に合わせて内容が1秒1秒変わるセルになってしまいますよね。
ここで、「内容を固定するため行を更新(Update row)」というステップが必要になります。
その更新対象の列を特定させるために、名前のValueの頭に「※」を入れて目印にします。
### 内容を固定するため行を更新(Update row)
▼ステップ詳細

目印（「※」がついた名前）がひっかかるように検索します。（複数当てはまる場合は最初に引っかかった行が更新されるので注意です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/2e4d86b4-d1d7-9730-f371-eb7437158b34.png)
そして、目印「※」を削除して更新します。

一見意味のない更新に見えますが、この空更新を挟むことで**セルの入力内容が固定されます。**
セルの中身には、「NOW関数」ではなく、この更新が行われた時点での日付・時刻が入力されている状態になります。
（2021月5月時点での裏技です。バグかもしれないので修正されるかもしれません）

▼ログが追加されたスプレッドシート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/04f31763-5af4-7806-944e-0aa2bbb7a7e0.png)



### 内容をSlackに送信
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/54eeebe1-d9b2-c03c-5815-d51719462325.png)

以下のように表示されます。
▼出勤時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/614ba5b6-0145-f9e1-9643-e76fc9700510.png)

▼退勤時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/bca24943-ff61-8dda-e946-d187edf4a298.png)

パッと見でBot投稿とわかるようになっていると良いです。

アイコンを設定するのもおすすめです。
自分は↓のサイトでアイコンを作成してます。

https://hatchful.shopify.com/ja/


### 運用

出退勤時にフォームを起動して入力するだけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/62c4b882-22f5-029b-4701-c8259a382607.png)

自分の名前でフィルターをかけて一日ごとに何してたかを管理できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/9b38dcf2-d68b-4028-2b6f-49aac63ac953.png)

VLOOKUPで整形するのもおすすめです。休憩時間込みで実働時間が集計できるので重宝してます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/9e919325-67fc-4482-b6d2-e46cd05231aa.png)


## QAシステム

▼作ったワークフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/3135d898-4a8e-941e-5866-ed2ea21ab579.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/0dacb392-b367-cc24-4362-308f15ec7d8b.png)

▼出力先のスプレッドシート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/2fdedbe1-ce2d-7523-f2cc-6d6ac90f21e1.png)


1. 質問用のフォームを開く
1. フォームの入力内容でスプレッドシートに行を追加
1. QAのNOを参照
1. 目印にしていた質問者を修正
1. 内容をSlackに送信＆回答用のフォームを開く
1. 回答内容でスプレッドシートを更新
1. 回答日時を固定
1. 回答内容をSlackに送信

と処理します。

### 質問用のフォームを開く
「質問内容」を入力します。
運用によっては「カテゴリー」や「優先度」などの項目を足すのも良いですね。

### フォームの入力内容でスプレッドシートに行を追加
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/788e1301-1890-37a1-3fee-42cd57ce67bb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/ca89a994-138f-c41c-1bcd-6db3ca85e1d4.png)

NOに `=ROW()-1`と入れることで、QAごとのNOを採番します。
回答日も「出退勤システム」と同じ要領で入れます。
ステータスも「質問中」に更新しましょう。（ソートに使えます）
質問者に「※」を入れて、更新対象の列の目印にします。

### QAのNOを参照
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/3a6884dd-f0dc-2000-ef4a-438804ad7c72.png)
参照をするときは、関数（`=ROW()-1`）でなく、実際にセルに表示されている値を取得する仕様です。（値の固定はされません。）
QAのNOを取得しておくことで、目印の「※」が無くても列を特定・更新できます。
（「※」だと、同じ質問者が２つ投稿した場合にQAが特定できなくなってしまいます…）


### 目印にしていた質問者を修正
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/851a3254-03b2-1ff1-880f-dbb85a16700e.png)
NOが取得できたので、さっそくNOをキーに質問者欄の目印を削除しましょう。
このときに、NOと回答時間が固定されます。

### 内容をSlackに送信＆回答用のフォームを開く
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/c3965653-9952-56c9-1ebf-86bbacffea08.png)
Slackに質問が投稿されたことを通知します。
ここで、「メッセージを送信」ではなく「フォームを送信」にするのがミソです。
（「メッセージを送信」でメッセージの中にボタンを入れる→ボタンを押したらフォーム送信もアリですが、工程は少ないほうがいいですよね）
質問に対する回答を入力してもらいます。

▼以下のように表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/59a1176e-bcd0-a13d-7c18-0313c999a039.png)



### 回答内容でスプレッドシートを更新
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/1162f96d-1896-d2e8-d44d-22088eecb81d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/deadbbe3-57a7-8fb1-da9c-7d20c9584698.png)

NOをキーにスプレッドを更新します。
回答日時にNOW関数を使いましょう。
ステータスも「回答済」に更新します。

### 回答日時を固定
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/f0437cf5-d2af-6af1-946c-e5fb75e43f73.png)
NOを空更新して、回答日時のNOW関数を固定します。
ここで更新するカラムはなんでも良いです！

### 回答内容をSlackに送信
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/ccd66cc1-55ff-0c5d-e78d-1dd5e9200bdb.png)

最後に、回答内容をSlackに送信します
▼以下のように表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/9af5df6c-6b9b-7f6f-ae22-d979efc744bf.png)

絵文字を利用して、QとAの見栄えを良くしています。
絵文字を作成するときは、こちらのサイトが便利です。

https://emoji-gen.ninja/

▼ログが追加されたスプレッドシート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/5c476542-a89d-b297-21a7-f815b1ebcac7.png)


### 運用

質問者は、ショートカットを起動して質問するだけ。
回答者は、答えられそうな質問に対して回答するだけです。
双方向的なやり取りも、簡単に実装できます。

ログがスプレッドシートに残るので、あとから「質問中」のみでソートしたり、
CSVやEXCELで吐き出したりすることもできますよね。

同じようなことをスプレッドシート単体でやっていたり、Googleフォームでやっているようなら
このやり方に変えることをオススメします！

## 休憩宣言システム

▼作ったワークフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/4bdacbb8-d808-7750-5c2a-3cc857bf05ec.png)



スプレッドの関数を使うことで、1時間後の時刻を通知できます！
シンプルな作りでとても便利ですし、応用も効きやすいテクニックです。

1. 行を参照
1. Slackに通知

### 行を参照
スプレッドシートに、前もって
現在時刻と1時間後の時刻を表す関数、参照するときのキー値を入力しておきます

現在時刻 : `=NOW()`
1時間後の時刻 : `=NOW() + 1/24`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/45fb93be-df06-6b75-595a-937f1edeaae2.png)

hint列のキー値を元に参照します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/400915e6-ca81-7ffa-3098-9e5553021522.png)

### Slackに通知
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/f0dd543e-da7e-1bd8-2809-dfb9658f7dd5.png)

▼表示されるメッセージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/2d107440-d4ed-2bff-4318-e5d2633f9972.png)

### 運用
休憩に入る前にワークフローを起動するだけです。
何時から連絡がつくのかパット見でわかるので良いですね。

休憩時間終了を示す、戻りましたボタンを付けたりしても良いかもしれませんね。

## MeetURL作成システム
ワークフローとスプレッドシートのみの連携でも、たくさんの使い方があるのですが
「[GAS](https://developers.google.com/gsuite/aspects/appsscript?hl=ja)」と併用することで更に幅が広がります！
▼作ったワークフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/f1e94955-0117-3cec-c9ce-0217078c59eb.png)

1. 行追加（トリガー）
1. MeetURL取得
1. Slackに通知
1. トリガーで追加した行の削除

と処理します。

▼事前に作成しておくスプレッドシート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/df9f818a-6f58-a5b0-6376-48cb933b57c3.png)
B2のセルに参照用の値を入力しておいてください。

▼作ったGAS

```
// @ts-nocheck
function getMeetUrl() {
  const calendarId = 'primary'; // 一時的にイベントを作成するカレンダーのID。わからない人はこのままでOK
  const dt = new Date(); // 日付は適当に設定
  const date = dt.getFullYear() + '-' + (dt.getMonth() + 1) + '-' + dt.getDate();
  const requestId = Math.random().toString(32).substring(2); // 適当な文字列を作る
  const response = Calendar.Events.insert({
    summary: "temp_event",
    singleEvents: true,
    allDayEvent: true,
    start: {
      date,
    },
    end: {
      date,
    },
    conferenceData: {
      createRequest: {
        requestId,
        conferenceSolutionKey: {
          type: "hangoutsMeet"
        },
      }
    }
  },calendarId, { conferenceDataVersion: 1 })

  Calendar.Events.remove(calendarId, response.id)

  if (response.conferenceData.createRequest.status.statusCode === "success") {
    const meetUrl = response.conferenceData.entryPoints[0].uri
    SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("A2").setValue(meetUrl)
  }
}

```


実行されると、A2のセルにMeetのURLが自動生成されるというプログラムです。
参考元 : https://qiita.com/sskmy1024y/items/0ec5b61a7cfeb8563576


こちらのGASのトリガーを「スプレッドシート変更時」に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/f064f927-d05d-8e8b-672e-a2c9a8725b98.png)


### 行追加（トリガー）
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/5a1ba04a-300b-fda1-0c07-6ce133709526.png)
スプレッドに行を追加して、GASのトリガーを発動させます。
中身はどんなものでも構わないです。

### MeetURL取得
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/0220f4c8-477a-6c0e-b11d-47a5af83b3a8.png)

GASが発動し、新しいMeetのURLがスプレッドのA2セルに生成されているはずです。
あらかじめスプレッドシートに記載しておいた、B2のセルをキーに参照します


### Slackに通知
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/71116b9c-7e0f-3613-b8ff-37f4416fcb6a.png)

取得したMeetのURLをSlackに通知します

### トリガーで追加した行の削除
▼ステップ詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260763/6852ac18-f729-397d-43d5-89f4d742c39b.png)
スプレッドに列が追加され続けて重くなることを防ぐため、追加した行を削除します。

### 運用
弊社もテレワークが主となり、Meetを多用しています。
Meetを生成するためのチャンネルでショートカットを起動し、突発的な会議や、ちょっとした口頭確認を行っています。

リアクション（絵文字）でワークフロー起動するようにしても良いかもしれません。

### あとがき

ワークフローの強化によってSlackの可能性がぐっと広がったと思います！
ノーコードで実装できるので、敷居も低くてノンプログラマーの方でも扱えるのがとても良いです。

良き業務効率化ライフを！