天天看點

拆解PowerApps - 請假申請 - 7

上一節我們完成了頁面 NewRequestScreen 的解析,那個頁面相當于是送出請假申請的第一步,選擇要請的假期的類型。

本節接下來會沿着這個申請,一步步解析相關的頁面。

當點選了假期類型後,所跳轉到的頁面就是下面這個 SelectDatesScreen,讓使用者選擇假期的開始日期和結束日期。

拆解PowerApps - 請假申請 - 7

1. 頁面結構

從上圖能看出的是,整個頁面由多種獨立控件組成。從上到下,這個頁面涉及到圖示、标簽、圖檔、幾何形狀、日期拾取器和按鈕六種控件。

2. 控件解析

接下來我們就逐個看這些控件和如何結合在一起運作的。

首先,注意到SelectDatesScreen層面上設定了 OnVisible 屬性:

OnVisible  = If(!_editingRequest && !_reviewRequest, Set(_leaveStart,Today());Set(_leaveEnd,Today()));    //如果目前既不是編輯之前的申請(!_editingRequest) 也不是檢視之前的申請(!_reviewRequest),就把開始日期和結束日期都設定成當天(相當于是建立一個申請)。

//注意: 本節多次用到這兩個布爾類型的變量 _editingRequest 和 _reviewRequest。

//這兩個變量在之前的HomeScreen裡有做過初始化設定,後續根據申請頁面的狀态不同,還有幾個頁面也對其進行了初始化設定。

2.1 iconBackSelectDates  - 左上角的傳回按鈕

OnSelect = Back();Reset(LeaveStartDatePicker);Reset(LeaveEndDatePicker)     //傳回上一頁,然後重置兩個日期拾取器

2.2 LabelSelectDatesHeader - 頁面标題

Text = If(_editingRequest, "Edit ", "Select ") & "dates"   //根據目前頁面的屬性是編輯之前的申請還是建立申請(通過變量 _editingRequest 進行控制),顯示不同的标題

2.3 ImageLeaveType    - 假期類型圖示  

Image = If(_editingRequest, LookUp(LeaveTypeCollection, Upper(type)=Upper(First(RequestEdit).LeaveType)).icon, _selectedLeaveType.icon) 

//和上面的标簽控件很類似,也是根據目前頁面的屬性進行相應的後續處理。差別在于上面是直接固定設定好不同情況下的文字提示,這裡是根據情況設定不同的圖示。

//如果目前是編輯頁面,就通過LookUp函數從LeaveTypeCollection裡找出對應的假期類型圖示; 否則就利用上一節傳遞過來的變量 _selectedLeaveType, 其實也是個對象,通過 . 運算符來擷取所選的假期對應的圖示。 

//這裡還涉及到第四節設定的一個集合 RequestEdit ,其中存儲的時使用者要編輯的請假申請資料,後續會繼續提及。

2.4 LabelLeaveType   - 假期類型名稱  

Text = If(_editingRequest, First(RequestEdit).LeaveType, _selectedLeaveType.type)     //還是類似的邏輯,同時又用到了上一節傳來的變量

2.5 LabelCurrentBalanceText   

Text = "Current balance: "    //文字固定的提示标簽

2.6 LabelCurrentBalanceVal    - 目前可用的假期天數

Text = LookUp(RequesterBalanceCollection,     //Lookup函數的第一個參數:要去查詢的資料源,這裡設定的是第三節裡建立的集合 RequesterBalanceCollection。順便回憶一下,這個集合裡存儲的是員工目前可用的假期天數。

          Upper(type)=If(_editingRequest, Upper(First(RequestEdit).LeaveType), Upper(_selectedLeaveType.type)),     //Lookup 函數的第二個參數:查詢條件

          Text(balance) &If(balance<2, " day", " days"))    //LookUp函數的結果,這裡利用Text函數将依據 Type條件查詢傳回的結果,也就是假期天數(balance)轉成了文本,然後和文字 day 或者 days組合成新的文本。

上面四個控件在有資料時,所顯示出來的效果如下圖所示:

拆解PowerApps - 請假申請 - 7

2.7 Rectangle9_4  - 區域分割線

2.8 LabelSelectDates  - 提示性的文本資訊

Text = "Select Dates"    //文字固定的提示标簽

2.9 Label19    -- 假期起始日期的提示性文本

Text = "*From"        //文字固定的提示标簽

2.10 LeaveStartDatePicker - 用來選擇假期的起始日期

這個控件有四個關鍵的屬性設定:

 - DateTimeZone = Local    //日期的時區設定

 - DefaultDate = If(_editingRequest, First(RequestEdit).StartDate, _reviewRequest, _leaveStart ,Today())   //設定頁面打開後,日期選擇器預設顯示的日期。這裡利用 IF(條件1,結果1,條件2,結果2,..., 條件n, 結果n, 預設結果 )的格式,定義了三種不同狀态的顯示日期: 編輯狀态,檢視狀态,其它狀态。

 - OnChange = Set(_leaveStart, LeaveStartDatePicker.SelectedDate)    //利用日期選擇器選擇了其它日期後,将新選的日期指派給變量 _leaveStart

 - StartOfWeek = StartOfWeek.Sunday      //每周的起始日期設定為周日,這個設定會直接影響到諸如第四節裡的假期天數計算邏輯。

2.11 Label19_1 - 假期結束日期的提示性文本

Text = "*From"        //文字固定的提示标簽

2.12 LeaveEndDatePicker  - 用來選擇假期的結束日期

