FlowLibs
Browse Cloud FlowsConnectorsAI ToolsDev ToolsPricingAboutContact
Dev Tools/Power Fx

Power Fx Cheat Sheet

A working reference for Power Fx — the low-code formula language behind Power Apps, cards, and Copilot Studio. Text, logic, tables, error handling, people, choices, theming, offline storage, reusable components, and the delegation rules that decide whether a formula scales.

Power Fx30 min read·Updated 2026-06-16
Power AppsPower FxCanvas AppsVariablesPatternsDelegationError HandlingOffice 365 UsersThemingComponentsFormulas

On this page

  • Fundamentals
  • Text functions
  • Logic & conditionals
  • Error handling & signals
  • Tables & collections
  • Collection shaping
  • Records, scope & references
  • Variables & state
  • Choices & option sets
  • Users & people
  • Math & numbers
  • Date & time
  • Navigation & behavior
  • Validation & conversion
  • JSON & untyped objects
  • UI & theming
  • Offline & storage
  • Components & reuse
  • Formula style guide
  • Common patterns
  • Delegation & performance
  • Tip

Fundamentals

Power Fx is declarative and functional: you describe *what* a value should be, and the runtime recalculates it when dependencies change — like a spreadsheet cell. There are no statements that run top-to-bottom; behaviour formulas (on OnSelect, OnChange) chain side effects with ;.

  • Where it runs: canvas apps, model-driven custom pages, cards for Teams/Outlook, and Copilot Studio topics.
  • Named formulas (App.Formulas) define reusable values that recompute automatically — prefer them over OnStart variable soup.
  • `=` vs `:=` — comparisons use =; record/scope assignment in functions like Patch/With uses :.
  • Operators: & concatenates, &&/And, ||/Or, !/Not, in / exactin for membership.

Use named formulas, not OnStart

Values defined in App.Formulas are lazy and always current, so the app opens faster and you avoid stale globals. Reserve OnStart for one-time navigation or Set calls that genuinely must run once.

Text functions

12/12
FunctionWhat it doesExample → result
Concatenate / &Join strings"Hi " & First.Name → "Hi Ada"
Left / Right / MidSubstring by positionMid("FlowLibs",1,4) → "Flow"
LenLength of a stringLen("abc") → 3
Lower / Upper / ProperChange caseProper("ada lovelace") → "Ada Lovelace"
Trim / TrimEndsRemove extra spacesTrim(" a b ") → "a b"
SubstituteReplace by match (all)Substitute("a-b-c","-","/") → "a/b/c"
ReplaceReplace by positionReplace("12345",2,2,"X") → "1X45"
FindPosition of substring (1-based)Find("@","a@b") → 2
StartsWith / EndsWithPrefix / suffix testEndsWith("report.pdf",".pdf") → true
TextFormat number/date to stringText(1234.5,"$#,##0.00") → "$1,234.50"
ValueParse string to numberValue("42") → 42
Split / ConcatString ↔ table of valuesSplit("a,b,c",",") → 3-row table

Logic & conditionals

7/7
FunctionWhat it doesExample
IfBranch on condition(s)If(Score >= 50, "Pass", "Fail")
SwitchMatch a value to resultsSwitch(Status,"New",1,"Done",3,0)
CoalesceFirst non-blank valueCoalesce(Nickname, FullName, "Guest")
IsBlank / IsEmptyNull / empty-table testIf(IsBlank(Email), Notify("Required"))
IsError / IfErrorCatch + replace errorsIfError(1/Qty, 0)
And / Or / NotBoolean compositionAnd(IsToday(Due), !Done)
in / exactinMembership (case-insen / -sen)"sql" in "Azure SQL" → true

IfError beats IsError

Wrap risky expressions with IfError(value, fallback) so a single bad row or divide-by-zero does not blank the whole control. Use IfError(value, fallback, afterError) when you also need to log.

Error handling & signals

With formula-level error management on (default for new apps), errors flow through your formulas and surface to the user unless you catch them. Catch them with IfError in a formula, report them centrally in App.OnError, and raise your own with Error().

