【非エンジニア向け】特定の日から営業日で逆算した日にSlackで自動でリマインドさせる方法（Zapier使用）

# はじめに

「締切の○営業日前にSlackでリマインドを飛ばせたらいいな」と感じた経験はありませんか？
私は社内の業務効率化を推進する部署におり、メンバーの業務が少しでも楽に&ミスなく行えるよう、今年も細々と効率化・自動化を進めていたのですが、
その中でも本件は社内で特に需要が高く、どうやって実現しているのか聞かれたり、他の課題へ応用した活用事例も多く生まれた自動化だったので、この記事ではその設定方法をご紹介します。

ちなみに筆者はコードをまったく書けない/分からない非エンジニア人材です！
なるべく非エンジニアの方がそのまま真似しやすいように、スクショ多め・手順を詳細めに記載しています。
この自動化ではZapierで作成したワークフローを使用しますが、Zapierに関する基本的な解説は割愛し、Zapierで単純なワークフローが作成できる方を想定して説明します（説明通り設定すれば初めての方でも完コピしていただけると思います！）
※[Zapier](https://zapier.com)とは、様々なWebサービスやアプリ（例えばGmailやSlack、Googleスプレッドシートなど）を連携し、ノーコードで自動化できるアメリカ発のサービスです。例えば「スプレッドシートの内容が更新されたらSlackでメッセージを送信する」といったワークフローを、プログラミングの知識がなくても実装することができます。

# このワークフローでできること

特定の日（何かのタスクの締切日や重要なイベントの日、などを想定しています）から任意の営業日（3営業日前、など）で逆算したリマインド希望日時に、Slackで自由なメッセージを投稿できます。
![qiita01_2312 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/190dfd56-3f8d-c473-0ce8-331031bb6ab4.png)
※コーポレートグループで行う毎月の給与振込対応について、Slackでリマインドを投稿している例

- 特定の日は「毎月25日」のように固定されている場合だけでなく、例えば「タスク管理ツール上で登録されている当該タスクの締切日」や「Googleカレンダーの当該予定の開始日時」などを柔軟に自動抽出させて指定することも可能です。
    - 「タスク管理ツールの〇〇フォルダに入っているタスクは、すべて締切1営業日前にリマインドする」「Googleカレンダーで「〇〇」という文字列を含む予定は、すべて開始日時の5営業日前にリマインドする」といった設定が可能になります。
- 営業日を逆算する際は、土/日/祝日だけでなく、会社独自の祝日や長期休暇なども柔軟に除外することが可能です。
    - 例えば1/4の1営業日前にリマインドしたい場合、会社の年末年始休暇が12/29〜1/3であれば、12/28と逆算させることが可能になります。
- リマインド希望日時は、日付だけでなく時間まで柔軟に設定できます。
    - 例えば「締切日の3営業日前の朝10時」とか「イベント日時の1営業日（24時間前）」などの条件が設定可能です。

この記事では、以下条件のワークフローを例として説明します。

- 給与支給日は毎月25日（当日が営業日でない場合は前営業日）
- 給与支給日の4営業日前までに、振込対応を行う必要がある（以下「振込期限」とします）
- 振込期限の2営業日前の午前11時に、Slack上で振込対応タスクのリマインドを行う（以下「リマインド日」とします）

# 構築に必要なもの

- Zapier
    - アカウント（Multi-step Zaps を作成できるStarterプラン以上）
- Slack
    - アカウント
    - リマインドを投稿したいチャンネル
- Googleスプレッドシート
    - アカウント
    - 以下2つのワークシートを用意します。（2つのワークシートは同じスプレッドシート内に作成して問題ありません。また、1つのワークシート内に以下2つの機能をまとめることも物理的には可能ですが、見栄えと管理しやすさから分けています）
        - Workday関数を使って、給与支給日・振込期限・リマインド日を算出するシート（以下「振込日判定シート」とします）
             ![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/31322597-7b28-8af3-b4a4-798811967d1a.png)
        - 祝日や独自の休暇など、営業日から除外する日をリスト化したシート（以下「祝祭日シート」とします）
             ![Untitled (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/06ed422c-27ed-3a24-56c3-633f3793a968.png)

# スプレッドシートの作り方

### 振込日判定シート
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/81c82ee7-99b5-a132-1a50-d1a824d46b0b.png)
- 必要なセル
    - D3セル：「給与支給日は毎月25日（当日が営業日でない場合は前営業日）」というルールに基づいて計算した正しい給与支給日（YYYY-MM-DD形式）
    - D4セル：給与支給日の4営業日前である振込期限（YYYY-MM-DD形式）
    - E4セル：振込期限の2営業日前であるリマインド日（YYYY-MM-DD形式）

※Zapierでリマインド日時を正しく・最小のコストで指定するために、すべてYYYY-MM-DDの形式にします。

- 各セルの設定方法
    - 給与支給日
        - まずはC3セルで「当月25日」を、YYYY-MM-DD形式で指定します。
            - `=year(today())&"-"&month(today())&"-"&25`　などで指定できます。
        - 次にD3セルで「当日が営業日でない場合は前営業日」を考慮した正しい給与支給日を、Workday関数で指定します。
            - `=WORKDAY(C3+1,-1,'祝祭日シート'!A:A)`　で指定できます。
                - C3セルの翌日（+1）を開始日として、祝祭日シートの日付と土日を除外した1営業日前（-1）の日付を算出させています。C3セルが営業日であればC3セルと同様の日付に、C3セルが営業日でない場合は前営業日の日付になります。
    - 振込期限
        - D4セルで「給与支給日（D3）の4営業日前（-4）」を、Workday関数で指定します。
            - `=workday(D3,-4,'祝祭日シート'!A:A)`　で指定できます。
    - リマインド日
        - E4セルで「振込期限（D4）の2営業日前（-2）」を、Workday関数で指定します。
            - `=workday(D4,-2,'祝祭日シート'!A:A)`　で指定できます。

:::note info
【応用Tips】
「リマインド日の○時にリマインドを投稿する」という時刻の指定方法ではなく、「特定の日時から○営業日前の日時」という形で指定をしたい場合は、
スプレッドシート上で日付だけでなく時間も含めたデータを指定した上で、後述のワークフローの3ステップ目でその日時を投稿日時として設定すれば実現可能です。
:::

### 祝祭日シート
![Untitled (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/d62870ed-23fb-c757-8c92-386d2c2a5bba.png)
- 必要な情報
    - 営業日から除外する日付
        - 今回はMM/DD/YYYY形式にしていますが、Workday関数が正しく日付と認識できる形式であれば、特に指定はありません。
        - B列に休日名を記載していますが、あくまで管理上の目的です。A列に除外する日付さえ書いてあれば問題なく機能します。
        - 毎年翌年分を記載するフローを組む、あらかじめ数年分をまとめて記載しておくなど、何らか工夫しながら忘れずに手動で更新する運用が必要です。

# ワークフローの構成
Zapierで以下のワークフローを作成します。
1. 毎月1日になったら、このワークフローを開始する
2. 振込日判定シートを参照し、「振込申請期日」の行の値を取得する
3. リマインド日の11時になったら、Slackでリマインドを投稿する
![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/942c7c80-1c81-aaf4-6032-9ab3255d4614.png)

# ワークフローの作り方
### 1. 毎月1日になったら、このワークフローを開始する
![Untitled (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/833c1afc-9671-386a-ed56-fea68d3735a0.png)
- App & event
    - App：Schedule by Zapier
    - Event：Every Month
- Trigger
    - Day of the Month：ワークフローを開始したい日
        - 振込日判定シートの計算がリマインドさせたい月分の日付に更新された後、かつリマインド日よりも前であればいつでも問題ありません。
        - 今回は、毎月1日になると振込日判定シート上で給与支給日や振込期限・リマインド日が当月分に更新されるので、1日としています。
    - Time of Day：ワークフローを開始したい時間
        - リマインドする時間とは異なるので、ここはあまり気にしなくて問題ありません。
        - 今回は、日中だと当社環境のZapier上で多数のワークフローが稼働するため、混み合わないであろう午前1時としています。
    - Test : テストを行い、テスト結果は無視して続行

:::note info
【応用Tips】
例えば「タスク管理ツール上で登録されている当該タスクの締切日」や「Googleカレンダーの当該予定の開始日時」を用いてリマインドしたい場合は、
このトリガーステップを「Schedule by Zapier」ではなく、タスク管理ツールやGoogleカレンダーのAppにした上で、
「タスクの期限が到来したら」「予定の開始時刻になったら」といった趣旨のEventを設定し、タスク期限や予定の開始時刻の○日前にワークフローを開始する、というように設定することで実現可能です。
:::

### 2. 振込日判定シートを参照し、「振込申請期日」の行の値を取得する
![Untitled (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/2ccad7ce-11ca-5b7c-26ba-17e675e187c9.png)
- App & event
    - App：Google Sheets
    - Event：Lookup Spreadsheet Row
- Account
    - 当該スプレッドシートに閲覧以上の権限があるGoogleアカウント
- Action
    - Drive：スプレッドシートがある共有/マイドライブを指定（任意）
    - Spreadsheet : スプレッドシートのIDを指定（プルダウンで指定するか、以下でIDを抽出して直接記入）
        - IDはスプレッドシートのURLの`d/`と`/edit`の間の英数字（スクショ赤枠箇所）で確認できます
            ![2212qiita_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/0d2327c3-ad3f-1b63-c0e2-482c27e30903.png)
    - Worksheet : 振込日判定シートを指定
    - Lookup Column：リマインド日が記載されている行（今回は4行目）を検索するために使いたい文字列（今回はスクショB4セルの「振込申請期日」を検索キーにしています）がある列（今回はB列）の1行目にある文字列（今回はB1セルの「2024年01月」）を、プルダウンで指定
        ![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/fb32d77d-c43e-ff7c-6927-10eb6f130d21.png)
        - ややこしいですが、要は本来だと毎回4行目の値を取得してもらえればよいものの、このEventでは行番号を直接指定できないため、『現状「2024年01月」と書いてあるB列の中で、「振込申請期日」と書いてある列を探してその行番号の値を取得してきてください』という依頼の出し方になっています。
    - Lookup Value：上記同様、リマインド日が記載されている行（今回は4行目）を検索するために使いたい文字列（今回はスクショB4セルの「振込申請期日」）を、プルダウンで指定
    - Supporting Lookup Column / Supporting Lookup Value / Bottom-Up：指定不要
        - Lookup Column / Lookup Valueだけでは1行に絞れない場合には、補助として検索条件を指定できます。
    - Should this step be considered a “success” when nothing is found?：任意（今回はNo）
        - ここで参照すべき行がうまく検索できなかったとしてもワークフローを続行したいか（今回であればSlackにリマインドを投稿したいか）どうかという質問です。
        - 行が見つからないことは基本的に想定されないため今回はNoとしていますが、検索に失敗する可能性がある場合はあえてYesにすることで、おかしなリマインドが投稿されることによってワークフローが正しく機能していないことを気づくきっかけとなる可能性もあります。
    - Create Google Sheets Spreadsheet Row if it doesn’t exist yet?：False
        - ここで参照すべき行がうまく検索できなかった場合に、新規の行を作成するかという質問です。
        - 行が見つからないことは基本的に想定されず、また万一ワークフローの挙動がおかしい場合であっても新規行を作成して何か解決するわけではないため、Falseとしています。
- Test：テストを行い、リマインド日のデータが正しく取得できていることを確認する

:::note info
【応用Tips】
「タスク管理ツール上で登録されている当該タスクの締切日」や「Googleカレンダーの当該予定の開始日時」を用いてリマインドしたい場合は、
このステップの前に「1のトリガーステップで取得したタスクの締切日や予定の開始日時を、振込日判定シートのC3セルに転記する」というステップを挟むことで（AppはGoogle Sheets、EventはUpdate Spreadsheet rowなどを使えば設定できます）
振込日判定シート上で希望のリマインド日を作成することが可能となります。
上記ステップの詳細設定で抽出するタスクや予定の条件を設定したり、Filter by Zapierのステップを加えることで、リマインドさせるタスクや予定を柔軟に指定することも可能です。
:::

### 3. リマインド日の11時になったら、Slackでリマインドを投稿する
![qiita02_2312 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530171/6ff4e2eb-75ce-1440-d7d6-fa238f5df30e.png)
- App & event
    - App：Slack
    - Event：Send Channel Message
- Account：メッセージを送信したいチャンネルに入れる権限のアカウントであればOK
- Action
    - Channel：メッセージを送信したいチャンネルを指定
    - Message Text：送信したいメッセージを指定
        - メンションなどの表記方法については以下の記事が大変参考になります。
            - **[Zapier から Slack にメッセージを投稿するときの設定まとめ](https://blog.pirox.dev/2020/04/27/071145)**
        - 今回は、タスク期限がわかりやすくなるように、2のTestでリマインド日とともに取得できた振込期限の値を文中に挿入しています。
    - Send as a bot?：Botからのメッセージに見せたければYes、Account で指定したユーザーからのメッセージに見せたければNoを選択
    - Bot Name / Bot Icon：Botからのメッセージに見せる場合、Botの名前 / アイコンを自由に設定可能
    - Schedule At：2で取得したリマインド日を挿入し、後ろに「T〇〇:〇〇」の形式で通知したい時間を直接入力
- Test : テストすると設定どおりにメッセージが送信されるので、想定通りの判定となっているか確認してください。

### 以上のワークフローをPublish → Onに設定すれば、完了です！

# おわりに
あわただしく業務に追われていると、どうしても重要なタスクが漏れてしまいやすくなりますが、
そんな中でも少しでも安心して目の前の業務に集中できるよう、このようなリマインダーを開発しました。
元々はもう少し手軽に、単に平日のみをカウントするリマインダーを簡易的に設定しながら対処していたのですが、
それだとGWや年末年始のように休日が続く期間には特に役に立たなくなってしまうため、高度化してみました。
実装も比較的簡単で使い勝手も良く、応用の仕方も無限大だと思うので、ぜひ参考にしてみてください！