Power Apps で勤務シフト作成アプリを作る その２ 最低限の機能実装編

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

　その２では、その１で作成したデータベースをもとに実際にアプリを作成していきます。
　手順が非常に多いため、細かいプロパティの設定はかなり省略しています。
　また、分かりやすく説明しようと試みた結果、少し効率の悪い手順があるかもしれません。
　諸々ご了承ください。

# アプリに最低限の機能を実装する
　アプリはタブレット型で作成します。
![スクリーンショット (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/04f355fc-ede7-4a36-ec68-dd4f816a9a47.png)

　利用するリストと接続をしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/092464a8-9b35-ad61-80c7-7e28164d9a95.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/59851f7b-9e09-dce0-dbef-e2fb956bc371.png)



## 月別カレンダーを作成する
　まずは、勤務シフト表の肝となる、月別カレンダーを作成します。
　App の OnStart で、当月の初日と当月の日数を表す2つの変数 FirstDayOfMonth, DaysOfMonth と、1～31をただ格納しただけのコレクション DayTable を設定します。
　記述したら、OnStart を実行しておきましょう。

```:OnStart
Set(FirstDayOfMonth, DateAdd(Today(),1-Day(Today()),Days));
Set(DaysOfMonth, DateDiff(FirstDayOfMonth,DateAdd(FirstDayOfMonth, 1, Months),Days));
ClearCollect(DayTable, [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]);
```

![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/456e7f5f-3363-f972-28ab-188194c80de1.png)

　続いて、表示月を切り替えるアイコンを追加します。
　まずは表示月のラベル LabelThisMonth を追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/a2f4881d-e581-9ae2-4966-7862777983f9.png)
　続いて先月に切り替えるアイコン IconPrevMonth と、次月に切り替えるアイコン IconNextMonth を追加します。
　各々の OnSelect で、先ほど定義した 当月初日格納変数 FirstDayOfMonth と当月日数格納変数 DaysOfMonth を更新します。

先月：

```:IconPrevMonth-OnSelect
Set(FirstDayOfMonth, DateAdd(FirstDayOfMonth,-1,Months));
Set(DaysOfMonth, DateDiff(FirstDayOfMonth,DateAdd(FirstDayOfMonth, 1, Months),Days));
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/788c393f-48db-cab1-7c2d-ca759a214509.png)

次月：

```:IconNextMonth-OnSelect
Set(FirstDayOfMonth, DateAdd(FirstDayOfMonth,1,Months));
Set(DaysOfMonth, DateDiff(FirstDayOfMonth,DateAdd(FirstDayOfMonth, 1, Months),Days));
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/5c7a61e3-d614-70dd-09bd-af0f4468433b.png)

　続いて、カレンダーを挿入します。「横方向（空）」のギャラリー GalleryMain を挿入し、Items に以下を記述することで DayTable から当月の日数分だけ配列を取得できるようにします。 
　なお、後々微調整を容易にするため、ギャラリーの「テンプレートのパディング」は 0 にしておきましょう。

```:GalleryMain-Items
Filter(DayTable, Value<=DaysOfMonth)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/2dc905ff-5b97-dd57-58ad-3e7a99593eae.png)


　続いて、ギャラリー内に日付を表示するラベル LabelDay を追加します。
　テキストは Items の値そのままです。

```:LabelDay-Text
ThisItem.Value
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/c91ce5ea-cdbb-fc3f-223d-36b81f00ecaf.png)

　続いて、以後の処理で何をやっているか分かりやすくするため、日付を8桁の数値で表したラベル LabelDayValue を追加します。