7/7
FunctionWhat it doesExample
IfError / IsErrorCatch + replace, or testIfError(Patch(DS,…), Notify("failed"))
IsBlankOrErrorBlank or error in one testIsBlankOrError(LookUp(U, Id = x))
ErrorRaise or rethrow a custom errorError({Kind: ErrorKind.Validation, Message: "Bad input"})
Errors(source)Errors from the last data opErrors(Tasks)
FirstError / AllErrorsError context in a handlerNotify(FirstError.Message)
NotifyBanner message (≤ 500 chars)Notify("Saved", NotificationType.Success)
TraceTelemetry to Monitor / App InsightsTrace("checkout", TraceSeverity.Information)

Try / catch a save

powerfx
IfError(
    Patch(Orders, Defaults(Orders), { Total: Value(txtTotal.Text) }),
    Notify($"Could not save: {FirstError.Message}", NotificationType.Error);
    Trace("save failed", TraceSeverity.Error, { detail: FirstError.Message })
)
IfError stops the chain on failure and gives you FirstError for the message + log.

Form OnSuccess / OnFailure

powerfx
// Submit button — OnSelect
SubmitForm(frmEdit)

// Form — OnSuccess
Notify("Saved", NotificationType.Success); Back()

// Form — OnFailure
Notify(frmEdit.Error, NotificationType.Error)
Let the form raise the events — don’t hand-roll success/failure in the button.

App.OnError is report-only

By the time App.OnError runs the error already happened — you can log it via FirstError/AllErrors but you can’t replace it; only IfError can do that. To pass an error up the chain, rethrow with Error(AllErrors). If you invent your own error codes, use values above 1,000 to avoid clashing with system errors.

Tables & collections

11/11
FunctionWhat it doesExample
FilterRows matching a conditionFilter(Tasks, Status = "Open")
SearchSubstring search across columnsSearch(Tasks, txtFind.Text, "Title")
LookUpFirst matching row (or a field)LookUp(Users, Id = 7).Email
Sort / SortByColumnsOrder a tableSort(Tasks, Due, Ascending)
FirstN / LastN / First / LastTake rowsFirstN(Sort(T, Date, Descending), 5)
AddColumns / DropColumnsReshape a tableAddColumns(T, "Year", Year(Date))
CountRows / CountIfCountCountIf(Tasks, Status = "Open")
Distinct / GroupByUnique values / aggregateDistinct(Tasks, Owner)
ForAllMap a formula over rowsForAll(Cart, Patch(...))
Collect / ClearCollect / PatchWrite to a collection / sourceClearCollect(colCache, Source)
WithLocal named scopeWith({r: LookUp(U, Id=x)}, r.Name)

Patch a record (create or update)

powerfx
Patch(
    Tasks,
    Coalesce(LookUp(Tasks, Id = selectedId), Defaults(Tasks)),
    {
        Title: txtTitle.Text,
        Status: ddStatus.Selected.Value,
        DueDate: dpDue.SelectedDate
    }
)
Create when ID is blank, otherwise update — the defaulted-record pattern.

Collection shaping

These functions return a *new* shaped table — they never mutate the source. Reach for them to trim columns before caching, build lookup tables, or roll child rows up onto a parent.

8/8
FunctionWhat it doesExample
AddColumnsAppend computed columnsAddColumns(Cart, "Line", Qty * Price)
DropColumnsRemove columnsDropColumns(Cart, "Internal")
RenameColumnsRename columnsRenameColumns(Data, "old", "new")
ShowColumnsKeep only these columnsShowColumns(Users, "Id", "Mail")
GroupByGroup rows into a nested tableGroupBy(Sales, "Region", "ByRegion")
UngroupFlatten a grouped tableUngroup(grp, "ByRegion")
ForAllProject a new table per rowForAll(Sequence(5), { n: Value })
SequenceGenerate N rows (1..N)Sequence(7) → 1..7

Roll a child total onto each group

powerfx
AddColumns(
    GroupBy(LineItems, "OrderId", "Lines"),
    "OrderTotal", Sum(Lines, Amount)
)

Build a table from a delimited string

powerfx
ForAll(
    Split(txtCsv.Text, ",") As line,
    { Value: Trim(line.Value) }
)

ForAll returns a table — it is not a loop

ForAll evaluates its formula for every row and returns the resulting table; it has no guaranteed order. Don’t use it purely for side effects when a set-based function (UpdateIf, RemoveIf, or Patch(Source, ForAll(...))) will do the same write in one delegated call.

