
Power Appsのギャラリー機能を使い、各個人のOutlookスケジュールを詳細に表示する方法を紹介します。

Outlookのスケジュールを自動的に取得するためには Power Automate を使います。
例では当日を含めて6日分の予定を30分毎に更新し、特定のSharePoint Listに保存しています。
詳しいやり方は先にこちらをご覧ください。
使用している環境の紹介
この予定表示は、こちらで紹介している「テレワークか出社か表示するアプリ例」で実装している機能です。


このうち、青島さん(仮名)を例にして紹介していきます。
具体的なやり方
予定を保存したSharePoint Listをキャンバスアプリに接続し、コレクションに格納します。
Apps.OnStartでもいいですし、スクリーンのOnVisibleなどを利用するといいでしょう。
ClearCollect(AoshimaCollection, 青島スケジュール)
続いて名前を表示するボタンを作ります。
ボタンのTextは表示させたい人の名前を入力し、OnSelectは次の式を入れます。
Set(OnesSchedule, AoshimaCollection);
Set(OnesName, Self.Text);
Navigate(scrScheduleDetail, ScreenTransition.Fade);
ここではグローバル変数を2つ宣言しています。
- OnesSchedule:AoshimaCollectionをOnesScheduleに格納しています。
 - OnesName:ボタンのTextの値をOnesNameに格納しています。
 
Selfはそのコントロールが持つプロパティの値を参照することができる、非常に便利な関数ですね。
Navigate関数で別のスクリーンに遷移します。
ここではscrScheduleDetailというスクリーンをあらかじめ作成済みです。
ところが実は、このコードは問題を抱えています。
人が増えても大丈夫なように工夫しておく
※ ここのやり方はちょっと複雑なことを書いていますので、難しい人は飛ばして次の段落へ進んでください ※
私が作成した「テレワークか出社か表示するアプリ例」は、30人を越えるメンバーの予定を表示しています。
ここで問題になるのが、人が増えた時に関数の管理が大変になることです。
もう一度さきほどのコードを見てみます。
Set(OnesSchedule, AoshimaCollection);
Set(OnesName, Self.Text);
Navigate(scrScheduleDetail, ScreenTransition.Fade);
人が増えたときに問題になるのは、1行目の Set(OnesSchedule, AoshimaCollection) の AoshimaCollection の箇所。
ここはいわゆるハードコーディング(直打ち)してしまっているので、いざ修正や変更となるとボタンの数だけ1つ1つ手直ししなくてはいけません。
そこでFormulasを使用します。

Formulasで設定する内容は、常にアプリに反映されます。
Apps.OnStartのように挙動が重たくなることもなく、変数などをこちらで宣言しておくことで開発・メンテナンスがとても簡単になります。
Formulasには次のように入れます。
ScheduleItems=
Table(
    {
        Name: "青島",
        Collection: AoshimaCollection
    }
);

ポイントは、Nameの値をボタンのTextと一致させておくことです。
その上で、ボタンのOnSelectの関数を次のようにします。
Set(OnesSchedule, LookUp(ScheduleItems, Name=Self.Text).Collection);
Set(OnesName, Self.Text);
Navigate(scrScheduleDetail, ScreenTransition.Fade);
1行目の AoshimaCollection が LookUp(ScheduleItems, Name=Self.Text).Collection に変わりました。
Formulasで定義したScheduleItemsのうち、Name項目がボタンのText(Selt.Text=青島)に一致する項目を見つけ、そのCollection項目の中身(AoshimaCollection)をOnesScheduleに格納する、という内容です。
もし人が増えてきたら、Formulasは次のように増やしていきます。
ScheduleItems=
Table(
    {
        Name: "青島",
        Collection: AoshimaCollection
    },
    {
        Name: "伊藤",
        Collection: ItoCollection
    },
    {
        Name: "上田",
        Collection: UedaCollection
    },
    {
        Name: "榎本",
        Collection: EnomotoCollection
    },
    {
        Name: "大塚",
        Collection: OtsukaCollection
    }
);
ここでの注意点は2つあります。
- コード末尾は必ず ; で終えること
 - 〜Collectionは Apps.OnStartで宣言しておかないとFormulasでエラーになる
 
これを守っておけば大丈夫です。
ギャラリーを入れ子にするのがポイント
続いて scrScheduleDetailという名前で空のスクリーンを追加します。
まず先にツリービューをお見せします。

