マニュアル
PR

Power Automateで複数人の空き時間を検索する方法

sanane
記事内に商品プロモーションを含む場合があります

はじめに

この記事では、Power Automate で「会議の時間を検索 (V2)」(Find meeting times V2)を使い、複数メンバー全員が空いている会議候補をまとめて自動で出す方法を、画像付きで解説します。

power automate 空き時間 検索」で調べると、コネクタの入力欄が独特で「出席者をどう渡すのか」「継続時間の単位は?」「なぜ候補の時間帯がズレるのか」とつまずきがちです。本記事では、Teams のメッセージから起動 → アダプティブカードで条件を入力 → 候補を Teams カードで返すという実用的な最小構成を作りながら、公式ドキュメントで分かりにくい仕様を1つずつ噛み砕きます。

  • Teams のメッセージからワンクリックでフローを起動できる
  • 出席者・開始日・会議の長さ・営業時間をカードで入力するだけ
  • 全員が空いている会議候補の一覧が Teams に返ってくる

本記事は「会議の時間を検索 (V2) コネクタの基礎」に軸足を置いています。アクションの日本語表示名は環境やバージョンで変わることがあるため、名称が違っても同じ役割のアクションを選べば問題ありません。

Power Automateの基本・料金・他の実例一覧はこちら。

あわせて読みたい
Power Automateとは?できること・使い方・始め方を実例28本で解説
Power Automateとは?できること・使い方・始め方を実例28本で解説

完成フローの全体像

今回作るのは、Teams のメッセージから起動するインスタント クラウド フローです。全体は次の流れになります。

フローの構成
  1. 選択されたメッセージに対して (V2)(Microsoft Teams)― トリガー
  2. アダプティブ カードを投稿して応答を待機する(Teams)― 条件入力フォーム
  3. 会議の時間を検索 (V2)(Office 365 Outlook)― 空き時間を検索
  4. 選択(Select)― 候補を1行テキストに整形
  5. 作成(Compose)― 結果カードの JSON を組み立て
  6. チャットやチャネルにカードを投稿する(Teams)― 結果を返す
Power Automateの空き時間検索フロー全体像(トリガーから結果カード投稿まで)

デザイナーには「マイ プロフィールの取得 (V2)」も並んでいますが、このフローでは使っていないため無くても動きます。実行ユーザーのタイムゾーンを動的に使いたい場合だけ残してください。

ステップ1:Teamsのメッセージから起動するトリガーを作る

まずはフローの入口(トリガー)を作ります。トリガーは Microsoft Teams の 「選択されたメッセージに対して (V2)」です。Power Automate でインスタント クラウド フローを新規作成し、トリガーの一覧からこれを選んで開始します。これを選ぶと、Teams のメッセージのメニューからフローを呼び出せるようになります。

インスタントクラウドフロー作成画面でMicrosoft Teamsの「選択されたメッセージに対して(V2)」トリガーを選ぶ

トリガーを置いたら、ここから下のステップ(入力カード → 空き時間検索 → 結果カード)を順に追加していきます。

ステップ2:入力フォームをアダプティブカードで作る

続いて、検索条件を 「アダプティブ カードを投稿して応答を待機する」アクションで集めます。フロー ボットがチャットに入力カードを投稿し、利用者が「検索」を押すまで待機します。

投稿者・投稿先の設定
  • 投稿者フロー ボット
  • 投稿先フロー ボットとチャットをする(実行ユーザー個人宛)
アダプティブカードを投稿して応答を待機するアクションのMessage欄に入力カードのJSONを設定した画面

カードの入力項目(Input)は次の5つです。各 Input の id はあとで式から参照するので、名前を控えておきましょう。

  • 出席者attendees)― メールをカンマ区切りで入力(Input.Text)
  • 開始日startDate)― 検索したい日(Input.Date)
  • 会議の長さ(分)duration)― 30 / 60 / 90 / 120 から選択(Input.ChoiceSet・既定60)
  • 営業開始時刻bizStart)― 既定 9:00(Input.Time)
  • 営業終了時刻bizEnd)― 既定 17:00(Input.Time)
Teamsチャットに表示された空き時間検索の入力カード(出席者・開始日・会議の長さ・営業時間・検索ボタン)

あとで使う式は body('アダプティブ_カードを投稿して応答を待機する')?['data']?['attendees'] のように カードの id をそのままキーにして参照します。Input の id が式のキー(attendees / startDate / duration / bizStart / bizEnd)と1文字でも違うと値が空になり、検索が空振りします。必ず一致させてください。

ステップ3:「会議の時間を検索 (V2)」を設定する(つまずき4点)

