PowerAutomateを使って、メールに添付されたCSVの取り込みを自動化する


# やりたいこと
定期的にシステムから送付されるCSVファイル(メールに添付)の中のデータを使って、エクセルのピボットテーブルを作っています。またこのデータは差分ではないので、毎回完全に置き換えになります。
手動で対応するのが大変なので、これを自動化してみました。ピボットテーブルのもとになっているテーブルのみを書き換える形です。

# tl;dr;
とりあえず問題なくできる。ただ、
- とても時間がかかる(ライセンスに依存してキャップされているらしい)
- テーブル内の全部の行を削除する方法がわかりにくい
- CSVを簡単に読めるアクションがほしい…

# 環境
PC: Windows10
ライセンス: Power Automate for Office 365

# 元データ

```txt: data.csv

"Name","Certification","Status"
"Alice","Python 3","Pass"
"Bob","Basic Data Management, L2","Ongoing"
"Cris","LPIC Lv2","Postponed"
```
本物は共有できないので、例。ポイントは以下の通りで、微妙に面倒な要素があります。
1. 先頭に空行がある
2. ヘッダ行がある
3. カンマ区切りだけど、データの中にもカンマがありうる
4. ただカンマの入る可能性が2列目のみ(自分の知る範囲では1個まで)

# 実装
## 更新するファイルの準備
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/8be0e580-77f2-3ac3-dd85-7aa36a9e9023.png)

SharePoint(OneDrive)上にエクセルファイルを作成し、カラム名をCSVに合わせたテーブルを作成します。

## PowerAutomateのフロー作成

全体は以下。
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/f75a7895-2e2d-4f34-0a60-022d2547187c.png)

### トリガー
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/c50143a7-dfa1-7700-6840-afcea02407da.png)
この条件は人それぞれですが、自分の場合は特定のフォルダに特定の件名で、添付ファイル付きで来た時を条件にしています。

### テーブルの初期化
テーブルからすべての行を削除するというアクションはないので、一覧を表示させてそれをすべて削除するという形で実現しています。
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/c52f7bc5-2868-32ab-922c-dcfd39a18ef3.png)

注意として、この「表内に存在する行を一覧表示」はデフォルトだと256件しか拾ってきません。その上限を設定の項目から変更しています。
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/be6c7e97-ce37-0a5c-0ba7-05ca25b9f5ef.png)

次に「Apply to each」アクションを使って、取得した行に対して削除を行います。全件マッチさせるために、適当なキー列と選び、キー値をそのキー列の値にしています。(文字で書くとわかりにくい)
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/64c084d1-8375-f5c2-c573-ad173f06aead.png)

### CSVからの値取得
このやり方は参考の2つ目のサイトからそのままお借りしています。
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/4a501f6a-b515-6ccc-9e35-da485dd372cd.png)

- コンテンツ→添付ファイルの内容を入れる変数
- 改行文字→CSVの改行文字をいれる変数。これだけ値のところでEnterをいれています。ほかは初期値を指定していません。
- 行の配列→CSVの各行を配列としていれる変数
- 列の配列→1つの行をカンマ区切りで配列にしたものをいれる変数

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/fda36ee2-eef1-4ebc-7912-818720d80471.png)
添付ファイルの内容を「コンテンツ」変数に格納。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/b24ca3bb-9ecc-1c49-4b9f-ae1ec7993977.png)
取得したコンテンツを「改行文字」でスプリットして「行の配列」に格納。式は
`split(variables('コンテンツ'),variables('改行文字'))`と指定。

### エクセルのテーブルへ追記
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/5d2a6730-6413-1600-8f2b-8776b6db965a.png)

先頭の空行など余分なデータを除く必要があり、多少複雑になっています。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/ae6878f4-24fe-4d9a-e9ad-aa9183a7b6ce.png)
まず、Apply to eachを選択し、先ほど取得した「行の配列」を入力として使用します。
次に、「列の配列」にそれぞれの行をカンマ区切りにした配列を格納します。
値に指定する式は`split(items('テーブルへの追記'),',')`です。※Apply to eachを「テーブルへの追記」と名前変更しているので、それを指定します

次にヘッダー行を除くために条件を通します。ここでは`replace(variables('列の配列')[0],'"','')`がNameでないこと、としてフィルタしています。出力はダブルクォーテーションで囲まれてくるので、それを除外したものと比較する形にしています。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/a20a3472-bf55-808c-9f4a-bc439cca3469.png)
そしてヘッダ行ではなかった場合、今度は値自体がカンマを含むケースを処理するために、`length(variables('列の配列'))`を使って場合分けしています。カンマなしならカラム3つ分出てくるので、それらをそのままテーブルの各カラムに対応させて追記します。ここでもダブルクォーテーションは除外しています。

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/ffc189c4-ff02-6936-abe8-bfb70d461ad0.png)
データ内にカンマがあれば、配列の長さが4になるので、その場合は、値はconcatでくっつけて、`concat(replace(variables('列の配列')[1],'"',''),replace(variables('列の配列')[2],'"',''))`としています。

# 結果
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159980/16066a5d-2bdd-95f1-f46d-9dbab31e2e24.png)

ちなみに、かなり時間がかかります。裏で頑張ってくれるので完成後はいいのですが、作成＆デバッグ時はかなりストレスたまります。そのため今回のように、テーブルを全入れ替えするような運用はそもそも避けた方がいいかもしれません。自分の場合はCSV出力が別システムでコントロール不可なので、いったんこの形にしています。

# 参考
Power Automate 受信メールに添付されたExcelファイルのテーブルから行の取得を行う
https://blog-tips.sekenkodqx.jp/2021/09/16/power-automate-comment-answer-get-row-variable-excel-table/

CSVをエクセルの表に転記する
https://tech.walkit.net/powerautomate-csv-xlsx#toc3

データテーブルから行または列を削除する
https://docs.microsoft.com/ja-jp/power-automate/desktop-flows/how-to/delete-row-column-datatable
※ただこのオフィシャルな方法よりもよさそうなやり方がある…。

Power Automateで256行より大きいExcelファイルを扱う方法！
https://www.teijitaisya.com/powerautomate-row/