運作邏輯和上面那個選擇起始日期的控件一樣,隻是從開始日期變成了結束日期。

 - DateTimeZone = Local   

 - DefaultDate = If(_editingRequest, First(RequestEdit).EndDate, _reviewRequest, _leaveEnd, Today())

 - OnChange = Set(_leaveEnd, LeaveEndDatePicker.SelectedDate)

 - StartOfWeek = StartOfWeek.Sunday   

2.13 Label1 - 當日期選擇不規範時(比如結束日期比開始日期還早),用來顯示警告資訊,提示使用者重新選擇正确的日期。

Text  = If(LeaveStartDatePicker.SelectedDate > LeaveEndDatePicker.SelectedDate || And(!_editingRequest, LeaveStartDatePicker.SelectedDate < Today()), "Start date must occur on or " & If(LeaveStartDatePicker.SelectedDate > LeaveEndDatePicker.SelectedDate,"before end date", "after today"))

如下圖,出錯時的警告提示效果:

拆解PowerApps - 請假申請 - 7

2.14 Rectangle9_5  - 區域分割線

2.15 ButtonNextSelectDates - 頁面最下面的下一步按鈕

OnSelect = 

//**** 計算假期申請天數的預備代碼段 - 開始位置 ****和第四節裡計算假期申請天數的代碼段相同的邏輯

If(LeaveStartDatePicker.SelectedDate <= LeaveEndDatePicker.SelectedDate,    //隻是這裡開頭是通過一個 IF語句來處理條件判斷,第四節裡是直接開始

    Set(_inclusiveTotalDaysRequested, DateDiff(LeaveStartDatePicker.SelectedDate, LeaveEndDatePicker.SelectedDate, Days) + 1);   //這裡也有點不同,但也隻是變量名稱的差别,邏輯上完全一樣。

    Set(_numFullWeeks, RoundDown(_inclusiveTotalDaysRequested / 7, 0));

    Set(_numFullDaysPartialWeek, _inclusiveTotalDaysRequested - _numFullWeeks * 7);

    Concurrent(Set(_startWeekday, Weekday(LeaveStartDatePicker.SelectedDate)), Set(_endWeekday, Weekday(LeaveEndDatePicker.SelectedDate)));

   //下面的IF 代碼段計算從所申請的總天數減去整周用掉的天數後,剩下的工作日天數

    If(_numFullDaysPartialWeek = 6,       If(_startWeekday <= 2, Set(_numPartialWeekdays, 5), Set(_numPartialWeekdays, 4)        ),

      _numFullDaysPartialWeek = 5,        If(_startWeekday = 2, Set(_numPartialWeekdays, 5), _startWeekday = 1 || _startWeekday = 3 || _startWeekday = 4, Set(_numPartialWeekdays, 4), Set(_numPartialWeekdays, 3)        ),

      _numFullDaysPartialWeek = 4,        If(_startWeekday = 2 || _startWeekday = 3, Set(_numPartialWeekdays, 4), _startWeekday = 1 || _startWeekday = 4, Set(_numPartialWeekdays, 3), Set(_numPartialWeekdays, 2)        ),

      _numFullDaysPartialWeek = 3,        If(_startWeekday = 6 || _startWeekday = 7, Set(_numPartialWeekdays, 1), _startWeekday = 1 || _startWeekday = 5, Set(_numPartialWeekdays, 2), Set(_numPartialWeekdays, 3)        ),

      _numFullDaysPartialWeek = 2,        If(_startWeekday = 7, Set(_numPartialWeekdays, 0), _startWeekday = 1 || _startWeekday = 6, Set(_numPartialWeekdays, 1), Set(_numPartialWeekdays, 2)),     

      _numFullDaysPartialWeek = 1,        If(_startWeekday = 1 || _startWeekday = 7, Set(_numPartialWeekdays, 0), Set(_numPartialWeekdays, 1)        ),

      _numFullDaysPartialWeek = 0, Set(_numPartialWeekdays, 0)

    );

      Set(_workDaysInRequest, _numFullWeeks * 5 + _numPartialWeekdays);  

      Set(_holidaysInRequest, CountIf(Holidays, StartDate >= LeaveStartDatePicker.SelectedDate, StartDate <= LeaveEndDatePicker.SelectedDate));

      Set(_requestedDays, _workDaysInRequest - _holidaysInRequest)

);

//**** 計算假期申請天數的代碼段 - 結束位置 - 最終請假的天數存儲在上面最後一個變量 _requestedDays 裡****   

If(_editingRequest,  Patch(RequestEdit, First(RequestEdit), {StartDate: LeaveStartDatePicker.SelectedDate, EndDate: LeaveEndDatePicker.SelectedDate, DaysCount:_requestedDays }) ;  Navigate(EditRequestScreen, None),

   _reviewRequest, Back(), 

   Navigate(SelectApproverScreen, None)

)

//最後這個 IF 是在上面計算完假期天數後,再根據不同的頁面狀态執行不同的動作。

//如果目前是編輯頁面,就把新選的日期通過 Patch 指令暫存到 RequestEdit 集合裡,然後跳轉到EditRequestScreen頁面;

//如果目前是檢視頁面,就直接傳回上一個頁面;

//其它狀态,就跳轉到SelectApproverScreen頁面。

附注:本節用到的函數:

Set, Concurrent, IF, Navigate, Reset, LookUp, First, Upper, Text, Patch

----------- 本節完成了對SelectDatesScreen頁面的解析,我們下一節再見------------

繼續閱讀