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カレンダー表示が完成です。
やりたいことがここに乗ってて本当に良かったです。
出来ればもっと細かく知りたいのですが可能でしょうか
下記部分より
>>
ここで作成したSharePointリストをPowerAppsで読み込んでみましょう。
まずSharePointリストをPowerAppsから参照できるようにします。「データ」>「データの追加」>「SharePoint」で作成した「Outlook代替」リストを指定します。
次にSharePointリストのデータをPowerAppsの「カレンダー」シナリオに合うように読み込みます。単にMyCalendarEventsという名前のテーブルに「Outlook代替」リストの中身を流し込めば十分です。下の例では「SharePoint読込」というボタンのOnSelectに以下のような関数を定義しています。
ClearCollect(MyCalendarEvents, Outlook代替); ←どこを変えるのでしょうか
テンプレートで使われているMyCalendarEventsというコレクションにデータを流し込むコネクタを変えています。
テンプレートでは、ドロップダウンのOnSelectで、outlookコネクタを使って予定表を読み出します。
私の書いた例では、新しく作ったボタンのOnSelectで、SharePointコネクタを使ってリストを読み出しています。
リストの列名をOutlook予定表を読みこんだものと揃えることで、データをMyCalendarEventsに流し込む一点だけを変更することでテンプレートを動作させています。
大変勉強になりました。
一つ教えていただきたいのですが、最後の小さい丸を日をまたいだイベント分表示する際、Countraws以降どのように変更すればよいでしょうか。
書きかけなのを忘れていました。今しがた更新したので確認してください。
更新ありがとうございます。出来ました。
自分なりに考えて似たような構文までは出来ていたのですが、エラーになっており困っていました。
本当に助かりました。