はじめに:データ編集、まだ「一件ずつ」ですか?
Power Appsで業務アプリを開発する中で、このような操作フローを実装することは非常に多いのではないでしょうか。
- ギャラリー(一覧)でデータを確認する
- 編集したいアイテムを選択し、別の編集画面に遷移する
- フォームで値を変更し、保存ボタンを押す
- 一覧画面に戻り、次のアイテムを選択する
この方法は確実ですが、多くのデータを一度に更新したい場合、ユーザーに何度も画面遷移を強いることになり、非効率です。ユーザーが心の内で「Excelの表入力なら一瞬で終わるのに…」と感じていても不思議ではありません。
本記事では、そのフラストレーションを解消するための設計パターン例として、「グリッド風入力ギャラリー」の構築手法を紹介します。ギャラリーを単なる「閲覧用リスト」から「高機能な入力フォーム」へと発展させ、ユーザーの満足度と業務効率を飛躍的に向上させるスキルを習得しましょう。
完成イメージと具体的な利用シーン
百聞は一見に如かず。まずは、今回完成を目指す「グリッド風入力ギャラリー」の完成イメージをご覧ください。

このように、ギャラリーの各行に配置された入力コントロールを直接編集し、最後に一つの「一括保存」ボタンを押すだけで、全ての変更がデータソースに反映されます。この仕組みは、多くのビジネスシーンでその真価を発揮します。
- 週報・勤怠報告: 1週間分(月〜金)の行が並んだギャラリーで、各曜日の作業時間や内容をまとめて入力・保存。
- 在庫棚卸し: 商品リストを一覧表示し、実際の在庫数をその場で次々と入力・更新。
- 経費精算: 発生した複数の経費明細(交通費、会議費など)を、Excelのような感覚で一度に追加・編集。
あなたの業務では、どのような場面でこの仕組みを活用できるでしょうか。ぜひ想像しながら読み進めてみてください。
実装の鍵:ForAll関数とPatch関数の役割
この一括編集機能を実現する技術的な核となるのが、ForAll関数とPatch関数の組み合わせです。それぞれの役割を正確に理解することが、実装への第一歩となります。
- ForAll関数: 処理の反復を指示する:
ForAll関数は、指定したテーブルやコレクションの全てのレコードに対して、同じ処理を繰り返し実行する役割を担います。今回のシナリオでは、「ギャラリーに表示されている全ての行に対して」という指示を出す、いわば現場監督のような存在です。 - Patch関数: データを実際に更新する:
Patch関数は、データソースの特定のレコードを新規作成または更新する関数です。ForAll関数という監督の指示を受け、各行のデータを実際にデータベースに書き込みに行く、実直な作業員とイメージしてください。
この2つを組み合わせることで、「ギャラリーの全ての行(ForAll)に対して、それぞれの行の入力内容でデータソースを更新(Patch)する」という、強力な一括処理が実現できるのです。
【ハンズオン】経費精算アプリでの実装手順
それでは、具体的な実装手順をステップ・バイ・ステップで見ていきましょう。今回は、多くの業務で共通する「経費精算」をテーマに進めます。
Step 0: データソースの準備
まず、データソースとしてSharePoint上に以下の構成でカスタムリストを作成します。

