Hidden Gems: 7 Overlooked Power Apps Functions That Solve Real Problems
Move beyond the basics with seven Power Apps functions that often get ignored—learn how they can simplify your formulas, improve performance, and unlock new possibilities.
When you start building canvas apps, you quickly learn the heavy hitters: If, Filter, Patch, Collect. But Power Apps ships with over a hundred functions, and some of the most useful ones rarely make it into tutorials. Over the course of building a real-world project management tool, I discovered seven functions that solved problems I used to work around with awkward workarounds. This article walks through each one with a concrete scenario—a simple Task Tracker app connected to a SharePoint list—so you can see how they fit into a real app.
The Scenario: A Lean Task Tracker
We're building a small app to track team tasks. The underlying SharePoint list has these columns:
- Title (text)
- Owner (Person or Group)
- Deadline (Date and Time)
- Status (Choice: Not Started, In Progress, Done)
- Priority (Choice: Low, Medium, High)
- Category (Choice: Development, Design, Marketing, Other)
The app needs to let users add tasks, animate a prompt when a task is overdue, combine two collections for a clean dropdown, generate blank rows for quick data entry, debug variable values, send task summaries to Power Automate, and assign unique keys to records that lack them. Each of these needs one of our hidden gems.
1. Coalesce – The Empty‑Value Safety Net
Coalesce takes a list of values and returns the first one that isn't blank. It’s shorter than If(IsBlank(...), ...) and reads more clearly.
In the Task Tracker: When a user adds a task but leaves the Priority field empty, we want to default to Medium. The formula in the OnSelect of the Submit button:
Patch(
ProjectTasks,
Defaults(ProjectTasks),
{
Title: TaskTitleInput.Text,
Owner: User().Email,
Deadline: DeadlineDatePicker.SelectedDate,
Status: "Not Started",
Priority: Coalesce(PriorityDropdown.Selected.Value, "Medium"),
Category: CategoryDropdown.Selected.Value
}
)I also use Coalesce to write a single Patch that works for both insert and update:
Patch(
ProjectTasks,
Coalesce(
LookUp(ProjectTasks, ID = varRecordID),
Defaults(ProjectTasks)
),
{
Title: TaskTitleInput.Text,
Owner: User().Email,
Status: StatusDropdown.Selected.Value,
Priority: Coalesce(PriorityDropdown.Selected.Value, "Medium")
}
)Without Coalesce you'd need two separate Patch calls inside an If, which clutters the app and makes maintenance harder.
Coalesce itself is not delegation‑aware, but when used inside LookUp it works fine because LookUp already delegates. For large data sources, avoid using it directly in a Filter that expects full delegation.
2. Sin – Natural‑Feeling Animation
Sin (sine) is a trigonometric function, but in canvas apps it shines for creating smooth, bouncy animations without a custom component.
In the Task Tracker: We want a small arrow icon to bounce up and down next to any task whose deadline has passed, urging the user to act. The icon’s Y property uses:
160 - Sin(Timer1.Value / Timer1.Duration * 2 * Pi()) * 40
Set up a timer:
| Property | Value |
|---|---|
Autostart | true |
Duration | 1000 |
Repeat | true |
The 160 is the resting Y‑position, and * 40 controls the bounce amplitude. The result is a fluid vertical oscillation that looks far more organic than jumping between two static Y values.
Use Sin animations sparingly—animating too many elements at once can hurt frame rate on low‑end devices. Limit to one or two prompter icons per screen.
3. Ungroup – Clean Dropdowns with a Blank Option
Ungroup reverses a GroupBy operation, but it can also be used creatively to build a dropdown that includes a blank option at the top.
In the Task Tracker: We need a dropdown that lists all Category values plus an empty item at the top so the user can clear the selection. The formula for the dropdown’s Items property:
Ungroup(
Table(
{CatItems: Table({Result: Blank()})},
{CatItems: RenameColumns(
Distinct(ProjectTasks, Category),
"Result",
"Value"
)}
),
"CatItems"
)This wraps a blank record and the distinct categories into a single column table via Ungroup. The dropdown now shows a blank first line, and when the user selects it, the filter returns all records.
Alternative approaches (like using Collect to prepend a blank) require mutating a global collection. Ungroup does it declaratively.
Distinct delegates to supported data sources (like SharePoint) for the count of distinct values, but the table construction with Ungroup happens client‑side. Performance is fine for lists up to a few hundred distinct values.
4. Sequence – Generate Numbers, Dates, and Blank Rows
Sequence creates a single‑column table of numbers from 1 to N. Combine it with ForAll to build arrays of dates, characters, or even empty rows.
In the Task Tracker: The user can choose how many blank rows they want in a gallery for quick data entry. The gallery’s Items property:
ForAll(
Sequence(Value(RowCountInput.Text)),
{Title: Blank(), Owner: Blank(), Deadline: Blank(), Status: "Not Started"}
)When the user types 5 in RowCountInput, the gallery shows 5 blank rows. After editing, they batch‑submit all rows with a single Collect wrapped in a ForAll.
Another neat use: generate the next 7 days for a date picker:
ForAll(Sequence(7), {DateValue: Today() + Value})Be careful with large values in Sequence. Generating thousands of rows client‑side can slow down the app. For the blank‑row scenario, cap the input to a reasonable number (e.g., 20).
5. Trace – Debugging Without Set Variables
Trace sends a message to the Monitor tool (and optionally to Azure Application Insights). It’s perfect for logging variable values during development without cluttering your app with labels.
In the Task Tracker: We suspect the status update logic has a bug. The OnSelect of the Complete button:
Set(localStatus, StatusDropdown.Selected.Value);
Trace("Status before Patch: " & localStatus, Trace.Severity.Info);
Patch(
ProjectTasks,
Gallery1.Selected,
{Status: "Done"}
);
Trace("Status after Patch: " & localStatus, Trace.Severity.Info)Open the Monitor tool (from the Advanced tools menu) and watch the output as you press the button. You can see the exact flow of your app in real time.
Trace also supports severity levels and custom records, which is invaluable when you start monitoring production apps with Application Insights. But even without that, the Monitor integration alone makes it a top debugging tool.
Forgetting to remove Trace calls from the final published app can clutter logs and (if Application Insights is connected) incur data costs. Use a global flag like varDebugMode to conditionally enable tracing.
6. JSON – Bridge to Power Automate
JSON converts a Power Apps table (collection, data source subset) into a JSON text string. This is the easiest way to pass structured data to a Power Automate flow.
In the Task Tracker: When the user clicks “Send Summary”, we gather all overdue tasks into a collection, convert it to JSON, and call a flow that sends an email.
ClearCollect(colOverdueTasks, Filter(ProjectTasks, Status <> "Done", Deadline < Today())); OverdueTasksFlow.Run( JSON(colOverdueTasks, JSONFormat.IncludeBinaryData) )
Inside the flow, add a Parse JSON action using this schema (auto‑generated from a sample). Then loop over the parsed array to send individual emails.
Power Apps flow triggers have a payload limit of about 10 MB. If your collection is large, either send in batches or pass only the necessary columns with ShowColumns before converting.
7. GUID – Unique IDs When You Need Them
GUID generates a globally unique identifier—a 32‑character hex string with dashes. It’s deterministic enough to use as a primary key when your data source doesn’t provide one.
In the Task Tracker: We occasionally collect data into a local collection and later batch‑Patch it to SharePoint. Before saving, we assign a temporary ID so we can update records later even if duplicates exist.
ClearCollect(
colTempTasks,
AddColumns(
colTaskInputs,
"TempID",
GUID()
)
)Now each row has a unique TempID. When we later Patch each record back to SharePoint, we can use TempID to identify the exact row, avoiding ambiguity with records that have identical names.
GUID is also useful for generating random passwords or tokens, though for security‑sensitive scenarios you should rely on a server‑side generator.
GUID is a client‑side function. If you need the ID to be generated inside a data source (to avoid race conditions), use your datasource’s auto‑increment or NewGuid() in SQL. For local collections, GUID is perfectly safe.
Common Mistakes and Troubleshooting
- Coalesce expects its arguments to be evaluated in order. If you pass an expensive function (like a
Filterwith a large source) as the first argument, it runs even if a later argument is used. Keep lightweight values early. - Ungroup fails if the column name passed as the second argument doesn’t exist exactly (case‑sensitive in most data sources). Double‑check spelling.
- Sequence +
ForAllcreates a new scope forThisRecord.Value. If you need the iteration index, useForAll(Sequence(N), { Index: Value, ... }). - Trace output in Monitor is not persisted beyond the session unless you set up Application Insights. Don’t rely on it for long‑term auditing.
- JSON without
JSONFormat.IncludeBinaryDatamay strip important media or attachment data. UseIncludeBinaryDataonly when needed because it increases size. - GUID collisions are astronomically unlikely, but if you merge collections from multiple devices, consider adding a device prefix.
Final Recommendation
These seven functions—Coalesce, Sin, Ungroup, Sequence, Trace, JSON, and GUID—each address a common pain point that many app makers solve with more verbose or brittle formulas. Taking the time to weave them into your toolkit will make your apps cleaner, more performant, and more maintainable.
Start by picking one that resonates with a problem you face today. For example, if you’re tired of writing multi‑branch If statements to handle blank values, refactor one screen to use Coalesce tomorrow. Over the next few weeks, you’ll wonder how you ever managed without them.
References
- Original article: 7 Lesser Known Power Apps Functions And Why I Use Them by Matthew Devaney
- Microsoft Power Apps function reference: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/
- Coalesce: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-isblank-isempty
- Sin: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-trig
- Ungroup: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-groupby
- Sequence: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-sequence
- Trace: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-trace
- JSON: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-json
- GUID: https://docs.microsoft.com/en-us/power-platform/power-fx/reference/function-guid