Kilroy 365

Microsoft365 主にPowerPlatformについての備忘録

複数条件の絞り込みにトグル/チェックボックスを利用する

f:id:KilroyWaaasHere:20220129021641j:plain

はじめに

ギャラリーに表示したアイテムを絞り込む用途って、多いですよね。

Filter関数を使用するのが一般的ですが、Filter関数は

Filter(Table*, Formula1 [, Formula2, ... ] )という感じの構文で、複数条件を指定して絞り込むことができます。

詳しくはDocsを参照してください。

この複数条件の指定については、If関数で条件分けをしがちですが、Ifでの条件分けは条件が多くなればなるほど複雑化して可読性が悪くなっていき、後から参照したり修正したりする際にとても不便です。

選択肢列の絞り込みをする場合だと、Ifを使用しない、シンプルで読みやすい絞り込みの書き方が存在します。詳しい説明は後回しにするとして、まずは例をあげてみます。

データソース

SharePointリストをデータソースに、次のように選択肢列を2つ設定してみます。

f:id:KilroyWaaasHere:20220128080033j:plain

絞り込みの書き方

Filterの条件をこのようにすることで、複数条件の絞り込みを、Ifを使わずシンプルに書くことができます。

f:id:KilroyWaaasHere:20220128002445j:plain

動作は以下。ちゃんと2つのコンボボックスの選択に従ってフィルターされています。

20220128001516

今回の記事はこれの応用で、トグルまたはチェックボックスを使ったフィルターを、この書き方に当てはめる方法を説明していきます。

 

トグルとチェックボックス

トグル(日本語では切り替えコントロール) とチェックボックスの説明は以下。

どちらも、データ型としてはboolean(はい/いいえ)を扱い、コントロールの状態を変化させることによって、true/falseを切り替えます。

トグルならon、offでそれぞれtruefalseを、チェックボックスならチェックを入れるとtrueを、チェックを外した状態ならfalseを返します。

UIが違いますが、目的は同じようなものなので、どちらを使うかは用途よりも使い勝手やデザインの好みによるところが大きいのではないかと思います。

今回の場合だと、データに要素がいくつもあり、それぞれの要素にあてはまるか、そうでないかで絞り込んでいく用途が想像できます。 製品データがあって、多数あるオプションの有無で絞り込みをかけたりする場合などに使えそうです。

オプションの数だけ絞り込み条件数が多くなるので、なおさらシンプルで読みやすい書き方が求められます。

上で紹介した書き方を当てはめ、シンプルに書けると便利ですね!

 

複数条件絞り込みのシンプルな書き方の説明(ざっくりと)

f:id:KilroyWaaasHere:20220128005357j:plain まずは冒頭で上げた例で複数条件をどのように絞り込んでいるか、ざっくりと見ていきます。

コンボボックスの数だけ条件➀、条件②・・・と絞り込み条件を追加していく感じの書き方になっていて、それぞれのコンボボックスでの絞り込み条件の中身は条件A、条件BをORでつないだ形になっています。

条件Aでコンボボックスが空かどうかの判別を、条件Bで選択肢列にコンボボックスの選択と同じものがあるかどうかを判別しているのですが、上の画像中で説明している通り、条件にはデータソースと直接関係のない条件も設定することができます。

この場合、trueならすべてのレコードが該当、falseならすべてのレコードが非該当というように判断されるようです。

これを利用して、条件➀は以下に示すように、コンボボックスが選択なしの状態だとすべてのレコードが、選択している場合は、選択肢と一致するレコードが絞り込まれる、という仕組みになっています。

f:id:KilroyWaaasHere:20220128011035j:plain

そして、Filterの構文上、条件➀、条件②は、ANDでつないだのと同義になっているので、条件➀かつ条件②に当てはまるもの、という感じで絞り込まれていきます。

条件は追加も可能ですので、それぞれの絞り込み条件の中身(条件A、条件B)にORやANDで条件を追加したり、絞り込みの条件(条件➀、条件②)を追加して増やしていくことができます。

 

トグル/チェックボックスへあてはめる

絞り込みの理屈が理解できたところで、トグル/チェックボックスへあてはめる方法を考えていきます。

この書き方のミソは、コントロール(コンボボックス、トグル…)の条件を変えてやることで、すべてのレコードに該当する条件と、絞り込まれる条件とが切り替わるように設定する ことです。

チェックボックスを例にとると、

  • チェックがついていない状態 ➡ すべてのレコード
  • チェックがついている状態 ➡ 絞り込みがかかる

ような条件です。

そんな条件どうやるの???

実のところ、トグル/チェックボックスを普通に使うとこんな条件は作り出せません(思いついていないだけかも知れませんが)。

例えば、データソースにBoolean1というBoolean型の列を設定し、tglBoolean1というトグルコントロールで絞り込みをかけるとします。

コンボボックスの例をまねて、トグルがオフの際に全レコードが適用される、すなわちtrueになる条件と、トグルの値とBoolean1の値が一致する条件というような書き方をしてみます。

tglBoolean1.Value=false || Boolean1=tglBoolean1.Value

こんな感じにしてみましょう。先の例と同様に || をまたいで前者を条件A、後者を条件Bとします。

…はい、ダメですね。

条件Aは、トグルがオフの際にtrue、オンの際にfalseとなるので、それぞれ全レコードが該当、非該当ということになり、問題ありませんが、条件Bの方が問題です。

条件Bについて見てみます。

トグルがオフの時、falseが返りますが、これがBoolean1にチェックのついていないレコードに一致してしまい、絞り込みがかかってしまいます。

データソースを見ると、Boolean型の列は一見、チェックのついていないところに何も入っていないように見えますが、実際にはBlankではなく、falseとなっているので、トグルのfalseと一致してしまいます。 f:id:KilroyWaaasHere:20220128105842j:plain

