HTMLを使って、Power Appsで参照用テーブルを作成するTips

# キャンバス アプリのコントロール数を抑えたい
`Power Apps`は簡単にアプリケーションが作成できる魅力的なサービスです。
サクっとできてしまうため、アイディアが出ればでるほど、**機能をモリモリ**にしてしまうこともしばしば。

しかしながら、コントロール数が多くなってしまうことは、様々な意味で課題があります。
メンテナンスが非常に大変になることももちろんですが、コントロール数には制限があったり、[1つのアプリに500を超えるコントロールを追加するような状態](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/performance-tips#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E6%95%B0%E3%81%AE%E5%88%B6%E9%99%90)は、望ましい状態ではありません。

https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/performance-tips#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E6%95%B0%E3%81%AE%E5%88%B6%E9%99%90

コントロール数が増えていくにつれて、Power Appsのパフォーマンスも低下し、UXにも影響がでます。可能であれば、最小限のパーツに揃えて構築していくほうが望ましいでしょう。

# HTMLテキストを活用する
個人的に良く遭遇するシーンが、`表形式`のコントロールの追加です。
表データってニーズが高いんですよね。（これ以上は言わない）

テーブルの表現は、Power Appsのコントロールに存在しています。

- [Power Apps での データ テーブル コントロール](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/control-data-table)
- [テーブル モダン コントロール (プレビュー)](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/modern-controls/modern-control-table)

しかし、[クラシック コントロールのデータ テーブル](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/control-data-table)は、コンテナーへ格納しづらかったり、[モダン コントロールは、プレビュー機能](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/modern-controls/modern-control-table)であることから、なかなか実装に踏み切りづらいときもあります。

使えるなら使いたいのですが、本当に悩みます。

:::note info
作者の個人的なアプリ作成では、モダン コントロールのテーブル一択です。
デザインも洗練され、機能も魅力的。
:::

**モダン コントロールのテーブルが如何に素敵なコントロールか、そちらは下記の記事を紹介させていただきます🐟**

https://qiita.com/Takashi_Masumori/items/78cb22abab713c004c83

https://youseibubu.com/apps/modern_table/

https://powerplatformnikki.com/moderntablecontrol/#google_vignette

## ギャラリーで表を描画する🧐
`垂直ギャラリー`に、`テキスト ラベル`を整頓してテーブルらしく描画することもできます。
この手法は、テーブルの列に応じて、`テキスト ラベル`が必要で、あまりスタイリッシュとは言い難いでしょう。

前述で書いたような、コントロール数がかさむアンチパターンと思っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/a31b2cb7-e2bd-cbd4-0289-ca35ee9d9acb.png)

たった4列でもコントロール数が10個と多い・・・💦

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/69a67ba3-8fbe-8291-9fc6-796dacdbb638.png)

作るのも正直手間です。

# HTML テキスト コントロールを使う
ここで登場するコントロールが、[HTML テキスト コントロール](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/control-html-text)です。