ここがこの記事の核心です。コネクタの入力欄に、カードの回答を式で整形して渡します。詳細パラメーターは 最大候補数=20 / 出席者の最小割合=100 / アクティビティ ドメイン=Unrestricted にしています。

会議の時間を検索(V2)の詳細パラメーター(最大候補数・最小割合・アクティビティドメイン・必須出席者・継続時間・開始終了時刻)

(A) 出席者は「; 区切りの文字列」。カンマ入力を変換する

「会議の時間を検索 (V2)」の必須出席者 / 任意出席者 / リソース出席者は、いずれもセミコロン(;)区切りの文字列を受け取ります。配列ではありません。一方、カードでは利用者にやさしいカンマ区切りで集めているので、必須出席者欄で次の式を使い、カンマをセミコロンへ変換します。

replace(replace(trim(body('アダプティブ_カードを投稿して応答を待機する')?['data']?['attendees']),' ',''),',',';')

trim で前後の空白を、内側の replace(...,' ','')すべての空白を除去し、最後にカンマ(,)をセミコロン(;)へ置換します。これで taro@example.com, hanako@example.comtaro@example.com;hanako@example.com になります。

(B) 継続時間は「分(数値)」。文字列を int() で数値化

会議の継続時間は PT30M のような ISO8601 ではなく、30 / 60 / 90 といった「分」の整数で渡します。カードの ChoiceSet が返すのは文字列なので、int() で数値化します。

int(body('アダプティブ_カードを投稿して応答を待機する')?['data']?['duration'])

ChoiceSet の値(value)は「60」のような数値文字列にしておきます。表示名を「60分」にするのは構いませんが、value を「60分」にすると int() が失敗して実行時エラーになります。

(C) 検索範囲は「開始日+営業時間」。タイムゾーンとActivityDomainの罠

検索する時間帯は 開始日+営業開始/終了時刻から組み立て、開始日当日の営業時間内だけを探します。コネクタへ渡す開始/終了はUTC基準なので、convertTimeZone で JST(Tokyo Standard Time)から UTC へ変換してから渡します。

開始時刻

convertTimeZone(concat(body('アダプティブ_カードを投稿して応答を待機する')?['data']?['startDate'],'T',body('アダプティブ_カードを投稿して応答を待機する')?['data']?['bizStart'],':00'),'Tokyo Standard Time','UTC','yyyy-MM-ddTHH:mm:ss')

終了時刻bizStartbizEnd に変えるだけ):

convertTimeZone(concat(body('アダプティブ_カードを投稿して応答を待機する')?['data']?['startDate'],'T',body('アダプティブ_カードを投稿して応答を待機する')?['data']?['bizEnd'],':00'),'Tokyo Standard Time','UTC','yyyy-MM-ddTHH:mm:ss')

2026-07-0109:00 を連結して 2026-07-01T09:00:00 を作り、これを JST として UTC へ変換します(9時間引かれて 2026-07-01T00:00:00)。

ActivityDomain の罠:アクティビティ ドメインを Work にするとメールボックスの勤務時間が優先され、こちらが渡した開始/終了が無視されて候補が想定外の時間帯・複数日に広がることがあります。指定した営業時間だけで素直に探したいなら Unrestricted にしてください。

(D) 候補(meetingTimeSuggestions)の主なフィールド

検索結果は meetingTimeSuggestions という候補の配列で返ります。1件ずつに次のようなフィールドが入っています。

フィールド意味
meetingTimeSlot.start.dateTime / .start.timeZone候補の開始日時とタイムゾーン
meetingTimeSlot.end.dateTime / .end.timeZone候補の終了日時とタイムゾーン
confidence候補の信頼度(%)
organizerAvailability開催者の空き状況
suggestionReasonその候補が提案された理由
emptySuggestionsReason候補が0件のときに入る理由コード

ステップ4:候補を整形してTeamsカードで返す

候補の配列を、人が読める1行テキストへ整形してから結果カードにします。

候補整形(選択 / Select)

選択(Select)アクションの「元」に meetingTimeSuggestions を指定し、テキストモードのマップに次の式を入れます。UTC で返る日時を JST 表記に直しています。

選択(Select)アクションで候補配列を1行テキストに整形する設定画面
concat(convertTimeZone(item()?['meetingTimeSlot']?['start']?['dateTime'],'UTC','Tokyo Standard Time','MM/dd HH:mm'),' - ',convertTimeZone(item()?['meetingTimeSlot']?['end']?['dateTime'],'UTC','Tokyo Standard Time','HH:mm'))

これで 07/01 09:00 - 09:30 のような行が候補の数だけ並びます。

