飲食店のセルフオーダー画面を応用したPower Appsでのデータコントロール

# はじめに
`Power Apps`のキャンバスアプリ・モデル駆動型アプリは、基本的に下記の流れで動作します。

1. **テーブル・ビュー** : データソースのデータを *一覧化* する
1. **フォーム** : 選択したデータの詳細を*閲覧*または *編集* する

https://learn.microsoft.com/ja-jp/power-apps/

**テーブル・ビュー** > **フォーム**の流れは、単一のデータの登録・更新・削除するうえで理にかなった仕組みです。

しかしながら、実際の業務を振り返ってみると、私たちが常日頃から見ているデータは、*複数*（*場合によっては大量*）扱っており、そのインターフェースは*Excel*がどうしても好まれているのではないでしょうか。

# Power AppsでExcelを模倣する
> 複数のデータをテーブルの画面でコントロールする

この要望を満たす場合、モデル駆動型アプリでは[編集可能グリッド コントロール](https://learn.microsoft.com/ja-jp/power-apps/maker/model-driven-apps/make-grids-lists-editable-custom-control)、[Excelを用いた入出力](https://learn.microsoft.com/ja-jp/training/modules/export-dataverse-excel/?source=recommendations)機能が提供されています。

https://learn.microsoft.com/ja-jp/power-apps/maker/model-driven-apps/make-grids-lists-editable-custom-control

https://learn.microsoft.com/ja-jp/training/modules/export-dataverse-excel/?source=recommendations

慣れ親しんだこともあり、Excelのような操作感は、やはり好まれる機能です。

## キャンバス アプリでExcelの操作感を再現する
Dataverse、モデル駆動型アプリでは機能が提供されていますが、一方でキャンバス アプリでは、**一括編集が可能なグリッド コントロールは、標準で提供されていません。**

*Power AppsのRock Star*である[Reza Dorrani](https://www.youtube.com/channel/UCvBYTqRx-n_8KzFO0MJlUVw)氏が例として、ギャラリー コントロールを活用した[Power Apps Editable Grid using Gallery & Modern Controls (2023)](https://www.youtube.com/watch?v=76RJyaoW0BQ&list=PLTyFh-qDKAiHeIy4xwTFpz_03poNzPuQU)という動画で紹介してくださっています。

 - ギャラリー コントロールをテーブルのようにサイズ感をフィットさせる
     - データソースは、データの追加・更新を実施する*SharePoint Lists*
 - データの更新を反映するコレクションを設け、条件に応じて更新を実施する
     - 更新を実施するイベントは、ギャラリーの各行に配置された**非表示のボタン コントロールのOnSelect**
 - テキスト入力・ドロップダウンを設けて、`OnChange`プロパティで**非表示のボタン コントロールのOnSelect**を更新する

上記の仕組みで、ギャラリー内のコントロールの値が変更されるたびに、*OnChange* > *OnSelect*が走り、*SharePoint Lists*に反映するコレクションが更新されます。

*Cool*な作り！さすが**Reza**!!
と驚いたものですが、実装してみて以下のような課題が発生しました。

### OnChangeプロパティ
> *OnChange* > *OnSelect*の流れで、コレクションが完全に更新されているのか不透明

こちらの機能を用いた感想ですが、Excelのような操作間で考えると、コンマ数秒の時間で値が更新され、そして*SharePoint Lists*を中心としたデータソースに、更新コレクションを反映することになります。

しかしながら、`OnChange > OnSelect(コレクションの更新)`は完了しているでしょうか。
少なくともユーザー側からみてそれは検知できません。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/overview

上記は[Microsoft Power Fx の概要](https://learn.microsoft.com/ja-jp/power-platform/power-fx/overview)です。

> Power Fx は Microsoft Power Platform 全体で使用されるロー コード言語です。 汎用、厳密な型指定、宣言型、そして関数型のプログラミング言語です。
Power Fx は、人が使いやすいテキストで表現されています。 作成者が Excel のような数式バーまたは Visual Studio Code のテキスト ウィンドウで直接操作できるローコード言語です。
>> [Microsoft Power Fx の概要](https://learn.microsoft.com/ja-jp/power-platform/power-fx/overview)

**Excelのような操作感**を目指したものとあります。
Excelのよくあるエラーを思い出してみましょう。

非常にデータ容量が大きいExcelの場合、一つのセルを更新しただけでも、Excelのアプリケーションで処理が止まってしまう現象があります。入力したイベントのあとで、複数のプロセスが実行されているためです。

Excelの場合、上記のような明示的に処理の課題がわかりますが、Power Appsの場合は、ブラウザ内でのデータ処理状況が可視化できないため、誤った操作を促してしまう可能性があります。

::: note info
つまるところ、大きなデータセットに対して、この実装をしたらエラーが大量にでて、多数の人にご迷惑をおかけしたという筆者の体験談です。
:::

# 飲食店のセルフオーダー画面を参考にする
今回は*Excelを模倣する*という選択をしてしまったことによって失敗してしまいました。

そもそも*Excel手法にこだわる必要があるのか*🤔という点から問いただすべき。
*Excelがいいなら、Excel運用でよくないか*🤔となります。

思い切って観点を変えてみましょう。
私の場合は`飲食店のセルフオーダー画面を参考`にしてみました。

https://smaregi.jp/price/table-order.php

## セルフオーダー機能のデータ処理を考える
飲食店を中心に見かけることが多くなった`セルフオーダーアプリ`

アプリの内容を観察してみると
 - メニューを閲覧するビュー
 - 選択されたメニューを表示するビュー
 - 注文（または会計など）を実行するボタン

非常にシンプルな導線になっています。
仮に大本のデータが`メニューを閲覧するビュー`に多く存在していたとしても、
 1. `選択されたメニューを表示するビュー`のデータに一時保存
 1. `一時保存されたデータセット`を確認・編集（注文の取り消し・追加）
 1. 注文

と処理がまとまっています。

こちらをもとに、キャンバス アプリで`SharePoint Lists`のデータを操作することを考えると、*レコードの更新*や*削除*は上記をもとにした操作が実現できそうですね。

*レコードの追加*という部分は、*あらかじめ選択したレコードを流用・一部編集して追加する*というシーンに活かせそうです。

ということで実際にアプリを作成してみます。

# 選択式データ操作をPower Appsで実現する

画面キャプチャが実際に作成したアプリケーションです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/fca5e6ec-d81f-a9dd-8445-50571b75cafb.png)

:::note info
データは全てダミーです

 - CDジャケットは、`Grok AI`で作成
 - アーティスト名、アルバム名、価格は`GPT-4o`で作成
:::

これをもとに選択式で値を更新したり、追加する方法を考えていきたいと思います。

一時的に選択した値を格納するコレクションを`colOrders`と命名します。

選択したアイテムを格納する式は、`ボタン コントロール`の`OnSelect`に下記の式を設定します。

```javascript:OnSelect
Collect(colOrders,ThisItem);
```

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-clear-collect-clearcollect

至ってシンプルですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/3443585e-570f-74cc-c9f3-f2215344b029.png)

上記を設定すると、複数回設定することを防げます。
大本のデータソースが`SharePoint Lists`のため、一意の値である`ID`が活用できていますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/16dbda0a-a89b-9664-6d43-79518d49846b.png)

## カートの部分

追加したアイテムを表示する`Cart`の部分は、ギャラリー コントロールで結果を反映しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/4108ccc6-6944-2838-5718-b44d36d64d60.png)

