PowerAppsで組織のメンバー（限られた範囲）をドロップダウンの選択肢に表示

先日、[PowerAutomateで組織のメンバーを一覧する](https://qiita.com/mizukyf/items/356af2573278c9de7de8)というお話をしました。
今日はこれに関連するお話です。

PowerAutomateでワークフローを構築・運用していると、時折、自組織のメンバーを一覧したいことがあります。
似たような話で、PowerAppsでアプリを構築・運用していると、時折、アプリのフォームで自組織のメンバーをドロップダウンの選択肢に表示したいことがあります。
そのようなシーンでのソリューションのご紹介です。

# Problem

PowerAppsでSharePointなどのデータソースを指定すると、当該データソースのレコードを参照・更新が可能なフォームを伴うアプリを簡単に構築できます。
そのフォームに含まれるドロップダウンリストの選択肢に自組織のメンバー（Office365のテナントで登録されたユーザー）のうちでも限られた範囲のメンバーを表示したい場合、どうすればいいでしょうか？
限られた範囲とは所属（`Department`）や役職（`JobTitle`）で絞り込まれた範囲のことです。

# Solution

組織のメンバー数によりソリューションは変わってきます。
その説明に入る前に、まずは解説に用いるサンプルデータの説明をしておきます。

今回は次のようなSharePointリストを用意し：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/b2cffa37-a07a-ad39-b978-850f56f54765.png)
これに基づいてモデル駆動型アプリを作成（スキャッフォールディング）しました：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/421d766c-c037-0b57-8570-ec36f4ff4101.png)
もちろんSharePointリストの`User`列に対応するドロップダウンリストも生成されています：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/9812e80e-a61b-8fe7-a23c-4507d1e37476.png)

このフォームにフォーカスを移すと（コンボボックスなのでいきなりリストは表示されず）検索ワードを入力できる状態になります：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/c237bb43-256f-0c06-1573-ada4177fcbe3.png)
適当なワードを入れると、組織内でそれに該当するメンバーが候補として表示されます：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/86415371-864f-2181-243c-18e01c77a0c3.png)

表示名やメールアドレスにマッチするものならなんでもこの一覧に表示されます。
「これで十分だ！」という方はそもそもこの記事を読んでいらっしゃらないでしょう。

## 組織のメンバーは999人以内

自組織のメンバー（Office365のテナントで登録されたユーザー）が999人以内の場合は Office365 Users（Office365ユーザー）コネクターを利用します。

まずは「＋データの追加」でアプリに Office365 Users（Office365ユーザー）コネクターを追加します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/0ae42b03-39ed-2ba1-d98f-307385e86546.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/6362770b-5da4-cff5-e7b6-e0eede230492.png)

ドロップダウン（コンボボックス）のDataCarfValueコントロールのプロパティを編集します：
| プロパティ | 内容 |
|:-----------|:------------|
| Items       | `AddColumns(Office365ユーザー.SearchUser(), "Claims", "i:0#.f\|membership\|" & Lower(Mail), "Email", Mail)`        |
| IsSearchable     | `true`      |

するとOffice365 Usersコネクターから取得されたユーザー情報をもとに選択肢が表示されるようになりました：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/facc5052-3f19-f042-2ae2-3ed7db313936.png)

先程の `Items` プロパティの式は何をしているのでしょうか？
```
AddColumns(
    Office365ユーザー.SearchUser(), 
    "Claims", "i:0#.f|membership|" & Lower(Mail),
    "Email", Mail
)
```

Office365 Usersコネクターから取得したレコードの1件1件に対して、各レコードの情報を元にして `Claims` 列と `Email` 列を追加しています。
こうすることでコネクターから取得したユーザー情報の体裁を、SharePointリストの「ユーザーまたはグループ」型の列に対応するドロップダウンリストに対して有効なものにしているわけです。

この状態ではまだ絞り込みがかかっていないので `Items`プロパティの式を修正します：

```
Filter(
    AddColumns(
        Office365ユーザー.SearchUser(), 
        "Claims", "i:0#.f|membership|" & Lower(Mail),
        "Email", Mail
    ), 
    StartsWith(Department, "ここに部署名のプレフィックス")
)
```

この例では`Filter()`関数を使用してユーザー情報の `Department`列の内容に基づく前方一致フィルタリングをかけています。
もう一度アプリを実行してみると、フィルタリングされた結果が表示されることを確認できるはずです。
条件を決める引数のところはこれをご覧の皆さんのアプリの要件にしたがって適宜変更してください。

## 組織のメンバーが1,000人以上いる！

さて、問題は組織のメンバーが1,000名以上いる場合です。
前述の Office365 Usersコネクターが提供する `SearchUser()`関数は最大で999件までしか結果を返してくれません。
`Filter()`関数はこの結果に対して絞り込みをかけるわけで、`SearchUser()`関数が返してくれなかったユーザーの中に条件に合致するものがあっても`Filter()`関数にはどうしようもありません。

どうしたらよいでしょうか？

私の知っている限りでは、独自のデータソースを用意する以外にありません。
ここで先日の記事 [PowerAutomateで組織のメンバーを一覧する](https://qiita.com/mizukyf/items/356af2573278c9de7de8) の出番です。
この記事では PowerAutomateのワークフローを使用して組織のメンバーの中でもある特定のメンバーの配下のメンバー（部下、部下の部下、部下の部下の・・・）を再帰的に収集する方法を示しました（そのためにここでも Office365 Usersコネクターを使用しています）。

1. まずはこうした仕組みを使ってユーザー情報をかき集めます。
1. 続いて収集したデータをSharePointリストやExcel Onlineのテーブルとして保存します。
1. 当該リストやテーブルをコネクターを使用してPowerAppsアプリに関連付けます。
1. 「999人以下」ケースと同様にユーザー情報に `Claims`列や `Mail`列を補いつつドロップダウンリストの `Items`プロパティに設定をします。

```
AddColumns(
    収集したユーザー情報を提供するデータソース, 
    "Claims", "i:0#.f|membership|" & Lower(Mail),
    "Email", Mail
)
```

スマートな方法とは言い難いです。
リアルタイム性も失われます。
しかしOffice365 Usersコネクターの `SearchUser()`関数の仕様に基づく制約は取り払われます。
ひとつの解として、ご検討ください。