```:LabelDayValue-Text
Text(DateAdd(FirstDayOfMonth, ThisItem.Value-1,Days), "[$-ja]yyyymmdd")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/69f8892c-9733-651e-b581-9bf0dc22c305.png)

　ここまでで、月別カレンダーは完成です。
　こんな感じで動きます。
![カレンダー完成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/43dc4b8d-23f7-7adb-4821-ed0613defb5a.gif)



## 勤務パターンを設定できるようにする
　先ほど作成した月別カレンダーに、勤務者毎に勤務パターンを設定するためのドロップダウンリストを追加します。
　の前に、まずは勤務者情報を表示する必要がありますので、「縦方向（空）」のギャラリー GalleryUser を追加します。
　データソース（Items）は勤務者が格納されている"勤務シフト_ユーザー"にします。
　こちらも、後々微調整を容易にするため、ギャラリーの「テンプレートのパディング」は 0 にしておきます。
　各行の高さを表す「テンプレートのサイズ」は適当に60くらいにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/bfe8a936-a48a-4f72-4db0-738ed86a014b.png)

　今追加した GalleryUser 内に、勤務者名を表示するラベル LabelUser を追加します。

```:LabelUser-Text
ThisItem.uWorkUser.DisplayName
```

![スクリーンショット (38).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/678963ec-a9b1-f702-93af-bbce137caeb4.png)


　続いて、最初に追加したギャラリー GalleryMain 内に、入れ子となる「縦方向（空）」のギャラリー GalleryWorkPatternPerUser を追加します。
　データソース（Items）は、この後勤務パターンを"勤務者毎"に設定していくため、勤務者が格納されている"勤務シフト_ユーザー"にします。
　こちらも、後々微調整を容易にするため、ギャラリーの「テンプレートのパディング」は 0 にしておきます。
　各行の高さを表す「テンプレートのサイズ」は先ほどの GalleryUser の値に合わせて60にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/9f4308db-2279-c5e8-5b95-6606e5d639ef.png)

　GalleryWorkPatternPerUser の位置（Y）を何となく合わせて、その後本ギャラリー内に勤務パターンを選択するドロップダウン DropdownWorkPattern を追加します。
　はじめに、未選択状態を許すため AllowEmptySelection を true にしておきます。
　その後、勤務パターンを選択するので、Items は"勤務シフト_パターン"とします。
　ドロップダウンの表示情報である Value は、勤務パターン名である pWorkPattern とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/7892fec8-94e5-706b-4acd-37b5d7282d71.png)

　続いて、ドロップダウンの初期値を設定します。
　勤務シフトデータを格納する"勤務シフト_メイン"から、とある日のとある勤務者の勤務パターンを探して初期値としますので、初期値 Default を以下のように設定します。
　"とある日"はカレンダー上部にある8桁の日付数値が格納されたラベル LabelDayValue.Text から、"とある勤務者"は直属のギャラリーが勤務者情報を保持しているので ThisItem.uWorkUser から参照できます。

```:DropdownWorkPattern-Default
First(Filter(勤務シフト_メイン, mWorkDateValue=Value(LabelDayValue.Text), mWorkUser.DisplayName=ThisItem.uWorkUser.DisplayName)).mWorkPattern
```

　うまくいけば、その１の手順で格納した値が初期値として表示されると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/d2275391-2031-c210-3878-ea3c68f65401.png)

　最後に、ドロップダウンを変更した場合にリストに書き込む処理を加えます。ここはちょっと複雑です。
　ここでは、以下の場合は「とある日のとある勤務者のレコード」が存在するため既存レコードを上書きし、それ以外（＝新規）の場合は新規レコードを追加する処理を行う必要があります。

- 勤務者から希望勤務が申請されている場合
- 既に１回勤務パターンを設定している場合

　よって、「とある日のとある勤務者のレコード」があるかどうかを判定し、それによって処理を分岐させます。

```:DropdownWorkPattern-OnChange
If(IsEmpty(Filter(勤務シフト_メイン, mWorkDateValue=Value(LabelDayValue.Text), mWorkUser.DisplayName=ThisItem.uWorkUser.DisplayName)),
    Patch(勤務シフト_メイン, Defaults(勤務シフト_メイン), {mWorkDate: DateAdd(FirstDayOfMonth, Value(LabelDay.Text)-1,Days), mWorkDateValue: Value(LabelDayValue.Text), mWorkUser:ThisItem.uWorkUser, mWorkPattern: DropdownWorkPattern.Selected.pWorkPattern}),
    UpdateIf(勤務シフト_メイン, And(mWorkDateValue=Value(LabelDayValue.Text),mWorkUser.DisplayName=ThisItem.uWorkUser.DisplayName), {mWorkPattern: DropdownWorkPattern.Selected.pWorkPattern})
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/1d5bfb95-d182-176d-1fcb-43dc71bc212a.png)

　これで、勤務パターンを設定する作業は完了です。


# おわりに
　ここまでで、"最低限"勤務パターンを勤務者毎に設定できるようになりました。
　こんな感じで動きます。
![OnChange完成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405544/dc5bcccc-2e32-3047-8fbb-1f44b2b2bb15.gif)


　ただ、このままでは、素早く連続してドロップダウンを変更していくと、書き込みが追い付かずエラーとなります。
　その３では、この書き込みの問題を解消する方法や、希望勤務の表示などの機能を実装します。

　その３はこちら：https://qiita.com/KodamaJn/items/00af61369887d4b8dff6