仮にショッピングアプリの用意、現在追加されているレコードの`数量`や`合計金額`を反映したい場合は、[グループ化](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-groupby)が必要です。

```javascript:Items
GroupBy(colOrders,ID,groups)
```

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

一意の値である`ID`でグループ化してしまいましょう。

### 値をコントロールする
ショッピングアプリを再現する場合、画像が示す箇所でカートに追加した値を増やしたり、減らしたりしたいものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/8b6c53f4-a267-c5a9-4c06-3ff4d2e611e4.png)

`−`の場合は

```javascript:OnSelect
Remove(
    colOrders,
    LookUp(
        colOrders,
        ID = ThisItem.ID
    )
)
```

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

`+`の場合は

```javascript:OnSelect
Collect(
    colOrders,
    LookUp(
        colOrders,
        ID = ThisItem.ID
    )
)
```

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-clear-collect-clearcollect

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

上記にて値をコントロールできます。

### 合計を表示
こうなってくると、**選択した値の合計値も表示したくなります。**
白線の枠内です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/5f372479-a84e-97ec-e7e1-736974150225.png)

合計は皆様ご存じの[Sum 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-aggregates)です。

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

```javascript:Text
$"¥{Text(Sum(colOrders,Price),"#,##0")}"
```

[Text 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-text)で桁区切りを追加しています。

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

このような形で身近にあるアプリケーションの再現はできそうです。
今回、ショッピングアプリを題材にレイアウトを紹介しましたが、今回の機能を用いて、**一括でデータソースに値を追加、編集・削除**といった処理も効率的に実現できます。

しかしながら今回は長くなってしまったので、ここまでとさせてください。
ブログを読んでいただき、ありがとうございました。