2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PowerAppsで他人のOutlookスケジュールを一覧表示する

Last updated at Posted at 2024-12-16

他人の予定表を取得するアプリ

  • Power Appsでよく出てくる方法はOutlookコネクタの「FindMeetingTimesV2」
    • この方法のデメリットは、空き時間しか分からない、他人が会議に返答していないと空き時間扱いになる
  • そこで、Graph APIを使ってOutlookと同じく会議の開始~終了の時間や参加の情報まで一覧で取得します。
  • 例えば以下のように表示します。 工夫すればガントチャート表示もできると思います。
    image.png

Outlookの予定表のアクセス権

デスクトップアプリの画面では、以下のような4段階のアクセス権があります。
既定では他人からタイトルと場所の表示が可能です。組織によっては共有相手が自組織の配下に制限されている場合もあります。
image.png

アクセス権と予定の取得方法を整理すると

  • Power AppsのOutlookコネクタでは、他人の予定が見えるのは空き時間のみのようです
  • 他人のメールアドレスを指定して予定を見るには、GraphAPIを使う必要がありそうです
  • 間違ってたらごめんなさい
予定表のアクセス権 他人から見える情報 Outlookコネクタ Graph API
空き時間情報の表示が可能 空き時間の表示 FindMeetingTimesV2 findMeetingTimes
タイトルと場所の表示が可能(既定) 会議時間、場所、タイトル 他人の予定は不可 getSchedule
全ての詳細を表示可能(本文を含む) 上記に加えて本文 他人の予定は不可 events

Graph APIとGetSucheduleエンドポイント

  • 以下のドキュメントの通りです
  • 予定表を見たい相手のカレンダーが自分に対して「タイトルと場所の表示が可能」で共有されていることが前提ですが、Outlookのように詳細な情報が取得できます

要求の例

  • メールアドレスアドレスと、開始時間、終了時間、時間間隔を指定します
POST https://graph.microsoft.com/v1.0/me/calendar/getSchedule
Content-Type: application/json

{
    "schedules": ["adelev@contoso.com", "meganb@contoso.com"],
    "startTime": {
        "dateTime": "2019-03-15T09:00:00",
        "timeZone": "Tokyo Standard Time"
    },
    "endTime": {
        "dateTime": "2019-03-15T18:00:00",
        "timeZone": "Tokyo Standard Time"
    },
    "availabilityViewInterval": 30
}

応答の例

  • ユーザーのスケジュールID、スケジュールアイテムが配列で返されます
  • 会議の応答ステータス、件名、場所、時間の情報が見えます
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.scheduleInformation)",
    "value": [
        {
            "scheduleId": "adelev@contoso.com",
            "availabilityView": "000220000",
            "scheduleItems": [
                {
                    "isPrivate": false,
                    "status": "busy",
                    "subject": "Let's go for lunch",
                    "location": "Harry's Bar",
                    "start": {
                        "dateTime": "2019-03-15T12:00:00.0000000",
                        "timeZone": "Pacific Standard Time"
                    },
                    "end": {
                        "dateTime": "2019-03-15T14:00:00.0000000",
                        "timeZone": "Pacific Standard Time"
                    }
                }
            ],
            "一部省略": {
            }
        }
    ]
}

Power AutomateとGraph APIで他人の予定を取得する

  • 直接Power Appsから呼び出すと応答JSONの解析が面倒そうなので、一旦Power Automateで前処理します
  • 最近登場したユーザー定義型変数に期待?

フロー全体像

image.png

解説

抜粋して解説します。

トリガー

  • Emails:メールアドレスをカンマ区切りで指定
  • DateTimeは開始時間、終了時間をJSTで指定
    image.png

Graph APIの呼び出し

image.png

JSONをフラットに変換してアプリで扱いやすくする

JSONの解析

  • GraphAPIの応答を、JSONの解析で加工しやすくしておきます
  • スキーマは一工夫が必要です
  • 予定がPrivateだとsubjectなどがnullになるので許容するよう変更が必要です

image.png

スキーマ
{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "scheduleId": {
                "type": "string"
            },
            "availabilityView": {
                "type": "string"
            },
            "scheduleItems": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "isPrivate": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        },
                        "status": {
                            "type": "string"
                        },
                        "subject": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "location": {
                            "type": [
                                "string",
                                "null"
                            ]
                        },
                        "isMeeting": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        },
                        "isRecurring": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        },
                        "isException": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        },
                        "isReminderSet": {
                            "type": [
                                "boolean",
                                "null"
                            ]
                        },
                        "start": {
                            "type": "object",
                            "properties": {
                                "dateTime": {
                                    "type": "string"
                                },
                                "timeZone": {
                                    "type": "string"
                                }
                            }
                        },
                        "end": {
                            "type": "object",
                            "properties": {
                                "dateTime": {
                                    "type": "string"
                                },
                                "timeZone": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "required": [
                        "status",
                        "start",
                        "end"
                    ]
                }
            },
            "workingHours": {
                "type": "object",
                "properties": {
                    "daysOfWeek": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "startTime": {
                        "type": "string"
                    },
                    "endTime": {
                        "type": "string"
                    },
                    "timeZone": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string"
                            }
                        }
                    }
                }
            }
        },
        "required": [
            "scheduleId",
            "availabilityView",
            "scheduleItems",
            "workingHours"
        ]
    }
}

Apply to Eachを入れ子にして、scheduleItemsを配列に格納していく

  • scheduleIdとscheduleItemsの要素がフラットになるように配列変数に追加していきます

image.png

作成の数式
{
  "scheduleId": @{items('Apply_to_each:本文')['scheduleId']},
  "status": @{items('Apply_to_eachItems')['status']},
  "subject": @{coalesce(items('Apply_to_eachItems')?['subject'], '-')},
  "location": @{coalesce(items('Apply_to_eachItems')?['location'], '')},
  "start": @{items('Apply_to_eachItems')?['start']?['dateTime']},
  "end": @{items('Apply_to_eachItems')?['end']?['dateTime']}
}


最後はアプリに応答します

image.png

Power Appsから呼び出す

  • 以下の数式でPower Automateを呼び出します
  • colSchedulesにスケジュール一覧がセットされるので、任意の形式で表示します
  • 以下の例で_userEmailに他人のEmailが入るようにします
  • カンマ区切りで指定すると複数ユーザーの予定を取得できると思います
// 8時~22時の時間テキスト
UpdateContext(
    {
        _startDatetimeJST : Text(DatePicker1.SelectedDate,"yyyy-mm-dd") & "T08:00:00",
        _endDatetimeJST : Text( DatePicker1.SelectedDate,"yyyy-mm-dd") & "T22:00:00"
    }
);

// スケジュールを取得
ClearCollect(
    colSchedules,
    ForAll(
        // フローを実行してParseJson
        Table(ParseJSON(
            Outlook_スケジュールを取得.Run(_userEmail, _startDatetimeJST,_endDatetimeJST).value
        )),
        // 匿名型を型オブジェクトにマッピング
        {
            scheduleId: Text(ThisRecord.Value.scheduleId),
            subject: Text(ThisRecord.Value.subject),
            location: Text(ThisRecord.Value.location),
            status: Text(ThisRecord.Value.status),
            start: DateAdd( DateTimeValue(ThisRecord.Value.start), 9,TimeUnit.Hours) ,
            end: DateAdd( DateTimeValue(ThisRecord.Value.end), 9,TimeUnit.Hours) 
        }
    )
);


If(IsEmpty(colSchedules),Notify("本日のスケジュールは一件も見つかりませんでした。",NotificationType.Information,2000))

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?