SharePoint Lists（画像あり）から画像入りHTMLファイルを作成する - Power Automate

# はじめに
定期的に`テーブル`を作成したくなる。
それが私です。

[Qiita Engineer Festa 2024](https://qiita.com/official-campaigns/engineer-festa/2024)が始まってから`Power Apps`や`Power Automate`で、`HTML`を駆使したテーブル作成してきました。

 - [HTMLを使って、Power Appsで参照用テーブルを作成するTips](https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc)
 - [親の顔より見たテーブルをHTMLで再現する](https://qiita.com/DEmodoriGatsuO/items/74754ba0ad1e4d7b6a20)

https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc

https://qiita.com/DEmodoriGatsuO/items/74754ba0ad1e4d7b6a20

今回は`SharePoint Lists（画像あり）`から画像込みの`HTML`テーブルを作成します。

ニーズは鑑みておりません。**プレミアムコネクタなしで使える技です。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/e8474de9-fed5-1609-e7e1-d5a2673a308a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/eb8faf18-60df-5d7a-0fc8-f5360b446344.png)

`SharePoint Lists（画像あり）`は下記を利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/85612bdb-81b5-abb7-6395-4ef980c82258.png)

列は下記に絞りました。
 - Title
 - Artist
 - Country
 - Art(画像列)

上記で`HTML`を作成します。
列を限定している理由は単純に多いと手間も比例することからです。

## アプローチ
今回は実験のため`SharePoint Lists` to `HTML`ファイルで実験します。