galDateは日付を表示するためのものです。
入れ子にしたgalScheduleDetailは、その日の予定を表示します。
galDateの中にgalScheduleDetailを入れ子にして使うのがここでのポイントですね。
galDateのItemsには次の式が入ります。
Table(
    {
        ID: 1,
        Date:
            Text(Today(), "m/d") & "(" &
            Switch(
                Weekday(Today()),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            ) & ")",
        LookupDate: Text(Today(), "yyyy/mm/dd"),
        LookupWeekday: 
        Switch(
                Weekday(Today()),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            )
    },
    {
        ID: 2,
        Date:
            Text(Today() + 1, "m/d") & "(" &
            Switch(
                Weekday(Today() + 1),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            ) & ")",
        LookupDate: Text(Today() + 1, "yyyy/mm/dd"),
        LookupWeekday: 
        Switch(
                Weekday(Today() + 1),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            )
    },
    {
        ID: 3,
        Date:
            Text(Today() + 2, "m/d") & "(" &
            Switch(
                Weekday(Today() + 2),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            ) & ")",
        LookupDate: Text(Today() + 2, "yyyy/mm/dd"),
        LookupWeekday: 
        Switch(
                Weekday(Today() + 2),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            )
    },
    {
        ID: 4,
        Date:
            Text(Today() + 3, "m/d") & "(" &
            Switch(
                Weekday(Today() + 3),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            ) & ")",
        LookupDate: Text(Today() + 3, "yyyy/mm/dd"),
        LookupWeekday: 
        Switch(
                Weekday(Today() + 3),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            )
    },
    {
        ID: 5,
        Date:
            Text(Today() + 4, "m/d") & "(" &
            Switch(
                Weekday(Today() + 4),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            ) & ")",
        LookupDate: Text(Today() + 4, "yyyy/mm/dd"),
        LookupWeekday: 
        Switch(
                Weekday(Today() + 4),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            )
    },
    {
        ID: 6,
        Date:
            Text(Today() + 5, "m/d") & "(" &
            Switch(
                Weekday(Today() + 5),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            ) & ")",
        LookupDate: Text(Today() + 5, "yyyy/mm/dd"),
        LookupWeekday: 
        Switch(
                Weekday(Today() + 5),
                1, "日",
                2, "月",
                3, "火",
                4, "水",
                5, "木",
                6, "金",
                7, "土"
            )
    }
)
簡単に解説します。
ID列
私が作った「テレワークか出社か表示するアプリ例」の仕様に合わせて6日分の日付を表示するようにしています。
ID列はあっても無くてもいいのですが、わかりやすくするために入れてます。
Date列
今日や明日などの日付と曜日を 4/14(月) の形式で表示させます。
Today関数を使うことで、動的に表示を変更しています。
LookupDate列
日付をyyyy/mm/ddで表示させます。
これは入れ子にしたgalScheduleDetailで利用する参照列として機能します。
LookupWeekday列
その日の曜日だけを取り出しています。
これはgalDateの曜日を色付けして表示するために機能します。
次に、各コントロールのプロパティを見ていきます。
lblDate
Text:
ThisItem.Date
Color:
Switch(
    ThisItem.LookupWeekday,
    "日", Color.Red,
    "土", Color.Blue
)
日曜日を赤色、土曜日を青色で表示するようにしています。
祝日には対応していないため、別途祝日Listなどを用意して接続すれば、より見やすい表示になるでしょう。
galScheduleDetail
Items:
Sort(
    Filter(OnesSchedule, Text(DateTime, "yyyy/mm/dd")=ThisItem.LookupDate),
    DateTime,
    SortOrder.Ascending
)
Height:
CountRows(
    Filter(
        OnesSchedule,
        Text(
            DateTime,
            "yyyy/mm/dd"
        ) = ThisItem.LookupDate
    )
) * 140
Height 140 を掛けるようにしています。
ご自身の環境に合わせて数字は変更してください。
lblScheduleTitle
Text:
ThisItem.'Title (Title0)'
lblTitle
Text:
Text(
    ThisItem.DateTime,
    "H時mm分"
)
SharePoint Listの作り方によっては列名が異なる場合があります。
ご自身の環境に合わせた列名に置き換えて使ってください。
応用に向けたアイディア
未実装ですが、アイディアだけは持っています。
開発時間対効果がどこまで期待できるかという問題がありますので、もし時間があるようなら作ってみたいと考えています。
複数人の予定を同時表示する
現状は1人だけの予定詳細しか見れませんが、何人かの予定を同時に表示させると便利になると思います。
バーで予定を表示する

今はテキストだけの表示ですが、こういう画像のように色付きバーで予定が見えるとわかりやすくなると思います。
複数人の予定を同時に表示するなら、横向きのバーがわかりやすいですね。
アプリから予定を変更する
これは機能的に実現可能かわかりませんが、市民開発アプリからOutlookの予定を変更できるようになると、もっと便利になるでしょう。
ギャラリーの入れ子は1階層までしか入らない
ギャラリーの入れ子は便利ですが、1階層までしか入れることができません。

入れ子を多様するとアプリが重たくなる原因にもなりますので、ほどほどに使いましょう。