Records, scope & references

6/6
KeywordWhat it refers toExample
ThisItemCurrent row in a gallery / formThisItem.Title
ThisRecordCurrent record in ForAll / Filter / SumForAll(Cart, ThisRecord.Qty * ThisRecord.Price)
SelfThe control the formula is onSelf.Fill
ParentThe containing control / screenParent.TemplateHeight
AsName a record scope to avoid ambiguityForAll(Orders As o, o.Total)
WithLocal named values for one formulaWith({r: LookUp(U, Id = x)}, r.Name)

Use As to disambiguate nested scopes

When you nest ForAll/Filter/Sum, the inner ThisRecord shadows the outer one. Name each scope with As (e.g. ForAll(Orders As o, ForAll(o.Lines As l, ...))) so you can reach both.

Variables & state

7/7
FunctionScopeExample
SetGlobal variable (whole app)Set(gblUser, User().Email)
UpdateContextContext variable (one screen)UpdateContext({locIsOpen: true})
Collect / ClearCollectCollection (in-memory table)ClearCollect(colCart, Source)
ClearEmpty a collectionClear(colCart)
PatchCreate / update a recordPatch(Tasks, Defaults(Tasks), {Title: "New"})
Remove / RemoveIfDelete rowsRemoveIf(Tasks, Status = "Done")
UpdateIfBulk-update rowsUpdateIf(Tasks, Status = "New", {Status: "Open"})

Set vs UpdateContext vs Collect

Use Set for values shared across screens, UpdateContext (or Navigate(Screen, t, {param})) for values local to one screen, and Collect/ClearCollect for tables of rows. Prefer named formulas for derived values that never need to be set imperatively.

Choices & option sets

Bind dropdowns and combo boxes to Choices() so they stay in sync with the column metadata instead of a hand-typed Table(). SharePoint choices return {Value}; Dataverse choices return the localized label set.

7/7
Function / propertyWhat it doesExample
Choices(source.Column)Valid values for a choice / lookup columnChoices(Tasks.Status)
Defaults(source)Blank record with column defaultsDefaults(Tasks)
ddl.Selected.ValuePicked value (single-select)ddStatus.Selected.Value
cmb.SelectedItemsPicked rows (multi-select)cmbTags.SelectedItems
DefaultSelectedItemsPreselect a combo boxFilter(Choices(Projects.Tags), …)
IsBlank(.Selected)Nothing picked yet?IsBlank(ddStatus.Selected)
Distinct(source, Col)Unique values when there is no choice columnDistinct(Tasks, Owner)

Patch single + multi choices

powerfx
Patch(
    Tasks,
    Coalesce(LookUp(Tasks, Task = selectedId), Defaults(Tasks)),
    {
        Status: ddStatus.Selected,        // single choice → the record
        Tags: cmbTags.SelectedItems       // choices (multi) → a table
    }
)
A single choice takes the option-set record; a multi-choice takes a table of records.

Preselect a combo box on an edit form

powerfx
Filter(
    Choices(Projects.Tags),
    Value in ThisItem.Tags.Value
)
ComboBox DefaultSelectedItems — match the row’s current values back to the choice set.

Choices keeps the dropdown honest

Because Choices() reads the column definition, adding an option at the source shows up in the app with no code change. Bind a combo’s Items to Choices(Source.Column) and only fall back to Distinct when the column isn’t a real choice/lookup.

Users & people

7/7
FunctionWhat it returnsExample
User()Signed-in user (built-in, no connector)User().Email → "ada@contoso.com"
Office365Users.MyProfile()Full profile of the current userOffice365Users.MyProfile().Department
Office365Users.UserProfile(id)Profile of another user…UserProfile("sam@contoso.com").JobTitle
Office365Users.Manager(id)That user’s managerOffice365Users.Manager(User().Email).DisplayName
Office365Users.DirectReports(id)A user’s reports (table)Office365Users.DirectReports(mgr)
Office365Users.SearchUserV2({…}).valuePeople-picker search resultsOffice365Users.SearchUserV2({searchTerm: txt.Text, top: 5}).value
Office365Groups.ListGroupMembers(id).valueMembers of a groupOffice365Groups.ListGroupMembers(gblGroupId).value

Patch a SharePoint Person column

