Power Automateを使って画像列の設定を含めたリスト作成を実行する

# はじめに
Power Appsを作るとき、画像データ込みの*SharePoint List*を使用するシーンがあると思います。
SharePoint List自体は、グリッドビューを使うことで、**「ExcelからCopy & Paste」**、
**「CSVやExcelのUpload」** で、サクッと入力できますが、
画像を挿入するとなると、都度都度、**画面からファイルを選択する** といった手間な作業になります。

Power AutomateのSharePointアクション **SharePoint に HTTP 要求を送信** で自動化が実現できます。

## 参考にさせていただいた記事

[Hiro (id:mofumofu_dance)](https://mofumofupower.hatenablog.com/entry/update_image_field)さんのBlogを大いに参考にさせていただきました。

https://mofumofupower.hatenablog.com/entry/update_image_field

 - ***Microsoft Reference***

https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest

このアクションを使って、**リスト作成の自動化** の例を紹介させてください。

# 準備
まず初めに今回実現することを整理します。
手順は下記の通り

1. 画像を準備、リネームをしておく
1. SharePointの **サイトのリソースファイル > Lists** こちらにアップロードしたい画像ファイルをアップロード
1. SharePointのリストの列をあらかじめ設定しておく
1. 画像以外の入力値を **Excel Onlineのファイル**に予め入力しておく

## 1. 画像を準備、リネーム
まずは画像を用意しておきましょう。
拡張子は統一し、主キーの役割が担う文字列にします。
今回は、50件のレコードが格納されるリストの予定です。

ファイル名は「S001.jpeg」「S002.jpeg」・・・といったように一意の内容にします。
**"拡張子の統一"と"上記の規則性"があることで、Loop処理しやすいように設計します。**

ファイルのリネームが面倒だったら、簡単なPythonのコード紹介します。
それかPower Automate for desktopを使いましょう。

```Python:rename.py
import os
import glob

i = 1
path = r"C:\Users\####\####\####\####\*.jpeg"
files = glob.glob(path)


for f in files:
    # フォルダが異なる場合は工夫しましょう
    # まずこのPyファイルが格納されたディレクトリでリネームすることを想定しています
    os.rename(f,"S" + str(i).zfill(3) + ".jpeg")
    i += 1
```
 - 下記の様な状態にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/87af81da-5d4a-9f9e-71e1-db480097db68.png)


# 2. SharePointの **サイトのリソースファイル > Lists** に画像ファイルをアップロード
SharePointのListに表示される画像ファイルはこちらに保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/9aab43a8-3a81-a75b-02cc-fbb9ef889337.png)

Photoというフォルダを作り、画像のアップロード先にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/323f8397-2e74-1683-c146-257d4e0c8ce5.png)

ファイルのアップロードは **ドラッグで一括選択、アップロードが可能です。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/711ecb02-d1c9-726b-544f-3f4d2261f965.png)

## 3. SharePointのリストの列をあらかじめ設定しておく
次にリストをあらかじめ設定しておきます。

|タイトル|Name|Furigane|Photo
|---|---|---|---
|主キー|1行テキスト|1行テキスト|画像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/16b4dd61-db06-4ec1-01fe-34697ad09ae7.png)


このようなイメージになります。
列名を英語にしている理由は、Power Appsなど展開する際に適しているからです。

:::note warn
内部名がエンコードされた文字列になり、参照がややこしくなります
:::

## 4. 画像以外の入力値を **Excel Onlineのファイル**に予め入力しておく
後述する`SharePointへのHTTPアクション`で、 ***レコードをpushしていく方法で進めます。***

 - テーブル - 情報は全てダミー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/96c5c03e-b55b-b6d0-b1db-29c0cee4fba8.png)

Power Automateの作成をスムーズに進めるために、SharePointの列名と同名にしています。
リレーションを認識しやすくするために、この設定にしております。

**ここまでが下準備です。**

# Power Automateを使って画像列の設定を含めたリスト作成のフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/9c86e57e-01da-c1e7-9a3d-1cba77980405.png)

1. Excel Onlineからテーブルのレコードをすべて取得しておく

