Skip to main content

Build an Overtime Timesheet App in Power Apps — Part 7: Build the My Overtime Screen

· 44 min read
Jagdish Kumawat
Founder @ Dewiride

People can log their overtime; this screen shows them what they've logged. It lists a month of their entries with a status badge on each, adds up the month and each Monday-to-Sunday week, moves between months, and lets them correct an entry until it's approved, by opening it on the Log Overtime screen.

This is Part 7 of a 20-part series.

  1. Part 1: Plan the App and Set Up the Demo Organization
  2. Part 2: Create the SharePoint Site and Lists
  3. Part 3: Keep Overtime Private with SharePoint Permissions
  4. Part 4: Create the Solution, Environment Variables and Canvas App
  5. Part 5: Build the Home Screen
  6. Part 6: Build the Log Overtime Screen
  7. Part 7: Build the My Overtime Screen (you are here)
  8. Part 8: Build the Approval Flow for Teams and Outlook
  9. Part 9: Show Approvers What's Waiting (coming soon)
  10. Part 10: Build the Departments Screen (coming soon)
  11. Part 11: Build the Reports Screen (coming soon)
  12. Part 12: Import the Old Excel Timesheet (coming soon)
  13. Part 13: Create the Monthly Payroll Workbook with Office Scripts (coming soon)
  14. Part 14: Build the Power BI Overtime Report (coming soon)
  15. Part 15: Share the App and Add It to Microsoft Teams (coming soon)
  16. Part 16: Test Every Role and Department (coming soon)
  17. Part 17: Build a Setup Flow That Creates the Lists (coming soon)
  18. Part 18: Run the Solution Checker and Export the Solutions (coming soon)
  19. Part 19: Install the App in a New Environment (coming soon)
  20. Part 20: Recap, Production Checklist and Next Steps (coming soon)

Part 6 built the Log Overtime screen, which adds a shift. This part builds the screen behind the Home screen's My overtime tile, and gives the Log Overtime screen an edit mode, so the same form corrects an entry. Each generic task has its own guide; this part gives the values for this app, and why.

What You'll Build​

The finished screen for November 2026, with one entry rejected:

The My overtime screen in Preview for November 2026: previous and next month buttons with the next one greyed out, Total for November 2026: 7.00 hours, the weeks Mon 26/10/2026 to Sun 01/11/2026: 6.00 hours and Mon 02/11/2026 to Sun 08/11/2026: 3.00 hours, a note about weeks and rejected entries, and three rows with Edit buttons: Sun 01/11/2026 from 09:00 to 13:00 in Radiology, Pending; Mon 02/11/2026 from 18:00 to 21:00 in the Emergency Department, Pending; and Fri 06/11/2026 from 17:00 to 20:30 in Radiology, Rejected

How the Screen Works​

The decisions behind the formulas:

  • One month at a time, starting with this one. Buttons move to the previous and next month. The next-month button stops at the current month, because overtime is logged after it's worked.
  • Only the person's own entries. Staff can only open their own entries in SharePoint anyway (Part 3). The screen also filters on their email, which keeps the query small, and keeps the maker, who owns the list and can read every entry, to their own.
  • SharePoint finds the rows; the app adds them up. SharePoint can filter by person and by date, but Sum and GroupBy can't be delegated to it. The screen loads the rows it needs with a filter SharePoint can run, keeps them in context variables, and works out the totals from those.
  • Full weeks. A week runs from Monday to Sunday, as the date picker in Part 6 does. The first and last weeks of a month take in days of the months around it, so the screen loads those days too: the weekly totals count them, and the month's total doesn't.
  • Rejected entries aren't counted in either total. They stay in the list with their badge, so people can correct them and send them again.
  • Edit until approved. Each entry that isn't approved has an Edit button, which opens it on the Log Overtime screen. Saving a change sends it back for approval.

Prerequisites​

Step 1: Add the MondayOf Function​

The weekly totals need the Monday each entry's week starts on, and the screen needs the Mondays around the month it shows. One function in App.Formulas, after Part 6's, works it out for any date (How to Find the Monday of a Week in Power Apps):

