こんな人向けの記事です
社内で何らかのプロジェクトやメンバーをExcelを使って管理していることってあると思います。また、これらのメンバーをTeamsのチームに招待してコミュニケーションをとるということを多いでしょう。
運用しているとすぐに気がつくはずです。
- ユーザー管理表とチームへの招待を一致させるのが超面倒くさい
- すでにメンバーから外れたユーザーをチームから退出させるの忘れがち
- いつの間にか有耶無耶に・・・
管理表はその人の属性やなんやかやを管理するには便利ですし、どうしても必要ということもあるでしょう。ならば、Excel表にメンバーを追加したり、削除(あるいはフラグによって)したときに自動的にTeamsのチームメンバーから追加、削除が行えれば最高に便利です。
この記事では、Excel表とTeamsのメンバーの自動同期をPower Automateのクラウドフローを使ってかんたんに実現します。
TeamsのメンバーはM365グループで管理されている
普段Teamsを使っているときにはあまり気にすることがありませんが、Teamsのチームに参加している所有者とメンバーは、裏側でM365グループという仕組みを使って管理されています。このグループのおかげで、Teamsの裏側にあるSharePointへのアクセス権もコントロールされています。
M365グループのメンバーを追加したり、削除したりという操作は、Power Automateからかんたんに実行できますので、今回の処理のポイントは、いかにして2つのメンバー表を比較してM365グループに追加するべきユーザーと、チームから取り除くべきユーザーを一覧にするかという点に集約されます。
Excel表を作ってみる
Excelを使ってSharePoint上に以下のようなテーブルを作成してみました。ちなみに、このExcelファイルは同期させるチームのSharePoint上に置いておくと管理しやすいのではないでしょうか?
ここに書かれたメンバーをクラウドフローに読み込むところから始めます。
以下のように「表内に存在する行を一覧表示」アクションを使って、ファイルの場所やテーブル名を指定します。早速テスト実行してみましょう。
テスト実行した結果はこのようになりました。出力の「クリックしてダウンロードします」を開いてみます。
ブラウザに表示される文字列をテキストエディタをつかって整形すると以下のような感じで取得できました。JSON形式なのですが、このままだと扱いづらいのでメールアドレス部分だけを配列化してやります。
選択アクションを使ってメールアドレスを配列化
配列を作るには「組み込み」のなかにある「選択」というアクションを使います。
選択アクションの開始には、前項目のValueを動的なコンテンツから指定します。これができたら、「マップ」の一番右側にある「T」のようなアイコンをクリックします。マップ入力欄の形が変わります。
形が変わったら、そこに「メール」を動的なコンテンツから選んで指定します。ここまでできたらまたテスト実行してみましょう。
選択の「出力」結果に注目してください。たったこれだけの操作で複雑なJSONがシンプルなメールだけの配列になりました。
終了日に日付が入っているユーザーは省く
Excelのメンバー表には「終了日」という項目を用意していました。ここに日付が入っているユーザーはメンバーから省くという運用方法はいかがでしょう?以下の例では「PattifF」さんに終了日を入れてみました。
このExcel表から、終了日に何も入力されていない人だけのリストを取得したいので、フィルタークエリに以下のような文字列を入力します。eqはイコールを表し、後半はシングルくウォーテーションが2つ入力されています。つまり「終了日列の文字が何もない」ものだけを一覧化するという意味になります。
終了日 eq ''
結果は以下のとおり。日付が入力されている「PattiF」さんが配列に現れなくなりました。
チームのメンバー一覧を取得する
さきほどは、Excel表に入力された、あるべきメンバーの一覧を取得しました。「選択」アクションがそのまま配列として利用できるので、わかりやすいよういに名前を「Excel表のメンバー」に変えておきました。
こんどは、ターゲットになるチームの既存メンバー一覧を取得します。まえにも説明したようにTeamsのチームはM365グループで管理されているので、「グループメンバーの一覧表示」アクションを使います。グループ名はチーム名と同期していますので、チーム名を選択すればOKです。このアクションも結果はJSONとして帰ってきますので、先程と同じように「選択」アクションを使ってメンバーのメールアドレスを配列に変換する処理も追加しましょう。
Excel表から配列を作ったときとおなじように、グループ一覧からも配列を作成することができました。最初の段階ではメンバーは私だけの状態です。Excel表からつくった配列では私をふくめて5名のメンバーが表示されていましたので、残る4名をチームに追加するべきメンバーとして配列にしてやればよいわけです。
2つの配列の差を抽出する
今回の処理のポイント1つめ。まずは追加するべきメンバーを抽出します。これには「アレイのフィルター処理」アクションを使います。わかりやすいようにチームメンバーを取得した「選択」アクションの名前も変えておきました。
フィルターアクションをどう使うかがポイントなのですが、次のような考え方ができます。
あるべき一覧に含まれていないならば真として残す
フィルターには「差出人」という欄があります。ここにはフィルターされる配列を設定します。元の配列に含まれていない人は結果として出てきませんので、「差出人」に設定するべきなのは「Excel表」のほうです。ここ間違いやすいので注意です。
次に設定するのはフィルターの条件ですが、左辺にはcontains関数を使います。この関数は第1引数に設定する配列の中に、第2引数の文字が含まれていればTrueを返します。
contains(body('既存チームのメンバー'),item())
上のように、第1引数には既存のチームメンバーの配列を。第2引数にはフィルターの「差出人」に設定した配列のなかから1項目ずつを比較させるために「item()」を設定します。
あるべきExcelメンバーの中のひとを一人ずつ既存のメンバーの中に存在するかを比較し、いない(false)ならば追加するべき人として残す処理がこれで実現します。
ポイント
Apply to eachを使いこなせる方は item() を見てピンと来たと思います。アレイのフィルター処理アクションはApply to eachと同じ感覚で取り出して、関数を使ってやや複雑な条件でフィルタリングすることが可能です。
フィルター処理の結果です。たしかに私以外の4名が追加するべきメンバーとして配列化されました。
余分なメンバーをチームに追加してから
こんどは反対にExcel表にいないメンバーをチームから取り除く処理を作ります。
予め表には載っていないメンバーである「Adele」さんをM365グループに追加しておきました。
M365グループの変化はちゃんとTeamsにも反映していますね。
取り除くべきメンバーの一覧をつくる
こちらも「アレイのフィルター処理」アクションを使います。考え方は以下のとおりです。
既存メンバーのうち、あるべきExcel表のメンバーに含まれないメンバーを抽出する
フィルターの「差出人」には最終的に抽出される人が含まれていないといけませんから、こちらに指定するのは「既存のチームメンバー」のほうです。あとは先程と同じ要領でExcel表のメンバーと1件ずつ比較をして、含まれない、つまり結果がfalseになる場合だけ通過させます。
テストしてみるとご覧の通り、Excel表には存在しないAdelVさんだけが出力に表示されています。
M365グループに対して追加、削除する
加えるメンバー、取り除くメンバーの一覧ができましたので、あとはM365グループに対する処理をつくってやるだけです。
警告
この処理を追加すると実際にユーザーがチームに追加されたり削除されたりするので、できればテスト用のユーザーで試したり、作成された配列に問題がないかしっかり確認してから実行するようにしてください。不注意で既存のチームからユーザーが消えても責任持てませんのであしからず。
処理をわかりやすくするためにスコープでくくっておきました。
すでに追加するべきメンバーは配列として取得していますので、配列の1項目ずつをグループに追加してやればOKです。このとき、配列からぬきだす1項目は「item()」として取得できます。JSONのときのように細かい指定が不要なのもシンプルな配列のよいところです。
同様にメンバー削除の処理もApply to eachで作成しました。
しばらくしてTeamsを確認してみると、Excel表どおり(終了日指定したメンバーは含まれず)の状態になっていました。
もっとスマートな追加方法もあり
処理としては以上で作成完了。トリガーを定期的な実行に修正すれば完成です。
Apply to eachは繰り返し処理なのですが、1名ずつユーザーを追加するのではなくて、一気に追加することができるとよりスマートです。
そんなことできるんですか?! できるんです。Graph APIならばね!
というわけで、参考にさせていただいたのがコルネさんのこちらの記事です。
Microsoft の公式資料はこちら!
なんと、カンマ区切りの配列で、Graph APIのエンドポイントにユーザーを突っ込んでやることができるようです。
できるかな?
まずはテストです。Graph APIはHTTPリクエストが必要で、普通はHTTPを飛ばすにはプレミアムコネクタが必要なのですが、機能限定型のHTTP要求アクションが用意されています。今回はグループへのメンバー追加ですので、使うのはグループ用のこいつです。
まずは1名のみ追加でテストしてみます。エンドポイントにはグループのオブジェクトID。
本文の配列には1名分のみ、ユーザーもオブジェクトIDで試したところ追加に成功しました。
今度はユーザーのオブジェクトIDに変えて、ユーザーのUPNで試してみます。
残念。ダメでした。
あらかじめExcelファイルにユーザーのオブジェクトIDを用意しておくならよいのですが、1名ずつアクションやAPIをつかって取得するならばAppley to eachを使う必要があり、結局いっぱつで登録する前に余分な前処理が必要なので、それならいいや、とも思ったのですが。
実践してやろうじゃないですか?ここからは半ばヤケクソ処理なのでお付き合いください。
追加すべきメンバー配列をひとつずつループでユーザーの検索に渡しました。
その結果から「作成」を使って以下の位置にあるオブジェクトIDを取り出し、予め作っておいた配列に追加します。ここまでが第一段階。
outputs('ユーザーの検索_(V2)')?['body/value'][0]?['Id']
うまくIDをが取得できていることをテストできたら、「作成」で取得したオブジェクトIDの前にエンドポイントを追加。これが配列に追加されるので、うまく行けばそのままHTTP要求のBodyに使えるのでは?
配列変数に追加した結果を「作成2」で確認していたんだけれど、それをおもむろにHTTP要求のBodyの中に貼ってみた。まあ、型違いのエラーよね?
なんと! 配列をテキスト化せずにそのまま「作成」を貼り付けたのに動いた?!
念の為、「作成」にいれないままの配列変数を直接貼ってみたら、こちらも動きました。 そうなんだ・・・。
まとめ
というわけで、かなり横道にそれましたが。今回の学びは以下のような点でした。
- 「選択」アクションを作ってメンバーの配列を作る
- 配列の差を抽出するにはアレイのフィルター処理アクションとContains関数をうまくつかう
- Graph APIを使えば一気にメンバーを追加できるけれど、あらかじめオブジェクトIDに変換しておく必要あり
- 配列をHTTP要求のBodyに直接貼り付けるとなぜかテキストとして認識されてそのまま使える
定期的な処理には、処理結果をTeamsのチャネルなどに報告させる処理を加えておくと、より管理できてる感がでて良いかと思います。よろしければ使ってください。
こんな人が書きました
こちらの記事はランゲルハンス島のDDさんが紹介しました。ブログでクラウドフローのTIPSのようなものを書いたり、Qiita記事を書いたりしていますのでご贔屓に。関西のPowerPlatform系の勉強会にときどき出没しますので、気軽に声をかけていただけると喜びます!