解決策

ではどうやったら、この問題が解決できるか。

少々邪道な方法ですが、解決策を思いついたので、書いていきたいと思います。

問題となっているのは、Boolean型の値がtrue/falseの二者択一で、trueでなければ必ずfalseになってしまうことです。true以外をBlankにして、コンボボックスのfalseと一致させないようにしないと、このような条件に当てはまる式が書けませんが、Boolean型ではどう頑張っても実現不可能でした。

Boolean型を回避

falseが出てこないようにするには、falseを出さなければ良いのです。(進次郎構文みたいですな...)

Boolean型では無理なので、列をテキスト列や選択肢列にしてあげます。今回は1行テキストでやってみます。

変数でtrue/falseを代替文字に変換

変数を使ってトグルのtrue/falseを別の文字に変換してやり、データソース側はtrueに対応する文字(今回の場合は○)を入力し、trueの代わりにしてフィルターします。

なお、falseの変換先の文字(今回は×)は捨て文字にし、使用しません。

トグルをtglTextBoolean1とし、チェックボックスをchbTextBoolean2、それぞれ対応するテキスト列をTextBoolean1、TextBoolean2とします。

//tglTextBoolean1.OnChange
Set(varTrue1,Switch(Self.Value,true,"○",false,"×"))

//chbTextBoolean2.OnCheck
Set(varTrue2,"○") 

//chbTextBoolean2.OnUncheck
Set(varTrue2,"×") 

のように、true/falseを変数で ○/× に変換します。

データソース側は絞り込みをかけたいものに○を入力し、それ以外はBlankのままにします。 f:id:KilroyWaaasHere:20220128150621j:plain

これで、falseを排除できました。以下のように絞り込み条件を書くと、複数条件の絞り込みができます。

Filter(
    FilterTest,
    IsBlank(cbbChoices1.Selected.Value) || Choices1.Value = cbbChoices1.Selected.Value,
    IsBlank(cbbChoices2.Selected.Value) || Choices2.Value = cbbChoices2.Selected.Value,
    tglTextBoolean1.Value=false || TextBoolean1=varTrue1,
    chbTextBoolean2.Value=false||TextBoolean2=varTrue2
)

実際に動かしてみたら以下のような感じで、ちゃんと動作してますね。

20220128154951

ギャラリー・フォームもトグル/チェックボックス

絞り込みはできましたが、編集もできないと片手落ちです。

データソースはテキストなので、そのままにしておくと、true以外の文字が入ったり、falseを書き込まれたりして条件が破綻しかねません。 どちらも絞り込みと同じくトグル/チェックボックスを実装するのがスマートです。

ここからは本題ではないので、サーっと説明していきます。

ギャラリー

ギャラリーは簡単ですね。 トグルとチェックボックスをギャラリーに追加して、

//tglGalTextBoolean1.Default
If(ThisItem.TextBoolean1="○",true,"",false)
//chbGalTextBoolean2.Default
If(ThisItem.TextBoolean2="○",true,"",false)

のように書いてやればOKです。式が単純なのでSwitchで書いてやっても良いです。

それぞれトグルとチェックボックスのDisplayModeをViewに変更しておきたいですが、トグルの場合はViewにするとトグル本体が消えてしまうので、見た目的にちょっともったいないです。 チェックボックスはView、トグルはトグルの見た目が必要な場合はEditに、必要ない場合はトグルを使わずLabelで表示してやればよいのではないでしょうか。

フォーム

それぞれTextBoolean1、TextBoolean2のデータカードにトグル、チェックボックスを挿入します。

f:id:KilroyWaaasHere:20220128162341j:plain

//トグル、チェックボックスのDefaultをそれぞれ次の通り設定
Switch(Parent.Default,"○",true,"",false)

まずこれで、データソースの値が反映されます。

次に、データをEditする場合を考えます。Submitボタンを押したとき、データソースに書き込まれるのはカードのテキストインプットのテキストなので、これをトグル/チェックボックスの値に応じて変えてやれば、変更をSubmitすることができます。

//テキストインプットのDefaultをそれぞれ次の通り設定
Switch(tglFrmTextBoolean1.Value,true,"○",false,"")
Switch(chbFrmTextBoolean2.Value,true,"○",false,"")

トグル、チェックボックスの値が正常にテキストインプットに反映されるのを確認したら、Visibleをfalseにして、テキストインプットを隠します。

これで、すべて終了です。動作を見てみましょう。

20220129003912

トグル、チェックボックスでの編集、新規作成、フィルターすべてOKです。

注意点

本来はBoolean型を扱うトグル・チェックボックスをテキスト型で使用する、ちょっと乱暴な使いかたですので、注意点があります。

アプリで触る分にはユーザーにテキスト入力をさせないようにできてますので、問題ないと思いますが、リストを直接触ることがあるなら破綻してしまう可能性があります。

SharePointのフォームをPowerAppsで作り、同じやり方で入力制限したり、ソース側でも入力の制限をかけてあげないと使っていくのは厳しいと思います。

やるならあくまで自己責任で、的な感じです。

おわりに

実のところ、初めはfalseの回避に変数を使用せず、Booleanのtrueをテキストの"true"として評価させるという、さらに無茶苦茶な方法を取っていました。

こちらでもできなくはないのですが(実際できた)、リストのテキスト列の挙動がおかしく、なんだかやばそうでした。

具体的にはテキスト列ににtrueと入力すると表示がTrueとなり、これをさらにtrueに書き換えると、値は入っているものの、表示がされなくなりました。

誤動作防止でそういう仕様になっているのか、エラーでそうなっているのかはわかりませんが、気持ち悪かったので、変数を使うことにしました。