App → Formulas (added after Part 6's)
MondayOf(AnyDate: Date): Date = DateAdd(AnyDate, 1 - Weekday(AnyDate, StartOfWeek.Monday), TimeUnit.Days);

Weekday(AnyDate, StartOfWeek.Monday) numbers the days from 1 for Monday to 7 for Sunday (How to Get the Day of the Week in Power Apps with Weekday), so a Sunday goes back six days and a Monday stays where it is. For Sunday 8 November 2026, it gave Monday 2 November:

The formula bar with MondayOf(Date(2026, 11, 8)), the preview strip reading 02/11/2026, 00:00:00 with Data type Date, and the text control showing 02/11/2026

Step 2: Add the Screen and Its Header​

Add a Blank screen (How to Add a New Screen in Power Apps) and rename it My Overtime Screen. Controls on this screen end in MO:

My Overtime Screen layout
My Overtime Screen
└─ conMainMO vertical: fills the screen
├─ conHeaderMO horizontal: copied from the Log Overtime screen
│ ├─ btnBackMO
│ ├─ lblTitleMO
│ └─ btnRefreshMO loads the month
└─ conBodyMO vertical: scrolling
├─ conMonthMO btnPreviousMonthMO, lblMonthMO, btnNextMonthMO
├─ lblTotalMO the month's total
├─ lblWeeksMO the weekly totals
├─ lblTotalsNoteMO
├─ lblEmptyMO shown when the month has no entries
├─ spnLoadingMO shown while loading
└─ galEntriesMO one row per entry
├─ lblEntryDayMO
├─ lblEntryTimesMO
├─ lblEntryDepartmentMO
├─ bdgStatusMO
└─ btnEditMO

The main container. Insert a vertical container, conMainMO, with the same settings as the Log Overtime screen's: X, Y 0; Width Parent.Width; Height Parent.Height; Align (horizontal) Stretch; Padding 0; Drop shadow None; Border radius 0.

The header. Copy conHeaderLO on the Log Overtime screen and paste it into conMainMO (How to Copy and Paste Controls Between Screens in Power Apps). Rename the copies conHeaderMO, btnBackMO and lblTitleMO, and set the title's Text to "My overtime". The Back button keeps its Back().

The Refresh button. Insert a button into conHeaderMO; it goes in at the end, after the title. Name it btnRefreshMO (How to Add a Refresh Button to a Screen in Power Apps):

PropertyValue
Text"Refresh"
Icon"ArrowClockwise"
Height40
LayoutIf(App.ActiveScreen.Size = ScreenSize.Small, ButtonLayout.IconOnly, ButtonLayout.IconBefore)
WidthIf(App.ActiveScreen.Size = ScreenSize.Small, 40, 112)
AccessibleLabel, Tooltip"Refresh this screen"

On a phone it shows only its icon, so the title has room: How to Show Only the Icon on a Button on Phones in Power Apps. Its OnSelect loads the month, in Step 4.

The body. Insert a vertical container into conMainMO after the header, conBodyMO: Flexible height On; Align (horizontal) Start; Gap 16; Padding 24; Vertical overflow Scroll; Drop shadow None; Border radius 0.

Step 3: Add the Month Bar​

The screen keeps the first day of the month it shows in a context variable, locMonthMO. Two buttons move it a month at a time, with the month's name between them: How to Add Previous and Next Month Buttons in Power Apps.

Insert a horizontal container into conBodyMO, conMonthMO (How to Add a Horizontal Container in Power Apps):

SettingValue
Flexible heightOff; Height 40
WidthMin(640, Parent.Width - 48)
Align in containerStart
Align (vertical)Center
Gap8
Padding, Drop shadow, Border radius0, None, 0

Min(640, Parent.Width - 48) keeps the screen's content 640 pixels wide on a large screen, and the full width on a phone, less the body's padding. The totals and the list use the same width.

Inside it, add two buttons with a Text control between them:

PropertybtnPreviousMonthMOlblMonthMObtnNextMonthMO
Text"Previous month"Text(locMonthMO, "mmmm yyyy")"Next month"
Icon"ChevronLeft""ChevronRight"
LayoutButtonLayout.IconOnlyButtonLayout.IconOnly
AppearanceSecondarySecondary
Size20, Semibold, centered
Width, Height40, 40Flexible width On, Height 4040, 40
AccessibleLabel"Previous month"Self.Text"Next month"
Tooltip"Previous month""Next month"

The label shows the month as November 2026 (How to Show the Month Name and Year in Power Apps). The buttons show only their arrows, so their AccessibleLabel and Tooltip say what they do. Each one moves locMonthMO and then runs the Refresh button's formula, which loads the new month (How to Use the Select Function in Power Apps):

btnPreviousMonthMO → OnSelect
UpdateContext({locMonthMO: DateAdd(locMonthMO, -1, TimeUnit.Months)});
Select(btnRefreshMO)
btnNextMonthMO → OnSelect
UpdateContext({locMonthMO: DateAdd(locMonthMO, 1, TimeUnit.Months)});
Select(btnRefreshMO)

locMonthMO is always the 1st, and a month added to the 1st is the 1st of the next month. The next-month button is disabled on the current month, whose first day is Date(Year(Today()), Month(Today()), 1) (How to Get the First Day of the Month in Power Apps):

btnNextMonthMO → DisplayMode
If(locMonthMO < Date(Year(Today()), Month(Today()), 1), DisplayMode.Edit, DisplayMode.Disabled)

In Preview, on November 2026, the next-month button is greyed out:

The top of the My overtime screen in Preview: the green header with Back and My overtime, and below it a previous-month button, the heading November 2026 and a greyed-out next-month button

Step 4: Load the Month's Entries​

The Refresh button's OnSelect loads the entries, and the screen's OnVisible selects the button. The same formula then runs when the screen opens, when the month changes and when someone selects Refresh:

A macOS-style code window titled btnRefreshMO → OnSelect: UpdateContext sets locIsLoadingMO to true, Refresh runs on OvertimeEntries, With works out FromDate and ToDate from MondayOf, a second With sorts the person's entries between the two dates by StartTime, UpdateContext keeps them in locLoadedMO and the month's in locEntriesMO, and a last UpdateContext sets locIsLoadingMO to false

btnRefreshMO → OnSelect
UpdateContext({locIsLoadingMO: true});
Refresh(OvertimeEntries);
With(
{
FromDate: MondayOf(locMonthMO),
ToDate: DateAdd(
MondayOf(DateAdd(DateAdd(locMonthMO, 1, TimeUnit.Months), -1, TimeUnit.Days)),
6,
TimeUnit.Days
)
},
With(
{
Loaded: Sort(
Filter(
OvertimeEntries,
EmployeeEmail = MyEmail && WorkDate >= FromDate && WorkDate <= ToDate
),
StartTime
)
},
UpdateContext(
{
locLoadedMO: Loaded,
locEntriesMO: Filter(Loaded, WorkMonth = Text(locMonthMO, "yyyy-mm"))
}
)
)
);
UpdateContext({locIsLoadingMO: false})
  • locIsLoadingMO is true while the entries load, so the screen can show a spinner instead of half-loaded totals (Step 7).
  • Refresh gets the list's latest data, so an entry changed somewhere else shows up too (How to Refresh Data in Power Apps with the Refresh Function).
  • FromDate is the Monday of the week the 1st is in. ToDate is the Sunday of the week the last day is in: the last day is the 1st of the next month less a day (How to Get the Last Day of the Month in Power Apps), and its week ends six days after its Monday. For November 2026, that's Monday 26 October to Sunday 6 December.
  • Filter asks SharePoint for this person's entries between the two dates. = on a text column, >= and <= on a date column and && can all be delegated, so SharePoint runs the whole query, however long the list grows (How to Filter a SharePoint List Between Two Dates in Power Apps).
  • Sort puts the entries in the order they were worked (How to Sort a Table in Power Apps with Sort).
  • The rows go into two context variables: locLoadedMO, the full weeks, for the weekly totals, and locEntriesMO, only the month's, for the list and the month's total. WorkMonth is the month as text, such as 2026-11, which Part 6's Save writes.

Microsoft's delegation overview explains why the totals can then use Sum and GroupBy: tables kept by With, UpdateContext or Set are a static in-memory list of records, so functions that can't be delegated work on all of them, with no delegation warning.

Then select the screen and set its OnVisible (How to Run a Formula When a Screen Opens in Power Apps with OnVisible):

My Overtime Screen → OnVisible
If(
IsBlank(locMonthMO),
UpdateContext({locMonthMO: Date(Year(Today()), Month(Today()), 1)})
);
Select(btnRefreshMO)

The first time the screen opens, locMonthMO is blank, so it starts on this month. After that it keeps its month: Microsoft's UpdateContext reference says a context variable holds its value until the app is closed, even when the user switches to another screen. So someone who opens an October entry and comes back is still on October, reloaded.

After the screen loaded November in Preview, Studio's Variables pane showed three rows in locEntriesMO and four in locLoadedMO. The fourth is 29 October, in the week that starts on Monday 26 October:

The Variables pane with Context variables expanded for the My Overtime Screen: locEntriesMO Table 3 rows, locIsLoadingMO Boolean false, locLoadedMO Table 4 rows, and locMonthMO DateTime 01/1 shortened by the pane

Step 5: Show the Month's Total​

Under conMonthMO, insert a Text control, lblTotalMO (How to Add a Text Control in Power Apps): Size 20, Font weight Semibold, Auto height on, Width Min(640, Parent.Width - 48), Align in container Start, Visible !locIsLoadingMO and AccessibleLabel Self.Text. Its Text adds up the month's entries that aren't rejected (How to Add Up a Column in Power Apps with Sum):

lblTotalMO → Text
$"Total for {Text(locMonthMO, "mmmm yyyy")}: {Text(Coalesce(Sum(Filter(locEntriesMO, Status.Value <> "Rejected"), Hours), 0), "0.00")} hours"

Step 6: Show the Weekly Totals​

Under lblTotalMO, insert a Text control, lblWeeksMO: Size 14, Auto height on, the same Width and Align in container, AccessibleLabel Self.Text, and Visible !locIsLoadingMO && !IsEmpty(locLoadedMO). Its Text gives one line per week:

A macOS-style code window titled lblWeeksMO → Text: Concat over Sort of AddColumns over GroupBy, which groups the entries that aren't rejected by a WeekStart column of MondayOf(WorkDate), adds WeekHours as the Sum of each week's Hours, and joins one line per week with its Monday, its Sunday and its hours, separated by Char(10)

lblWeeksMO → Text
Concat(
Sort(
AddColumns(
GroupBy(
AddColumns(Filter(locLoadedMO, Status.Value <> "Rejected"), WeekStart, MondayOf(WorkDate)),
WeekStart,
WeekEntries
),
WeekHours,
Sum(WeekEntries, Hours)
),
WeekStart
),
$"{Text(WeekStart, "ddd dd/mm/yyyy")} to {Text(DateAdd(WeekStart, 6, TimeUnit.Days), "ddd dd/mm/yyyy")}: {Text(WeekHours, "0.00")} hours",
Char(10)
)

From the inside out:

  1. Filter leaves out rejected entries from the full weeks the screen loaded.
  2. AddColumns gives each entry a WeekStart: the Monday of its week, from MondayOf (How to Add a Column to a Table in Power Apps with AddColumns).
  3. GroupBy makes one row per WeekStart, with that week's entries in a table column, WeekEntries (How to Group Records in Power Apps with GroupBy).
  4. AddColumns adds WeekHours, the Sum of each week's hours (How to Total Each Group in Power Apps with GroupBy and Sum).
  5. Sort puts the weeks in date order, and Concat joins one line per week, with Char(10), a line break, between them (How to Join Table Values into Text in Power Apps with Concat).

Each line shows the week's Monday and Sunday with their day names, such as Mon 26/10/2026 to Sun 01/11/2026: 6.00 hours (How to Show the Day Name of a Date in Power Apps). Every week has at least one entry, so its Sum is never blank.

Under it, a Text control, lblTotalsNoteMO, says what the totals count: Size 12, Auto height on, the same Width and Align in container, Visible !locIsLoadingMO, AccessibleLabel Self.Text, and this Text:

lblTotalsNoteMO → Text
"Weeks run from Monday to Sunday, including days in the next or previous month. Rejected entries aren't counted."

Without the note, a week's total that's bigger than the month's would look like a mistake.

Step 7: Show a Spinner and the Empty Month​

The spinner. Insert a Spinner into conBodyMO, spnLoadingMO, with Label "Loading your overtime...", Visible locIsLoadingMO and Align in container Start (How to Add a Loading Spinner in Power Apps). The totals and the list are hidden while it shows, by their !locIsLoadingMO.

The empty month. Insert a Text control, lblEmptyMO, with Size 14, Auto height on, the same Width and Align in container, and AccessibleLabel Self.Text (How to Show a Message When a Gallery Is Empty in Power Apps):

lblEmptyMO → Text
$"You haven't logged any overtime in {Text(locMonthMO, "mmmm yyyy")}."
lblEmptyMO → Visible
!locIsLoadingMO && IsEmpty(locEntriesMO)

September 2026, which has no entries, in Preview:

The My overtime screen in Preview for September 2026, with Total for September 2026: 0.00 hours, the note about weeks and rejected entries, and the message You haven't logged any overtime in September 2026

Step 8: Add the List of Entries​

Insert a Vertical gallery into conBodyMO. It came with sample rows and the layout Image, title, and subtitle; set Layout to Blank in its properties, and name it galEntriesMO (How to Add a Vertical Gallery in Power Apps and Connect It to a SharePoint List). Studio put it right after the month bar, so move it to the end of the body with Reorder → Move to end (How to Reorder Controls in a Container in Power Apps).

PropertyValueWhy
ItemslocEntriesMOThe month's entries, from Step 4
Flexible heightOn, minimum height 240Fills the rest of the body
WidthMin(640, Parent.Width - 48)The same width as the totals
Align in containerStart
TemplateSize, TemplatePadding112, 8Three lines per row, with space between rows
TemplateFillApp.Theme.Colors.Lighter80A light shade of the app's green theme
SelectablefalseRows aren't selected; the Edit button does the work
AccessibleLabel"Your overtime entries for the month"What screen readers announce
Visible!locIsLoadingMO && !IsEmpty(locEntriesMO)The opposite of the empty message

The row. Select the gallery's first row on the canvas, so new controls go into its template rather than the screen (Fixed: Control Added Outside the Gallery Instead of Inside It in Power Apps). Then insert three Text controls, a Badge and a Button. TW in the table stands for Parent.TemplateWidth, the width of the row:

ControlX, YWidth, HeightText or Content
lblEntryDayMO16, 12TW - 144, 24Text(ThisItem.WorkDate, "ddd dd/mm/yyyy")
lblEntryTimesMO16, 42TW - 32, 24The times and hours, below
lblEntryDepartmentMO16, 70TW - 144, 32ThisItem.Department
bdgStatusMOTW - Self.Width - 16, 1296, 24ThisItem.Status.Value
btnEditMOTW - Self.Width - 16, 7096, 32Step 9

The day is Size 16 and Semibold; the other two lines are Size 14. ThisItem is the entry the row shows (How to Use ThisItem in a Power Apps Gallery). The times line adds next day when a night shift finishes after midnight (How to Show That a Shift Ends the Next Day in Power Apps):

lblEntryTimesMO → Text
$"{Text(ThisItem.StartTime, "hh:mm")} to {Text(ThisItem.EndTime, "hh:mm")}{If(Day(ThisItem.EndTime) <> Day(ThisItem.WorkDate), " next day", "")}, {Text(ThisItem.Hours, "0.00")} hours"

The badge colors the status with its Intent: green for Approved, red for Rejected and yellow for Pending (How to Add a Badge Control in Power Apps and How to Use the Switch Function in Power Apps):

bdgStatusMO → Intent
Switch(
ThisItem.Status.Value,
"Approved", BadgeIntent.Positive,
"Rejected", BadgeIntent.Critical,
BadgeIntent.Caution
)

Its AccessibleLabel, "Status: " & ThisItem.Status.Value, tells screen reader users what the badge is, such as Status: Pending.

The padding. My first rows showed a thin grey scroll bar at the end of the day and of the times. The modern Text control starts with a padding of 5 at the top and the bottom, which left a 24-pixel control less room than one line of text needs. Set PaddingTop and PaddingBottom to 0 on the three text controls: Fixed: Scroll Bar Appears Inside a Text Control in Power Apps. The rows on the canvas afterwards:

Two gallery rows on the Studio canvas at 100% zoom: Mon 02/11/2026 with 18:00 to 21:00, 3.00 hours, Emergency Department, and Fri 06/11/2026 with 17:00 to 20:30, 3.50 hours, Radiology, each with a Pending badge and an Edit button, and no scroll bars

Step 9: Add the Edit Button​

btnEditMO opens the row's entry on the Log Overtime screen, and only shows until the entry is approved (How to Stop Editing an Item Once It's Approved in Power Apps):

