Udemy 新コース: 作って学ぶPower BI!

【質問コーナー】Power Apps のOutlook 会議スクリーンで時間指定をしてスケジュールする

本記事は質問コーナーの連続する2つ目の記事です。
1件目は以下にあります。

YouTubeから当サイトを発見いただき、以下のようなご質問をいただきました。

YouTubeチャンネルはこちら

チャンネル登録お願いします!
参考
ギークフジワラ YouTube チャンネルYouTube

YouTubeでご相談した者です。
大変申し訳ないのですが、どうしても分からないので、こちらにご相談させて下さい。

PowerApps+Outlookで予定表のアプリを作ろうとしています。
以下に詳細を記載します。

・会議スクリーン(新しい画面からの選択)を使用
・タブ分けされている内容を1つにまとめる
・時刻の選択を無くす
・期間をドロップダウン形式の時間に変える(2つのドロップダウンにして、○時:〇〇分にする)
・時刻、期間の枠以外は使用するためそのまま残す

このようなアプリを構想して作成しているのですが、この会議スクリーンが、「時刻」の選択をしないと送信ボタンが押せないようになっています。
時刻ではなくて自分で作った時間(ドロップダウン形式)にしてOutlookに書き込みできるようにするにはどの様に関数を変えたら良いか分かりません。
もし可能でしたら教えて頂ければ幸いです。よろしくお願い致します。

質問としては2つあると理解しております。

  1. Microsoft が標準でスクリーンテンプレートとして用意している会議スクリーンにて、タブ分けされている「招待」、「スケジュール」を一つのスクリーンにしたい。
  2. FromToの時間形式のドロップダウン2つで時間指定をしてスケジュールしたい。
ご質問いただきましてありがとうございました!
本日は上記の2について答えていきます!

開始時間、終了時間指定ではなく開催期間でのスケジュールになっている

Outlookのデスクトップアプリで会議予約をする際、開始時間、終了時間を指定して予約するUIに慣れていると思います。以下はMac用のOutlookアプリのイベント作成画面です。

 

Power Apps の会議テンプレートではなぜか開催期間での指定になっていて、しかも8時始まりが固定で計算されていくので、8:30から9:30までというような時間指定ができません。

 

例えば、1時間と指定してみるとリストには9:30からのパターンは表示されません。

これをデスクトップ版と同じようなUにしてみようと思います、完成形は以下のようなイメージです。

 

概要

以下のような手順で作っていきます。

  1. 開始時間(From)、終了時間(To)のドロップダウンリストを追加する
  2. 元からある期間指定のドロップダウンリストが関与している関数を1で作成したドロップダウンリストで代用できるように関数を書き換える
  3. エラー発生を無くすようにDisplayModeとフィルターを使い項目にセキュリティを掛ける

回答例

いろいろな方法はあると思います。一つの例に過ぎないため例とさせていただきます。

開始時間(From)、終了時間(To)のドロップダウンリストを追加する

以下のようにドロップダウンリストを設置します。わかりやすいように緑色にしました。

ドロップダウンリストの名前はそれぞれ以下のようにします。

開始時間:

コード

FromTimeDropdown

終了時間:

コード

ToTimeDropdown

その時のFromTimeDropdown の Items プロパティは以下のように設定しておきます。とりあえずToTimeDropdownも同じにしておきます。

コード