powerfx
Patch(
    Projects, Defaults(Projects),
    {
        Title: txtTitle.Text,
        AssignedTo: {
            '@odata.type': "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
            Claims: "i:0#.f|membership|" & cmbPerson.Selected.Mail,
            DisplayName: cmbPerson.Selected.DisplayName,
            Email: cmbPerson.Selected.Mail
        }
    }
)
Person/group columns need a claims record — build it from the combo box selection.

Is the current user in a group?

powerfx
User().Email in Office365Groups.ListGroupMembers(gblAdminGroupId).value.mail

User() vs the Office 365 Users connector

User() is built in and free but only exposes Email, FullName, and Image. For job title, department, manager, or photos you need the Office 365 Users standard connector. Cache MyProfile() in a named formula or variable — never call it per gallery row.

Math & numbers

9/9
FunctionWhat it doesExample → result
Sum / AverageAggregate a columnSum(Orders, Total)
Min / MaxSmallest / largestMax(Orders, Total)
Round / RoundUp / RoundDownRound to N digitsRound(3.14159, 2) → 3.14
Int / TruncDrop the fractionTrunc(3.9) → 3
ModRemainderMod(10, 3) → 1
AbsAbsolute valueAbs(-5) → 5
Sqrt / PowerRoot / exponentPower(2, 10) → 1024
RandBetweenRandom integer in rangeRandBetween(1, 6)
CountRows / CountIfCount rowsCountIf(Orders, Total > 100)

Date & time

7/7
FunctionWhat it doesExample
Now / Today / UTCNowCurrent date-timeToday()
DateAddShift by intervalDateAdd(Today(), 7, Days)
DateDiffDifference between datesDateDiff(Start, End, Days)
DateValue / DateTimeValueParse string to dateDateValue("2026-06-15")
Text (format)Format a dateText(Now(), "yyyy-mm-dd hh:mm")
Weekday / Hour / MinuteExtract partsWeekday(Today())
IsToday / IsUTCTodayDate comparison helperFilter(T, IsToday(Created))

Format strings are case-sensitive

In Text(), mm is minutes and MM/mmmm are month. Use lowercase dd for day and yyyy for year. Times are local unless you work in UTCNow().

Navigation & behavior

9/9
FunctionWhat it doesExample
NavigateGo to a screen with a transitionNavigate(Home, ScreenTransition.Fade)
BackReturn to the previous screenBack()
NotifyShow a banner messageNotify("Saved", NotificationType.Success)
Reset / ResetFormReset a control / formReset(txtSearch)
SetFocusMove keyboard focusSetFocus(txtEmail)
LaunchOpen a URL, app, or deep linkLaunch("https://flowlibs.com")
SelectRun another control’s OnSelectSelect(btnSave)
ConcurrentRun formulas in parallelConcurrent(ClearCollect(a, A), ClearCollect(b, B))
TraceLog to Monitor / App InsightsTrace("checkout started")

Speed up OnStart with Concurrent

Wrap independent data loads in Concurrent(...) so they run in parallel instead of one after another — often the single biggest win for app launch time.

Validation & conversion

8/8
FunctionWhat it doesExample
ValueParse text to a numberValue("1234") → 1234
TextFormat a number / dateText(0.25, "0%") → "25%"
IsNumericIs the value a number?IsNumeric(txtQty.Text)
IsBlank / IsEmptyNull / empty-table testIsBlank(txtEmail.Text)
IsMatchTest text against a patternIsMatch(txtEmail.Text, Match.Email)
Match / MatchAllExtract via regexMatch("Order 42", "[0-9]+").FullMatch
GUIDNew / parse a GUIDGUID()
BooleanParse a boolean stringBoolean("true")

Built-in Match patterns

Prefer the Match enum over hand-written regex where you can: Match.Email, Match.Hyperlink, Match.MultipleDigits, Match.PhoneNumber. Add MatchOptions.Contains for partial matches.

JSON & untyped objects

6/6
FunctionWhat it doesExample
ParseJSONText to an untyped objectParseJSON(txtJson.Text)
Value (coerce)Read a number fieldValue(ParseJSON(x).price)
Text (coerce)Read a text fieldText(ParseJSON(x).name)
JSONObject / table to JSON textJSON(colCart, JSONFormat.IndentFour)
IndexNth row of a tableIndex(Filter(T, Active), 1)
Table / RecordBuild inline dataTable({Id: 1}, {Id: 2})