PropertyValue
Text"Edit"
Icon"Edit"
AppearanceSecondary
VisibleThisItem.Status.Value <> "Approved"
AccessibleLabel"Edit your entry for " & Text(ThisItem.WorkDate, "dd/mm/yyyy")

Most rows have an Edit button, so the accessible label names the entry's date: a screen reader user hears which one they're on. OnSelect opens the Log Overtime screen with the entry's ID in a context variable there, locEntryId (How to Go to Another Screen in Power Apps with Navigate):

btnEditMO → OnSelect
Navigate('Log Overtime Screen', ScreenTransition.None, {locEntryId: ThisItem.ID})

The formula bar with the OnSelect of btnEditMO set to Navigate('Log Overtime Screen', ScreenTransition.None, a record with locEntryId set to ThisItem.ID), the Tree view with the My Overtime Screen's controls, and the Edit button selected in the first row of the gallery on the canvas

Studio can't work out formulas that use ThisItem in its preview strip, and says This formula uses scope, which is not presently supported for evaluation. The rows show the result in Preview (How to See What a Formula Returns in Power Apps Studio).

Step 10: Open the Screens from the Home Tiles​

On the Home screen, set the My overtime tile's OnSelect, which Part 5 left as false:

btnMyOvertimeHS → OnSelect
Navigate('My Overtime Screen')