■ 手順
1. 変数を初期化する `HTML`文字列を格納する変数
1. [複数の項目の取得](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-items)　`SharePoint`
1. `For each`
    1. [SharePoint に HTTP 要求を送信します](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#send-an-http-request-to-sharepoint) 画像列情報を取得
    1. 3-1で[JSON の解析](https://learn.microsoft.com/ja-jp/power-automate/data-operations)
    1. 3-2の`画像列`から[JSON の解析](https://learn.microsoft.com/ja-jp/power-automate/data-operations)
    1. 3-3をもとに[パスによるファイル コンテンツの取得](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-file-content-using-path)
    1. `<td>`など`タグ`文字を含めて、`1`の文字列変数に追加
1. `</table>`を追加 `文字列変数に追加`
1. [ファイルの作成](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#create-file) `SharePoint`

https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-items

https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#send-an-http-request-to-sharepoint

https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-file-content-using-path

https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#create-file

::: note info
このアプローチでは`SharePoint`にHTMLファイルを作成しています。
`OneDrive for Business`を使えば、[ファイルの変換](https://learn.microsoft.com/ja-jp/connectors/onedriveforbusiness/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%A4%89%E6%8F%9B-(%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC))アクションで画像やPDFに変換することも可能です。
:::

https://learn.microsoft.com/ja-jp/connectors/onedriveforbusiness/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%A4%89%E6%8F%9B-(%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC)

### 1. 変数を初期化
まずは`HTML`を追加していくための変数を用意します。

```html:変数を初期化する HTML
<table border="1" cellpadding="10" cellspacing="0"><tr><th>Title</th><th>Artist</th><th>Country</th><th>Image</th></tr>
```

セルのパディングとヘッダーをここで決め打ちしてしまっています。
列数を増やす場合は、ここで既定してください。
動的な対処もできそうですが、今回は割愛で！

### 2. [複数の項目の取得](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-items)から`繰り返し処理`

特にフィルタークエリを決めずに[複数の項目の取得](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-items)を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/9d5b592d-c175-2751-1716-407540f94c9b.png)

この時のポイントですが、**このアクションで画像列の情報は取得できません。**
**添付ファイル**であれば、別のアクションで取得することができます。
 - 画像の`ファイル コンテンツ`
 - 画像の`ソース`

上記のいずれかがないと実行できないアクションになります。

### 3~. 繰り返し処理で画像を`base64`文字列で取得、HTML文字列に追加
まずはファイルコンテンツを取得するために、画像列の詳細が必要になります。
そのため、(2)で取得したListのIDから[SharePoint に HTTP 要求を送信します](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#send-an-http-request-to-sharepoint) 画像列情報を取得しましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b40a1a8b-d6af-bfec-341e-bff714015d7f.png)

 - サイトのアドレス `ListがあるSharePoint Site`
 - 方法 `Get`
 
```plaintext:URI
_api/web/lists/GetByTitle('{SharePoint Listsの名前}')/items(@{items('For_each')?['ID']})
```
 
こちらで画像列を含めた情報が返ってきます。
`JSON の解析`を実行すると私の場合、下記のスキーマになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/40cb6712-01d0-a561-e527-ecc0fd6ba6b6.png)

<details><summary>長いので折りたたみ</summary>

```json:schema
{
    "type": "object",
    "properties": {
        "statusCode": {
            "type": "integer"
        },
        "headers": {
            "type": "object",
            "properties": {
                "Cache-Control": {
                    "type": "string"
                },
                "Transfer-Encoding": {
                    "type": "string"
                },
                "ETag": {
                    "type": "string"
                },
                "Vary": {
                    "type": "string"
                },
                "Set-Cookie": {
                    "type": "string"
                },
                "Strict-Transport-Security": {
                    "type": "string"
                },
                "X-NetworkStatistics": {
                    "type": "string"
                },
                "X-SharePointHealthScore": {
                    "type": "string"
                },
                "X-SP-SERVERSTATE": {
                    "type": "string"
                },
                "DATASERVICEVERSION": {
                    "type": "string"
                },
                "SPClientServiceRequestDuration": {
                    "type": "string"
                },
                "SPRequestDuration": {
                    "type": "string"
                },
                "X-DataBoundary": {
                    "type": "string"
                },
                "X-1DSCollectorUrl": {
                    "type": "string"
                },
                "X-AriaCollectorURL": {
                    "type": "string"
                },
                "SPRequestGuid": {
                    "type": "string"
                },
                "Request-Id": {
                    "type": "string"
                },
                "MS-CV": {
                    "type": "string"
                },
                "X-Frame-Options": {
                    "type": "string"
                },
                "Content-Security-Policy": {
                    "type": "string"
                },
                "MicrosoftSharePointTeamServices": {
                    "type": "string"
                },
                "X-Content-Type-Options": {
                    "type": "string"
                },
                "X-MS-InvokeApp": {
                    "type": "string"
                },
                "P3P": {
                    "type": "string"
                },
                "X-AspNet-Version": {
                    "type": "string"
                },
                "X-Powered-By": {
                    "type": "string"
                },
                "x-ms-request-id": {
                    "type": "string"
                },
                "Timing-Allow-Origin": {
                    "type": "string"
                },
                "x-ms-apihub-cached-response": {
                    "type": "string"
                },
                "x-ms-apihub-obo": {
                    "type": "string"
                },
                "Date": {
                    "type": "string"
                },
                "Content-Type": {
                    "type": "string"
                },
                "Content-Length": {
                    "type": "string"
                },
                "Expires": {
                    "type": "string"
                },
                "Last-Modified": {
                    "type": "string"
                }
            }
        },
        "body": {
            "type": "object",
            "properties": {
                "d": {
                    "type": "object",
                    "properties": {
                        "__metadata": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string"
                                },
                                "uri": {
                                    "type": "string"
                                },
                                "etag": {
                                    "type": "string"
                                },
                                "type": {
                                    "type": "string"
                                }
                            }
                        },
                        "FirstUniqueAncestorSecurableObject": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "RoleAssignments": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "AttachmentFiles": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "ContentType": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "GetDlpPolicyTip": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "FieldValuesAsHtml": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "FieldValuesAsText": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "FieldValuesForEdit": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "File": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "Folder": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "LikedByInformation": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "ParentList": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "Properties": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "Versions": {
                            "type": "object",
                            "properties": {
                                "__deferred": {
                                    "type": "object",
                                    "properties": {
                                        "uri": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        },
                        "FileSystemObjectType": {
                            "type": "integer"
                        },
                        "Id": {
                            "type": "integer"
                        },
                        "ServerRedirectedEmbedUri": {},
                        "ServerRedirectedEmbedUrl": {
                            "type": "string"
                        },
                        "ContentTypeId": {
                            "type": "string"
                        },
                        "Title": {
                            "type": "string"
                        },
                        "OData__ColorTag": {},
                        "ComplianceAssetId": {},
                        "field_1": {
                            "type": "string"
                        },
                        "field_2": {
                            "type": "string"
                        },
                        "field_3": {
                            "type": "string"
                        },
                        "field_4": {
                            "type": "string"
                        },
                        "field_5": {
                            "type": "string"
                        },
                        "field_6": {
                            "type": "string"
                        },
                        "field_7": {
                            "type": "string"
                        },
                        "field_8": {
                            "type": "string"
                        },
                        "field_9": {
                            "type": "string"
                        },
                        "Art": {
                            "type": "string"
                        },
                        "ID": {
                            "type": "integer"
                        },
                        "Modified": {
                            "type": "string"
                        },
                        "Created": {
                            "type": "string"
                        },
                        "AuthorId": {
                            "type": "integer"
                        },
                        "EditorId": {
                            "type": "integer"
                        },
                        "OData__UIVersionString": {
                            "type": "string"
                        },
                        "Attachments": {
                            "type": "boolean"
                        },
                        "GUID": {
                            "type": "string"
                        }
                    }
                }
            }
        }
    }
}
```

</details>

このうち画像列である`Art`は入れ子になった`JSON文字列`です。
そのため、画像列を抜き出し、改めて`JSON の解析`を実行します。
 - Content `body('JSON_の解析_本文')?['d']?['Art']`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/9fff1cb3-de02-1dc6-0832-3aa4d49a2dfd.png)

スキーマはコチラ。

```json:schema
{
    "type": "object",
    "properties": {
        "type": {
            "type": "string"
        },
        "fileName": {
            "type": "string"
        },
        "nativeFile": {
            "type": "object",
            "properties": {}
        },
        "fieldName": {
            "type": "string"
        },
        "serverUrl": {
            "type": "string"
        },
        "fieldId": {
            "type": "string"
        },
        "serverRelativeUrl": {
            "type": "string"
        },
        "id": {
            "type": "string"
        }
    }
}
```

ここに`serverUrl`と`serverRelativeUrl`が書かれているため、画像列のパスが取得できます。
ここから[パスによるファイル コンテンツの取得](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#get-file-content-using-path)を実行すると画像の`ファイル コンテンツ`を取得することまでできます。

パスは`serverUrl`と`serverRelativeUrl`を結合すると完全パスになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/1034e2f3-773c-9f44-bd09-d5d099f0d6b3.png)

あとは`HTML`文字列に追加するだけです。
`HTML`文字列に追加する場合は、`base64`文字列で値を設定します。

```html:文字列変数に追加
<tr><td>@{item()?['Title']}</td><td>@{item()?['field_1']}</td><td>@{item()?['field_8']}</td><td><img src="data:image/jpeg;base64,@{base64(body('パスによるファイル_コンテンツの取得'))}"</td></tr>
```

:::note info
リストの列名はテキトウになってしまいました💦
:::

https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#base64

こちらで文字列による画像の表現をする準備ができました。

`</table>`でタグを閉じて

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/31076c68-522d-b75c-2675-c0de7cce66e7.png)

準備した文字列をもとに[ファイルの作成](https://learn.microsoft.com/ja-jp/sharepoint/dev/business-apps/power-automate/sharepoint-connector-actions-triggers#create-file) を実行すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b395eb0a-979a-46d6-ec24-ad87331e3917.png)

**SharePoint ListsからHTMLファイルに画像を起こせます🙌**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/f11570e8-6965-789e-5d6f-dd0c970e253c.png)

見づらい💦

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/b4269d05-8e90-bd8f-268b-530089c9c05e.png)

この方法を応用すると`画像`や`PDF`に情報の変換まで見込めます。
どこで使うかわからないですが、`base64`文字列ってこんなことにも使えるのか・・・と覚えておくことにしましょう。

今回もお付き合いいただきありがとうございました！