PowerAutomateでSharePointのドキュメントライブラリにあるファイル一覧をCSVに出力する

この記事は、[Power Automate Advent Calendar 2022](https://qiita.com/advent-calendar/2022/powerautomate) 12月9日担当分の記事です。

# はじめに
PowerAutomateで、SharePointのドキュメントライブラリのファイル一覧を出力する方法は、結構前に作ったのですが、これまでちゃんとまとめていなかったので、Advent Calendarをきっかけにまとめてみることにしました。
「ファイルの取得（プロパティのみ）」での100件の問題や、フィルタークエリ、CSVで保存する際のBOMの付け方など、（自分としては）結構苦労したところがあるので、まとめていきたいと思います。

# このフローの用途
SharePointのドキュメントライブラリのファイル一覧をCSVで取得するためにこのフローを作りました。

# フローの全体像
作成したフローのキャプチャは以下の通りです。ファイル数にもよりますが、1000ファイル程度であれば、数秒から10秒程度で処理が完了します。
#### トリガー、スイッチ
![トリガー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/921313bd-e510-363e-d750-862cfaa27e0e.jpeg)
#### ファイル情報の取得とCSV作成
スイッチのケースは複数ありますが、処理は全く同じで、取得するフォルダが違うだけなので省略します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/69dc95fd-24b4-8573-ee25-d54592fa31bc.png)

#### エラー発生時の通知
![エラー発生時通知用](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/0ac334c9-250a-d00c-90e4-f87106ad8e3a.jpeg)

# 説明
順を追って説明します。
### トリガー
だれでも使え、わかりやすい方法として、Formsを使いました。
このフローでは、ファイル一覧を取得するフォルダを複数から選ぶようにしているので、フォームには、ラジオボタンで選択肢を作成しました。
数秒で処理されてしまうので、最終的には削除しましたが、処理開始や完了の通知メール送信宛先を入力するようにしていたこともありました。

PowerAutomateのトリガーには、Formsの「新しい応答が送信されるとき」を使います。
![新しい応答が送信されるとき](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/3d3aa284-e746-ec34-52eb-a97e1a5c6fe8.jpeg)

Form Idは、どこにも言及なかったような気がするのですが、URLの「?id=」以降の文字列がForm Idです。
![Forms URL sample](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/72c90f14-d8a2-613e-a242-cecbe21d1c11.jpeg)

### フォームの入力内容を取得
どのフォルダのファイル一覧を作成するのかや、CSVのファイル名に日時を組み込みたいので、アクション「応答の詳細を取得する」で、フォームの入力内容などの詳細を取得します。
![応答の詳細を取得する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/841e90e2-a4e9-0e9a-71f9-da96924680eb.jpeg)

### フォームの送信時刻を変換
Formsに限らず、Microsoft365はだいたい全部そうだと思いますが、フォームの応答時刻はUTCなので、JSTに変換します。ついでに、時刻で並べ替えできる形式に変換します。
![タイムゾーンの変換](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/2b5f523d-cee1-b709-02fc-8c5871ced025.jpeg)

### フォームでの回答に応じて、フォルダを変更
「スイッチ」を使って、フォームの入力内容を基に、どのフォルダのファイル一覧を取得するか、ケースを分けます。

### エラー発生時のために、スコープでくくる
ここからの処理は、エラーが発生するときがあるので、全体をスコープでくくっておきます。スコープ内のどこかでエラーが発生した場合、スコープの次に設定するエラー発生時の処理を実行されるようになります。
![スコープ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/cb730ce2-c45d-549f-b5b4-fd4f6b927b89.jpeg)

### 指定したフォルダ内のファイル情報を取得
SharePointの「ファイルの取得（プロパティのみ）」を使い、フォルダ内の（基本は）すべてのファイルの情報を取得します。なお、「ファイルプロパティを取得」という紛らわしいものがあるのですが、これは指定したファイルひとつのプロパティを取得するものです。英語だと、「Get **files** (properties only)」と「Get file properties」になっているので、英語にしておいた方が迷わないです。
![GetFiles_propertiesOnly.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/4af9c29f-ab6a-bfcc-e37d-80493d90ef2d.jpeg)
![ファイルの取得（プロパティのみ）.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/d7b9d9f9-2c00-ab7c-a25e-ce02130ebb76.jpeg)

入力項目のうち、サイトアドレス等は迷わないと思いますが、Top Countにトラップがあります。「デフォルト＝すべて」と記載がありますが、これは嘘です。未入力のままだと、100件に制限されるので、ここでは実際の制限値である5000を入力しておきます。

このフィルタークエリは、ファイル形式がpdf、もしくは、ファイル名にある文字列が入るファイルを指定しています。

このあたりの詳細は、以下に記載がありますが、ファイル形式のフィールド名や、ファイル名のフィールド名は、どこにも書いていない気がします。フォーラムを検索し、"File_x0020_Type"がファイル形式、"FileLeafRef"がファイル名というのがわかりました。

https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/guidance/working-with-get-items-and-get-files

#### CSVへ変換
ファイル情報は取得できたので、これをCSVに変換します。
そのままだと、項目数が多すぎてしまうので、オプションを開いて、ColumnsをCustomに変更します。
ヘッダーは任意の見出し名とし、Valueに入れたい情報をDynamic Contentsから選んでいきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/14ed340b-4bcd-6e10-db66-46c4c146458b.png)

#### CSVファイルを保存
![ファイルの作成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/dc821342-ef57-1d9c-f866-e8e7090dc088.jpeg)
CSVにできたのであとは保存するだけですが、そのままではエンコーディングがBOMなしUTF-8になってしまい、SharePoint上や、Excelで開く際に、文字化けしてしまいます。あとからメモ帳等でBOMを付与してあげればよいのですが、面倒です。調べてみたら、CONCATでBOMを付与する方法を記載してくれている方がいました。

https://zenn.dev/karamem0/articles/2020_09_30_120000

![BOM付与](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/0151b3f4-b354-6cca-46bb-7bf298d494cb.jpeg)

ファイルコンテンツの欄に、以下の通り記載します。
```
concat(decodeUriComponent('%EF%BB%BF'), body('Create_CSV_Table'))
# Create_CSV_Tableの箇所は、CSVテーブル作成のアクション名を入れます
```

これで、BOM付きUTF-8で保存され、SharePoint上でも、Excelでも、特に追加の作業なく、正しく表示されます。
ここまでで終わりにしてもよいのですが、ゲストユーザーに利用してもらうため、エラー発生時には自分に通知が来るようにしたいので、エラー発生時の処理を入れます。

### エラー発生時のために、スコープでくくる
実行条件をエラー発生時などにし、Teamsの通知などのアクションを追加します。
![エラー発生時通知用](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478238/0ac334c9-250a-d00c-90e4-f87106ad8e3a.jpeg)

そのままだと、PowerAutomateのログ上は、「成功」として記録されてしまうので、「失敗」として終了させます。


# まとめ
まとめてみると、大した処理をしていないと思いますが、ここまで来るのに、結構手間取りました。PowerAutomateは、手軽に使えるのに、説明不足なところがある気がします。
ファイルの取得の100件で止まってしまう、フィルタークエリで使うフィールド名がよくわからない、BOMなしで保存されるので文字化けするあたりは、それぞれ解決するのに結構な時間がかかりました。
しかし、PowerAutomateを使うと、いろいろと楽になるので、今後も積極的に使っていきたいです。