Table(
{Name:"0時0分", Hour:0, Minute:0},
{Name:"0時30分", Hour:0, Minute:30},
{Name:"1時0分", Hour:1, Minute:0},
{Name:"1時30分", Hour:1, Minute:30},
{Name:"2時0分", Hour:2, Minute:0},
{Name:"2時30分", Hour:2, Minute:30},
{Name:"3時0分", Hour:3, Minute:0},
{Name:"3時30分", Hour:3, Minute:30},
{Name:"4時0分", Hour:4, Minute:0},
{Name:"4時30分", Hour:4, Minute:30},
{Name:"5時0分", Hour:5, Minute:0},
{Name:"5時30分", Hour:5, Minute:30},
{Name:"6時0分", Hour:6, Minute:0},
{Name:"6時30分", Hour:6, Minute:30},
{Name:"7時0分", Hour:7, Minute:0},
{Name:"7時30分", Hour:7, Minute:30},
{Name:"8時0分", Hour:8, Minute:0},
{Name:"8時30分", Hour:8, Minute:30},
{Name:"9時0分", Hour:9, Minute:0},
{Name:"9時30分", Hour:9, Minute:30},
{Name:"10時0分", Hour:10, Minute:0},
{Name:"10時30分", Hour:10, Minute:30},
{Name:"11時0分", Hour:11, Minute:0},
{Name:"11時30分", Hour:11, Minute:30},
{Name:"12時0分", Hour:12, Minute:0},
{Name:"12時30分", Hour:12, Minute:30},
{Name:"13時0分", Hour:13, Minute:0},
{Name:"13時30分", Hour:13, Minute:30},
{Name:"14時0分", Hour:14, Minute:0},
{Name:"14時30分", Hour:14, Minute:30},
{Name:"15時0分", Hour:15, Minute:0},
{Name:"15時30分", Hour:15, Minute:30},
{Name:"16時0分", Hour:16, Minute:0},
{Name:"16時30分", Hour:16, Minute:30},
{Name:"17時0分", Hour:17, Minute:0},
{Name:"17時30分", Hour:17, Minute:30},
{Name:"18時0分", Hour:18, Minute:0},
{Name:"18時30分", Hour:18, Minute:30},
{Name:"19時0分", Hour:19, Minute:0},
{Name:"19時30分", Hour:19, Minute:30},
{Name:"20時0分", Hour:20, Minute:0},
{Name:"20時30分", Hour:20, Minute:30},
{Name:"21時0分", Hour:21, Minute:0},
{Name:"21時30分", Hour:21, Minute:30},
{Name:"22時0分", Hour:22, Minute:0},
{Name:"22時30分", Hour:22, Minute:30},
{Name:"23時0分", Hour:23, Minute:0},
{Name:"23時30分", Hour:23, Minute:30}
)
30分おきにしていますが、個々の間隔は記述次第です。時間と分のドロップダウンリストを分ければより細かく指定ができると思います。

元からある期間指定のドロップダウンリストが関与している関数を1で作成したドロップダウンリストで代用できるように関数を書き換える

書き換える関数は結構たくさんあるんです。非常にわかりづらくなるため、先にポイントを説明します。

ポイント説明

元からある期間指定のドロップダウンリストは MeetingDurationSelect3 という名称です。

Title11というテキストラベル等の OnSelect プロパティの中にこのドロップダウンリストから期間を呼び出すために以下のような記述が多々あります。

コード

MeetingDuration: MeetingDurationSelect3.Selected.Minutes

上記はClearCollect 関数にてMeetingDurationというカラムに選択した時間(分)を格納しています。

こういった期間指定ドロップダウンリストの参照を新たに配置したドロップダウンリストに変更していきます。例えばこんな感じです。

コード

MeetingDuration: ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute-FromTimeDropdown.Selected.Hour*60-FromTimeDropdown.Selected.Minute

関数変更作業

Title11はClearCollect関数部分を以下のように変更します(ほかは残します)。

コード

ClearCollect(RoomTimeSuggestions, Office365Outlook.FindMeetingTimes(
     {RequiredAttendees: _allRoomsConcat, MeetingDuration: ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute-FromTimeDropdown.Selected.Hour*60-FromTimeDropdown.Selected.Minute,
     Start: _selectedMeetingTime.StartTime & "Z", 
     End: _selectedMeetingTime.EndTime & "Z", MinimumAttendeePercentage: "1",
     IsOrganizerOptional: "false", ActivityDomain: "Unrestricted"}).MeetingTimeSuggestions);

