Power Appsを使ってSharePointに複数のファイルをアップロードする
なんとなくイメージでは簡単そうにできそうな気がしていましたが、やってみると意外と難しくて忘れそうなことも多かったので記事化しました(はやく専用コントロール作ってM〇crosoftさん・・・)。
できるだけ解説多めに盛り込んでみたので、参考にしてもらえると嬉しいです。
実装の構成はおおよそ下図のような形です。

設定は次のような順番で進めていきます。
- SharePoint Listの作成
- Power Appsでキャンパスアプリを作成
- データソースにListを追加
- Attachmentコントロールの取得
- Galleryコントロールの追加
- フローの新規作成
- アプリにフローを追加してButtonコントロールで実行
- 0KBテキストファイルのアップロード
- フローの実行結果からJSONフォーマットを作成
- フローにSharePointへ保存するステップを追加
主に紫がPower Appsでの作業、緑がSharePointでの作業、青がPower Automateでの作業になります。
実装はPower Apps for Teamsでやっていますが、通常のPower Appsでもほぼ同様にできます。
また、プレミアムコネクタなどの有料オプションは不要です。
SharePoint Listの作成
ファイルをアップロードするSharePointサイトを開き、サイトコンテンツから空白のリストを新規作成します。


今回はTestListという名前のリストを準備しました。
Power Appsでキャンパスアプリを作成
ここではSharePoint Uploadという名前の新規キャンパスアプリを作成します。

データソースにListを追加
続いてアプリのデータソースにSharePointリストを追加します。
データからデータの追加をクリックしてSharePointをクリックします。

接続の追加をクリックします。

直接接続で接続します。

SharePointのURLを入力して接続ボタンをクリックします。
URLはSharePointでホーム画面を開いた時のアドレスバーのURLをそのままコピーしてください。
一覧の選択が表示されたらTestListにチェックを入れて接続します。

下図のようにデータソースにTestListが表示されればOKです。

Attachmentコントロールの取得
続いてAttachmentコントロールを取得します。
といってもそんなコントロールはどこにもないのですが、

実は編集フォームの中にサブコントロールとして埋め込まれています。
で、この編集フォームの中にあるAttachmentコントロール(非公式名称)を取り出すためにはSharePointリストの連携が必要となります(実は最初のリスト作成はそのためだけのリストだったりします。実際にはリストの中にデータはたまっていきません)。
というわけで編集フォームを追加します。

データソースに先ほど連携したTestListを指定します。

そうすると編集フォームが下図のように変化します。今回利用するのは赤枠で囲っているAttachmentコントロールの部分だけです。

左のツリービューからフォームコントロールを展開していき、クリップマークのコントロールを切り取ります。

切り取りしたらキャンパス内の適当な位置に貼り付けます。
なにかエラーが出ていますが正常な反応(サブコントロールだけ抜き出したからデータソース連携が切れた)なので大丈夫です。

編集フォームはもう不要なので削除します(はやくも用済みでかわいそう)。

Attachmentコントロールにエラーが出ていますのでエラーを消していきます。
数式バーで編集をクリックして、エラーが出ているプロパティの値をすべて消していきます(下図の4か所)。

ついでにコントールの名前がわかりにくいのでAttachmentFilesに変更しておきます。

下図のような状態になればOKです。

続いてAttachmentFilesコントロールのOnAddFileとOnRemoveFileオプションに下記のコードを追加します。
ClearCollect(AttachmentCollection,AttachmentFiles.Attachments);
やっていることは、ファイルの添付または削除をしたときにAttachmentCollectionというCollect変数にAttachmentFilesコントロールのAttachmentsを代入しています。
ちなみに現時点でテスト実行すると、”ファイルを添付”という部分をクリックすることでファイル選択ダイアログが表示されます。

ここで複数のファイルを選択して”開く”ボタンをクリックすると、このようにPowerAppsの一時的な領域にファイルがアップロードされます。

この状態でAttachmentCollectionの中身を確認してみると、NameとValueという2つの要素があり、Nameにはファイル名が入っていることがわかります。

Valueは簡単に表現すると、PowerAppsアプリの一時的な保存領域を示すファイルパス(個人的にCプログラミングとかのポインタと近いイメージ)と考えてください。
Galleryコントロールの追加
少し難しい話ですが、PowerAppsに一時的に保存されたデータそのものを取り出すためにはImage形式で読み込むと取り出すことが可能です。
詳しい説明は省略(後日解説版記事を作成・・・予定)しますが、ここでの目標はGalleryコントロールを使ってImage形式に変換することです。
ということで垂直ギャラリーを追加します。

ギャラリーを追加したら、ギャラリーコントロールの名前をAttachmentGalleryに変更して、データソースをAttachmentCollectionに変更します。

すると、既定ではタイトル部分にAttachmentCollection.Nameが、サブタイトル部分にはAttachmentCollection.Valueが表示されます。

今回はPowerAppsに一時的に保存されたファイルのデータそのものにアクセスしたいため、ImageにAttachmentCollection.Valueを指定します。
ドロップダウンリストでは指定できないため、Imageコントロールを選択して直接、ImageプロパティにThisItem.Valueを指定します。

ここまででテストとしてアプリを実行して複数ファイルを添付すると下図のような表示になります。

なお、JPGやPNGやSVGといった画像ファイルをアップロードすると、ギャラリーコントロールのImageコントロールによって画像データそのものが表示されます。
それ以外のファイルの場合は画像の表示はなにもありませんが、見えないだけで実際にはファイルデータそのものが読み込まれています(ここが理解の難しいところですが・・・)。
フローの新規作成
先ほどのギャラリーコントロールによってPowerAppsへのファイルアップロードとアップロードしたファイルのデータへのアクセス手段が確立できたので、次はそのデータを受け取ってSharePointへ保存するフローを作成します。
設定はとりあえずスキップでOKです(後で追加します)。

