親の顔より見たテーブルをHTMLで再現する

# 親の顔より見たテーブル

このデザイン見たことある!!

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">どう見てもExcelの標準書式のテーブル <a href="https://t.co/rTABnUNn9c">pic.twitter.com/rTABnUNn9c</a></p>&mdash; 出戻りガツオ🐟 Microsoft MVP (@DemodoriGatsuo) <a href="https://twitter.com/DemodoriGatsuo/status/1802285458736742473?ref_src=twsrc%5Etfw">June 16, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

:::note info
なんか盛り上がりました🔥
:::


そう思ったそのデザインは、`Excel`や`PowerPoint`でお馴染みの標準書式の`テーブル`でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/8e49feb0-5085-4a79-fe1f-2a37f5762bdc.png)

 - ヘッダー
     - 濃い青`#4472C4`
     - 文字は白`#ffffff`
 - ボディ
     - データ行の交互に背景色が異なる縞模様
     - 偶数行
         - 濃い青`#cfd5ea`
     - 奇数行`#e9ebf5`
     - 境界線は白`#ffffff`
     - 文字色は黒白`#000000`

**伝統的なスタイルですね。**

このデザインのテーブルを`Power Apps`でも再現したい!!ということで、完全に無駄ですが再現に挑戦してみたいと思います

# PowerPointを調査する
まずは、このテーブルの詳細を調べましょう。

`PowerPoint`で表を挿入すると・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/c3d8d0e4-099a-4775-3898-d8d3c9865bbf.png)

シックなテーブルになってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/01ae6078-f365-dcac-52ed-f74644773ccf.png)

これが今の`Office テーマ`なんですね。
時代の変化を感じます。

:::note info
執筆時点は2024.06.17
:::

私が`親の顔より見た書式`は`Office 2013-2022 テーマ`のようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/09dfe93d-8f39-a3f9-8600-43b88cbd4e97.png)

こちらを指定すると、既定のテーブルはお馴染みのデザインになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/d68c6281-03ea-6e75-dac8-e8e9922e7884.png)

詳細を覗いてみると、ヘッダーの塗りつぶしは`#4472C4`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/ec391460-50ff-8b3b-95bb-aaec534780b3.png)

奇数行の塗りつぶしは`#cfd5ea`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/c51965b3-80d0-b89c-cfd5-9abbad41188f.png)

偶数行の塗りつぶしは`#e9ebf5`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/d8483cce-cf6f-3a85-857e-2618be152f85.png)

となっているようです。

# Power Appsで再現する
こんな感じになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/702a2a0b-2caf-f8fd-0304-b1c06220f643.png)

```html:HtmlText
<table style='width:100%; border-collapse: collapse;'>
    <thead>
        <tr>
            <th style='border: 1px solid #fff; padding: 8px; text-align: center; background-color: #4472C4; color: #fff;'>商品分類</th>
            <th style='border: 1px solid #fff; padding: 8px; text-align: center; background-color: #4472C4; color: #fff;'>数量</th>
            <th style='border: 1px solid #fff; padding: 8px; text-align: center; background-color: #4472C4; color: #fff;'>金額</th>
        </tr>
    </thead>
    <tbody>
        <tr style='background-color: #cfd5ea;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>黄皿(120)</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>4</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥480</td>
        </tr>
        <tr style='background-color: #e9ebf5;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>赤皿(180)</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>6</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥1,080</td>
        </tr>
        <tr style='background-color: #cfd5ea;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>黒皿(260)</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>1</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥260</td>
        </tr>
        <tr style='background-color: #e9ebf5;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>白皿(100)</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>5</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥500</td>
        </tr>
        <tr style='background-color: #cfd5ea;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>130一品</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>3</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥390</td>
        </tr>
        <tr style='background-color: #e9ebf5;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>150一品</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>2</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥300</td>
        </tr>
        <tr style='background-color: #cfd5ea;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>360一品</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>1</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥360</td>
        </tr>
        <tr style='background-color: #e9ebf5;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>200お椀</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>2</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥400</td>
        </tr>
        <tr style='background-color: #cfd5ea;'>
            <td style='border: 1px solid #fff; padding: 8px; text-align: left;'>450ラーメン</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>2</td>
            <td style='border: 1px solid #fff; padding: 8px; text-align: right;'>¥900</td>
        </tr>
    </tbody>
</table>
```

`style`をタグに何度も書くのが手間ですね。
ある程度やむなしですが、これでは再現性がありません。

## 固定的な文字列は[App.Formulas](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/object-app#formulas-property)に書き込んで、`定数`として扱いましょう。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/object-app#formulas-property

https://qiita.com/DEmodoriGatsuO/items/4d023dec427555014734

https://qiita.com/PowerPlatform4/items/64e5279958241fdef4c3