Title12はClearCollect関数部分を以下のように変更します(ほかは残します)。

コード

ClearCollect(MeetingTimes, AddColumns(Office365Outlook.FindMeetingTimes(
     {RequiredAttendees:Concat(MyPeople, UserPrincipalName & ";"), MeetingDuration:ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute-FromTimeDropdown.Selected.Hour*60-FromTimeDropdown.Selected.Minute,
     Start:Text(DateAdd(MeetingDateSelect3.SelectedDate, FromTimeDropdown.Selected.Hour*60+FromTimeDropdown.Selected.Minute, Minutes), UTC), 
     End:Text(DateAdd(MeetingDateSelect3.SelectedDate, ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute, Minutes), UTC),
     MaxCandidates:15, MinimumAttendeePercentage:1, IsOrganizerOptional: false, ActivityDomain: "Unrestricted"}).MeetingTimeSuggestions,
     "StartTime", Text(DateAdd(MeetingDateSelect3.SelectedDate, 
     FromTimeDropdown.Selected.Hour*60+FromTimeDropdown.Selected.Minute, Minutes), UTC), 
     "EndTime", Text(DateAdd(MeetingDateSelect3.SelectedDate, ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute, Minutes), UTC)));

上記の中で含まれているコードについて説明します。

1.時間を分に変換して期間を計算しています。時間は60をかけて分に直しています。まさに置き換えっぽいやり方です。

コード

MeetingDuration:ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute-FromTimeDropdown.Selected.Hour*60-FromTimeDropdown.Selected.Minute

2. 開始時間は日付指定のカレンダーボックスからの日付に分の単位で足しています。時間は先程と同じように60かけて分に直しています。

コード

