Build a Custom Weekly Work Log App in Power Apps
Design a flexible time entry system with dynamic rows, inline editing, automatic totals, and SharePoint storage.
Tracking how people spend their time is a common business need, and Power Apps makes it surprisingly easy to build a tailored solution. Instead of using a generic template, creating your own app gives you full control over the fields, validation, and approval flow you may want later.
In this guide you'll walk through building a weekly work log where users can add multiple rows representing different activities, enter hours for each weekday, see a running total, and save everything back to SharePoint. The same principles apply if your week starts on Sunday or your team uses different categories – you'll learn the patterns that make the app adaptable.
The Scenario You'll Build For
Imagine a small consultancy where each consultant fills in a weekly summary of how they spent their time. Every week they can have several lines such as:
- Client Meeting
- Development Work
- Internal Admin
- Training
- Other
Each line holds hours for Monday through Friday, and a calculated total. After editing, the user saves the entire week in one go. Managers (added later) can then review and approve entries.
This example uses a SharePoint list as the data source, but you can substitute Dataverse or Excel with minimal changes.
Creating the SharePoint List
First, set up a list named WeeklyTimeLog with these columns:
| Column Name | Type | Notes |
|---|---|---|
| Activity | Single line of text | Dropdown values will come from the app |
| Mon | Number | Whole or decimal hours |
| Tue | Number | |
| Wed | Number | |
| Thu | Number | |
| Fri | Number | |
| Total | Calculated | Formula: =Mon+Tue+Wed+Thu+Fri |
The calculated column is useful for reporting outside Power Apps, but you'll also compute the total inside the app for rows that haven't been saved yet.
Starting the App in Power Apps Studio
- Open Power Apps Studio and create a new blank phone app.
- Go to the Data pane and add your WeeklyTimeLog list as a data source.
- Rename the screen to something like
scrn_TimeLog.
Now we'll build the interface without relying on any built-in layout template – just containers, labels, and a gallery.
Building the Header and Action Bar
At the top of the screen, add a Label for the app title – for example "Week Log". Below it place a horizontal Container that will hold a + button and, later, a Save icon.
Inside that container, insert an Add icon (choose Icon.Add). Set its OnSelect to create a new blank row in a local collection:
Collect(colLogEntries, Defaults('WeeklyTimeLog'))The collection colLogEntries will hold all rows currently being edited. It starts empty; the user adds rows as needed.
Column Headers
To make the input area easy to scan, add six Label controls inside a horizontal container placed just below the action bar. Use these texts:
Activity, Mon, Tue, Wed, Thu, Fri, Total
Name each label so you can reference its position later, for example:
lbl_ActivityHeaderlbl_MonHeaderlbl_TueHeaderlbl_WedHeaderlbl_ThuHeaderlbl_FriHeaderlbl_TotalHeader
Set the container's LayoutMode to Horizontal, adjust LayoutGap to 5 or 10, and give each label a fixed Width you'll reuse for the corresponding inputs. (In a real app you might calculate widths proportionally, but fixed widths work fine for a phone layout.)
Creating the Editable Rows with a Gallery
Add a Vertical gallery and set its Items property to the collection:
colLogEntries
Adjust the TemplateSize to around 80 and TemplatePadding to 0 so rows are compact.
Inside the gallery you'll place:
-
A Dropdown for the Activity column.
- Set
Itemsto["Client Meeting", "Development Work", "Internal Admin", "Training", "Other"]. - Set
DefaulttoThisItem.Activityso that existing values survive screen navigation.
- Set
-
Five Text Inputs for Mon through Fri.
- Name them
txt_Mon,txt_Tue,txt_Wed,txt_Thu,txt_Fri. - Set their
Defaultto the correspondingThisItem.Mon,ThisItem.Tue, etc. - Change the input format to number:
TextFormat = TextFormat.Number. - Align each input under its header by putting its
Xproperty equal to the header'sXproperty. For example:
powerfxX property of txt_Monlbl_MonHeader.X
Set the
Widthto the header'sWidthas well. Repeat for the other fields. - Name them
-
A Label for the calculated total of each row.
- Position it at
lbl_TotalHeader.Xand use the sameWidth. - Its
Textproperty:
- Position it at
Coalesce(
Sum(
Value(txt_Mon.Text),
Value(txt_Tue.Text),
Value(txt_Wed.Text),
Value(txt_Thu.Text),
Value(txt_Fri.Text)
),
0
)The Coalesce function prevents a blank from showing when all inputs are empty.
Deleting a Row
Insert a Trash icon (or use Icon.Delete) at the right side of the gallery template. Its OnSelect should both remove the item from the collection and, if the row has already been saved to SharePoint, queue it for deletion later.
Remove(colLogEntries, ThisItem); If( !IsBlank(ThisItem.ID), Collect(colDeleteLogEntries, ThisItem) )
The separate delete collection is a safe pattern: the actual SharePoint deletion happens only when the user clicks the final Save button.
Saving Everything Back to SharePoint
Add a Save icon (or a button) in the action bar. When clicked, the app should:
- Update any rows that already have an ID (existing records).
- Create new rows for those without an ID.
- Delete rows collected in
colDeleteLogEntries.
The cleanest approach is to iterate over the gallery's AllItems using ForAll. Because ForAll calls Patch for each row, it can handle millions of records – though for a typical weekly log (under 50 rows) you won't hit any delegation limits.
// Update or create each row
ForAll(
gal_LogEntries.AllItems,
Patch(
'WeeklyTimeLog',
If(IsBlank(ID), Defaults('WeeklyTimeLog'), LookUp('WeeklyTimeLog', ID = ID)),
{
Activity: drp_Activity.Selected.Value,
Mon: Value(txt_Mon.Text),
Tue: Value(txt_Tue.Text),
Wed: Value(txt_Wed.Text),
Thu: Value(txt_Thu.Text),
Fri: Value(txt_Fri.Text)
}
)
);
// Remove rows the user marked for deletion
ForAll(
colDeleteLogEntries,
Remove('WeeklyTimeLog', ThisRecord)
);
// Clear the temporary collections
Clear(colDeleteLogEntries);
ClearCollect(colLogEntries, 'WeeklyTimeLog') // optional: reload clean dataAfter saving, you may reload the SharePoint list into the collection so that the gallery shows the current saved state.
Loading Existing Data When the App Starts
To show past entries when the user opens the app, load the SharePoint list into the collection on screen OnVisible:
ClearCollect(colLogEntries, 'WeeklyTimeLog')
This automatically populates the gallery with previously saved rows. The user can then add new rows, edit existing ones, or delete them before saving again.
Performance and Delegation Notes
Because all data manipulation happens inside a local collection (colLogEntries), delegation is not an issue for the add/edit/delete operations. The only delegation-sensitive step is the initial ClearCollect from SharePoint. For a list with fewer than 2,000 items this is fine. If you expect many users with many weeks of data, consider adding a filter (e.g., Filter('WeeklyTimeLog', WeekOf = selectedWeek)) before loading into the collection.
The calculated Total column in SharePoint is a convenience for reporting – the app computes its own total per row, so there is no dependency on SharePoint recalculation delays.
Common Pitfalls and How to Avoid Them
- Text inputs not showing saved values – Make sure the
Defaultproperty points toThisItem.ColumnNameand that the column exists in the collection. AfterClearCollect, columns match SharePoint exactly. - Dropdown loses selection after save – Because
Patchreturns a new record, the gallery may refresh. UseThisItem.Activityin theDefaultproperty rather than a static default. - Gallery rows don't align with headers – Ensure both the header container and the gallery template use the same
Xoffsets andWidthvalues. SettingLayoutGapin the gallery to0and manually positioning controls is more reliable. - Total label shows blank – The
Coalescefunction returns the sum only if at least one input contains a number. If all inputs are empty,Sum(...)results in blank, andCoalescereturns0. That's correct behavior. - Delete collection not cleared – Always
Clear(colDeleteLogEntries)after processing deletions, otherwise duplicates can occur.
Final Recommendation
The design shown here gives you a solid foundation for any kind of time tracking, job logging, or even simple expense entry. Start with the SharePoint list and a gallery-driven UI; later you can add a header view (week selection, approval status) and integrate a review screen for managers.
Building it yourself means you understand every piece and can adapt it when your business rules change. That's far more valuable than downloading a template.
References
- Original tutorial: https://www.matthewdevaney.com/make-a-power-apps-timesheets-app-part-1/
- Microsoft Learn:
Patchfunction overview (search "Patch function Power Apps") - Microsoft Learn:
ClearCollectandCollectin Power Apps
Learn how small coding practices—like using descriptive names, flattening conditions, and simplifying logic—can make your apps easier to update and less error-prone.
Move past the gallery and discover the hidden patterns for validation, navigation, and smart submission handling in your data entry forms.
PowerShell unlocks admin capabilities that the Power Platform admin center simply doesn’t offer—from recovering deleted apps to blocking trial licenses. Here’s how to wield them safely.