[App.Formulas](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/object-app#formulas-property)に、固定的な`HTML`文字列を下記のように設定しておくと

```javascript:App.Formulas
tblProperties = {
    startTh: "<th style='border: 1px solid #fff; padding: 8px; text-align: center; background-color: #4472C4; color: #fff;'>",
    endTh: "</th>",
    tdTextAlignLeft: "<td style='border: 1px solid #fff; padding: 8px; text-align: left;'>",
    tdTextAlignRight: "<td style='border: 1px solid #fff; padding: 8px; text-align: right;'>",
    endTd: "</td>"
};
```

[$ (文字列補間)](https://qiita.com/DEmodoriGatsuO/items/84a5edae4cdb5db60764)を活用することで、少しはましにはなります。

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

```html:HtmlText
$"<table style='width:100%; border-collapse: collapse;'>
    <thead>
        <tr>
            {tblProperties.startTh}商品分類{tblProperties.endTh}
            {tblProperties.startTh}数量{tblProperties.endTh}
            {tblProperties.startTh}金額{tblProperties.endTh}
        </tr>
    </thead>
    <tbody>
        <tr style='background-color: #cfd5ea;'>
            {tblProperties.tdTextAlignLeft}黄皿(120){tblProperties.endTd}
            {tblProperties.tdTextAlignRight}4{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥480{tblProperties.endTd}
        </tr>
        <tr style='background-color: #E9EBF5;'>
            {tblProperties.tdTextAlignLeft}赤皿(180){tblProperties.endTd}
            {tblProperties.tdTextAlignRight}6{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥1,080{tblProperties.endTd}
        </tr>
        <tr style='background-color: #cfd5ea;'>
            {tblProperties.tdTextAlignLeft}黒皿(260){tblProperties.endTd}
            {tblProperties.tdTextAlignRight}1{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥260{tblProperties.endTd}
        </tr>
        <tr style='background-color: #E9EBF5;'>
            {tblProperties.tdTextAlignLeft}白皿(100){tblProperties.endTd}
            {tblProperties.tdTextAlignRight}5{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥500{tblProperties.endTd}
        </tr>
        <tr style='background-color: #cfd5ea;'>
            {tblProperties.tdTextAlignLeft}130一品{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}3{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥390{tblProperties.endTd}
        </tr>
        <tr style='background-color: #E9EBF5;'>
            {tblProperties.tdTextAlignLeft}150一品{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}2{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥300{tblProperties.endTd}
        </tr>
        <tr style='background-color: #cfd5ea;'>
            {tblProperties.tdTextAlignLeft}360一品{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}1{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥360{tblProperties.endTd}
        </tr>
        <tr style='background-color: #E9EBF5;'>
            {tblProperties.tdTextAlignLeft}200お椀{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}2{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥400{tblProperties.endTd}
        </tr>
        <tr style='background-color: #cfd5ea;'>
            {tblProperties.tdTextAlignLeft}450ラーメン{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}2{tblProperties.endTd}
            {tblProperties.tdTextAlignRight}¥900{tblProperties.endTd}
        </tr>
    </tbody>
</table>
"
```

# 動的な作成に対処する
直書きすると格好が悪くなりますが、`Power Apps`の`コレクション`に対応させる場合はどうなるでしょうか。

同じ`テーブルデータ`を`コレクション`に格納する式はコチラです。

```javascript:OnSelect
ClearCollect(
    colHTMLTable,
    Table(
        {
            商品分類: "黄皿(120)",
            数量: 4,
            金額: "¥480"
        },
        {
            商品分類: "赤皿(180)",
            数量: 6,
            金額: "¥1,080"
        },
        {
            商品分類: "黒皿(260)",
            数量: 1,
            金額: "¥260"
        },
        {
            商品分類: "白皿(100)",
            数量: 5,
            金額: "¥500"
        },
        {
            商品分類: "130一品",
            数量: 3,
            金額: "¥390"
        },
        {
            商品分類: "150一品",
            数量: 2,
            金額: "¥300"
        },
        {
            商品分類: "360一品",
            数量: 1,
            金額: "¥360"
        },
        {
            商品分類: "200お椀",
            数量: 2,
            金額: "¥400"
        },
        {
            商品分類: "450ラーメン",
            数量: 2,
            金額: "¥900"
        }
    )
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/eb3fa3f1-5615-07d7-4d29-bd33c7ad2766.png)

こちらを[Concat 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concatenate)を使って上手い具合にまとめてみましょう。

```javascript:HtmlText
$"<table style='width: 100%; border-collapse: collapse;'>
     <thead>
         <tr>
             {tblProperties.startTh}商品分類{tblProperties.endTh}
             {tblProperties.startTh}数量{tblProperties.endTh}
             {tblProperties.startTh}金額{tblProperties.endTh}
         </tr>
     </thead>
     <tbody>{Concat(
    With(
        {colHTMLTable: colHTMLTable},
        ForAll(
            Sequence(CountRows(colHTMLTable)),
            Patch(
                Index(
                    colHTMLTable,
                    Value
                ),
                {Idx: Value}
            )
        )
    ),
    $"<tr style='{If(
        Mod(
            Value(Idx),
            2
        ) = 0,
        "background-color: #cfd5ea;",
        "background-color: #e9ebf5;"
    )}'>
             {tblProperties.tdTextAlignLeft}{商品分類}{tblProperties.endTd}
             {tblProperties.tdTextAlignRight}{数量}{tblProperties.endTd}
             {tblProperties.tdTextAlignRight}{金額}{tblProperties.endTd}
         </tr>"
)}</tbody></table>"
```

`コレクション`に格納した値を、[Concat 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concatenate)を使ってまとめています。

列数に応じて要素を増やさなければならない要件は満たせていないものの、**要素数の増減に対応できました。**

偶数、奇数列に応じて`#cfd5ea`,`#e9ebf5`と色が変えるために、下記の関数でインデックス列を追加しています。

```javascript
With(
    {colHTMLTable: colHTMLTable},
    ForAll(
        Sequence(CountRows(colHTMLTable)),
        Patch(
            Index(
                colHTMLTable,
                Value
            ),
            {Idx: Value}
        )
    )
)
```

# おわりに
つぶやきが盛り上がったことから、ついつい書いてしまいました。
今回もお読みいただき、ありがとうございました。