Power Automateで業務効率化した話①

# 概要
Power Automate（Microsoft提供の自動化ツール）を使って、Outlook & slackを連動させて業務効率化をしたので、どういう自動化プロセスを組み込んだのか説明します。
<br>
**【この記事を読むと分かること】**
- Outlookにメールが来た時にslackで通知を出す方法
- Outlookにメールが来た時に自動で返信用メールの下書きを作成する方法

# 問題意識
お仕事でお客さんからデータをもらって、自社でこねこねして、こねた結果をお客さんにまた返すという仕事（以下こねこね連携と呼ぶ）の担当になりました。

全体のフローはこんな感じです↓
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/27c01a17-12be-9393-1a9c-7bad67054ca6.png">
> 黄緑色の矢印が自分の担当作業

このお仕事をもらったときに思ったこと：
- このプロセスにおける自分の役割は伝書鳩が多い：実際にこねこねしてくれるのは別の人なので、自分は「こねこねしてね」という作業依頼を作業担当者に出す、「こねこね終わりました」という完了連絡をお客さんにする…というような役割が多い
- こねこね連携に割く時間は最小限に留めたい：他の仕事のほうが楽しいのでそっちはこれまで通り引き受けたい
- そもそも、この下半分のプロセスが月7回も繰り返されるのにいちいちメッセージ作って投げて…するのはあまりにめんどくさい：めんどい←これが本音

というわけで、5番と6&8番の作業をPower Automateを使って（半）自動化します。
（ちなみにデータの受け渡し自体は別経路なので、添付ファイルの自動保存や新規ファイルの添付は今回のフローに含まれません。）

※Power Automateのフローの全体像を見たい方は記事末の **まとめ** 参照

<br>

# 対応策
## 特定の単語を含むメールが来たときにslackにメッセージを投稿する
まず、こねこね用データ連携メールが来たら
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/6eb7c096-1aed-d7db-7812-e3ad95cfb158.png">
というメッセージがslackで出るようにして、メール受信と同時にこねこね作業担当者に自動で連絡がいくようにしたいと思います。

<br>

### 1\. メールの受信を検知する
Power Automateで「When a new email arrives」というトリガーを設定します。

今回は「こねこね用データ連携メールが最初に来たとき」だけ後続のフローが動くようにしたいので、件名に
①「【格納連絡】」という単語が含まれる
②「RE」や「Re」という単語が含まれない
というフィルターを設定しました。

:::note
**「When a new email arrives」というトリガーにフィルターを設定する**
「When a new email arrives」の右上にある「…」から「設定」を開き、「トリガーの条件」（図中黄色）の項目に

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/5318e49b-d95e-e823-92c2-03e1e4c8626e.png">

以下を指定する
```
@and(contains(triggerBody()?['Subject'], '【格納連絡】'), not(contains(triggerBody()?['Subject'], 'RE')), not(contains(triggerBody()?['Subject'], 'Re')))
```

:::

これで、最初の【格納連絡】メールだけをトリガーとしてslackメッセージが自動的に投稿され、返信メールを送ったときに後続のフローがいちいち作動しないようになります。


### 2\. 連携ファイル名の取得
次に、メール本文の中から連携ファイル名だけを抽出してきましょう。
連携ファイル名は、こんな感じ↓で連携されてきますので
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/025ec320-4c9e-cd6b-ad2d-c17acb524a24.png">
「■ファイル名」の後ろでファイル名っぽい箇所だけうまく抽出すればオッケーです。

:::note
**Html形式からテキストになおす**
Html形式のままだと後続処理で文字列を抽出するのが難しいので、まず```Htmlからテキスト（プレビュー）```というアクションを使用してテキストにならします。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/f7277e9a-d836-d024-6b93-c3f3ff011ca7.png">

> 「When a new email arrives」で取得しているメール本文を挿入する（「動的なコンテンツ」から挿入可能）

:::

:::note
**■以降80字取得**
先述の通り「■ファイル名」の次の行以降に連携ファイル名が記載されていますので、「■」以降でファイル名が含まれていそうな80字分をメール本文から抽出します。
（ちなみに80字というのは、ファイル名を不足なく取得可能だが関係ない文章があまり含まれないという長さを決めで指定しています。）

