Power Apps で勤務シフト作成アプリを作る その４ 周辺機能実装編

本記事は5回シリーズ（の予定）です。
その１はこちら：https://qiita.com/KodamaJn/items/afc40f565aca772ab67f
その２はこちら：https://qiita.com/KodamaJn/items/a16e7bb021780e51850d
その３はこちら：https://qiita.com/KodamaJn/items/00af61369887d4b8dff6
その４はこちら：本記事
その５はこちら：執筆中…

　その４では、アプリで作成した勤務シフトを各勤務者の予定表に追加する機能と、各勤務者が希望勤務を申請できる機能を実装します。

# 周辺機能を実装する
## 設定した勤務パターンを各勤務者の予定表に入れる
　１クリックで、設定した勤務パターンを各勤務者の予定表に入れられるようにします。
　今回は、制御を簡単にする都合上、本機能を実行したユーザーが、各勤務者を会議招集するスタイルで実装します（つまり実行したユーザーのカレンダーには勤務者数分の勤務パターンが追加されます）。また、クリックするたびに予定表に勤務情報が追加されていきます。諸々ご了承ください。
　まず、Power Apps から直接予定表にアクセスするために、Outlook コネクタを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/aac7faa5-56ee-7c41-db63-4775c7e29387.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/1ad3dcf6-3215-222a-e3cb-ee167ec75dba.png)

　続いて、"カレンダーに追加する"アイコン IconAddToCalendar を追加します。
![スクリーンショット (76).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/e26fe618-fd24-988d-4ebb-e57e0049e7ad.png)

　そして、OnSelect に以下の処理を追記します。前回の記事（[その３](https://qiita.com/KodamaJn/items/00af61369887d4b8dff6)）でも登場した ForAll と AddColumn を利用しています。

```:IconAddToCalendar-OnSelect
ForAll(
    AddColumns(ShiftData, 
        "sWorkDateStartTime", Text(mWorkDate, "[$-en-US]yyyy-mm-ddThh:mm") & ":00.000Z",
        "sWorkDateEndTime", Text(DateAdd(mWorkDate, 1, Days), "[$-en-US]yyyy-mm-ddThh:mm") & ":00.000Z"
    ),
    Office365Outlook.V2CalendarPostItem(
        First(Filter(Office365Outlook.CalendarGetTables().value, Or(DisplayName = "予定表", DisplayName = "Calendar"))).Name, 
        mWorkPattern, 
        sWorkDateStartTime, 
        sWorkDateEndTime, 
        {
            RequiredAttendees:mWorkUser.Email, 
            TimeZone: "(UTC+09:00) Osaka, Sapporo, Tokyo", 
            IsAllDay: true
        }
    );
);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/65c32963-94a3-8452-a846-b48e712978e8.png)

　ちょっと複雑なので解説します。
　ここではまず、現在表示されている月の勤務パターンをまとめて各ユーザーの予定表に追加したいので、ForAll 関数を使用します。
　[Power Apps での ForAll 関数](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-forall)

　ForAll 関数の第1引数では、AddColumns を用いてその後で利用する予定追加の開始/終了時間の情報を追加しています。今回は終日の予定とするため、終了時間は開始時間+1日にしています。
　続いて ForAll 関数の第2引数で、Office365Outlook.V2CalendarPostItem を用いています。この関数を用いて、件名、開始時間、終了時間、会議に参加するユーザー等の情報を指定することで、実行したユーザーの予定表に予定を作成することができます。
　V2CalendarPostItem の第1引数では、ユーザーのどの予定表に作成するかを指定します。「どの予定表？？」って思われる方もいらっしゃるかと思いますが、ユーザーの予定表は複数作成することができるため（"誕生日"などが最初から存在していることをご存知の方もいらっしゃるかと思います）、ここで一般的に利用される"予定表"（あるいは"Calendar"）を指定しています。
　続いて第2～第4引数で、作成する予定の件名、開始時刻、終了時刻を指定します。件名は勤務パターンとします。
　さらに、オプションとして"｛｝"内に"各勤務者のメールアドレス、タイムゾーン、終日の予定（true）を指定しています。
　
　Office 365 Outlook コネクタについては、こちらの記事がとても読みやすくまとめられていますので、是非ご参照ください。
　[Power Apps のトリセツ（もちろん非公式）＃ Outlook スケジュール編](https://tech-blog.cloud-config.jp/2020-02-19-powerapps-torisetsu-outlook-schedule/)

<br>
　ということで、設定した勤務パターンを各勤務者の予定表に入れる作業は完了です。
　こんな感じで動きます（注：今回は自分で自分の予定表に追加しています）。
　各勤務パターンに開始/終了時間も持たせれば、時間単位の予定表追加も可能になりますね。
![予定表追加完成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/8fcd6770-e79c-96c5-95ec-f31d8671e665.gif)



## 希望勤務申請アプリを作成する
　ここでは、先ほどまで作成した勤務シフト作成アプリとは別に、各勤務者が希望の勤務パターンを登録するための希望勤務申請アプリを、ざざっと作成します。
　ベースとなるデータソースは、各勤務者の希望勤務パターンや実際の勤務パターンを日別に登録する"勤務シフト_メイン"となりますので、このリストからアプリを自動生成するところから始めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/38d2e75a-253a-f125-123e-32a82368fe60.png)

　続いて、App の OnStart にて、以後 Gallery や Form で利用する用途で、利用ユーザーのメールアドレスを保持する変数 UserEmail と、今月１日の日付を保持する変数 FirstDayOfMonth を以下の通り設定します。

```:App-OnStart
Set(UserEmail, User().Email);
Set(FirstDayOfMonth, DateAdd(Today(),1-Day(Today()),Days));
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/f97088d2-5715-65a3-8509-95c7aa159ded.png)