1. 後工程でString型の変数が必要になるので宣言しておく
1. 定数的にSharePointのFilePathを取得しておく
    - 大切なポイントとして、パスの指定について`/ → %252f`に変換するプロセスがあるので、先に変換しておく
1. **テーブルの行数に応じたLoop処理を実施する**
    1. ファイル名`拡張子`の文字列を設定

    1. 画像列にPushする画像データのIDを取得するために **「ファイル メタデータの取得」**
    1. 上記のアクションで取得したETAGからIDを取得する
        - ここについては下記のブログを参照されることをお勧めします。
        - SharePoint リストの画像列に Power Automate からアクセスする方法
https://mofumofupower.hatenablog.com/entry/update_image_field
    1. HTTP要求のために **文字列用の変数に、Image用のオブジェクトを挿入する**
        - 文字列型変数ではない場合、適切なJSONではないとErrorが発生する
    1. **SharePointへのHTTP要求を送信する**

## 詳細
まず`2023.01.27`時点ですが、画像列に画像データを挿入するアクションは見当たらず、
HTTP要求による対処を余儀なくされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/c5553c05-fade-913b-2b47-1c6e87710cf0.png)

HTTP要求 `POST`メソッドも難解なものではないですが、`ポイントはあくまでImageの挿入です。`
ざっくりと説明すると下記の様なオブジェクトを挿入することになります。

```JSON:Format
{
    "type": "thumbnail",
    "fileName": "----.jpeg",
    "nativeFile": {},
    "fieldName": "Photo",
    "serverUrl": "https: //####.sharepoint.com",
    "fieldId": "## fieldのid ##",
    "serverRelativeUrl": "/sites/## endPoint ##/SiteAssets/Lists/## サイトの格納先のフォルダ名 ##/----.jpeg",
    "id": "##画像のETAG ID##"
}
```

 - 画像のETAG IDの抽出の仕方 - 関数の例 - ブログから引用
```
@toLower(replace(split(outputs('ファイル_メタデータの取得')?['body/ETag'],'}')?[0],'\"{',''))
```

しかしながら上記のオブジェクトを挿入するうえでの課題として、エスケープ文字が含まれたフォーマットになっており、
単純な書き方にはなりません。

```
"{\\\"type\\\":\\\"thumbnail\\\",\\\"fileName\\\":\\\"----.jpeg\\\",\\\"nativeFile\\\":{},\\\"fieldName\\\":\\\"Photo\\\",\\\"serverUrl\\\":\\\"https://####.sharepoint.com\\\",\\\"serverRelativeUrl\\\":\\\"/sites/## endPoint ##/SiteAssets/Lists/## サイトの格納先のフォルダ名 ##/----.jpeg"\\\",\\\"id\\\":\\\"##画像のETAG ID##"}\\\"}"
```
見ているだけで目が痛くなりそうです・・・。
また入力するにもミスが起こりやすい課題もあります。

その場合は、`GET Method`であらかじめレコードの構成を見ておくと、書きやすくなります。

 - 別でフローを作って確認することをおすすめします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/31b5d58e-d5d5-f25d-4785-8225cd454df9.png)

 - 紹介したブログに内容が凝縮されております！

# Flowについて
`Apply to each`を使っているため挙動時間が遅そうに感じますが、とても速いです！
30秒で完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/eb29d008-dd16-2c70-5473-bf6273150112.png)

Microsoft様の進化は、とてつもなく速いので、この方法も必要なくなるかもしれませんが、
現在の対策として紹介させていただきました🙇

# Result
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/e96a860a-0cd4-d014-dc30-8a92755f0835.png)

**これがパっと作れるのは嬉しい！**

画像込みで展開できる方法として、スムーズにできる方法として紹介させていただきました。
**Power Apps** で画像参照したアプリを作るうえで便利ですので、その際にご利用ください！

実際私はこんなものを作りました！

https://note.com/bonito_vba_gas/n/nbf0415ebc1f3

👆のnoteの状況とは異なり、base64文字列形式からSharePointのList参照に変えています。