具体的には、```データ操作の「作成」```アクションを追加し、入力欄にsubstring関数を使ったコードを書いておきます。
```
substring(body('Html_からテキスト'),add(indexOf(body('Html_からテキスト'),'■'),0),80)
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/ef6b9256-e21a-13eb-f93e-1a6c2d71b132.png">


:::

:::note
**改行削除**
ここでテキスト中の改行を削除してしまいます。
というのも、こねこね用データ連携メールは様々な送り手から様々な形式で送られてくるためか、テキスト形式にならしたときになぜかファイル名の途中で改行が入ってしまうということがあります（実体験）。
今回は改行を無に帰すという操作を挟んでおくことで、ファイル名を一連のテキストとして認識可能な形にしておきます。

改行を削除するには、改行変数を設定したうえで、改行を```''```で置換します。

***① 改行変数を設定する***
```変数の「変数を初期化する」```アクションで、「種類」に文字列、「値」に改行を指定します。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/c43368ba-aa7b-6f60-d4b1-1e3f11dae0bf.png">

> 値欄が空白に見えるが、エンターキーを一回押して改行を入れている。

<br>

***② 改行変数を```''```で置換する***
```データ操作の「作成」```アクションを追加し、入力欄にreplace関数を使って改行変数を```''```で置換するコードを書いておきます。
```
replace(outputs('■以降80字取得'), variables('改行'), '')
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/6711b0d6-d383-d323-66ce-a23eab325fb8.png">

:::

ここまで処理すると、メール本文を
```
■ファイル名 XXXXXX.csv YYYYY.zip お手数おかけ
```
というような形のテキストで抽出するところまでできています。
続いて、ここからファイル名部分だけを取り出していきましょう。

:::note
***終了位置調整***
「■」以降80字を抽出すると、上の例の「お手数おかけ」のように、ファイル名とは関係のない地の文が入ってきてしまうことがあります。
「お手数おかけ」部分を除くため、最後の```.```から3文字までの範囲でテキストを切り出します。

```データ操作の「作成」```アクションを追加し、入力欄にsubstring関数、add関数、lastIndexOf関数を使ったコードを書いておきます。
```
substring(outputs('改行削除'),0, add(4,lastIndexOf(outputs('改行削除'),'.')))
```
> lastIndexOf関数で```.```のindex番号を取得し、add関数で```.```から4文字のindex番号を作成、substring関数の終了位置として渡している。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/6711b0d6-d383-d323-66ce-a23eab325fb8.png">

<br>
<br>

***開始位置調整***
続いて「■ファイル名」を取り除きます。
こねこね用データ連携メールでは「ファイル名」や「連携データ名」などの様々な名前が■の後に書かれる可能性がありますが、すべて「～名」という表現なのは共通しています。

そこで、```データ操作の「作成」```アクションを追加し、slice関数を使って「名」より後の文字列だけを抽出します。
```
slice(outputs('終了位置調整'), add(2,indexOf(outputs('終了位置調整'), '名')))
```
> 「名」のindex番号を取得し、add関数で「名」の後一文字目のindex番号を作成、slice関数の開始位置として渡している。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/2c52dcd3-12eb-9f6f-c0ba-f4ab7cf421e2.png">
:::

これで
```
XXXXXX.csv YYYYY.zip
```
という形でファイル名だけを抽出できました。
最後に、ファイル名を改行区切りにしてファイルごとに一行ずつ表示されるようにします。

:::note
**ファイル名を改行区切りにする**
```データ操作の「作成」```アクションを追加し、replace関数を使って```' '```を先ほど作成した改行変数で置換します。
```
replace(outputs('開始位置調整'), ' ', variables('改行'))
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/fc22d19a-0509-3c97-92ea-e73cbdf47245.png">
:::
これで
```
XXXXXX.csv
YYYYY.zip
```
という形にファイル名を整形できました。

<br>

### 3\. slackメッセージ投稿
では最後に、slackに投稿するメッセージを設定しましょう。

:::note
**メッセージの投稿(V2)**
```slackの「メッセージの投稿(V2)」```アクションを追加し、任意のチャネル名・メッセージテキストを指定します。

今回はメッセージに、メールの件名と先ほど作成した改行区切りのファイル名を含めるようにしています。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/ebfeec7f-6505-a778-4c11-f2f4484027e4.png">

> <@メンバーID>とすることでメンションも可能（図中黄色部）

ボットとして投稿することもできますが、今回はユーザーとして投稿しています。
こうすることで自分で投稿メッセージを削除できるようになるので、テストメッセージを送るときは特にこの設定を「はい」にしておくのが良いと思います。
:::

以上で、こねこね用データ連携メールが来たときに、slackで作業担当者を呼び出して連携ファイル名をお伝えすることができるようになりました。

では続いて、お客さんへのメール連絡のフローを半自動化していきましょう。

<br>

## 特定の単語を含むメールが来たときに、自動的に返信メールを作成してOutlookの下書きフォルダに保存する
データをもらったら「データちゃんと届いたで」、こねこねが終わったら「こねこね終わったデータ返したで」という連絡をお客さんにしないといけません（フロー図の6番と8番の作業）。
今回は、上と同じトリガー（件名に「格納連絡」が含まれ「Re」が含まれないメールを受信したとき）で2パターンの返信メールの下書きが自動で作成されるフローを作っておくことにします。
2パターンとも同じ流れで作成できるので、以下では「データちゃんと届いたで」メールの下書きの作成方法を例に説明します。

### 1\. ccリストの作成
まずccリストを作ります。
というのも、単純に返信メールを作るとメールの送り主だけが宛先に指定されるので、ccリストを別で作成しておいてあげる必要があります。

:::note
**ccリスト**
```データ操作の「作成」```アクションを追加し、受信メールのcc欄の内容をテキストとして保持します。

```
string(triggerBody()?['ccRecipients'])
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/6d440e70-8ec6-57aa-a235-f17825912476.png">
:::

