月別アーカイブ: 2022年10月

Power Automateの実行ユーザーから特定の個人へTeamsチャットのメッセージ送信

PowerAutomateのインスタントクラウドフローは、フローの所有者のほかに「実行のみユーザー」という権限でほかのユーザーに共有できます。この機能を使って、フローを実行するユーザーAから別のユーザーBへTeamsチャットでメッセージを送信することを考えます。

Teamsコネクタのアクションを調べていくと、チャットまたはチャネルでメッセージを投稿するを使用すればチャットのメッセージを送れるような気がします。ところが、チームのチャネルに投稿する方法とグループチャットに投稿する方法はわかりやすいわりに、普通のチャットすなわち個人から個人へチャットする場合はどうしたら良いかぱっと見でわかりません。そこで、このページでは個人から個人へチャットを送る方法を2つ紹介します。

フローの例

フローの例を下図に示します。分岐の右側のフローが方法1、左側が方法2です。

方法1: グループチャットの宛先に1人だけ入れる

それアリ?という感じがしますが、これが最もそれらしい振る舞いをします。

まず、チャットの作成アクションで追加するメンバーに宛先となるメールアドレスを入力します。ここで、宛先のメールアドレスがひとつだけの場合、フロー実行者と宛先の2者間のチャットを指定する会話IDが返ります。グループチャットのタイトルを指定する欄がありますが、タイトルを何にしようと影響はなく、常に2者間の通常のチャットを指定する会話IDが返ります。

こうして得られた会話IDを使って、チャットまたはチャネルでメッセージを投稿するアクションを動作させます。投稿者をユーザーとすればフローの実行者がチャットを送信することになります。投稿先をグループチャット、グループチャットには先ほどの会話IDを入れます。メッセージの記入欄が表示されるので、そこに動的なコンテンツを含むメッセージ本文を記入します。リンクを張りたい場合などは、ボタンを押してHTMLを記述します。

チャットの作成アクションの宛先について注意が必要な点として、実行ユーザー自身を指定できません。もしチャットの宛先にフローの実行者が入る可能性がある場合は、後述する方法2を使用します。

チャットの作成アクションは、宛先が複数のときと今回試したような宛先が1つのときで挙動が違うのに注意してください。宛先が複数あるとき、すなわちグループチャットを作成する場合にはグループチャットの構成メンバーとタイトルが同一であろうとチャットの作成アクションが動作するごとに異なる会話IDが生成されます。

方法2: フローボットとのチャット

チャットまたはチャネルでメッセージを投稿するアクションで、投稿者を「フローボット」、投稿先を「フローボットとチャットをする」に設定します。
宛先の指定は、Recipientに受信者のメールアドレスを指定するだけで十分です。
メッセージの記入欄が表示されるので、そこに動的なコンテンツを含むメッセージ本文を記入します。リンクを張りたい場合などは、ボタンを押してHTMLを記述します。

番外編: チャット相手を指定してTeamsクライアントを立ち上げる

URIスキーマを使うと、宛先を指定した状態でTeamsクライアントのチャット画面を開かせることができます。
宛先のメールアドレスがexample@onmicrosoft.comのとき
https://teams.microsoft.com/l/chat/0/0?users=example@onmicrosoft.com
のように書きます。
PowerAppsのLaunch関数でこのようなURIスキーマを開かせることで、通常のTeamsクライアントでチャットを送る動作をとれます。

番外編: Power AppsからTeamsコネクタを使ってメッセージを送る

Power AppsのSharePointコネクタでリストを読み込んだり、Outlookコネクタでメールを送信したりするのと同様に、Teamsコネクタでメッセージを送信できます。私はやり方がわからなかったのでAutomateで処理しましたが、Power AppsからTeamsのグループチャットに直接メッセージを送る方法を真似すればできそうな気がします。

Power Apps上で処理が完結できると、エラー処理を含めてユーザーにフィードバックを与えながら処理をできるので、全体としてUXが向上すると期待できます。

追記: PowerAppsから直接Teamsにメッセージを送信する方法をまとめました。

PowerAppsカレンダー画面の拡張 データソースをOutlookからSharePointリストに変えて

PowerAppsではシナリオとして典型的な操作を行うための画面が用意されています。複雑な機能を実現するのにシナリオで用意された画面を改変することで自分の目的を達成することができます。この記事では、予定表の表示に使用する「カレンダー」シナリオを拡張する例を紹介します。

シナリオで用意された画面の構成を調べる

改変するには元がどうなっているかを理解する必要があります。「カレンダー」シナリオで用意された画面の構成を調べてみましょう。