"StartTime", Text(DateAdd(MeetingDateSelect3.SelectedDate, FromTimeDropdown.Selected.Hour*60+FromTimeDropdown.Selected.Minute, Minutes), UTC

3.終了時間も開始時間と同じ原理で、今度はToTimeDropboxから時間を計算します。

コード

"EndTime", Text(DateAdd(MeetingDateSelect3.SelectedDate, ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute, Minutes), UTC

検索アイコンを設置する

元々あったドロップダウンリスト及びその上にあるラベルのVisibleプロパティをfalseにして表示されないようにします。

その場所に検索ボタンを設置します。

検索ボタンの関数は以下のように設定します。これと同じ関数をMeetingDateSelect3コントロール(カレンダー)のOnSelectプロパティを修正します(同じコードでOK)。

コード

Concurrent(
Reset('1TextSearchBox3'),
Set(_showMeetingTimes, false),
UpdateContext({_loadingMeetingTimes: true}),
Set(_selectedMeetingTime, Blank()),
Set(_selectedRoom, Blank()),
Set(_roomListSelected, false),

ClearCollect(MeetingTimes, AddColumns(Office365Outlook.FindMeetingTimes(
{RequiredAttendees:Concat(MyPeople, UserPrincipalName & ";"), MeetingDuration:ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute-FromTimeDropdown.Selected.Hour*60-FromTimeDropdown.Selected.Minute,
Start:Text(DateAdd(MeetingDateSelect3.SelectedDate, FromTimeDropdown.Selected.Hour*60+FromTimeDropdown.Selected.Minute, Minutes), UTC), End:Text(DateAdd(MeetingDateSelect3.SelectedDate, ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute, Minutes), UTC),
MaxCandidates:15, MinimumAttendeePercentage:1, IsOrganizerOptional: false, ActivityDomain: "Unrestricted"}).MeetingTimeSuggestions,
"StartTime", Text(DateAdd(MeetingDateSelect3.SelectedDate, FromTimeDropdown.Selected.Hour*60+FromTimeDropdown.Selected.Minute, Minutes), UTC), "EndTime", Text(DateAdd(MeetingDateSelect3.SelectedDate, ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute, Minutes), UTC))));

UpdateContext({_loadingMeetingTimes: false});
Set(_showMeetingTimes, true)

送信アイコンの関数の変更

送信アイコンのOnSelect関数配下のように変更します。以下の関数で変更している点は関数に合わせてUTCに変更しているところです。

コード

/*sends a meeting invite if necessary fields are filled out (attendees, subject, meeting time selection)*/
Set(_myCalendarName, LookUp(Office365Outlook.CalendarGetTables().value, DisplayName = "Calendar").Name);
Set(_myScheduledMeeting, Office365Outlook.V2CalendarPostItem(_myCalendarName,
 '1TextMeetingSubject3'.Text, Text(DateAdd(DateTimeValue(_selectedMeetingTime.StartTime), 0, Minutes)),
 Text(DateAdd(DateTimeValue(_selectedMeetingTime.EndTime), 0, Minutes)),
 {RequiredAttendees:Concat(MyPeople, UserPrincipalName & ";") & _selectedRoom.Address, Body: '1TextMeetingMessage3'.Text, Location: _selectedRoom.Name, Importance: "Normal", ShowAs: "Busy", ResponseRequested: true}));
 Concurrent(
   Reset(TextMeetingLocation3),
   Reset('1TextMeetingSubject3'),
   Reset('1TextMeetingMessage3'),
   Clear(MyPeople),
   Set(_selectedMeetingTime, Blank()),
   Set(_selectedRoomList, Blank()),
   Set(_selectedRoom, Blank()),
   Set(_roomListSelected, false)
)

Title10 ラベルのテキストプロパティは以下のように変更します。こちらでもTimeZoneOffsetを0に変更しています。

コード

Text(DateAdd(DateTimeValue(ThisItem.StartTime), 0, Minutes), DateTimeFormat.ShortTime)

ここで、開始時間だけでなく終了時間もわかったほうがいいのでTitle10ラベルをコピーします。関数はEndTimeに変更しています。

Title10ラベルのOnSelectプロパティは以下のように変更します。

コード

MeetingDuration: ToTimeDropdown.Selected.Hour*60+ToTimeDropdown.Selected.Minute-FromTimeDropdown.Selected.Hour*60-FromTimeDropdown.Selected.Minute

エラー発生を無くすようにDisplayModeとフィルターを使い項目にセキュリティを掛ける

フールプルーフを避けるために、また、不要なエラー処理を行うのを避けるためにある段階ではそもそも入力ができないようなセキュリティをかけていきます。

送信ボタンにセキュリティをかけるためにきちんとメーティングタイムを選択したかどうかという条件を追加します。

これ標準で入ってないんですよね。これは今回の開発があるなしに関わらず標準で実装しておかないといけないと思います。

 

検索ボタン、新たに追加したドロップダウンリスト2つのDisplayModeは以下のように設定します。

すると連絡先が追加されていないと触れないようになり、Outlookの予定表からデータを取ってこないように出来ますので、誰の予定を見たいのか?といったエラーを回避できるわけです。

 

ToTimeDropdownは、FromTimeDropdownよりも未来の時間を選択できないといけないわけです。なのでFromTimeの時間と比較した関数を書いていき、Filterでリストを絞ります。

その関数は以下のとおりです。

コード

Filter(
    Table(
{Name:"0時0分", Hour:0, Minute:0},
{Name:"0時30分", Hour:0, Minute:30},
{Name:"1時0分", Hour:1, Minute:0},
{Name:"1時30分", Hour:1, Minute:30},
{Name:"2時0分", Hour:2, Minute:0},
{Name:"2時30分", Hour:2, Minute:30},
{Name:"3時0分", Hour:3, Minute:0},
{Name:"3時30分", Hour:3, Minute:30},
{Name:"4時0分", Hour:4, Minute:0},
{Name:"4時30分", Hour:4, Minute:30},
{Name:"5時0分", Hour:5, Minute:0},
{Name:"5時30分", Hour:5, Minute:30},
{Name:"6時0分", Hour:6, Minute:0},
{Name:"6時30分", Hour:6, Minute:30},
{Name:"7時0分", Hour:7, Minute:0},
{Name:"7時30分", Hour:7, Minute:30},
{Name:"8時0分", Hour:8, Minute:0},
{Name:"8時30分", Hour:8, Minute:30},
{Name:"9時0分", Hour:9, Minute:0},
{Name:"9時30分", Hour:9, Minute:30},
{Name:"10時0分", Hour:10, Minute:0},
{Name:"10時30分", Hour:10, Minute:30},
{Name:"11時0分", Hour:11, Minute:0},
{Name:"11時30分", Hour:11, Minute:30},
{Name:"12時0分", Hour:12, Minute:0},
{Name:"12時30分", Hour:12, Minute:30},
{Name:"13時0分", Hour:13, Minute:0},
{Name:"13時30分", Hour:13, Minute:30},
{Name:"14時0分", Hour:14, Minute:0},
{Name:"14時30分", Hour:14, Minute:30},
{Name:"15時0分", Hour:15, Minute:0},
{Name:"15時30分", Hour:15, Minute:30},
{Name:"16時0分", Hour:16, Minute:0},
{Name:"16時30分", Hour:16, Minute:30},
{Name:"17時0分", Hour:17, Minute:0},
{Name:"17時30分", Hour:17, Minute:30},
{Name:"18時0分", Hour:18, Minute:0},
{Name:"18時30分", Hour:18, Minute:30},
{Name:"19時0分", Hour:19, Minute:0},
{Name:"19時30分", Hour:19, Minute:30},
{Name:"20時0分", Hour:20, Minute:0},
{Name:"20時30分", Hour:20, Minute:30},
{Name:"21時0分", Hour:21, Minute:0},
{Name:"21時30分", Hour:21, Minute:30},
{Name:"22時0分", Hour:22, Minute:0},
{Name:"22時30分", Hour:22, Minute:30},
{Name:"23時0分", Hour:23, Minute:0},
{Name:"23時30分", Hour:23, Minute:30}
),Hour*60+Minute>=FromTimeDropdown.Selected.Hour*60+FromTimeDropdown.Selected.Minute+1)

完成!

完成形は以下のとおりです。この状態で送信ボタンを押すと…

Outlookに登録されます。

 

開いてみると、こんな感じで指定した時間でちゃんと登録されていることがわかります。

 

以上、ご参考になれば幸いです。

 

2 COMMENTS

Tommy

コメント失礼します。
わかりやすくとても参考になる記事を作成していただきありがとうございます。
この変更作業をすべて終えてからテストしてみたところ、適当な日付時間指定を行い、会議室の選択を押したところ以下のエラーが出て解決策が分かりませんでした。

「この値’2023-05-18T11:00:00:000ZZ’を日付または時刻の値に変換することはできません。」
※指定した日付時刻は2023/5/18 20:00-20:30を指定しています。

つきましてはお知恵をお借りしたいのですが、ご教示いただけないでしょうか?
お手数おかけして恐縮ですが、何卒よろしくお願いします。

ギークフジワラ

コメントありがとうございます。
日付のデータ形式になっていないためのエラーですね。Outlook サービス側に仕様変更があったかもしれません。おそらく以下の箇所が日付表示形式に変換できなかったようなので試してみていただけますでしょうか?

本記事の「関数変更作業」のセクションに説明のある
Title11 ににおける2つの「 & “Z”」を削除していただければいいのではないかなと思います。
修正してみてうまくいくようでしたら記事内容を変更いたします。

また参考にMS Learn にて日付の形式は以下に説明があります。
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/standard-date-and-time-format-strings#Resources#Resource

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Index