Dataverseの多対多のリレーションテーブルを、コンボボックスの単一選択・複数選択の結果でフィルタリングする方法について紹介します。
テーブル
上記の画像のように多対多のリレーションが組まれているテーブルを用意しました。
商品マスタのようなテーブルから、注文された商品をフィルタリングするイメージです。
コンボボックスとギャラリーを設置し、コンボボックスで商品テーブルを選択、ギャラリーに注文テーブルを表示します。
単一選択でフィルタリングする方法
コンボボックスのItemsには商品テーブルを指定します。
ギャラリーには以下の数式を設定します。
Filter(
注文,
Or(
注文 in ComboBoxItem.SelectedItems.注文.注文,
IsEmpty(ComboBoxItem.SelectedItems),
IsBlank(ComboBoxItem.Selected)
)
)
//ComboBoxItem.Selected.注文
コンボボックスで選択した商品に紐づく注文テーブルのIDが含まれる注文テーブルのIDを検索しています。
ComboBoxItem.Selected.注文でも同じ値が取れるので、他の検索条件がなければこちらの方がシンプルです。
複数選択でフィルタリングする方法
SelectedItemsプロパティは使えない
コンボボックスの出力プロパティを.SelectedItemsにするだけでは、「指定された列は、このコンテキストではアクセスできません。」というエラーが出てしまいます。
おそらく.SelectedItemsでは商品テーブルが注文テーブルのリレーション列内にある状態でテーブルを取得しているため、処理を複雑にしないようにアクセスを制限しているのではないかと思います。
SelectedItems(テーブル)ではinが利用できませんが、Selected(レコード)ではinが使える(=つまり行ごとに計算させれば…)というところから着想を得て、多対多のリレーションでも複数選択による検索をする方法を見つけたので以降で解説します。
高さが伸縮可能なギャラリーとコンテナーを使って疑似的なフィルタリング
少し複雑ですが高さが伸縮可能なギャラリーとコンテナーを使用することで、疑似的なフィルタリングが可能になります。
高さが伸縮可能なギャラリーはテンプレート内のコントロールの高さに応じてテンプレートの高さが変化するギャラリーで、コントロールの高さが0またはVisibleがfalseの場合はテンプレートの高さが0になります。
この特性を利用して、対象のレコードはコンテナーを表示、対象外のレコードはコンテナーを非表示とすることで疑似的にフィタリングをします。
複数選択でフィルタリングする作り方
挿入→レイアウト→高さが伸縮可能な空のギャラリーを挿入します。
ギャラリーのItemsには複数選択フィルタリング以外の条件式を記載します。今回はないので注文テーブルのみを入力します。
コンテナーをギャラリー内に配置し、必要に応じてラベルなどを設置します。
コンテナーのVisibleに以下の数式を設定します。
Or(
CountIf(
ComboBoxItem.SelectedItems.商品テーブル,
ThisRecord.商品テーブル in ThisItem.商品.商品テーブル
) <> 0,
IsEmpty(ComboBoxItem.SelectedItems),
IsBlank(ComboBoxItem.Selected)
)
この数式を図解するとこんな感じです。
Id:2の蝉のぬいぐるみだけをコンボボックスで選択している場合、A1はの商品テーブルに含まれているためCountIfの結果が1となり、コンボボックスのVisibleがtrueになります。
複数選択している場合でもCountIfは繰り返し処理して計算してくれるので、行ごとに多対多の検索をしてくれます。
コンテナーを使用しているので、ヨウセイさんの横スクロールギャラリーとも相性がいいですね!
コメント