The formula bar with btnMyOvertimeHS OnSelect set to Navigate('My Overtime Screen'), and the Home screen with Welcome, Admin, Department: Management, and the My overtime tile selected between Log overtime and Departments

Change the Log overtime tile, which Part 6 set to Navigate('Log Overtime Screen'), so it always opens an empty form:

btnLogOvertimeHS → OnSelect
Navigate('Log Overtime Screen', ScreenTransition.None, {locEntryId: Blank()})

A context variable holds its value until the app is closed, so after someone edits an entry, locEntryId would still hold its ID the next time the screen opened. The blank ID tells the screen to add a new entry.

Step 11: Give the Log Overtime Screen an Edit Mode​

The Log Overtime screen now opens in two ways: with an entry's ID to edit it, or with a blank ID to add one. Each formula that differs asks IsBlank(locEntryId): How to Use One Screen to Add and Edit Items in Power Apps.

Load the entry when the screen opens. Replace its OnVisible:

Log Overtime Screen → OnVisible
UpdateContext(
{
locIsSaving: false,
locEntry: If(IsBlank(locEntryId), Blank(), LookUp(OvertimeEntries, ID = locEntryId))
}
);
Reset(dpWorkDateLO);
Reset(cmbStartLO);
Reset(cmbEndLO);
Reset(numBreakLO);
Reset(cmbDepartmentLO);
Reset(txtReasonLO)