PowerAppで新しい携帯電話レイアウトのキャンバスアプリを作成します。続いて、新しい画面を使いする操作から、シナリオの「カレンダー」を選択します。

操作に成功すると、次のような画面が表示されます。画面上部のドロップダウンはPowerAppsで表示する予定表を選択するのでしょうか。ドロップダウンの右のカレンダーアイコンはまだよくわかりません。画面の下部はまずドロップダウンから予定表を選択せよとの指示です。

アプリの動作を確認するため、画面右上の再生ボタンかAltキーを押しながら画面をクリックします。ドロップダウンから「日本の休日」を選択すると、画面が以下のように変わります。

この画面を見ると、「カレンダー」シナリオの画面構成がどうなっているか、だいたい見当がつくでしょう。画面上段は表示すべきカレンダーの選択、画面中段は日付の選択、画面下段は選択した日に入っている予定の一覧です。

また、ドロップダウンを操作したときに画面の大部分が表示されたことから、ドロップダウンに主要なデータ操作が仕込まれていると予想できます。そこで、ドロップダウンのOnSelectやOnChangeを見てみましょう。

ドロップダウンのOnSelectを見ると、何行にもわたるコードが記述されていました。各行を読んでいくと、Office365Outlookコネクタを利用して予定表に登録されている予定の一覧を読み出すGetEventsCalendarViewV2を実行している行があります。この行ではClearCollect関数を使って、読みだした予定の一覧をMyCalendarEventsという名前のコレクション(テーブル)に保持するようだとわかります。

予定表から読みだされるデータはどのような形式かを確認します。PowerAppsの編集画面からコレクションの中身を確認してみましょう。次のような横に長い画面が出てきます。

ここで大事なのは列名とその列にどのようなデータを入れることになっているかです。また、多くの列がありますがほとんどPowerAppsのアプリでは使用していないデータです。一通り列名とデータを確認すると、このあと使いそうなデータは次の4つくらいでした。

列名入っているデータ(予想)入っているデータの型(予想)
End予定の終了年月日時刻時刻
Location予定の場所テキスト
Start予定の開始年月日時刻時刻
Subject予定の題名テキスト

Outlookの予定表から読みだした各予定の情報は高々この程度です。これらがClearCollect関数でMyCalendarEventsという名前のテーブルに格納されているとわかったら、同じ形式のテーブルを用意してやれば、「カレンダー」シナリオの画面をそのまま使いまわせるでしょう。具体定期には、SharePointリストで上の表にまとめたような列を持つリストをOutlook予定表の代わりにデータソースにできるはずです。

SharePointリストに登録したアイテムを予定として読み出す

前のセクションで予定を入れるのに必要なSharePointリストの列は4つ(End, Start, Location, Subject)だろうと見積もりました。このような列を持つSharePointリストを作ってみます。

EndとStartは「日付と時刻」型の列とします。時間を含めるを「はい」にして列を作成します。LocationとSubjectは1行テキストとします。

試しにデータを入れてみました。ここでは「Outlook代替」という名前のリストにしています。

ここで作成したSharePointリストをPowerAppsで読み込んでみましょう。

まずSharePointリストをPowerAppsから参照できるようにします。「データ」>「データの追加」>「SharePoint」で作成した「Outlook代替」リストを指定します。

次にSharePointリストのデータをPowerAppsの「カレンダー」シナリオに合うように読み込みます。単にMyCalendarEventsという名前のテーブルに「Outlook代替」リストの中身を流し込めば十分です。下の例では「SharePoint読込」というボタンのOnSelectに以下のような関数を定義しています。

ClearCollect(MyCalendarEvents, Outlook代替);

「日本の休日」カレンダーには存在しない「hoge」なるイベントを予定表に表示できました。「Outlook代替」で仮に登録したデータが表示されています。

ついでに表示される項目を変更してみましょう。上の図で太字のhogeと表示されているのはSubject列の値です。この部分のTextにはThisItem.Subjectが定義されています。これをThisItem.TitleにすればTitle列の値が表示されます。

「カレンダー」シナリオでは、開始時刻Start、件名Subject、所要時間(終了時刻Endと開始時刻Startの差分を分単位で表示)、場所Locationを表示する構成になっています。これを置き換えたり、追加したり削除したりすることで、自分の用途に必要十分な予定表を作れるでしょう。

予定表に表示される予定の条件を変更する

「カレンダー」シナリオの初期条件では、選択した日付に開始される予定が一覧に表示されます。予定を一覧表示するギャラリーのItemsは次のように定義されています。Text関数はDateTimeFormat.ShortDateで年月日を返します。

