きっかけ
自社の会議室は180日後までが予約可能に設定されてます。
定期定例会は定期予定設定で期日未定で参加者設定できますが、会議室は180日以内であれば定期予定の会議場所として設定できるものの、それより先の予定は都度確保しなければならないです。
会議室確保の競争が激しい場合、開放タイミング早々に予約しなければならないため、予約ストレスからの解放を目指して自動化を行いました。
PowerAutomate:子フローの作成 をベースにOutlook会議室予約を子フロー化したので内容を紹介します。
なお、同じような苦労をしている人が周りにもいること、将来の引継ぎなどふまえ、フローの共同所有や実行のみの共有なども行う前提で作成してます。
本フローの共有方法は、PowerAutomate:子フローの共有 に記載してます。
フロー内では祝日判定を行うため、PowerAutomate:子フロー:営業日判定 を利用してます。
<親フロー処理例①:週次で180日後の会議室予約>
180日後の週次定例会(毎週月曜10~11時)の会議室(候補:room1~4)を予約するサンプルフローです。月曜の180日後は水曜なので、定期実行は水曜に行い、会議室解放時に即予約できます。

<親フロー処理例②:180日後までの週次定例の会議室予約>
明日(1日後)~180日後までの週次定例会(毎週月曜10~11時)の会議室(候補:room1~4)を予約するサンプルフローです。180回ループを繰り返しますが、子フロー内で平日月曜のみしか予約しないよう制御し、祝日以外の週次定例を180日後までまとめて予約できます。

子フロー全体像
①トリガ設定
親フローからは7つの引数を渡します。
- [必須:文字列] 会議名
- [必須:文字列] 会議開始時間(日本時間で
HH:mm:ss形式) - [必須:文字列] 会議終了時間(日本時間で
HH:mm:ss形式) - [必須:文字列(配列)] 会議室配列(JSON配列形式)
- [必須:文字列] 実行者メアド
- [任意:数値] 曜日数値(1:月曜、2:火曜、3:水曜、4:木曜、5:金曜)
- [任意:数値] 経過日数(未指定の場合は180)
会議室配列
Outlookアドレス帳で設備・会議室等に登録される会議室メールアドレスをJSON配列文字列として設定します。予約したい会議室の優先順位が「room1@hoge.com」「room2@hoge.com」「room3@hoge.com」の場合は以下となります。
実行者メアド
本フローを共同利用するための設定のため、本人しか使わないフローであれば、本入力や設定は不要です(必要に応じて実装修正してください)。
曜日数値
親フローが毎日処理するようなものの場合、曜日指定があれば、予約日が指定曜日に一致する場合のみ予約処理を行い、指定がなければ曜日チェックは行わないようにします。
経過日数
自社では180日までの会議室が予約できる(会社によって違うかも)ので、今日を起点に明日なら「1」、明後日なら「2」を指定、未指定の場合は180日とします。
フロー処理曜日と予約曜日を揃える場合は7の倍数を指定する。
※上限が180日の場合、「175」を指定すれば処理日と同じ曜日の最大値になります
②変数初期化
『変数を初期化する』で以下10個の変数を設定します。
| 名前 | 種類 | 初期値 |
|---|---|---|
| 会議名 | 文字列 | @{triggerBody()['text']} |
| 経過日数 | 整数 | 180 |
| 会議開始時間 | 文字列 | @{null} |
| 会議終了時間 | 文字列 | @{null} |
| 曜日変数 | 整数 | -1 |
| 会議室配列 | 文字列 | @{null} |
| 通知メアド | 文字列 | @{null} |
| 予定登録ユーザID | 文字列 | @{null} |
| 処理ステータス | 整数 | 0 |
| エラーメッセージ | 文字列 | @{null} |
③スコープ1:入力チェック
③-1) 会議名=空値?
『条件』で入力会議名の空値判定をします。
- 左辺: (式)triggerBody()?['text']
- 条件:次の値に等しい
- 右辺: (式)null
③-2) 処理ステータス変数の設定(会議名エラー=-11)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-11
③-3) 経過日数=空値?
『条件』で経過日数の空値判定をします。
- 左辺: (式)triggerBody()?['number_1']
- 条件:次の値に等しい
- 右辺: (式)null
③-4) 経過日数正常?
『条件』で経過日数が0~180の範囲内かを判定します。
<And条件1>
- 左辺: (式)triggerBody()?['number_1']
- 条件:次の値以上
- 右辺: (値)0
<And条件2>
- 左辺: (式)triggerBody()?['number_1']
- 条件:次の値以下
- 右辺: (値)180
③-5) 経過日数変数の設定
『変数の設定』で経過日数を指定値に設定します。
- 値:
@{triggerBody()?['number_1']}
③-6) 処理ステータス変数の設定(会議名エラー=-12)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-12
③-7) 会議日付作成
『作成』で経過日数をふまえた会議日付変数を作成します。
- 値:
@{addDays(convertFromUtc(utcNow(),'Tokyo Standard Time'),variables('経過日数'),'yyyy-MM-dd')}
③-8) 会議開始時間変数の設定
『変数の設定』で会議開始時間を指定値に設定します。
- 値:
@{concat(outputs('会議日付作成'),'T',formatDateTime(triggerBody()['text_1'],'HH:mm:ss'))}
③-9) 会議開始時間正常?
『条件』で会議開始時間の正常値判定をします。
- 左辺: (式)variables('会議開始時間')
- 条件:次の値を含む
- 右辺: (値)T
前段処理が失敗した場合も処理されるよう三点メニュー→「実行条件の構成」で「に失敗しました」にもチェックを入れます。

