はじめに
今日はクラウドフローで複数のExcel から情報を取り出します。
部署ごとで取りまとめた参加者一覧を、すべて取得するフローです。
取得元となるExcel は、簡単のため初めからテーブルを用意しています。
配布するフォーマットとしてテーブルの使用ができない場合は、少々複雑になりますが、Office Scriptsを利用する 「スクリプトの実行」 や 「テーブルの作成」 アクションを併用してください。
結論
こんなことはせずに、Microsoft Formsで申請フォームを作った方がいいです。
どうしてもファイルが分かれてしまう場合でも、Power Queryでまとめて取得する方が単純です。
…と、詮無きことを初めに言っておきます(∵)
それでも、どうしても、Power Automate フローで処理したい場合や、1つの手段として参考に知っておきたい方は、以降もご覧ください。
フローの流れ
やりたいことのわりには、かなりステップが多いです。
あまりまっとうなやり方のようにも思えないので、オススメはしません。(しつこいですが何度か述べます)
このフローのポイント
Excelを動的に指定するのがとても大変だったので、まずは何が大変か? を解説します。
Excel を扱うためのインプット
まず、1つのExcel ファイルから情報を取得する方法を確認してみましょう。
こんな感じですね。
複数のファイルを処理するためには、すくなくともこのファイル
を動的な指定にする必要があります。
ループ回さないといけないですからね。
動的な指定にするために、このアクションで指定しているインプット情報についてもう少し詳しく確認します。
指定したインプットは、メニューのコードのプレビューから確認することができます。
このプレビュー中のinputs
->parameters
の中身が、アクションに指定しているインプット情報です。
フローを作成している画面では、プルダウンで簡単に指定できていますが、裏側ではこんな謎の文字列が使われているんですね。
なので、ここではfile
に指定されている01GUGTXNDMB2L7APU4ERHL2PVJTRVLZCTS
と同等の情報を動的に指定することが必須となります。(ファイルごとに異なる値です)
インプット情報を動的に取得したい
さて、フォルダ内の複数のファイルを指定するために、先ほどのfile
に指定できる情報を取得しましょう。
フォルダ内のファイルを取得するには、SharePointコネクタの 「ファイルの取得(プロパティのみ)」 を使用します。
エントリーフォルダを制限することで、特定のフォルダ内のファイルを取得できます。
しかしながら、このアクションで取得できるファイルの情報の中に、ファイルを特定するための情報はいくつかあるのですが、そのどれもがfile
に指定できる情報とは異なる値となっています。
「ファイル メタデータの取得」 アクションでも、目的の情報がありません。
ファイルの情報を取得できるアクションは、粗方試したのですが、このfile
をそのまま取得できるアクションは見つかりませんでした…
問題の解決
ダメもとで、フローの実行結果から、目的の値01GUGTXNDMB2L7APU4ERHL2PVJTRVLZCTS
で検索をかけてみたところ、偶然にも?見つけることができました!
スクロールして、どこで取れたのか確認すると・・・
・・・サムネイル?
つまり、このサムネイルURLから何とかして取り出すことができれば使えそうです。
フローの解説
ということで、全体の流れをさらいつつ、フローの解説を行います。
①目的のファイルを抽出
最初にフォルダ内からExcel ファイルをすべて取り出します。
先ほど説明した 「ファイルの取得(プロパティのみ)」 を使用すればOKですね。
ただし、このままでは同じフォルダにある他のファイルやフォルダも巻き込んでしまいます。
「アレイのフィルター処理」 を使い、ファイル名や拡張子でフィルターしましょう。
このフローでは拡張子付きのファイル名が.xlsx
で終わることを条件にフィルタしています。
②file
の取り出し
抽出したExcelファイルを対象にApply to each でループ処理を行います。
サムネイルURLからfile
に指定する情報を取り出すことから始めましょう。
最初に{Thumbnail}/Small
を取り出します。(サイズはなんでもいいです)
取り出したURLは以下のような形式です。
https://eastus1-mediap.svc.ms/transform/thumbnail?provider=spo&inputFormat=xlsx&cs=fFNQTw&docid={fileが含まれるURL}&access_token={アクセストークン}&width=96&height=96
docid
という属性の中にほしい情報があるので、まずはdocid
を取り出します。
「&docid=」から「&」までの文字を取り出せばよいので、split関数を使って、以下のように取り出しました。
split(split(outputs('作成'), '&docid=')?[1], '&')?[0]
「指定文字で区切った何番目の値」という指定方法です。
PowerAutomate フローでの文字列処理には、よくこのsplit関数を使いますので覚えておくとよいと思います。
取り出したdocidは次のような文字列です。
https%3A%2F%2F***.sharepoint.com%3A443%2F_api%2Fv2.0%2Fdrives%2Fb!ZyHUfhrcDUi_Yrz1JztkhXPR-FcSuXlElbX8IdlU93YfUHA3Vp79R4aubyL2fvUN%2Fitems%2F01GUGTXNDMB2L7APU4ERHL2PVJTRVLZCTS%3Fversion%3DPublished
パーセントエンコーディングという形式で変換されているので、デコードして元に戻してあげます。
decodeUriComponent(outputs('作成:サムネイルURL内のdocId'))
デコードした結果です。
https://***.sharepoint.com:443/_api/v2.0/drives/b!ZyHUfhrcDUi_Yrz1JztkhXPR-FcSuXlElbX8IdlU93YfUHA3Vp79R4aubyL2fvUN/items/01GUGTXNDMB2L7APU4ERHL2PVJTRVLZCTS?version=Published
またここから「?」の前の文字列のうち、「/」で区切った「9番目」の要素を取り出します。
関数では以下となります。
split(split(outputs('作成:デコードしたdocId'),'?')?[0],'/')?[8]
配列の要素は0始まりなのが注意点ですね。
ここまでしてようやくfile
の取り出しができました。大変でしたね…
ちなみに、同じ情報の中に、ドキュメントライブラリを指定するためのdrive
の情報も含まれています。
思いついたら何かに応用してみてください(∵)
③テーブルの取得
ファイルが特定できるようになったので、次はテーブルに記載された情報を取り出したい…のですが、テーブルを指定するId
がわかっていません。
なので、いったん 「テーブルの取得」 アクションでファイルの中のテーブルを全て取りだし、テーブル名でフィルタしてId
を検索します。
④テーブルの情報を取得して変数に格納
取得したテーブルId
を使って、テーブルの情報を取得します。
ここでテーブルId
をカスタム値として使用しますが、フィルタした結果は配列になっているので、first/last 関数やobject?[0] の形式で配列から単一の要素を取り出します。(型変換)
body('アレイのフィルター処理:テーブル名')?[0]?['id']
取得した結果をまとめるために、変数に追加しますが、「配列変数に追加」アクションを使用するには、1行ずつ追加しないといけないので、Apply to each がまた必要になります。
これでもいいのですが、不要なループは実行時間がかかるなど、問題があるので可能であれば避けたいです。
一度に配列に追加するため、ここではunion 関数を使用しています。
変数の自己参照はできないため、作成アクションに変数をまるまる保管してあげるのがポイントです。
union(
outputs('作成:Temporary'),
outputs('表内に存在する行を一覧表示')?['body/value']
)
⑤HTMLテーブルにしてメッセージとして送信
今回は、テーブルの列構成に関わらず実行できるようにしているため、不要な列(ItemInternalIdなど)が含まれています。
キレイに成形したい場合は、テーブルの形式に合わせて「選択」アクションでMAPしてあげると綺麗にできます。
おわりに
Power Automate でのファイルの扱いって、ファイルを特定する方法がアクションごとに癖があって難しいですね。
Graph API を使えばもう少しバチっと決まりそうな気もしますが、今回は標準アクションのみで実装してみました。
(逆に難しくなっている気もします)
個人的にはクラウドフローとExcel の相性が良くない気がしているのですが、なにかのご参考になれば幸いです。