続【多品一葉のデータ】をひとつのリストだけを使ってPower Appsで扱うひとつの方法

## はじめに
先日、多品一葉のデータをひとつのリストにJson形式で保管しそれを画面表示させる方法を紹介したところ、以外にも好評だったので気をよくして、今回はリストにデータを登録する部分を紹介しようと思います。

今回、はじめて読むよという方は、まずは前回の情報をご一読いただけると光栄だ。

https://qiita.com/yamachan67/items/ca24304ef2a5c2825957

### 画面イメージ
前回の画面はあまりにもショボかったので、それっぽいUIに作り直してみた。まずはそれを見ていただくことにしようと思う。
![2024-08-05_19h49_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/033764dd-536a-d3a1-fd97-bd3e1548412b.png)
どうだろう、いわゆるリストをもとに自動生成した画面だが右側の明細表示の下部にテーブルコントロールを配置している。それだけなのだが、いかにもPower Appsらしい画面になったのではないだろうか。

## 前回との変更点
### ギャラリーのOnSelect
UIは変えたものの多品を表示するまでのロジックは基本的に変えていない。ただ、ギャラリーのOnSelectの処理を若干変更している。

前回のOnSelectは次のようになっていた。
```
UpdateContext(
           {
               dataTable: ForAll(
                   Table(ParseJSON(CheckedGallery.Selected.Details)),
                   {
                   // ThisRecord.Value.<フィールド>の<フィールド>部分は手入力する。
                       番号: Text(ThisRecord.Value.No),
                       商品名: Text(ThisRecord.Value.PrdName),
                       単価: Value(ThisRecord.Value.UnitP),
                       点数: Value(ThisRecord.Value.Qty),
                       金額: Value(ThisRecord.Value.Amt)
                   }
               )
           }
       );
```
これだと選択したレコードに１件以上の明細データがJsonとして存在することが前提だが、データの登録途中で一時保存した場合など、明細をまだ入れていないケースが発生しかねないので、少し工夫が必要だ。
そこで、今回のOnSelectでは次のようにしてある。
```
If (
    IsBlank(RecordsGallery1.Selected.Details),
    UpdateContext(
        {
            dataTable: Table(
                {
                    番号: Blank(),
                    商品名: Blank(),
                    点数: Blank(),
                    単価: Blank(),
                    金額: Blank()
                }
            )
        }
    ),
    UpdateContext(
        {
            dataTable: ForAll(
                Table(ParseJSON(RecordsGallery1.Selected.Details)),
                {
                    // ThisRecord.Value.<フィールド>の<フィールド>部分は手入力する。
                    番号: Text(ThisRecord.Value.No),
                    商品名: Text(ThisRecord.Value.PrdName),
                    単価: Value(ThisRecord.Value.UnitP),
                    点数: Value(ThisRecord.Value.Qty),
                    金額: Value(ThisRecord.Value.Amt)
                }
            )
        }
    )
);
```
ようするに選択したリストのDetails列が空なら、項目だけ用意した空のテーブルを準備し、それをコンテキスト変数dataTableにセットしている。

### 編集モード
右側の明細画面を編集モードにするとテーブルコントロールの横にアイテムを追加するボタンを用意しました。
それを押すと次のようなダイアログが表示される。
![2024-08-05_22h20_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/106f79f0-7694-e392-b2c0-58d3e8bc34b9.png)

今回データを登録する処理で重要なポイントは２箇所、そのうちのひとつがこのダイアログの追加ボタンになる。

#### 追加ボタン
では、その追加ボタンの中を見てみましょう。
```
// ダイアログを非表示に
UpdateContext({dspDialog: false}); 
// ダイアログへ登録したデータをレコード型の変数へ
Set(
    newRecord,
    {
        番号: Text(
            Max(
                dataTable,
                番号
            ) + 1
        ),
        商品名: TextInputCanvasPrdName.Value,
        単価: Value(TextInputCanvasUnitP.Value),
        点数: Value(NumberInputQty.Value),
        金額: Value(NumberInputQty.Value * TextInputCanvasUnitP.Value)
    }
);
// ダイアログ入力値をdataTableに追加する
If(
    IsBlank(dataTable),
    UpdateContext(
        {
            dataTable: Collect(
                Table(),
                newRecord
            )
        }
    ),
    UpdateContext(
        {
            dataTable: Collect(
                dataTable,
                newRecord
            )
        }
    )
);
//入力項目のリセット(クリア)
Reset(TextInputCanvasPrdName);
Reset(TextInputCanvasUnitP);
Reset(NumberInputQty);
```
まずダイアログのvisibleプロパティにセットしたdspDialog変数をfalseにして、ダイアログを非表示にしている。これは一連の式の最後に持ってくる人も多いだろうが私はたいてい先頭でしている。なぜなら、キャンセルボタンと処理の順番を合わせたかったからだけだ。