③-10) 処理ステータス変数の設定(会議名エラー=-13)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-13
③-11) 会議終了時間変数の設定
『変数の設定』で会議終了時間を指定値に設定します。
- 値:
@{concat(outputs('会議日付作成'),'T',formatDateTime(triggerBody()['text_2'],'HH:mm:ss'))}
③-12) 会議終了時間正常?
『条件』で会議開始時間の正常値判定をします。
- 左辺: (式)variables('会議終了時間')
- 条件:次の値を含む
- 右辺: (値)T
会議開始時間と同様に、前段処理が失敗した場合も処理されるよう三点メニュー→「実行条件の構成」で「に失敗しました」にもチェックを入れます。
③-13) 処理ステータス変数の設定(会議名エラー=-14)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-14
③-14) 会議室配列作成
『作成』で入力された会議室配列文字列をJSONエンコードで配列化した変数を作成します。
- 値:
@{json(triggerBody()['text_3'])}
③-15) 会議室配列正常?
『条件』で会議室配列の正常値判定をします。
<And条件1>
- 左辺: (式)outputs('会議室配列作成')
- 条件:次の値に等しくない
- 右辺: (式)null
<And条件2>
- 左辺: (式)length(outputs('会議室配列作成'))
- 条件:次の値より大きい
- 右辺: (値)0
会議開始時間と同様に、前段処理が失敗した場合も処理されるよう三点メニュー→「実行条件の構成」で「に失敗しました」にもチェックを入れます。
③-16) 会議室配列変数の設定
『変数の設定』で会議室配列を指定値に設定します。
- 値:
@{outputs('会議室配列作成')}
③-17) 処理ステータス変数の設定(会議名エラー=-15)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-15
③-18) 曜日数値設定なし?
『条件』で入力曜日数値の空値判定をします。
- 左辺: (式)triggerBody()?['number']
- 条件:次の値に等しい
- 右辺: (式)null
③-19) 曜日数値正常??
『条件』で曜日数値が0~6の範囲内かを判定します。
<And条件1>
- 左辺: (式)triggerBody()?['number']
- 条件:次の値以上
- 右辺: (値)0
<And条件2>
- 左辺: (式)triggerBody()?['number']
- 条件:次の値以下
- 右辺: (値)6
③-20) 曜日変数の設定
『変数の設定』で曜日変数を指定値に設定します。
- 値:
@{triggerBody()?['number']}
③-21) 処理ステータス変数の設定(会議名エラー=-16)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-16
③-22) ユーザ検索
(Office365ユーザー)『ユーザーの検索 (V2)』で検索語句を入力実行者メアドに設定します。
- 値:
@{triggerBody()?['text_4']}
③-23) メアドあり?
『条件』で指定メアドのユーザ検索が行えたかを判定します。
- 左辺: (式)empty(first(outputs('ユーザ検索')?['body/value'])?['mail'])
- 条件:次の値に等しい
- 右辺: (値)false
会議開始時間と同様に、前段処理が失敗した場合も処理されるよう三点メニュー→「実行条件の構成」で「に失敗しました」にもチェックを入れます。
③-24) 通知メアド変数の設定
『変数の設定』で通知メアドを指定値に設定します。
- 値:
@{first(outputs('ユーザ検索')?['body/value'])?['mail']}
③-25) 予定登録ユーザID変数の設定
『変数の設定』で予定登録ユーザIDを指定値に設定します。
- 値:
@{first(outputs('ユーザ検索')?['body/value'])?['id']}
③-26) 処理ステータス変数の設定(会議名エラー=-17)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-17
③-27) 処理ステータス:入力エラーなし?
『条件』で処理ステータスが初期値0から変更されてないかを判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (値)0
③-28) レスポンス設定(入力エラー)
『PowerApp または Flow に応答する』で処理ステータスを返り値として設定します。
処理ステータス:@variables('処理ステータス')
③-29) 取消(入力エラー)
『終了』で状態=「取り消し済み」として処理を止めます。
④スコープ2:日付チェック
④-1) 処理ステータス=未処理(スコープ2処理待ち)?
『条件』で処理ステータスが初期値0から変更されてないかを判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (値)0
④-2) 指定曜日?
『条件』で指定曜日の処理対象か判定します。
<Or条件1(指定曜日処理しない)>
- 左辺: (式)variables('曜日変数')
- 条件:次の値に等しい
- 右辺: (値)-1
<Or条件2(指定曜日処理かつ曜日一致)>
- 左辺: (式)dayOfWeek(outputs('会議日付作成'))
- 条件:次の値に等しい
- 右辺: (式)variables('曜日変数')
④-3) 子フロー:営業日判定
『子フローの実行』で子フロー:営業日判定 を呼び出します。
- 子フロー:
子フロー:営業日判定 - 入力日付:
@{outputs('会議日付作成')}
④-4) 平日?
『条件』で指定日付が営業日か判定します。
- 左辺: (式)int(outputs('子フロー:会議日営業日判定')?['Body']?['営業日位置'])
- 条件:次の値に等しくない
- 右辺: (値)-1
④-5) 処理ステータス設定(祝日=-22)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-22
④-6) エラーメッセージ変数の設定(-22)
『変数の設定』でエラーメッセージを指定値に設定します。
- 値:
指定日は祝日のため処理スキップしました。
④-7) 処理ステータス設定(祝日=-21)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-21
④-8) エラーメッセージ変数の設定(-21)
『変数の設定』でエラーメッセージを指定値に設定します。
- 値:
指定日付は対象曜日ではないため処理スキップしました。
⑤スコープ3:会議室予約
⑤-1) 処理ステータス=未処理(スコープ3処理待ち)?
『条件』で処理ステータスが初期値0から変更されてないかを判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (値)0
⑤-2) HTTP要求:会議室予約状況確認
Office365 Outlook『HTTP要求を送信します』で以下パラメータを設定し、指定時間帯、指定会議室(複数)の空き状況を取得します。
| パラメータ名 | 値 |
|---|---|
| URI | https://graph.microsoft.com/v1.0/users/@{variables('予定登録ユーザID')}/calendar/getSchedule |
| メソッド | POST |
| 本文 | {"schedules": @{variables('会議室配列')}, "startTime": { "dateTime": "@{variables('会議開始時間')}", "timeZone": "Tokyo Standard Time" }, "endTime": { "dateTime": "@{variables('会議終了時間')}", "timeZone": "Tokyo Standard Time" }, "availabilityViewInterval": 15} |
| コンテンツの種類 | application/json |
| CustomerHeader1 | Prefer: outlook.timezone="Tokyo Standard Time" |
⑤-3) 空き会議室抽出
データ操作『抽出』で以下パラメータを設定し、指定時間帯、指定会議室(複数)の空き状況を取得します。
- 差出人:
@outputs('HTTP要求:会議室予約状況確認')?['body/value'] - 左辺: (式)length(item()?['scheduleItems'])
- 条件:次の値に等しい
- 右辺: (値)0
⑤-4) 空き会議室あり?
『条件』で抽出配列が設定されるか判定します。
- 左辺: (式)length(body('空き会議室抽出'))
- 条件:次の値より大きい
- 右辺: (値)0
⑤-5) 空き会議室で繰り返し
『それぞれに適用する』で抽出した空き会議室配列を繰り返し処理します
- 出力選択:
@{body('空き会議室抽出')}
⑤-6) 処理ステータス=0(予約待ち)?
『条件』で処理ステータスが初期値0から変更されてないかを判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (値)0
⑤-7) イベントの作成(会議室予約)
Office365 Outlook『HTTP要求を送信します』で以下パラメータを設定し、会議室予約します。
| パラメータ名 | 値 |
|---|---|
| URI | https://graph.microsoft.com/v1.0/users/@{variables('予定登録ユーザID')}/calendar/events |
| メソッド | POST |
| 本文 | {"subject": "@{variables('会議名')}", "start": { "dateTime": @{variables('会議開始時間')}", "timeZone": "Asia/Tokyo" }, "end": { "dateTime": "@{variables('会議終了時間')}", "timeZone": "Asia/Tokyo" }, "location": { "locationEmailAddress": "@{items('空き会議室で繰り返し')?['scheduleId']}" }, "attendees": [{"emailAddress": { "address":"@{variables('通知メアド')}" }, "type": "required" }, { "emailAddress": { "address":"@{items('空き会議室で繰り返し')?['scheduleId']}" }, "type": "required" }]} |
| コンテンツの種類 | application/json |
⑤-8) 予約成功?
『条件』で予定登録処理が成功したか判定します。
<Or条件1>
- 左辺: (式)
@outputs('イベントの作成(会議室予約)')['statusCode'] - 条件:次の値に等しい
- 右辺: (値)200
<Or条件2>
- 左辺: (式)
@outputs('イベントの作成(会議室予約)')['statusCode'] - 条件:次の値に等しい
- 右辺: (値)201
<Or条件3>
- 左辺: (式)
@outputs('イベントの作成(会議室予約)')['statusCode'] - 条件:次の値に等しい
- 右辺: (値)204
前段処理が失敗した場合も処理されるよう三点メニュー→「実行条件の構成」で「に失敗しました」「がタイムアウトしました」にもチェックを入れます。

⑤-9) 処理ステータス変数の設定(成功=1)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
1
⑤-10) 処理ステータス設定(空き会議室なし=-30)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
-30
⑤-11) エラーメッセージ変数の設定(-30)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
指定日付に指定会議室の空きがありませんでした。
スコープ4:エラー通知
⑥-1) 処理ステータス=正常?
『条件』で処理ステータスが正常(=1)を判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (値)1
⑥-2) 処理ステータス=0(未処理)?
『条件』で処理ステータスが未処理(=0)を判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (値)0
⑥-3) エラーメッセージ変数の設定(0)
『変数の設定』で処理ステータスを指定値に設定します。
- 値:
Outlook連携できませんでした。
⑥-4) エラーメッセージ未設定?
『条件』でエラーメッセージが未設定か判定します。
- 左辺: (式)variables('エラーメッセージ')
- 条件:次の値に等しい
- 右辺: (式)null
⑥-5) エラーメッセージ変数の設定(デフォルト)
『変数の設定』でエラーメッセージを指定値に設定します。
- 値:
エラーが発生しました(エラーコード:@{variables('処理ステータス')})
⑥-6) 指定曜日エラー?
『条件』で指定曜日エラーか判定します。
- 左辺: (式)variables('処理ステータス')
- 条件:次の値に等しい
- 右辺: (式)-21
前述の「親フロー処理例②」のように本フロー呼び出しが連発する場合、指定曜日エラーが多発するため通知対象外としてます。
⑥-7) 処理エラーメール送信
Office365 Outlook『メールの送信(V2)』で以下パラメータを設定し、エラーメールを送信します。
| パラメータ名 | 値 |
|---|---|
| 宛先 | @{variables('通知メアド')} |
| 件名 | 会議室予約エラー通知(@{variables('会議名')}:@{outputs('会議日付作成')}分) |
| 本文(コードビュー) | <p>@{variables('エラーメッセージ')}<br>リスケ、別会議室予約は個別設定してください。</p> |
⑦応答設定
『PowerApp または Flow に応答する』で処理ステータスを返り値として設定します。
処理ステータス:@variables('処理ステータス')
