PowerAutomate: Teams 参加者レポートをCSV化して利用する

# 背景
社内で講義を開催したり参加した場合、研修ポイントってのが貰えます。
で Teams の参加者レポートの出番
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645569/04b0064e-b933-2237-915f-ec4156c7a520.png)

とはいえこのままじゃ使えないので
上手く処理して、他のデータとマージできる状態にしてやれば、便利じゃないかってお話。

まぁ実際は C# でツール作ってはいるんですが、意外にいろんな用途で使いたいことがあったので、取り込みベースとして用意してみた

# 参加者レポート
見ると分かるけど・・以下ちょっと特殊

- CSV といいつつ、TSV ( Tab Separated Values )
- Header が7行ほど先頭に付いてる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/231017df-c1c1-c4b8-0918-5bac4ef67cd0.png)

# 検討
自動で「参加者のレポート」がダウンロード出来たら勝手に変換して通知

ってことまでやりたいと思ったけど。以下理由でダメそう

- SharePoint にあげられるファイルではなさそう
- スレッド検知は出来たけど、更新されることは検知出来無さそう
- スレッド検知された時点で、レポートはない
- F12 で確認してみたけど・・cortana.api ってなに？<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6f2067f2-452e-400f-0fb4-eb8938323105.png)

Graph API で調べると以下辺りで追っていくと取れそうな感じもする
とはいえ、起動方法が Selected Message トリガーになって面倒そうなのもあって、今回はパス

https://docs.microsoft.com/en-us/graph/api/onlinemeeting-get?view=graph-rest-beta&preserve-view=true&tabs=http

https://docs.microsoft.com/en-us/graph/cloud-communications-online-meeting-artifacts

ということで、今回は簡潔に以下とする

1. Share/OneDrive にファイルをアップロード
1. TSV → CSV 変換

この先としては、用途毎に変換処理と、関連データをどっかに持つ必要がある・・かな。

# 概要
1. 起動トリガーと、CSV Contents 取得
    1. SharePoint 版
    1. OneDrive 版
1. TSV → CSV 変換

## 起動トリガーと、CSV Contents 取得
### SharePoint の場合
TriggerBody() の結果そのものが FileContent なので、そのまま解析処理へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6ccd3d02-88a4-a8b6-9ae5-6d163045eb87.png)

### OneDrive の場合
FileContent を取得する為に、[Get File Content](https://docs.microsoft.com/ja-jp/connectors/onedriveforbusiness/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB-%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%81%AE%E5%8F%96%E5%BE%97) アクションを利用して、解析へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/fc913521-d340-c0af-55c6-21f510917b9c.png)

## TSV → CSV 変換
フローはこんな感じ
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/13282892-7069-ae6e-e566-4d53f90bcf27.png)

簡単に説明すると・・
- Select Text2CSV
    - 改行コードで Split() して行分割
    - タブコードで Split() して列(Columns) 分割
    - Length はフィルター用<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/c7da656f-37dd-66b0-399c-d4b95117940c.png)
- Filter Array
    - 「会議の概要」などがファイルの先頭7行にあるので、この部分を除外。Skip(7) で飛ばしてもOK<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/4b56569f-167d-912f-b715-0e1d34a14c66.png)
- Compose Headers
    - 次の Select で Mapping する為に Header のみ保存
- Select Mapping CSV
    - Header と、各行の列データを組み合わせて データ整形<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/74e4ffa1-40cd-80fe-2cc5-bb28c3597254.png)

- Create CSV table
    - CSV 構造を元に Table 生成<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/8644c2d8-959b-2595-e9b3-155e4bf19208.png)

# フロー
SharePoint 側の Select Text2CSV　以下のサンプル

OneDrive で使うときは、以下修正
- Select Text2CSV での TriggerBody() のところを、FileContent アクションへ

変更前
> @{split(triggerBody(), decodeUriComponent('%0A'))}

変更後
> @{split(body('Get_file_content_CSV'), decodeUriComponent('%0A'))}

```json: フローのクリップボード
{"id":"2347bef4-bc10-4b78-8919-ebb5c21d15a7","brandColor":"#8C3900","connectionReferences":{"shared_sharepointonline":{"connection":{"id":"/providers/Microsoft.PowerApps/apis/shared_sharepointonline/connections/shared-sharepointonl-15e7a58d-6555-418d-a955-a6b286a76a7b"}}},"connectorDisplayName":"Control","icon":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KIDxwYXRoIGQ9Im0wIDBoMzJ2MzJoLTMyeiIgZmlsbD0iIzhDMzkwMCIvPg0KIDxwYXRoIGQ9Im04IDEwaDE2djEyaC0xNnptMTUgMTF2LTEwaC0xNHYxMHptLTItOHY2aC0xMHYtNnptLTEgNXYtNGgtOHY0eiIgZmlsbD0iI2ZmZiIvPg0KPC9zdmc+DQo=","isTrigger":false,"operationName":"Scope","operationDefinition":{"type":"Scope","actions":{"Select_Text2CSV":{"type":"Select","inputs":{"from":"@split(triggerBody(), decodeUriComponent('%0A'))","select":{"Columns":"@split(item(), decodeUriComponent('%09'))","Length":"@length(split(item(), decodeUriComponent('%09')))"}},"runAfter":{},"metadata":{"operationMetadataId":"63fe7035-9056-40a7-bb01-fa32a4c330ec"}},"Filter_array_SkipMeetingHeader":{"type":"Query","inputs":{"from":"@body('Select_Text2CSV')","where":"@greater(item()['Length'], 2)"},"runAfter":{"Select_Text2CSV":["Succeeded"]},"metadata":{"operationMetadataId":"0f50ee20-44a4-4586-a1d3-406c14e72922"}},"Compose_Headers":{"type":"Compose","inputs":"@first(body('Filter_array_SkipMeetingHeader'))?['Columns']","runAfter":{"Filter_array_SkipMeetingHeader":["Succeeded"]},"metadata":{"operationMetadataId":"dbcfdb8c-4815-42e1-9fb5-146a995062ca"}},"Create_CSV_table":{"type":"Table","inputs":{"from":"@body('Select_Mapping_CSV')","format":"CSV"},"runAfter":{"Select_Mapping_CSV":["Succeeded"]},"metadata":{"operationMetadataId":"7dad3500-46ec-4292-b480-d6b384443c68"}},"Select_Mapping_CSV":{"type":"Select","inputs":{"from":"@skip(body('Filter_array_SkipMeetingHeader'), 1)","select":{"@{outputs('Compose_Headers')[0]}":"@item()?['Columns'][0]","@{outputs('Compose_Headers')[1]}":"@item()?['Columns'][1]","@{outputs('Compose_Headers')[2]}":"@item()?['Columns'][1]","@{outputs('Compose_Headers')[3]}":"@item()?['Columns'][3]","@{outputs('Compose_Headers')[4]}":"@item()?['Columns'][4]","@{outputs('Compose_Headers')[5]}":"@item()?['Columns'][5]","@{outputs('Compose_Headers')[6]}":"@item()?['Columns'][6]"}},"runAfter":{"Compose_Headers":["Succeeded"]},"metadata":{"operationMetadataId":"239d1bf5-05e7-4758-a7a6-8b1bc52b07a4"}}},"runAfter":{},"metadata":{"operationMetadataId":"96c01f67-ea26-406c-852f-82287c07a98b"}}}
```

# あとがき
あとは、変換するだけ・・
なんだけど、意外に一意に簡単に紐づけて変換するのが面倒だなぁ、というのが実感

# keyword
how to convert Meeting Attendance Reports TSV to CSV in Power Automate