Googleスプレッドシートに記入した出勤スケジュールをSlackへ投げる

Googleスプレッドシートで出勤スケジュールを共有することになったのですが、毎日スプレッドシートを開いてメンバーの予定を確認するのも手間なので、当日の朝に出勤予定をSlackに投げるようにしました。

# 参考

以下の記事を参考にしています。多謝。
腕に覚えのある方はこちらを見てもらった方がシンプルでわかりやすいかと思います。

GoogleSpreadSheetからSlackへメッセージと飛ばしてみよう｜noinoi
https://note.com/noinoi/n/na9a575d5c4fe


# コード

↑で紹介されているコードを、以下の要件を満たすように弄りました。

* 現在日付から歴度を計算する
* 計算した歴度で抽出元のシートを決める
* 全員休みの日はSlackに投げない


こんなスプシに対して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576051/0405bbc6-63ae-9844-f773-124964a6e365.png)

こんなコードになりました。

```js
function myFunction() {
    var webhook = "https://hooks.slack.com/services/ナンタラカンタラ";
    var today = new Date();

    // 抽出元スプレッドシート
    var spread_sheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/ナントカカントカ/edit');

    // シート名生成
    var target_sheet_month = today.getMonth() + 1;
    var target_sheet_year = today.getFullYear();
    if (today.getDate() > 15) {
        target_sheet_month = today.getMonth() + 2;
    }
    if (target_sheet_month == 12) {
        target_sheet_year = today.getFullYear() + 1;
        target_sheet_month = 1;
    }

    var target_sheet_name = target_sheet_year + "年" + target_sheet_month + "月度";


    // var target_sheet = spread_sheet.getSheets()[0];
    var target_sheet = spread_sheet.getSheetByName(target_sheet_name);
    var data_arrays = target_sheet.getRange("A7:M40").getValues();

    // メッセージ作成用変数
    var message = "";
    var names = [];

    // 名前の配列を生成
    var column_cnt = 0;
    for (var i = 3; i <= 10; i++) {
        if (data_arrays[0][i] == "") {
            // 空白に当たったら抜ける
            break;
        }
        column_cnt = i;
        names.push(data_arrays[0][i]);
    }


    data_arrays.forEach(function (data_array) {
        // セルの0列目からセルの日付を取得
        cell_date = new Date(data_array[0]);
        
        // 今日の予定
        if (cell_date.getMonth() == today.getMonth() && cell_date.getDate() == today.getDate()) {

            // カレンダー上の休日かどうか
            var holiday_flg = false;
            if (data_array[1] == "土" || data_array[1] == "日"|| data_array[2] == "祝") {
                holiday_flg = true;
            }

            for (var i = 0; i <= column_cnt - 3; i++) {
                keyword = data_array[i + 3];
                
                if(holiday_flg){
                    if (keyword == "休み") continue;    // 休日に休みの予定は通知しない
                }
                if (keyword == "") keyword = "出勤";
                message += "*" + names[i] + "*" + " - " + keyword + "\n";
            }
            return false;
        }
    });

    if (message == "") {
        //本日の通知はなし
        return;
    }

    var jsonData = { "username": (today.getMonth() + 1) + "/" + today.getDate() + "の出勤予定", "text": message };
    var payload = JSON.stringify(jsonData);
    var options =
    {
        "method": "post",
        "contentType": "application/json",
        "payload": payload
    };

    UrlFetchApp.fetch(webhook, options);
}

```
弄った部分を以下でご紹介します。

## シート名生成

大抵の会社は月度と歴度が異なると思いますが、弊社も同様です。
本日日付から歴度を算出してシート名を決定します。

```js
    // シート名生成
    var target_sheet_month = today.getMonth() + 1;
    var target_sheet_year = today.getFullYear();
    if (today.getDate() > 15) {
        target_sheet_month = today.getMonth() + 2;
    }
    if (target_sheet_month == 12) {
        target_sheet_year = today.getFullYear() + 1;
        target_sheet_month = 1;
    }

    var target_sheet_name = target_sheet_year + "年" + target_sheet_month + "月度";
```

参考ページでは先頭のシートを取得していますが、シート名でデータ取得元のシートを決定できるようなので、そのようにしました。

```js

    // var target_sheet = spread_sheet.getSheets()[0];
    var target_sheet = spread_sheet.getSheetByName(target_sheet_name);
    var data_arrays = target_sheet.getRange("A7:M40").getValues();
```

## 名前の配列を生成
7行目のD～K列（枠はもっとあるけど…）を回し、名前が無かったらループを抜けます。
何列目まで名前があるかを`column_cnt`に採りつつ。

```js

    // 名前の配列を生成
    var column_cnt = 0;  // 空だった場合のことは考えないゆる仕様
    for (var i = 3; i <= 10; i++) {
        if (data_arrays[0][i] == "") {
            // 空白に当たったら抜ける
            break;
        }
        column_cnt = i;
        names.push(data_arrays[0][i]);
    }
```

## 今日の予定

B列に曜日、C列に祝日を持っているわけですが、システム部のメンバーは土日祝休む人が多いので、わざわざ休みの日に全員休み！みたいな予定を投げて未読を積み上げるのも変な話です。
そのため、土日祝に出勤の予定がある人だけを抽出します。

```js

        // 今日の予定
        if (cell_date.getMonth() == today.getMonth() && cell_date.getDate() == today.getDate()) {

            // カレンダー上の休日かどうか
            var holiday_flg = false;
            if (data_array[1] == "土" || data_array[1] == "日"|| data_array[2] == "祝") {
                holiday_flg = true;
            }

            for (var i = 0; i <= column_cnt - 3; i++) {
                keyword = data_array[i + 3];
                
                if(holiday_flg){
                    if (keyword == "休み") continue;    // 休日に休みの予定は通知しない
                }
                if (keyword == "") keyword = "出勤";
                message += "*" + names[i] + "*" + " - " + keyword + "\n";
            }
            return false;
        }
```

なお、土日祝に全員休みの場合

```js

    if (message == "") {
        //本日の通知はなし
        return;
    }
```
これが効いて、Slackへのメッセージ送信自体行われないという仕組みです。


# 実行トリガーの設定

だいたい9時くらいから仕事を始めるので、それより前に実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576051/cd02cdaa-1a37-f37c-0317-a3f402167853.png)


# Slackへの投稿結果

こんな感じで投稿されます。
書式が効くので、いろいろ遊べますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576051/c49b26c4-9308-4ac5-1779-c0aeb1a96841.png)

# 閑話休題：勤務表の運用目的

* メンバー各人で休みのスケジュールが異なるため、休日の共有
* どの倉庫に出勤しているか、出勤場所の共有
* その他、遅刻や早退予定の共有

バリューブックスのシステム部は、長野県上田市の秋和倉庫に事務所があり、基本的にはここに出勤します。（＝空白のセル）
同じ上田市内に岡倉庫、上田原倉庫があり、そちらに出勤することもありますし、リモートワークの場合は自宅で出勤となります。今日の居場所をアピールするのに書いておくと、あれ？あの人今日ドコ？ということがなくなって幸せになれるよね、みたいなざっくりした運用です。
スプシでもいいのですが、他にもイイ感じのツールを探し中です。

# 留意事項

* 遊びで作ったものなので月跨ぎのテストなどきちんとしていません。動くといいな～くらいのノリです。適宜お好きなように修正して使ってください。