The OnVisible property of the Log Overtime Screen in the expanded formula bar: UpdateContext with locIsSaving set to false and locEntry set to an If that gives Blank when locEntryId is blank and otherwise looks up the entry

locEntry is the entry, read fresh from the list by its ID, or blank when adding (How to Find a Record in Power Apps with LookUp). ID = locEntryId is the one comparison SharePoint can delegate on its ID column. The resets then run after locEntry is set, so every field starts from its default for this entry (How to Reset a Control to Its Default Value in Power Apps with Reset).

Start each field from the entry. Each default falls back to Part 6's when there's no entry:

ControlPropertyFormula
dpWorkDateLODefaultDateCoalesce(locEntry.WorkDate, Today())
numBreakLODefaultCoalesce(locEntry.BreakMinutes, 0)
txtReasonLODefaultlocEntry.Reason

Coalesce returns its first value that isn't blank: the entry's date when editing, and today when adding (How to Replace Blank Values in Power Apps with Coalesce).

The time pickers list the 288 times of day in TimeChoices, and an entry stores a date and time. Time(Hour(…), Minute(…), 0) takes the time of day from it, and Filter finds that time in the list. When adding, !IsBlank(locEntry) is false, so nothing is chosen, as in Part 6:

cmbStartLO → DefaultSelectedItems
Filter(TimeChoices, !IsBlank(locEntry) && Value = Time(Hour(locEntry.StartTime), Minute(locEntry.StartTime), 0))
cmbEndLO → DefaultSelectedItems
Filter(TimeChoices, !IsBlank(locEntry) && Value = Time(Hour(locEntry.EndTime), Minute(locEntry.EndTime), 0))

