はじめに
Power Appsでコレクションの特定のフィールドをDistinct関数などを使って一覧表示させ、そこで選択されたアイテムのみ表示させる。
みたいなことをやりたいケースがあるかと思います。
今回はそれのやり方をまとめます。
こんな感じですね。
フィルタ方法
フィルタするデータの用意
今回は以下のようなデータを用意しました。
ClearCollect( col, { Name: "Aさん", TaskName: "タスクα", Status: StatusCode.作業完了 }, { Name: "Bさん", TaskName: "タスクβ", Status: StatusCode.作業完了 }, { Name: "Bさん", TaskName: "タスクγ", Status: StatusCode.作業完了 }, { Name: "Bさん", TaskName: "タスクδ", Status: StatusCode.作業完了 }, { Name: "Cさん", TaskName: "タスクζ", Status: StatusCode.未着手 }, { Name: "Dさん", TaskName: "タスクε", Status: StatusCode.作業完了 }, { Name: "Eさん", TaskName: "タスクβ", Status: StatusCode.作業中 }, { Name: "Fさん", TaskName: "タスクζ", Status: StatusCode.未着手 } )
StatusCode
はこちらの定義
Set( StatusCode, { 未着手: 0, 作業中: 1, 作業完了: 2 } )
コンボボックスでアイテムを検索できるようにするには委任可能な関数を設定する必要があり、Distinct関数は委任ができない関数なので、コレクションにいれることにしました。
Power Apps での Combo box コントロール - Power Apps | Microsoft Learn
ClearCollect(NameLists, Distinct(col, Name)); ClearCollect( StatusLists, AddColumns( Distinct(col, Status), "Name", Switch( Value, 0, "未着手", 1, "作業中", 2, "完了" ) ) ); ClearCollect(TaskNameLists, Distinct(col, TaskName));
このコレクションたちをコンボボックスに設定しています。
コンボボックスの名前はこんな感じ(属性に合わせて設定しています。)
コンボボックスが1つの場合のフィルタ方法
まずはフィルタ条件のコンボボックスが1つしかない場合のフィルタ方法です。
まずやり方を記載するとこんな感じになります。
Ungroup( ForAll( NameCmb.SelectedItems As NameCmbSelected, Filter( col, Name = NameCmbSelected.Value ) ), "Value" )
やり方自体は結構単純でコンボボックスで選択されたアイテム数分、ForAll関数でループを行い、選択されたアイテムで、そのコンボボックスに対応してフィールドでフィルタを行っています。
これによってフィルタされた結果は各レコードにテーブル型のデータが入ることになります。
この形式のままだと困るので、Ungroup関数でグループ化の解除を行っています。
Ungroup関数は使う機会の少ない関数かもですが、こんな感じで入れ子になったテーブルを解除するのに便利な関数なので、この機会に使い方を覚えておきましょう。
コンボボックスが複数の場合のフィルタ方法
続いてフィルタ条件のコンボボックスが複数ある場合のフィルタ方法です。
やり方はこんな感じ。
Filter( Ungroup( Ungroup( Ungroup( ForAll( NameCmb.SelectedItems As NameCmbSelected, ForAll( StatusCmb.SelectedItems As StatusCmbSelected, ForAll( TaskNameCmb.SelectedItems As TaskNameCmbSelected, Filter( col, Name = NameCmbSelected.Value && Status = StatusCmbSelected.Value && TaskName = TaskNameCmbSelected.Value ) ) ) ), "Value" ), "Value" ), "Value" ), !IsBlank(Name) && !IsBlank(TaskName) && !IsBlank(Status) )
基本は1つの場合の時と同じです。
ただコンボボックスが複数個あるので、その分ループ(ForAll)を行う回数が増えてますね。
ForAll関数を入れ子にした結果を返しているので、入れ子にした分だけテーブルの中にテーブルがあります。
よって、ForAllを入れ子にした分だけUnGroupを実施してあげる必要があるわけですね。
またこのようにフィルタさせると、選択されたアイテムの組み合わせすべての条件でフィルタすることになるので、空のレコード(フィルタ結果が空)が返ってくる場合があります。
この結果はいらないですね。
なので、
Filter( ..., !IsBlank(Name) && !IsBlank(TaskName) && !IsBlank(Status) )
で空レコードの削除を行っています。
おわりに
やり方さえ理解しちゃえば、めちゃくちゃ難しいことしている。というわけではないのですが、0から考えたり、他の人がかいたものをいきなりみると面倒なやつですね。
私もまた、0からこのやり方思い出すの面倒なのでブログにメモした口ですw
解説結構雑にしちゃったので、不明点あればコメントなどどうぞー