ParseJSON returns Untyped

ParseJSON gives an *untyped object* — coerce each field explicitly with Text(), Value(), DateValue(), or Boolean() before use, and index arrays with Index(obj, n).

UI & theming

6/6
Function / propertyWhat it doesExample
RGBAColor from channels (0–255, 0–1 alpha)RGBA(0, 120, 212, 1)
ColorValueColor from hex / CSS nameColorValue("#0078D4")
ColorFadeLighten (+) or darken (−) a colorColorFade(Brand, -20%)
Color.NameNamed color enumColor.White
SelfThe current controlColorFade(Self.Fill, -10%)
ParentContaining control / screenParent.Width

Theme tokens as named formulas

powerfx
Brand = RGBA(0, 120, 212, 1);
BrandDark = ColorFade(Brand, -25%);
Surface = RGBA(250, 250, 252, 1);
TextMuted = RGBA(96, 94, 92, 1);
SpaceM = 16;
App.Formulas — one source of truth for the palette and spacing.

Hover / pressed states with Self

powerfx
// Button Fill
If(Self.IsHovered || Self.IsPressed, BrandDark, Brand)

Name your theme once, reference everywhere

Define colors and spacing in App.Formulas, then bind control properties to the tokens — re-skinning the app becomes a one-line change, and named formulas recompute lazily so there’s no OnStart cost. For responsive layouts, prefer containers and Parent.Width over hard-coded X/Y.

Offline & storage

6/6
Function / signalWhat it doesExample
SaveDataPersist a collection to the deviceSaveData(colCart, "cart")
LoadDataReload a saved collectionLoadData(colCart, "cart", true)
ClearDataErase saved storageClearData("cart")
Connection.ConnectedIs the device online?If(Connection.Connected, …)
Connection.MeteredOn a metered network?If(!Connection.Metered, Sync())
ConcurrentRun loads in parallelConcurrent(LoadData(a,"a"), LoadData(b,"b"))

Online-or-cache startup

powerfx
If( Connection.Connected,
    ClearCollect(colTasks, Tasks); SaveData(colTasks, "tasks"),
    LoadData(colTasks, "tasks", true)
)
App.OnStart — fetch live and cache when online, fall back to the cache when offline.

Parallel cache load

powerfx
Concurrent(
    LoadData(colTasks, "tasks", true),
    LoadData(colPrefs, "prefs", true)
)

SaveData has hard limits

SaveData is capped at 1 MB in Teams and the web player (mobile gets a device-dependent 30–70 MB), it can’t run in Studio’s browser preview, and LoadData *appends* — Clear the collection first if you want a replace. Web storage is plain text, so never cache secrets. For large or relational Dataverse data, use built-in mobile offline instead.

Components & reuse

Canvas components are reusable control groups with their own custom properties — the canvas equivalent of a function or a UI component. Put shared ones in a component library and import them per app.

5/5
Custom propertyDirectionTypical use
Input (data)Host → componentPass the items, theme color, or title in
Output (data)Component → hostExpose the selected item / computed value
Input (function)Host → componentInject a formula the component calls
Output (function)Component → hostLet the host supply a callback
Behavior (event)Component → hostRaise OnChange / OnSelect-style events

Read an input, raise an event

powerfx
// Inside the component — a label's Text
cmpHeader.Title          // Input (data) custom property

// The component raises its event from a button OnSelect
cmpHeader.OnAction()     // Behavior custom property

// On the instance in the host app — OnAction:
Navigate(DetailScreen)

Components don’t see app scope

A canvas component can’t read screen controls or globals directly — everything it needs comes in through input custom properties, and everything it returns goes out through output properties. That isolation is exactly what makes it reusable across screens and apps.

Formula style guide

Consistent naming and formatting make formulas reviewable. FlowLibs house style follows the Microsoft canvas coding standards: type-prefixed control names, lifted named formulas, and comments that explain the *why*.

8/8
PrefixControl / objectExample
btnButtonbtnSave
txtText inputtxtEmail
lblLabellblTitle
galGallerygalTasks
frmEdit formfrmTask
cmb / ddlCombo box / dropdowncmbOwner
colCollectioncolCart
gbl / locGlobal / context variablegblUser / locIsOpen