SortByColumns(Filter(MyCalendarEvents, Text(Start, DateTimeFormat.ShortDate) = Text(_dateSelected, DateTimeFormat.ShortDate)), "Start")

それでは、複数日にまたがる予定はどうなるでしょうか?先に作成した「Outlook代替」リストには25日から27日またがる予定「ほげ」が入っています。しかし、この予定表では26日や27日に予定「ほげ」が表示されません。

関数を書き換えて、日をまたぐ予定も表示されるようにしましょう。SortByColumnsはただの並べ替えですので、まず注目すべきはFilter関数の中身です。

Filter(MyCalendarEvents, Text(Start, DateTimeFormat.ShortDate) = Text(_dateSelected, DateTimeFormat.ShortDate))

予定の開始日時Startと予定の終了日時Endを使って、選択した日(0時から24時)にかかる予定を表示するようにするにはどうしたらいいでしょうか。状況を整理するため、下図を見てください。表示したい予定の条件は何通りかありますが、表示したくない予定は「終了時刻が選択日の0時より前」と「開始時刻が選択日の24時以降」の2パターンであることがわかります。

「終了時刻が選択した日の0時よりも前の予定」と「開始時刻が選択した翌日0時以降の予定」はいずれも選択した日にかかる予定ではありません。したがって、これの否定Notを取ればいいわけです。選択した日の0時_dateSelectedを使って以下のように書けます。

日付の大小関係を比較するにはDateTimeValue関数で日付を数値に変換します。また、日付の計算にはDateAddまたはDateDiff関数を使います。日付の計算は特殊なので、使い方の例も見てみましょう。

Filter(MyCalendarEvents, 
    Not(
        Or(
            DateTimeValue (End) < DateTimeValue (_dateSelected),
            DateTimeValue (Start) >= DateTimeValue (DateAdd( _dateSelected, 1, Days))
        )
    )
)

否定Notで書くと一見してわかりにくいので、ド・モルガンの法則を使って書き換えておきます。「(AまたはB)の否定」は「(Aの否定)かつ(Bの否定)」に同値です。日本語で表現すれば、予定の終了日時が選択日の0時以降でありかつ予定の開始日時が選択日の24時よりも前ということです。日本語で表現しても、それっぽい感じがします。

Filter(MyCalendarEvents, 
        And(
            DateTimeValue (End) >= DateTimeValue (_dateSelected),
            DateTimeValue (Start) < DateTimeValue (DateAdd( _dateSelected, 1, Days))
        )
    )
)

これで当日にかかる予定で複数日にまたがるものを拾えるようになりました。

「カレンダー」シナリオでは、予定が入っている日付の下に小さい丸が表示されます。これの予定が入っている判定は前述の条件と同じく予定の開始日が日付と一致するです。前節で改変したように、複数日にまたがる予定がある場合に、予定がかかるすべての日に対して小さい丸を表示するようにしてみましょう。

小さい丸のVisibleプロパティは次のように指定されています。

/*Visible if calendar events are found on this day*/               
CountRows(Filter(MyCalendarEvents,
 DateValue(Text(Start)) = DateAdd(_firstDayInView,ThisItem.Value,Days)
)) > 0 
&& !Subcircle1.Visible 
&& Title2.Visible

予定の開始日時のDateValue(年月日)が、この日と同じ
かつSubcircle1(選択された日表示)がVisibleでない
かつTitle2 (日付) がVisibleである
という意味です。

1行目のCountRows関数に与えている当日の予定を抽出するFilter条件式を改変すれば目的を達成できそうです。
上の例から、カレンダーの一覧表示において、各日付はDateAdd(_firstDayInView, ThisItem.Value, Days)で表現できることがわかりました。これは各日付の0時を指す日時になります。予定がその日にかかるかを判定するには、予定の終了がその日の0時よりも後であって、かつ予定の開始が翌日0時よりも前であれば良いです。翌日0時は上の例にならってDateAdd(_firstDayInView, ThisItem.Value + 1, Days)と書けます。に予定がかかるかを判定したいので、基準となる日付は一覧の最初の日と最後の日です。したがって、Filter関数を次のように書き換えることになります。

/*Visible if calendar events are found on this day*/               
CountRows(Filter(MyCalendarEvents, 
        And(
            DateTimeValue (End) >= DateAdd(_firstDayInView, ThisItem.Value, Days),
            DateTimeValue (Start) < DateAdd(_firstDayInView, ThisItem.Value + 1, Days)
        )
    )
) > 0 
&& !Subcircle1.Visible 
&& Title2.Visible

以上でSharePointリストをソースとしたPower Appsカレンダー表示が完成です。