The department starts on the person's own when adding, as in Part 6, and on the entry's when editing, found by the ID the entry stores:

cmbDepartmentLO → DefaultSelectedItems
If(
IsBlank(locEntry),
Filter(Departments, IsActive = true, Department = MyDepartment),
Filter(Departments, ID = locEntry.DepartmentId)
)

Say which mode it's in. The title:

lblTitleLO → Text
If(IsBlank(locEntryId), "Log overtime", "Edit overtime")

The Back button. The screen now opens from the Home screen and from My Overtime, and Back() returns to whichever opened it (How to Go Back to the Previous Screen in Power Apps with Back). Change btnBackLO's AccessibleLabel from "Back to the Home screen" to "Back to the previous screen".

Step 12: Stop an Entry Overlapping Itself​

My first try at editing showed this on an entry I hadn't changed: This overlaps the overtime you logged from 02/11/2026 18:00 to 02/11/2026 21:00. That was the entry itself. Part 6's overlap check looks for any of the person's entries that overlap the shift, and when editing, the entry being edited is one of them:

The Edit overtime screen for 02/11/2026 from 18:00 to 21:00 with the message This overlaps the overtime you logged from 02/11/2026 18:00 to 02/11/2026 21:00, and a disabled Save button

The check has to skip the entry being edited, but not with ID <> locEntryId in the SharePoint query: SharePoint only delegates = on its ID column, and the whole check would then run on the first 500 entries. Instead, Filter finds the overlapping entries in SharePoint, With holds them in memory, and a LookUp there skips the one being edited (How to Exclude the Item Being Edited from a LookUp in Power Apps).

In App.Formulas, replace ShiftProblem with this version, which takes the ID of the entry being edited:

App → Formulas (ShiftProblem)
ShiftProblem(ShiftDate: Date, StartAt: Time, EndAt: Time, BreakMins: Number, EntryId: Number): Text =
With(
{Starts: ShiftStart(ShiftDate, StartAt), Ends: ShiftEnd(ShiftDate, StartAt, EndAt)},
With(
{
Minutes: DateDiff(Starts, Ends, TimeUnit.Minutes),
Overlapping: Filter(OvertimeEntries, EmployeeEmail = MyEmail && StartTime < Ends && EndTime > Starts)
},
With(
{Clash: LookUp(Overlapping, ID <> EntryId)},
If(
EndAt = StartAt, "The start and finish times are the same.",
Minutes > 1440, "A shift can't be longer than 24 hours.",
BreakMins >= Minutes, "The break must be shorter than the shift.",
Ends > Now(), "This shift hasn't finished yet. Log it after it ends.",
!IsBlank(Clash), $"This overlaps the overtime you logged from {Text(Clash.StartTime, "dd/mm/yyyy hh:mm")} to {Text(Clash.EndTime, "dd/mm/yyyy hh:mm")}.",
""
)
)
)
);

And pass the ID from the problem message, the only place that calls it:

lblProblemLO → Text
If(
IsBlank(cmbStartLO.Selected) || IsBlank(cmbEndLO.Selected),
"",
ShiftProblem(dpWorkDateLO.SelectedDate, cmbStartLO.Selected.Value, cmbEndLO.Selected.Value, numBreakLO.Value, locEntryId)
)

When adding, locEntryId is blank, and ID <> Blank() is true for every entry, so nothing is skipped. The same entry, opened for editing again:

The Edit overtime screen for 02/11/2026 from 18:00 to 21:00, 3.00 hours, Emergency Department and its reason, with no message and an enabled green Save button

A new shift from 23:00 to 02:00 on 24 October still showed the overlap message, and the App checker listed no delegation warnings.

Step 13: Save Changes to an Entry​

Patch creates an entry when its second argument is Defaults, and changes one when it's the entry's record (How to Create or Update a SharePoint List Item with Patch in Power Apps). Two things change in Part 6's Save: the record to patch, and the success message:

btnSaveLO → OnSelect
UpdateContext({locIsSaving: true});
With(
{
Starts: ShiftStart(dpWorkDateLO.SelectedDate, cmbStartLO.Selected.Value),
Ends: ShiftEnd(dpWorkDateLO.SelectedDate, cmbStartLO.Selected.Value, cmbEndLO.Selected.Value)
},
IfError(
Patch(
OvertimeEntries,
If(IsBlank(locEntry), Defaults(OvertimeEntries), locEntry),
{
WorkDate: dpWorkDateLO.SelectedDate,
StartTime: Starts,
EndTime: Ends,
BreakMinutes: numBreakLO.Value,
Hours: Round((DateDiff(Starts, Ends, TimeUnit.Minutes) - numBreakLO.Value) / 60, 2),
DepartmentId: cmbDepartmentLO.Selected.ID,
Department: cmbDepartmentLO.Selected.Department,
Reason: Trim(txtReasonLO.Text),
EmployeeName: MyProfile.displayName,
EmployeeEmail: MyEmail,
Status: {Value: "Pending"},
WorkMonth: Text(dpWorkDateLO.SelectedDate, "yyyy-mm")
}
),
UpdateContext({locIsSaving: false});
Notify("Your overtime wasn't saved. " & FirstError.Message, NotificationType.Error),
UpdateContext({locIsSaving: false});
Notify(
If(IsBlank(locEntry), "Your overtime was saved. It's waiting for approval.", "Your changes were saved. The entry is waiting for approval."),
NotificationType.Success
);
Back()
)
)

Status stays {Value: "Pending"} for both, so a corrected entry goes back for approval, whatever it was before. Hours, WorkMonth and the copied names are worked out again too, since the date, times or department may have changed. The list's content approval, from Part 3, also sets a changed item's approval status back to Pending, wherever it's changed: the Edit button only keeps the app tidy, and the list protects the data.

Step 14: Try It​

Select the Home screen and preview with F5, then select My overtime (How to Preview a Canvas App in Power Apps Studio). Start from the Home screen: OnVisible runs when someone goes to the screen, so a preview that starts on My Overtime has no month and no entries. I made that mistake on my first preview, which showed Total for : hours with no month name: How to Run a Formula When a Screen Opens in Power Apps with OnVisible.

To fill the screen, I logged two more of the maker's shifts with the Log Overtime screen: 29 October, 18:00 to 20:00 in the Emergency Department, and Sunday 1 November, 09:00 to 13:00 in Radiology. The approval flow comes in Part 8, so to see each badge I set two statuses by hand in the OvertimeEntries list (How to Edit an Item in a SharePoint List): the night shift of 24 October to Approved, and 6 November to Rejected. The first time, SharePoint opened Edit 2 items, because an item I'd selected earlier was still ticked. I closed it without saving and edited one item at a time.

November, at the top of this post: 7.00 hours, the two pending entries, without the rejected 3.50. The first week, Monday 26 October to Sunday 1 November, has 6.00 hours: 29 October's 2.00, from October, and 1 November's 4.00. The next week has only 2 November's 3.00.

October, with the previous-month button: 10.00 hours. The approved night shift has no Edit button, and its times read 22:00 to 06:00 next day. The next-month button is enabled again:

The My overtime screen in Preview for October 2026 with an enabled next-month button, Total for October 2026: 10.00 hours, the weeks Mon 19/10/2026 to Sun 25/10/2026: 8.00 hours and Mon 26/10/2026 to Sun 01/11/2026: 6.00 hours, and two rows: Sat 24/10/2026, 22:00 to 06:00 next day, 8.00 hours, Emergency Department with an Approved badge and no Edit button, and Thu 29/10/2026, 18:00 to 20:00, 2.00 hours, Emergency Department with a Pending badge and an Edit button

Editing the rejected entry. Back in November, Edit on 6 November opened Edit overtime with the entry loaded. I changed Finish from 20:30 to 21:00 and added The list ran until 21:00. to the reason; the hours became 4.00, with no overlap message:

The Edit overtime screen in Preview with the date 06/11/2026, Start 17:00, Finish 21:00, an unpaid break of 0, Hours worked: 4.00 (4 h 0 min), Department Radiology, the reason Finished the evening scan list after a scanner fault delayed the clinic. The list ran until 21:00., 98 of 500 characters, and an enabled green Save button

Save showed Your changes were saved. The entry is waiting for approval. and went back to My Overtime, still on November: 11.00 hours, the second week 7.00, and 6 November Pending again, from 17:00 to 21:00:

The My overtime screen in Preview for November 2026: Total for November 2026: 11.00 hours, the weeks Mon 26/10/2026 to Sun 01/11/2026: 6.00 hours and Mon 02/11/2026 to Sun 08/11/2026: 7.00 hours, and three rows with Pending badges and Edit buttons: Sun 01/11/2026 from 09:00 to 13:00 in Radiology, Mon 02/11/2026 from 18:00 to 21:00 in the Emergency Department, and Fri 06/11/2026 from 17:00 to 21:00, 4.00 hours, in Radiology

Opening an October entry and selecting Back without saving returned to October, as Step 4's OnVisible intends.

Step 15: Check the Totals in SharePoint​

A view of the list can show the same totals, which makes them easy to check. In OvertimeEntries, I saved a new public view, By month: grouped by WorkMonth and then by EmployeeName, with a Sum of Hours in each group (How to Group Items in a SharePoint List View and How to Show Column Totals in a SharePoint List View). The maker's November group added up to 11.00, the screen's total:

The By month view of the OvertimeEntries list: the group EmployeeName: Admin User (3) with entries on 06/11/2026 from 17:00 to 21:00, 4.00 hours in Radiology, 02/11/2026 from 18:00 to 21:00, 3.00 hours in the Emergency Department, and 01/11/2026 from 09:00 to 13:00, 4.00 hours in Radiology, and Sum 11.00 outlined in red