Comments

powerfx
// line comment — explain the why, not the what
/* block comment
   spanning several lines */
Set(gblUser, User().Email)   // trailing comment

Format for readability

powerfx
Filter(
    Tasks,
    Status = "Open" &&
    AssignedTo.Email = User().Email
)
One argument per line, indented, operators trailing.

Name formulas and screens too

Prefix controls by type, suffix screens (scrHome), and lift repeated expressions into named formulas or With(). Keep the App checker on, and keep a formula under a screenful — if it needs scrolling, it probably wants a named formula or component.

Common patterns

Real formulas that combine several functions — each is a single expression you can drop straight into a property and adapt.

Search, filter, and sort a gallery

powerfx
SortByColumns(
  Filter(
    Search(Tasks, txtSearch.Text, "Title", "Owner"),
    Status = ddStatus.Selected.Value
  ),
  "DueDate", SortOrder.Ascending
)
Layer Search → Filter → SortByColumns on a gallery’s Items.

Cascading dropdown (distinct child values)

powerfx
Distinct(
  Filter(Cities, Country = ddCountry.Selected.Value),
  Name
)

Block submit on a duplicate

powerfx
If(
  CountRows(Filter(Members, Lower(Email) = Lower(txtEmail.Text))) > 0,
  Notify("That email already exists", NotificationType.Error),
  Patch(Members, Defaults(Members), { Email: txtEmail.Text });
  Notify("Added", NotificationType.Success)
)

Display name with fallback

powerfx
Coalesce(
  User().FullName,
  Proper(Left(User().Email, Find("@", User().Email) - 1)),
  "Guest"
)

Age in whole years from a date of birth

powerfx
RoundDown(DateDiff(dpDOB.SelectedDate, Today(), Days) / 365.25, 0)

Running total for the current row’s order

powerfx
Sum(Filter(LineItems, OrderId = ThisItem.OrderId), Amount)

Join selected items into a string

powerfx
Concat(Filter(Products, Selected), Name, ", ")

Toggle an item in a selection collection

powerfx
If(
  ThisItem.ID in colSelected.ID,
  Remove(colSelected, LookUp(colSelected, ID = ThisItem.ID)),
  Collect(colSelected, ThisItem)
)
Gallery item OnSelect — add if missing, remove if present.

Currency with a blank placeholder

powerfx
If(IsBlank(ThisItem.Price), "—", Text(ThisItem.Price, "[$-en-US]$#,##0.00"))

Start of this week (Monday)

powerfx
DateAdd(Today(), -(Weekday(Today(), StartOfWeek.Monday) - 1), Days)

Enable Submit only when the form is valid

powerfx
And(
  !IsBlank(txtName.Text),
  IsMatch(txtEmail.Text, Match.Email),
  Value(txtQty.Text) > 0
)
Use as the button’s DisplayMode: If(<this>, DisplayMode.Edit, DisplayMode.Disabled).

Three-level cascading dropdown

powerfx
// ddRegion.Items
Distinct(Locations, Region)

// ddCountry.Items
Distinct(Filter(Locations, Region = ddRegion.Selected.Value), Country)

// ddCity.Items
Distinct(
  Filter(Locations,
    Region = ddRegion.Selected.Value &&
    Country = ddCountry.Selected.Value),
  City
)
Each level filters by every level above it; clear children in the parent’s OnChange.

Save every edited gallery row at once

powerfx
Patch(
  Tasks,
  ForAll(galTasks.AllItems As row,
    {
      Task: row.Task,
      Status: row.cmbStatus.Selected.Value
    }
  )
)
Patch a table built from the gallery’s AllItems — one call, one round-trip.

Sum a related child table for the current row

powerfx
// SharePoint / SQL — filter the child table
Sum(Filter(OrderLines, OrderId = ThisItem.ID), Quantity * UnitPrice)

// Dataverse — walk the 1:N relationship directly
Sum(ThisItem.OrderLines, Quantity * UnitPrice)

Debounced search (wait for typing to stop)

powerfx
// txtSearch.OnChange — (re)start the timer
UpdateContext({ locStart: false }); UpdateContext({ locStart: true })

// tmrDebounce: Start = locStart, Duration = 400, Repeat = false
// tmrDebounce.OnTimerEnd
UpdateContext({ locSearch: txtSearch.Text, locStart: false })