新デザイナーは、配列の動的コンテンツをスカラー欄に挿すと Apply to each(For each)を自動生成します。開始と終了を別々に挿すと2重ループになって候補が N×N 件になる罠があります。選択(Select)でまとめて整形すれば、ループを増やさず1回で配列を変換できます。

結果カードJSON(作成 / Compose)

作成(Compose)で、結果表示用のアダプティブカード JSON を組み立てます。候補が0件のときは emptySuggestionsReason 相当の案内文に切り替えます。

作成(Compose)アクションで結果カードのJSONを組み立てる設定画面
concat('{"$schema":"http://adaptivecards.io/schemas/adaptive-card.json","type":"AdaptiveCard","version":"1.4","body":[{"type":"TextBlock","text":"✅ 空き時間 検索結果","weight":"Bolder","size":"Medium","wrap":true},{"type":"TextBlock","text":"',if(empty(body('空き時間検索')?['meetingTimeSuggestions']),'指定条件では空き時間が見つかりませんでした。営業時間や日付を変えて再検索してください。',join(body('候補整形'),'\n')),'","wrap":true}]}')

式の body('空き時間検索')body('候補整形') は、それぞれのアクション表示名です。表示名を変えている場合は、自分の環境の名前に置き換えてください。

結果をTeamsカードで投稿する

最後に 「チャットやチャネルにカードを投稿する」で、組み立てたカード(作成の出力)を実行ユーザー宛に返します。投稿者はフロー ボット、投稿先はフロー ボットとチャットをするです。

チャットやチャネルにカードを投稿するアクションで結果カードを実行ユーザーに返す設定画面

実際に起動して使ってみる

フローが完成したら、ステップ1で設定したトリガーから起動して動作を確認します。Teams の任意のメッセージで 「…(その他の操作)」→ フロー名を選ぶと起動します。続けて入力カードがチャットに届くので、条件を入力して「検索」を押すだけです。

Teamsメッセージの「その他の操作」メニューから空き時間検索フローを起動する

「メッセージから起動」はあくまで呼び出し口です。会議の調整依頼のメッセージから直接そのまま起動できるので、チャットの文脈を切らずに候補出しまで進められます。

よくある質問

Q
候補が0件になってしまいます

全員が忙しい時間帯を指定していないか、営業開始/終了時刻が逆になっていないかを確認してください。アクティビティ ドメインが Work だと勤務時間が優先されて期待した時間帯が外れることもあります。Unrestricted に変え、営業時間や開始日を広げて再検索してみてください。

Q
候補の時間が9時間ずれます

タイムゾーン変換の方向が逆になっている可能性があります。コネクタへ渡す開始/終了は JST → UTC、結果の表示は UTC → JST です。それでもずれる場合は、開始/終了の値の末尾に Z を付けて明示的に UTC と認識させてください。

Q
任意出席者や会議室も含めて探せますか?

はい。「会議の時間を検索 (V2)」には任意出席者・リソース出席者の欄もあり、いずれもセミコロン区切りの文字列で渡せます。会議室(リソース)の空きも含めた検索は、本フローの発展形として組み込めます。

まとめ

  • 出席者は「; 区切りの文字列」。カンマ入力は replace で変換する
  • 継続時間は「分」の数値int() で数値化する
  • 開始/終了は営業時間+ convertTimeZoneで組み立て、ドメインは Unrestricted
  • 候補配列は選択(Select)でまとめて整形し、ループ増殖を避ける

コネクタ独特の入力仕様さえ押さえれば、「複数人の予定を突き合わせて空き時間を探す」面倒な作業はワンクリックで片付きます。まずは最小構成で動かし、慣れてきたら会議室(リソース)の空き検索や、候補からそのまま予約まで進める発展形に挑戦してみてください。

あわせて読みたい

Power Automateの全体像・基本・料金・実例一覧はこちらにまとめています。

あわせて読みたい
Power Automateとは?できること・使い方・始め方を実例28本で解説
Power Automateとは?できること・使い方・始め方を実例28本で解説

検索した候補から、会議室予約まで自動化したい場合はこちら。

あわせて読みたい
Power Automateで会議室予約を自動化|空き会議室を検索してTeamsから予約する方法
Power Automateで会議室予約を自動化|空き会議室を検索してTeamsから予約する方法

検索結果をTeamsへ通知したい場合はこちら。

あわせて読みたい
Power AutomateでTeamsに自動通知する方法|Forms・SharePoint・メール起点で解説
Power AutomateでTeamsに自動通知する方法|Forms・SharePoint・メール起点で解説
記事URLをコピーしました