The view's sum counts every entry in the group, so it matches the app only while none of them is rejected.

Step 16: Check the Screen on a Phone​

In Preview, choose Apple iPhone 12, 13, 14 (How to Test a Power Apps Canvas App on Phone and Tablet Sizes). The content takes the full width, the total wraps onto a second line, and Refresh shows only its icon:

A phone preview of the My overtime screen: the green header with Back, My overtime and a refresh icon, the month bar for November 2026, Total for November 2026: 11.00 hours on two lines, the two weekly totals, the note, and three entry rows with Pending badges and Edit buttons, all at full width

Step 17: Run the App Checker​

Open the App checker and select Accessibility. It lists six errors, the same two as in Parts 5 and 6, now for three headings: lblTitleHS, lblTitleLO and lblTitleMO:

The Accessibility page of the App checker with Errors (6): Focus isn't showing (3) on lblTitleHS, lblTitleLO and lblTitleMO, and Missing tab stop (3) on the same three

Leave them, for the reasons in Fixed: "Missing Tab Stop" in the Power Apps App Checker and Fixed: "Focus Isn't Showing" in the Power Apps App Checker. Formulas, Performance and Data source listed nothing, so none of the new formulas has a delegation warning.

Step 18: Save the App​

Select Save. Don't publish yet: nobody else can open the app until Part 15 shares it. The screen's controls in the Tree view, next to the finished screen:

The Tree view with the My Overtime Screen expanded: conMainMO with conHeaderMO holding btnBackMO, lblTitleMO and btnRefreshMO, and conBodyMO holding conMonthMO with its two buttons and label, lblTotalMO, lblWeeksMO, lblTotalsNoteMO, lblEmptyMO, spnLoadingMO and galEntriesMO with btnEditMO, bdgStatusMO and three text controls, next to the canvas showing the November screen with the Refresh button in the header

Common Mistakes​

MistakeWhat happensDo this instead
Sum or GroupBy straight on the SharePoint listOnly the first 500 entries are added up, with a delegation warningLoad the rows with a delegable Filter first, as in Step 4
Loading only the month's datesThe first and last weeks miss their days in the months around itLoad from the Monday before the 1st to the Sunday after the last day
Text(Sum(...), "0.00") without CoalesceNo number in the total for a month with nothing to addCoalesce(Sum(...), 0)
ID <> locEntryId in the overlap check's SharePoint queryNothing is delegated; only the first 500 entries are checkedFilter in SharePoint, skip the edited entry in memory
Opening the Log Overtime screen from Home without locEntryId: Blank()It opens on the last entry editedPass a blank ID
Hiding Edit as the only protectionEntries can still be changed in SharePointContent approval on the list, from Part 3

Troubleshooting​

SymptomLikely causeFix
No month name and no entries in PreviewPreview started on My Overtime, so OnVisible didn't runPreview from the Home screen and select My overtime
Total for September 2026: hoursSum of no rows is blankCoalesce(…, 0) around the Sum
A grey scroll bar at the end of a row's textThe Text control's default padding in a 24-pixel controlPadding top and bottom 0
Editing an entry says it overlaps itselfThe overlap check doesn't skip the entry being editedStep 12
A new entry doesn't appearThe screen loaded before it was savedSelect Refresh
The next-month button is greyed outYou're on the current monthExpected: overtime is logged after it's worked

FAQ​

Why can a week's total be more than the month's?​

A week that starts in one month and ends in the next counts all its days, and the month's total counts only its own. The note under the weekly totals says so.

Why aren't rejected entries counted?​

A rejected entry isn't overtime the department agreed to, so it isn't in the person's totals. It stays in the list with its badge, so they can correct it and send it again.

Can people see each other's overtime here?​

No. The screen loads only the person's own entries, and in SharePoint, staff can only read their own anyway (Part 3).

Who sets an entry to Approved or Rejected?​

Part 8's approval flow, from the decision of the department's approvers. In this part, the two statuses were set by hand in SharePoint, only to see the badges.

Does this need premium licenses?​

No. The screen uses SharePoint and Office 365 Users, both standard connectors, and the app's license designation stays Standard.

Conclusion​

People can now see and correct their overtime:

  • a My Overtime screen with a month of the person's entries, a status badge on each, and next day on night shifts;
  • the month's total and Monday-to-Sunday weekly totals, worked out in the app from rows SharePoint filtered, leaving out rejected entries and reading 0.00 for an empty month;
  • previous and next month buttons that stop at the current month;
  • an Edit button until an entry is approved, and an edit mode on the Log Overtime screen that loads the entry, skips it in the overlap check and sends the change back for approval;
  • a By month view in SharePoint with the same totals.

Part 8 builds the approval flow: each new or changed entry goes to its department's approvers in Teams and Outlook, and their decision sets its status.

Additional Resources​

← Previous: Part 6: Build the Log Overtime Screen Next → Part 8: Build the Approval Flow for Teams and Outlook