　続いて、BrowseScreen1 へ。2か所手を加えます。
　まず、BrowseGallery1 の中身（Items）を、以下のように書き換えます。

```:BrowseGallery1-Items
SortByColumns(
    Filter(
        [@勤務シフト_メイン], 
        mWorkDateValue >= Value(Text(FirstDayOfMonth, "[$-ja]yyyymmdd")),
        mWorkUser.Email = UserEmail,
        StartsWith(mWorkPattern, TextSearchBox1.Text)
    ),
    "mWorkDate",
    If(SortDescending1, Descending, Ascending)
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/1f60ee5e-00dc-6953-1d3c-8a47d3628f4b.png)
　自動生成された Items の Filter 条件に「今月１日以降」と「本人の情報のみ」を追加し、SortByColums のソート列を勤務日に変更したものです。
　Filter 処理で今月１日以降とした根拠は「表示数が増えた時に今月１日以降の分があればいいよな」と思っただけで、特に厳密な根拠はありません。
　Filter 処理で日付フィルタを数値列で行っていることと、ユーザーフィルタの右辺を直接「User().Email」とせず変数を介したのは、いずれも委任警告を回避するためです。詳細は以下をご覧ください。
　[PowerAppsで遭遇する５つの委任問題とちょっと強引な回避方法（SharePointリスト利用時）その１](https://qiita.com/KodamaJn/items/4341865e6784847a005d)
<br>
　続いて、BrowseScreen1 の2か所目。
　BrowseGallery1 内の中身（Items）が分かりにくいので、適当に分かりやすくします。
　こんな感じにしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/0637139f-cfb2-5406-57bd-f4aca9d0f18c.png)


　続いて、EditScreen1 の修正へ。
　はじめに、EditForm1 内のカードを、最低限必要なもののみ残します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/430fb436-3e69-4923-fba7-d97743573104.png)

　まずは、勤務日を「新規登録時は来月１日を初期値とする」ように変更します。
　具体的には、勤務日である mWorkDate のデータカードの Default を以下に書き換えます。
　Form のモードが新規（New）の場合は、初期値を来月頭にしているだけです。わざわざこんなことをしなくても良いのですが、希望勤務を申請するのは前月なので、初期値を来月にしておかないと、申請する度にいちいち日付選択でカレンダーを翌月に切り替える必要があるため、こうしてみました。

```:mWorkDate_DataCard-Default
If(EditForm1.Mode = New,
    DateAdd(FirstDayOfMonth, 1, Months),
    ThisItem.mWorkDate
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/a80f188e-aa7d-6997-bf49-dcb88590c984.png)

　続いて、勤務日の数値を持つ mWorkDateValue のデータカードの Default を以下に書き換えます。
　この列は常に、勤務日である mWorkDate の数値版を格納すればよいだけなので、勤務日のカード内の日付選択コントロールの値を8桁の数値に変換したものを Default にしておけばよいです。

```:mWorkDateValue_DataCard-Default
Value(Text(DataCardValue8.SelectedDate, "[$-ja]yyyymmdd"))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/9780eea3-7b15-f071-b535-2d82ee37332b.png)

　続いて、以後の設定を行うために、メイン以外のデータソースと接続をしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/2106b973-e410-0429-c1ba-119c0484f248.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/1348ee78-ba33-314b-696e-ec2e9b4f1ddd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/1074cdf3-cba0-e877-cd45-3ffea4faedd3.png)

　続いて、勤務者は常に「申請した人」となるようにします。
　具体的には、勤務者のユーザー情報を持つ mWorkUser のデータカードの Default を以下に書き換えます。
　"勤務シフト_ユーザー"のリストから、自分のユーザー情報を抽出しているだけです。

```:mWorkUser_DataCard-Default
LookUp(勤務シフト_ユーザー, uWorkUser.Email = UserEmail).uWorkUser
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/8e74cf6c-216e-22c6-5a35-96a033638c39.png)

　最後に、希望勤務パターンを、登録されている勤務パターンのリストからドロップダウンで選択できるようにします。
　具体的には、希望勤務パターンの情報を持つ mRequestWorkPattern のデータカードを修正します。
　まずは、カード内のコントロールをドロップダウンリストに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/67dd8a0e-3dcb-0472-3af1-71200720596a.png)
　続いて、ドロップダウンの選択肢である AllowedValues を、"勤務シフト_パターン"のリストに登録されている勤務パターンになるように設定します。

```:mRequestWorkPattern_DataCard-AllowedValues
勤務シフト_パターン.pWorkPattern
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/361af958-7996-03cc-25ae-23889b6b1b9e.png)
　最後に、登録時に SharePoint リストに登録する情報 Update を、選択された勤務パターンの情報になるよう設定します。

```:mRequestWorkPattern_DataCard-Update
DataCardValue14.Selected.pWorkPattern
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/ac59b5ce-bf48-34ed-ccc5-1968d7a1eaee.png)
<br>

　ということで、各勤務者が希望の勤務パターンを登録するための希望勤務申請アプリは完成です。
　こんな感じで動きます。

![勤務希望申請アプリ完成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/bb90665e-dc54-6fd4-be12-7da74f666631.gif)




# おわりに
　ここまでで、希望勤務の収集から確定シフトの配布までと、勤務者とシフト作成者双方の機能を一通り実装できました。一連の業務をアプリに置き換えるために必要な最低限の機能は、これで揃ったのではないかと思います。
　その５では、必須ではありませんが、あったら安心 or もっと嬉しい追加機能を実装します。

　その５はこちら：執筆中…