// galResults.Items
Filter(Customers, StartsWith(Name, locSearch))
A short timer holds off the Filter until the user pauses — kinder to delegation.

Role-based visibility

powerfx
// App.Formulas — resolve the role once
IsAdmin = User().Email in colAdmins.Email;

// control Visible
IsAdmin

// or DisplayMode
If(IsAdmin, DisplayMode.Edit, DisplayMode.View)

Star rating (read + set)

powerfx
// star icon Color
If(ThisItem.Value <= gblRating, Color.Gold, Color.Gray)

// star icon OnSelect
Set(gblRating, ThisItem.Value)
A star icon inside a Sequence(5) gallery — ThisItem.Value is 1..5.

Multi-select ↔ delimited string

powerfx
// selected combo items → "a; b; c" for a text column
Concat(cmbTags.SelectedItems, Value, "; ")

// stored string → table for DefaultSelectedItems
ForAll(Split(ThisItem.Tags, ";") As t, { Value: Trim(t.Value) })

Client-side pagination

powerfx
FirstN(
  LastN(
    Sort(Tasks, Created, SortOrder.Descending),
    CountRows(Tasks) - (locPage - 1) * 20
  ),
  20
)
Page locPage (1-based), 20 rows per page — next: UpdateContext({locPage: locPage + 1}).

Result count with a no-results message

powerfx
With(
  { n: CountRows(galResults.AllItems) },
  If(n = 0, "No matches", $"{n} result(s)")
)

Delegation & performance

Delegation decides whether filtering/sorting happens at the data source (scales to millions of rows) or on the device (capped at the delegation limit, default 500, max 2,000). A blue underline / warning in the editor means a formula is *not* delegable and will silently truncate to that limit.

OperationDataverseSharePointSQL Server
= , <> (equals / not equals)YesYesYes
< > <= >= (compare)YesYesYes
StartsWithYesYesYes
EndsWithYesNoYes
Search() (substring)PartialNoPartial
in / exactinPartialNoPartial
Sort / SortByColumnsYesYesYes
Sum / Average / Min / MaxYesNoYes
CountRows / CountIfYesNoPartial
Filter on a calculated valueNoNoNo
GroupBy / DistinctNoNoNo
Delegation support varies by connector and column type — always verify against your own source.

Functions that never delegate

  • First / FirstN / Last / LastN, and GroupBy / Ungroup / Distinct on every connector.
  • Collection writers: Collect, ClearCollect, Concat, Concatenate, and AddColumns over a data source.
  • Any text or date transform *inside the predicate* — Left, Right, Mid, Len, Lower/Upper, &, and date math push the comparison to the device.
  • Sum / Average / CountRows on SharePoint, and Search on SharePoint columns.

Workarounds

  • Compare the raw column, not a transformed one: Filter(Orders, Status = "Open") delegates; Filter(Orders, Lower(Status) = "open") does not. Store a normalised column if you need case-insensitive matching.
  • Pre-filter at the source with a delegable predicate, then do the non-delegable shaping in memory on the (≤ 2,000-row) result.
  • Cache small, stable reference tables with ClearCollect in OnStart; never ClearCollect a large transactional table.
  • Replace per-keystroke Filter in a gallery with a debounced timer or a search button (see the recipe above).
  • For counts/sums on SharePoint, keep a roll-up/calculated column or move the data to Dataverse or SQL.

Tip

Every cheat table above is searchable

Use the filter box on each table to jump to a function fast. This whole guide is generated from one structured dataset, so it stays in sync with the MCP reference.

← All Dev ToolsUse these in your AI assistant →
Spotted an error or have a suggestion? Let us know
FlowLibs

A curated library of production-grade Power Automate cloud flow patterns. Packaged as managed solutions, ready to import into your environment.

Library

  • Browse Cloud Flows
  • Approvals
  • Email & Notifications
  • Reporting
  • Security & Compliance

AI

  • AI Tools
  • MCP Server
  • Generate a Token

Resources

  • About
  • FAQ
  • Support
  • Status
  • Contact
  • Power Automate Docs
  • Connector Reference

© 2026 FlowLibs. All rights reserved.

  • Privacy
  • Terms
  • Refunds
  • Cookies
  • Acceptable Use
  • DMCA
Help