フロー名をLocalFileUploadに設定して、トリガーからPowerApps(V2)を選択します。

ユーザー入力はJSONという形式のテキストだけをPowerAppsから取得する予定なので、テキストでJSONDataとします。

続いて作成ステップを追加してJSONDataを指定します。

ここでフローを一旦、保存しましょう。

アプリにフローを追加してButtonコントロールで実行
アプリの設定画面に戻って、Buttonコントロールを追加します。
TextはUpload Filesにしました。コントロールの名前もUploadFilesに変更しておきます。

UploadFilesボタンのOnSelectに下記のコードを設定します。
Clear(Base64DataCollection);//A
ForAll( //B
AttachmentGallery.AllItems,
Collect(
Base64DataCollection,{
Title:Title.Text,
Base64Data:Image.Image
}
)
);
Set(JSONData,JSON(Base64DataCollection,IncludeBinaryData));//C
Aの部分でBase64DataCollectionというコレクション変数のデータをすべて削除しています。
続いてBの部分でAttachmentGalleryのアイテムでForAllの繰り返し処理を行い、Base64DataCollectionのTitle要素にAttachmentGallery.Title.Textを、Base64Data要素にAttachmentGallery.Image.Imageを代入していきます。
そしてCの部分でコレクション変数からJSON形式のテキスト変数に変換してJSONDataという変数に代入しています。ここでIncludeBinaryDataを指定することで、JSONDataの中にBase64形式でエンコードされたファイルのバイナリデータが含まれます。
次に、フローの追加でアプリに先ほど作成したLocalFileUploadフローを追加します。

続いてUploadFilesボタンのOnSelectにフローを実行するコードを追記します。
引数には先ほど作成したJSONDataを指定します。
0KBテキストファイルのアップロード
続いて、ここまで作成したアプリを使って0(ゼロ)KBテキストファイルをアップロードします。
といっても、まだSharePointへデータ保存するフローのステップを作成していないので、実際にはSharePointへアップロードはされません。
目的としてはテストのためもありますが、JSONフォーマットを自動作成するのがメインの目的です。
後述しますが、すでにJSONフォーマットが作成済みであれば、ここでの作業は不要です。
ローカルPCのどこでもよいのでテキストファイルを作成します。今回はJSONフォーマットを入手したいだけなので内容にはなにも記述せず、0KBのテキストファイルとします。

つづいてアプリを実行して、ファイルを添付をクリックします。

ファイル選択ダイアログが表示されますので、先ほど作成した0KBテキストファイルを選択します。
すると下記画像のようになりますので、Upload Filesボタンをクリックします。

このあと、フローの実行結果からJSONフォーマットを作成します。
フローの実行結果からJSONフォーマットを作成
LocalFileUploadフローのダッシュボードを開き、先ほど実行した実行履歴を開きます。
状況がエラーとなっている、履歴が無いなどの場合はフローやPowerAppsの設定を見直してください。

作成ステップをクリックして、入力と出力どちらでも構わないので内容をすべてコピーしてテキストファイルなどに貼り付けます。
補足:ある程度容量のあるファイルをアップロードしていると、ここでのテキストがとても長くなるのでコピーの手間がかかります。MB単位のファイルだと、相当大変です。。。(経験済み)


続いてLocalFileUploadフローを編集します。
データ操作の中からJSONの解析ステップを追加します。

コンテンツにはJSONDataを指定して、スキーマはサンプルから生成ボタンをクリックします。
サンプルJSONペイロードの挿入画面が表示されたら、先ほどテキストファイルにコピーしたテキストをすべて貼り付けます。

完了をクリックすると、下図のようにスキーマが自動的に生成されます。

※JSONスキーマがすでに入手済みの場合は0KBテキストアップロードの作業は不要です。
ここまででフローは下図のようになります。

フローにSharePointへ保存するステップを追加
それではいよいよSharePointへ保存するステップを追加します。
SharePointからファイルの作成ステップを追加します。

ファイルアップロー先のサイトのアドレス、フォルダーのパスを指定します。
ドロップダウンリストなどから指定するとやりやすいです。


続いてファイル名にはJSONの解析で生成される動的コンテンツからTitleを選択します。
すると自動的にApply to eachが追加されます。
続いてファイルコンテンツをクリックして、式に下記のコードを入力してOKボタンを押します。
dataUriToBinary(items('Apply_to_each')['Base64Data'])

すると下図のようになります。

フローの全体像は下記のようになります。


テスト実行する
それではアプリを起動してテスト実行しましょう。もちろん、複数ファイルをアップロードしてみます。


SharePointで指定した場所にファイルがアップロードされているか確認します。

なお、既に存在する同じ名前のファイルを指定すると自動で上書きされます(上書き防止はまた別の機会に・・・)。
まとめ
編集フォーム、ギャラリーコントロールを利用すると複数ファイルをPowerAppsからSharePointにアップロードできます。
Image型にすると画像かどうかにかかわらずデータの中身が取得できることが慣れないポイント。
お願いだから専用コントロール作ってMi〇rosoft様
参考サイト
下記サイトで勉強させていただきました、ありがとうございました。
コルネの進捗や備忘録が記されたなにか 様
https://koruneko.hatenablog.com/entry/2021/07/07/021847
SPGuides.com 様
https://www.spguides.com/powerapps-upload-file-to-sharepoint-document-library/