TeamsとGoogle Apps Scriptで簡単出勤簿アプリ構築！

# はじめに
もう12月ですね！
12月といえばアドベントカレンダー。この記事は[私とあなたの Advent Calendar 2022](https://qiita.com/advent-calendar/2022/trade_eco)の初日の記事として書かれています。

# 本投稿の趣旨
サクッとアプリケーションを作って作業を自動化するととてもかっこいいですよね！

エンジニアの作業はDX化され、最近のコミュニケーションはもっぱらチャットだと思います。チャットに絡めたアプリケーションをうまく作っていければ、様々な用途につかえそうです。

今回は無料で運用でき、かつ実用的なアプリケーション構築例をご紹介したく「TeamsとGoogle Apps Scriptで簡単出勤簿アプリ構築！」をお送りします。

# 作成する簡単出勤管理アプリ
今回作成するアプリケーションは、チャットツールであるMicrosoft Teamsと、Web APIを作成することのできるGoogle Apps Scriptを利用して、出勤簿を自動作成するものです。

## アプリのコンセプト
このアプリケーションは、朝、Teamsに「\@hello 勤務開始」などとメッセージを入力すると、それを人ごと、日にちごとにGoogle Sheetsに記録してくれます。
リモートワークによりチャット上で挨拶をすることが多く、会社によっては出勤連絡をチャット上で行うことで管理しているところもあるかと思います。
ところが時々連絡を忘れてしまうことがあります。ほんとに忘れただけならいいんですが、病気や事故で連絡できない状態であればいち早く知らなければなりません。
もし勤怠連絡がSheet上で一覧視できて、出勤連絡がないことがわかれば、いち早く行動できます。
いつものチャットで出勤連絡ができ、チャットと違って流れていかずに一覧視できるのが、このアプリの良いところです。

# 作っていく
## Google Apps Script
まずは[Google Sheets](https://www.google.com/intl/ja_jp/sheets/about/)で空のドキュメントを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/064fa7aa-0729-c96e-635d-4bda8ee91c04.png)

作成したら、A１に「出勤簿」と入れておいてください。（アプリのコード簡略化のために大事です。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/0c4d9902-e237-1126-2a0f-b9d157aefde5.png)

Sheetsのメニューバー、拡張機能→Apps Scriptを選択します。

![スクリーンショット 2022-11-28 16.41.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/0b97027b-2955-2dee-5fac-c8c173448b9d.png)

コードを書いていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/beaf26e7-8813-3d67-d55c-11d092e5586e.png)

内容は以下。

```JavaScript: 
function removeFirstTag(text) {
  try {
  return text.substring(text.lastIndexOf(">")+1).trim();
  } catch (e) {
    return "";
  }
}
function findUserRow(sheet, userName) {
  const lastRow = sheet.getLastRow() + 1;
  var data = sheet.getRange(1, 1, lastRow, 1).getValues();
  for(var i=0;i<(lastRow-1);i++)
  {
      if(data[i][0] === userName) {
        return i + 1;
      }
  }
  return lastRow;
}
function sameDay(d1, d2) {
  return d1 && d2 && d1.getYear()===d2.getYear() && d1.getMonth()===d2.getMonth() && d1.getDay()===d2.getDay() ;
}
function findPostedDateColumn(sheet, postedTimestamp) {
  const lastColumn = sheet.getLastColumn() + 1;
  var data = sheet.getRange(1, 1, 1, lastColumn).getValues();
  
  for(var i=0;i<(lastColumn-1);i++)
  {
      if(sameDay(new Date(data[0][i]), postedTimestamp)) {
        return i + 1;
      }
  }
  return lastColumn;
}
function doPost(e) { // このメソッド（doGet or doPost）がWebから呼び出し可能です。今回はTeamsがWeb経由でこのメソッドを呼び出します。
  //　リクエストボディーを受け取って
  var posted = JSON.parse(e.postData.getDataAsString()); 
  //　Sheetsの内容を取得。
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
　　　　//　リクエストボディーから必要な情報を取り出して
  const userName = posted.from.name;
  const postedTimestamp = new Date(Date.parse(posted.timestamp));
　　　　//　記載すべき行と列を取得。
  let userRow = findUserRow(sheet, userName);
  let todayColumn = findPostedDateColumn(sheet, postedTimestamp);
　　　　//　記載すべき行列の現在の値を取得して。
  const currentValue = sheet.getRange(userRow, todayColumn).getValue();

  let respondMessage;
　　　　//　値がなければ追記。
  if(!currentValue) {
    const messageText = postedTimestamp.getHours()+":"+postedTimestamp.getMinutes() + " " + removeFirstTag(posted.text);
    sheet.getRange(1, todayColumn).setValue(postedTimestamp);
    sheet.getRange(userRow, 1).setValue(userName);
    sheet.getRange(userRow, todayColumn).setValue(messageText);//postedTimestamp.toLocaleString('ja-JP')); 
    respondMessage = "承り。"
  } else {　//　値があれば、すでに登録済みであることを示すメッセージを用意。
    respondMessage = "すでに登録済み → " + currentValue;
  }

  // Teamsへのレスポンスを作っています。
  const output = ContentService.createTextOutput(JSON.stringify({ "type": "message", "text": respondMessage }));
  output.setMimeType(ContentService.MimeType.JSON);
  return output;
}
```
コードが書けたらデプロイを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/b13c3bbb-fea5-21eb-cbad-5efc698bed6d.png)

途中、Google Apps ScriptがSheetsにアクセスする許可を求めてきますので、許可、デプロイを完了させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/6cf43fba-e984-866a-6bb7-4e698f4c35eb.png)

URLをコピーしておきます。Teamsの設定で使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/2114fda2-a0bc-914c-34a1-f8ea19a65db4.png)


## Teams

[TeamsのOutbounds Webhook](https://learn.microsoft.com/ja-jp/microsoftteams/platform/webhooks-and-connectors/how-to/add-outgoing-webhook?tabs=urljsonpayload%2Cjavascript)を使って、↑で作ったWeb APIを呼び出すようにします。

上記リンクの要領で、Teamsのチームのメニューをクリック、Manage Teams→Appsタブで下の方にあるCreate an outgoing webhookをクリック、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/089fccba-c7ff-50e4-2fd3-08667b9e4b30.png)
Nameはアプリケーションへのメンションとして使われるので打ちやすいもの、Helloなどがいいと思います。
URLは先程Google Apps Scriptのデプロイ時に取得できたものを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/8b539c55-c921-9530-1ed2-ac421c32e0e5.png)

これで、このチームのいずれかのチャネルで、アプリにメンションを飛ばすと、Google Sheetsに出勤簿が作成されていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25176/a32ed63c-5aa5-dc74-604d-10d7218a30a0.png)


#　この仕組を使って様々なアプリを作ってみてはいかがでしょう？

このように、Microsoft TeamsとGoogle Apps Scriptを使って、簡単に実用的なアプリを作成できます。
皆さんの身の回りにも、自動化したいお仕事が転がっていませんか？
今回ご紹介したような仕組みを利用して自動化してみてはいかがでしょう。
面白いアプリができたら、ぜひ教えて下さい。

そして、身の回りのいろんなことを自動化するうちにDXグセがついて、より価値の有るサービス作成につながるととても嬉しいです。


明日は @ryoa912 さんの投稿です。お楽しみに！