リスト名: 経費精算リスト
| 列の表示名 | データ型 | 備考 |
| タイトル | 1行テキスト | 経費の内容として利用します。 |
| 利用日 | 日付 | 経費を使用した日付。 |
| 勘定科目 | 選択肢 | 交通費, 会議費, 備品購入費, 交際費, その他 |
| 金額 | 数値 | 通貨表示を推奨します。 |
| 申請状況 | 選択肢 | 下書き, 申請中, 承認済, 差戻 |
Step 1: ギャラリーの配置と入力コントロールの設置
- Power Apps Studioで、[挿入] > [レイアウト] > [高さが伸縮可能な空のギャラリー]を選択し、スクリーンに配置します。
- ギャラリーの
Itemsプロパティに、先ほど作成したSharePointリスト'経費精算リスト'を設定します。)実務では、以下のように編集対象のステータス(「下書き」または「差戻」)のみに絞り込むと、より実践的なアプリになります。Filter( '経費精算リスト', 申請状況.Value = "下書き" Or 申請状況.Value = "差戻" ) - ギャラリーのテンプレート(一番上の項目)を選択した状態で、以下の入力コントロールを挿入します。
- 日付の入力: [入力] > [日付の選択] (例:
DatePicker1) - 内容の入力: [入力] > [テキスト入力] (例:
TextInput1) - 金額の入力: [入力] > [テキスト入力] (例:
TextInput2) - 勘定科目の選択: [入力] > [ドロップダウン] (例:
Dropdown1) - 状況の表示: [挿入] > [テキスト ラベル] (例:
StatusLabel1)
- 日付の入力: [入力] > [日付の選択] (例:
- 各コントロールが既存のデータを正しく表示するように、プロパティを設定します。
- 日付選択コントロール(
DatePicker1)「DefaultDate」:ThisItem.利用日 - 経費内容のテキスト入力(
TextInput1)「Default」:ThisItem.タイトル - 金額のテキスト入力(
TextInput2)「Default」:Text(ThisItem.金額) - 勘定科目のドロップダウン(
Dropdown1)- 「
Items」:Choices('経費精算リスト'.勘定科目) -
「DefaultSelectedItems」:ThisItem.勘定科目.Value
- 「
Label1のText:ThisItem.申請状況.Value
- 日付選択コントロール(
Step 2: 「一括保存」ボタンのロジック構築
最後に、画面上にボタンを一つ追加し、全ての変更を一度に保存するロジックを記述します。

- [挿入] > [ボタン] を選択し、配置します。ボタンの
Textプロパティを「一括保存」などに変更します。 - ボタンの
OnSelectプロパティに、以下の数式を記述します。
// 処理の実行中、ユーザーに待機を促すためのローディング画面を表示します(任意ですが推奨)。
UpdateContext({isLoading: true});
// ギャラリー内の全てのアイテムを対象に処理を開始
ForAll(
MyGallery.AllItems, // ギャラリー内の全てのアイテムに対して繰り返し処理
Patch(
'経費精算リスト', // 更新対象のデータソース
ThisRecord, // ForAllで処理中の現在のレコードを指定
{ // ここから下が更新する内容
// --- ユーザーが編集した内容 ---
利用日: DatePicker1.SelectedDate,
Title: TextInput1.Text,
金額: Value(TextInput2.Text), // テキスト入力を数値型に変換
勘定科目: Dropdown1.Selected,
// --- ステータスを自動更新 ---
// 保存と同時に、ステータスを「申請中」に設定する
申請状況: { Value: "申請中" }
}
)
);
// 処理完了後、ローディング画面を非表示にします。
UpdateContext({isLoading: false});
// データソースを再読み込みし、画面に変更を反映させます。
Refresh('経費精算リスト');
// ユーザーに処理の完了を通知します。
Notify("経費データの一括申請が完了しました。", NotificationType.Success);
【解説のポイント】
ForAll(YourGalleryName.AllItems, ...):ギャラリー内の全てのアイテムを対象に処理を開始します。Patch('経費精算リスト', ThisRecord, {...}):ThisRecordは、ForAllが現在ループ処理しているアイテムそのものを指します。これにより、正しい行のデータが更新されます。DefaultSelectedItems:選択肢列(Choices)のデフォルト値をギャラリーで設定する場合、DefaultではなくDefaultSelectedItemsプロパティにレコード(ThisItem.勘定科目)を設定するのが正しい方法です。Value(TextInput2.Text):テキスト入力コントロールから取得できる値は常に「テキスト型」です。数値型の「金額」列に保存するためには、Value()関数を使って明示的に「数値型」へ変換する必要があります。申請状況: { Value: "申請中" }:「申請状況」列も選択肢列のため、値を設定する際は{ Value: "(設定したい値)" }というレコード形式で指定します。
【補足】「申請状況」列の役割とワークフロー設計
今回のPatch関数のロジックでは、「申請状況」を{ Value: "申請中" }と自動で上書きしています。
これは、このアプリが「申請者」のためのアプリであることを前提としているためです。
- 申請者の役割:経費データを入力・編集し、「一括申請」ボタンを押すこと。
- アプリの役割::「一括申請」ボタンが押されたら、入力されたデータを保存すると同時に、ステータスを自動で「申請中」に変更し、承認フローに乗せること。
この設計により、申請者が誤ってステータスを「承認済」などにしてしまうヒューマンエラーを防ぎます。
この後、「申請中」になったデータは、「承認者」が閲覧する別のアプリやPower Automateの承認プロセスに引き継がれ、そこでステータスが「承認済」または「差戻」に変更される、というのが一連のワークフローの全体像となります。
さらなる応用と発展
この基本形をマスターすれば、さらに高度な機能へと発展させることが可能です。
ステータスに応じた編集制御(読み取り専用化):実務では「申請中」や「承認済」のデータは編集させたくないはずです。その場合、ギャラリー内の各入力コントロール(DatePicker1やTextInput1など)のDisplayModeプロパティを以下のように設定します。
// テキスト入力コントロールの DisplayMode プロパティの例
If(
ThisItem.申請状況.Value = "申請中" Or ThisItem.申請状況.Value = "承認済",
DisplayMode.View, // 「申請中」か「承認済」なら、表示のみ(編集不可)
DisplayMode.Edit // それ以外(「下書き」や「差戻」)なら、編集可能
)
- 新規行の追加:ギャラリーの
Itemsに設定しているコレクションに対し、Collect関数で空のレコードを追加するボタンを実装することで、新規データの追加にも対応できます。 - 入力値の検証(バリデーション):金額欄にテキストが入力された場合や、必須項目が空の場合にボタンを非活性化したり、入力コントロールの枠線を赤くしたりすることで、データ品質を向上させることができます。
- パフォーマンスへの配慮:一度に更新するデータが数百件を超える場合は、アプリの応答性に影響を与える可能性があります。その際は処理を分割したり、Power Automateを呼び出してバックグラウンドで処理させたりといった工夫が求められます。
まとめ:ユーザビリティの向上を考える
本記事では、ForAll関数とPatch関数を組み合わせることで、標準機能だけでは実現が難しい「グリッド風入力ギャラリー」を構築する手法を解説しました。
このテクニックは、単なる機能実装に留まらず、ユーザーの操作負担を劇的に軽減し、アプリケーションの価値を大きく高めるための重要な方策です。これまで何度も繰り返していたクリックや画面遷移からユーザーを解放し、本来の業務に集中できる環境を提供することができます。
今回紹介したパターンは、様々な一括処理に応用が利く非常に強力な武器となります。ぜひ、あなたの次のアプリ開発プロジェクトでご活用ください。