そして、ダイアログで入力した各項目の値をならべて、レコード型の変数にセットしている。
次に元のdataTableコンテキスト変数にダイアログからセットした変数を追加するのだが、dataTable変数が空かどうかで、セット方法が異なる。これが、今回のポイントと言えるだろう。

最後に、それぞれの画面項目をReset関数でクリアしてる。

この一連の処理をするとdataTableコンテキスト変数にはダイアログから入力した値が追加され、テーブルコントロールも追加されたコンテキスト変数を使って自動で再描画してくれるだろう。

#### チェックアイコン
詳細画面右上のチェックアイコンをクリックすると編集中のデータがSharePointリストに更新されるのだが、これが今回の処理の２つ目のポイントだ。
![2024-08-05_22h39_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/b3d4297d-4ec1-2dca-91a8-ddf826a44434.png)
このチェックアイコンのOnSelectには次の式がセットされている。
> SubmitForm(Form1);

はい。特に変わったことはしていない。Form1をそのままSubmitしているだけだ。

当初は、ここでPatch関数を使って書き出そうかと考えたのだが、SubmitFormの方が初学者には扱いやすいかと思い、あえてそのままSubmitFormを使うことにした。

となると、どこで、Jsonデータを処理するのだろうか。

実は、VisibleをfalseにしてあるだけでForm1には、Details_DataCardが残してある。
そして、そのUpdateプロパティを小細工してある。
![2024-08-05_22h51_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/7c10ee08-520d-de4b-29db-c2250c62ac7d.png)

赤枠の部分には、次の式をセットしている。
```
JSON(
    ForAll(
        dataTable,
        {
            No: Value(番号),
            PrdName: 商品名,
            UnitP: 単価,
            Qty: 点数,
            Amt: 金額
        }
    )
)
```
若干わかりにくいが、もともとギャラリーのOnSelectでJsonの各項目を日本語名にしてコンテキスト関数に保管したので、ここで再度、元の項目名に変更しているわけだ。

整理すると次のような形になっている。
|リストに保管するJson項目名||ギャラリのOnSelectで変数にセットした項目名|
|:-|:-:|:--|
|No|⇔|番号|
|PrdName|⇔|商品名|
|UnitP|⇔|単価|
|Qty|⇔|点数|
|Amt|⇔|金額|

これは、テーブルコントロールのヘッダー行を日本語で表示したかったこと、そして保管する複数行テキスト形式の列の制約として、最大63,999文字までしか保管出来ないこともあり、出来るだけシンプルな項目名にするための一工夫だ。

#### 保管結果の確認
![2024-08-05_23h09_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272254/fafefe73-76e4-d949-c8ed-5252f0ccf37b.png)
この通り、複数行テキスト型の項目にJsonデータとして多品が登録されているのが判るだろう。

## まとめ
二回に渡って多品一葉のデータをひとつのリストだけを使ってPower Appsで扱う例を紹介してきたが、情報を伝えるという目的だけで考えるなら、何もヘッダー＆明細、２つのリストを使って正攻法なデータ構造で構築しなくても使えるというのが判ってもらえたかと思う。

もちろん、長年SEとして歩んできた私の目から見ても、一見邪道なやり方なのは間違いない。ただ、正解なんて一つだけではない。時と場合によっては、これぐらい割り切ったデータの持ち方をした方が良い場合も必ずあるはずだ。

もし、この記事の読者の方がそういう場面に遭遇したとき、この記事を思い出して参考にしてもらえたら、とても嬉しく思います。