HTML 文字列で一つのコントロールから表を描画することができます。
文字列をどう作っていくか、そのアプローチが肝になるので、
1. [Power Automateを経由して作成する](https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc#power-automate%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E6%93%8D%E4%BD%9C%E3%81%8B%E3%82%89%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)
1. [Power Appsの中で作成する](https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc#power-apps%E3%81%AE%E9%96%A2%E6%95%B0%E3%81%A7%E5%B7%A5%E5%A4%AB%E3%81%99%E3%82%8B)

上記の二パターンを考えてみました。

## Power Automateのデータ操作から文字列を取得する
私のブログで登場する架空の従業員リスト(SharePoint Lists)を使って検証します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/86817b43-056d-baaa-ed6b-9b5634ace358.png)

この中から、`UserId（タイトル列）`、`user`、`department`,`post`を使って、テーブルの元データを作成します。

:::note warn
列名・内部名のひどさには、目をつむっていただけると幸いです🙇
:::


```javascript:Items
ForAll(
    Users, // 元のデータソースの名前
    {
        Name: user.DisplayName, // ユーザー列からDisplayNameのみ抽出
        Title: タイトル,
        Department: department, // 選択肢列から値のみ抽出
        Post: post.Value
    }
)
```

このデータを[JSON 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#json)でPower Automateに渡して、データ操作アクションを経由します。
- [JSON の解析](https://qiita.com/DEmodoriGatsuO/items/7cf3832e5e90dc576360)
- [HTML テーブルの作成](https://learn.microsoft.com/ja-jp/power-automate/data-operations#use-the-create-html-table-action)

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

[JSON の解析](https://qiita.com/DEmodoriGatsuO/items/7cf3832e5e90dc576360)と[JSON 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#json)のコンボは、もはや御用達ですね。

https://qiita.com/DEmodoriGatsuO/items/7cf3832e5e90dc576360

Power AppsからJSON文字列を受け取り

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/ca27836e-14cc-ab29-58c1-5078699eceff.png)

[JSON の解析](https://qiita.com/DEmodoriGatsuO/items/7cf3832e5e90dc576360)と[JSON 関数](https://learn.microsoft.com/ja-jp/azure/logic-apps/workflow-definition-language-functions-reference#json)を実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/cbc60ca8-b213-0279-6cdf-ec9e56abae81.png)

```json:Schema
{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "Department": {
                "type": [
                    "string",
                    "null"
                ]
            },
            "Name": {
                "type": [
                    "string",
                    "null"
                ]
            },
            "Post": {
                "type": [
                    "string",
                    "null"
                ]
            },
            "Title": {
                "type": [
                    "string",
                    "null"
                ]
            }
        },
        "required": [
            "Department",
            "Name",
            "Post",
            "Title"
        ]
    }
}
```

:::note info
`null`対策を忘れずに！
:::

`body('Parse_JSON')`をもとに、HTMLテーブルを作成。
列を明示的に指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/5d085771-0ac4-df05-0c66-d19468252e83.png)

```json:コード ビュー
{
  "type": "Table",
  "inputs": {
    "from": "@body('Parse_JSON')",
    "format": "HTML",
    "columns": [
      {
        "header": "タイトル",
        "value": "@item()['Title']"
      },
      {
        "header": "Name",
        "value": "@item()['Name']"
      },
      {
        "header": "Department",
        "value": "@item()['Department']"
      },
      {
        "header": "Post",
        "value": "@item()['Post']"
      }
    ]
  },
  "runAfter": {
    "Parse_JSON": [
      "Succeeded"
    ]
  },
  "metadata": {
    "operationMetadataId": "90accf8f-b3e8-4d8d-8098-4f1a76f39810"
  }
}
```

結果を`body('Create_HTML_table')`として`Power Apps`に戻します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/ee48dbc7-e8f3-c87a-4413-119015c9a686.png)

`Power Apps`では`ボタン コントロール`に下記を仕込みます。

```javascript:OnSelect
UpdateContext(
    {
        Response: GetHTML.Run(
            JSON(
                ForAll(
                    Users,
                    {
                        Name: user.DisplayName,
                        Title: タイトル,
                        Department: department,
                        Post: post.Value
                    }
                )
            )
        ).response
    }
)
```
上記の式で`Response`に`HTML`が反映されます。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/aca36cad-030d-192d-58c1-c9db73806402.png)

[HTML テキスト コントロール](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/control-html-text)の`HtmlText`は`Response`です。
罫線がないですが、表現はされます。`Power Automate`上でサクっと作れるのは嬉しいところ。

`<table border='1'>`で罫線を表示することはできますが、どこで処理するかは悩みどころ。

[Substitute 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-replace-substitute)で下記のようにタグを書き換えると、罫線の追加はできます。

```javascript:HtmlText
Substitute(Response,"<table>","<table border='1' cellpadding='10' cellspacing='0'>")
```

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-replace-substitute

## Power Appsの関数で工夫する
そもそもこれは`Power Automate`が必要な動作なのか・・・！！
`文字列の加工`なので、`Power Fx`の範疇で出来そうです。

1. `テーブル データ`を`コレクション`に格納する
1. `コンテキスト変数`に`ヘッダー`と`ボディ`を格納する
1. `HTML テキスト コントロール`に設定する

上記のアプローチを試みてみます。

```javascript:ヘッダーとボディの作成
// 1. テーブル データをコレクションに格納する
ClearCollect(
    colHTML,
    ForAll(
        Users,
        {
            Name: user.DisplayName,
            Title: タイトル,
            Department: department,
            Post: post.Value
        }
    )
);

// コンテキスト変数にヘッダーとボディを格納する
UpdateContext(
    {
        Header: "<tr><th>Title</th><th>Name</th><th>Department</th><th>Post</th></tr>",
        Body: Concat(
        colHTML,
            $"<tr><td>{Name}</td><td>{Title}</td><td>{Department}</td><td>{Post}</td></tr>"
        )
    }
);
```

`$（文字列補間）`は[最近ブログで紹介させていただきました！](https://qiita.com/DEmodoriGatsuO/items/84a5edae4cdb5db60764)
**式がスッキリして良いですね！**

https://qiita.com/DEmodoriGatsuO/items/84a5edae4cdb5db60764

[Concat 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concatenate)と組み合わせて、必要な部分にデータを挿入しています。

`HTML テキスト コントロール`に下記を挿入すると、[Power Automateで作成できた同じ表データ](https://qiita.com/DEmodoriGatsuO/items/a160994360cb34399fdc#power-automate%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E6%93%8D%E4%BD%9C%E3%81%8B%E3%82%89%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)が作成できます！

```javascript:HTMLText
$"<table border='1' cellpadding='10' cellspacing='0'>{Header}{Body}</table>"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/9454c819-c07d-de6d-97d9-5d4b55218b0a.png)

また[$（文字列補間）](https://qiita.com/DEmodoriGatsuO/items/84a5edae4cdb5db60764)が登場しましたね！[Concat 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concatenate)との組み合わせでバリューを発揮しそうな雰囲気がまだまだありそうです！

https://qiita.com/DEmodoriGatsuO/items/84a5edae4cdb5db60764

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concatenate

# おわりに
自分のこだわりだったり、ユーザーの要望を反映していくと、コントロール数はどうしても増えてしまう傾向にあります。
また作ることも非常に手間だったりと、ネガティブな影響が大きいです。

`HTML`となるとノーコード・ローコードから離れそうな印象もありますが、活用することで、コントロール数をかなり抑えられる恩恵もあります。

ほかにも`Tips`がありますので、今後のブログにもご期待ください！