<br>

### 2\. メール本文の作成
次にメール本文を作成しましょう。

:::note
**ファイル名をbr区切りにする**
「データちゃんと届いたで」メールでは受領したファイル名をメール本文に入れたいので、まずはファイル名を加工していきます。
どうして加工が必要かと言うと、メール本文はHtml形式のため、先ほどの改行変数でファイル名を区切るのではうまく改行されないからです。そこでさっきと同じ要領で、ファイル名を改行記号```<br>```で区切ったバージョンを作成します。
```
replace(outputs('開始位置調整'), ' ', '<br>')
```
<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/b36a45f6-d669-284d-3382-20141113c6fc.png">
:::

:::note
**メール本文**
続いて```データ操作の「作成」```アクションを追加し、メール本文を作成します。

<img width="450" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/10998ee3-7703-0999-fe44-08c52d2adef2.png">

> 先ほど作成したbr区切りのファイル名を動的コンテンツの追加から挿入している（図中「出力」部分）
:::

<br>

### 3\. 返信メールの下書きの作成
最後に、返信メールの下書きをOutlookの下書きフォルダに作成するフローを追加します。

:::note
**HTTP要求の送信**
Outlookの ```「HTTP要求を送信します」```アクションを追加し、URLに以下を指定することで、トリガーとなっている受信メールに対して返信を作成するようにします。
```
https://graph.microsoft.com/v1.0/me/messages/@{triggerBody()?['id']}/createReply
```
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/80a3ee52-10d8-e5f1-f8e5-0b036e2af85f.png">

> 本文欄中の```address```に先ほど作成したccリストを、```comment```に先ほど作成したメール本文を指定している
:::

これで、こねこねデータ連携メールを受信したときに返信用メールの下書きまで完成しているという状態を達成できました！

<br>

# まとめ
全部つなげるとこのようなフローになります↓

![全体フロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615890/ee1ba15f-1a12-7033-49ac-4f37a86296a4.png)

これで、こねこね連携作業の一部をうまく自動化することができました！

ちなみに、フロー作成前には思ってもなかったメリットとして、メールの返信の下書きがあることで、お客さんに連絡したかどうかが一目瞭然になったことが挙げられます。（つまり、下書きメール自体がToDoリストとして機能している。）

逆に思っていたよりうまくいっていない点としては、自分のPCが起動していない間はフローが動かないことが挙げられます。（本当は自分が有給等でお休みをとっていても動いてくれると助かる。）

つまりこのフローは完全にうまく機能しているわけではないのですが、こねこね連携に割く時間を減らすという当初の思惑はある程度達成できました。

めでたしめでたし。

<br>

# 作成にあたってお世話になったWEBページ
1\. [誰でもできる業務改善講座](https://blog-tips.sekenkodqx.jp/category/%e8%a8%98%e4%ba%8b/%e6%a5%ad%e5%8b%99%e6%94%b9%e5%96%84/rpa%e3%83%bb%e3%83%ad%e3%83%9c%e3%83%83%e3%83%88/power-automate/)
2\. [【PowerAutomate】返信メールの下書きを作成する（送信はしない）](https://notes.yakky-k.com/2022/10/powerautomate_13.html)
3\. [Power Automateで文章から文字列を抽出する。（文字数不明ver）](https://www.teijitaisya.com/powerautomate-text2/#google_vignette)
4\. [Power Automate のトリガー条件を使ってOutlookを色んな条件でトリガーさせる方法。](https://qiita.com/jooji/items/b87b60ef42843cfa4fbd)
5\. [Power Automate で 凝った Slack メッセージを投稿する](https://qiita.com/numa5h0/items/c9baa2632485a3d1b4d5)