The ability to create custom functions has been around for some time in other languages; Python, JavaScript, SQL, even Excel. This gives the opportunity to consolidate coding logic into our own custom formulas, where out-of-the-box functionality doesn’t do what we need. We can build the function once and use across our apps, any changes handled in one place that cascade down to wherever it’s in use. Power Apps User Defined Functions provides this for us, meaning we can keep our Power Fx dry (don’t repeat yourself) instead of wet (write everything twice).
We’ve had reusable components in Power Apps for some time, so taking it a level lower for reusable code seems logical. In this article, I’ll cover how to enable and a few examples of where they could prove useful.
Table of Contents
ToggleHow to enable / naming convention
At time of writing, Power Apps user defined functions are an experimental feature, so should not be used in production apps. To enable this feature in Power Apps, you’ll need to head to Settings > Updates > Experimental and turn on User-defined functions. Take note of the disclaimer at the top:
Creating a user defined function takes place in the same area as Named Formulas. If they’re together, I’d personally like to easily identify what’s what. With my prefix for named formulas being nf, I’ll settle on a prefix of udf for user defined functions.
Structure
Power Apps user defined functions are structured like so:
NameOfFunction
(InputValue1:ValueType1,
InputValue2:ValueType2):OutputType = Power Fx formula;
InputValue: Each input is a value you want to pass into the function.
ValueType: You’ll need to define what data type the input will be.
OutputType: What data type the result of the function will be. This doesn’t have to match the types of your Input values.
Power Fx formula: What is the repetitive Power Fx logic you want the function to run.
Each input property you add is then a mandatory property when you use the defined function in your app.
Because each user defined function is written in the named formulas area, you’ll need to make sure the Power Fx formula part ends with a semi-colon. As a reminder, you can find the Formulas area in Power Apps like so:
Examples
Most of the Power Apps user defined functions below are influenced by developments I’ve been part of, or seen, in the past 6-12 months or so. There will be tonnes more use cases but hope they give you a good understanding of what’s possible.
In their own right, each example can be done quickly and easily as a one-off in Power Fx. If these one-offs become repeated in an app, then it’s time to consider user defined functions. It also makes Power Fx a lot easier to read across your app, as it’ll be far less cluttered.
Evaluating booleans
In my app, I’m setting a local boolean variable:
UpdateContext({cvBoolean: !cvBoolean})
Typically, I might evaluate that boolean to drive an output. I might be duplicating this logic across other labels, or if using a global variable, across other screens:
If(cvBoolean,"I am true","I am false")
Power Apps user defined function: We’ll need an input type of boolean as that’s what we’re going to analyse. The output will need to be text:
udfBoolean(BooleanInput:Boolean):Text = If(BooleanInput, "I am true", "I am false");
The function is now available to use across my app. Simply insert the relevant boolean value into the formula:
// UDF to analyse a boolean and return relevant text
udfBoolean(cvBoolean)
Sum of user inputs
Performing simple calculations is common across an app. For example, we can target Text Input controls to get a total:
// Total of user inputs
txtValue01.Text + txtValue02.Text
Power Apps user defined function: This will need two number inputs and a number output. The formula here will reference both inputs:
udfSimpleCalc(Value1:Number,Value2:Number):Number = Value1+Value2;
When using in the app, we can plug in any two numeric values to get the total:
// UDF to sum two numbers
udfSimpleCalc(txtValue01.Text, txtValue02.Text)
Calculating percentages
I’ve manually configured Power Fx to calculate percentages hundreds of times. Not only working out the value, but concatenating with a % sign so it’s clear to the app users.
The following Power Fx performs the calculation and appends the symbol:
// Find percentage
$"{txtAchievedScore.Text / txtPossibleScore.Text * 100}%"
Power Apps user defined function: This will require two number inputs and a text output:
// Percentage
udfPercentage(Total:Number,Achievable:Number):Text = $"{Total / Achievable *100}%";
Across our app, we now just inject the values. Doing the calculation and appending the symbol will be done automatically:
Calculating total costs
Another simple calculation that’s a good candidate is adding percentages to values. In the UK, we have the joys of VAT (Value Added Tax) that currently has 3 possible rates: 0%, 5% and 20%.
I’ve a simple setup in an app for a user to add a cost and select the chosen rate:
The following Power Fx will calculate the total including VAT:
// Total inc VAT
txtNetCost.Text + (txtNetCost.Text * dpdVATRate.Selected.Value)
Power Apps user defined function: This will need a number input (for cost) and a text input (for VAT percentage). The output will be a number:
// VAT multiplication
udfTotalIncVAT(NetValue: Number, VATValue:Text):Number = NetValue + (NetValue * VATValue);
Refer to any numerical and percentage values across your app by using the function:
// UDF to calculate total inc VAT
udfTotalIncVAT(txtNetCost.Text, dpdVATRate.Selected.Value)
Text formatting
How many times have you written some Power Fx to format values? This can be a very common piece of code in an app, especially if building something related to Finance and needing to show currency.
Typically, we use the Text function in Power Apps to show a value with currency. This can be formatting a value directly or the output of a calculation, like below:
// Format total cost as £GBP
Text(txtPriceExcVAT.Text + (txtPriceExcVAT.Text * dpdVATPerc.Selected.Value),"£#,##0.00")
Power Apps user defined function: The function will need to absorb a number to format, returning a text value as an output. The formula will reference the input value to then format it:
// Currency format
udfCurrencyFormat(TotalValue:Number):Text = Text(TotalValue, "£#,##0.00");
When we call the function, it just needs the value. The conversion logic no longer needs to be typed for every instance in the app:
// UDF to format value to £GBP
udfCurrencyFormat(txtPriceExcVAT.Text)
You can also combine user defined functions together. In the previous example (above), the function udfTotalIncVAT performs a calculation for us. Let’s take the output of that and format it:
// UDF to format value to £GBP
udfCurrencyFormat(
udfTotalIncVAT(
txtPriceExcVAT.Text,
dpdVATPerc.Selected.Value
)
)
You can attack any other conversions in the same way, for example dates or times.
Conditional formatting
Another common scenario – conditional formatting logic. I’ve seen many apps replicating logic for fill and colour properties, invariably using the same RGBA or Hex values.
In this example, I’m working with a gallery of Star Wars characters. I want to apply conditional formatting to each characters allegiance.
I’ve used a named formula for my theming configuration:
// Theming
nfTheming = {
Colours: {
Cream: ColorValue("#FDF5DF"),
Teal: ColorValue("#5EBEC4"),
Pink: ColorValue("#F92C85"),
Grey: ColorValue("#2B2B2B")
}};
Setting up the conditional formatting is easy enough for the Characters gallery. A simple Switch function in the labels Fill property will do the trick:
// Apply conditional formatting
Switch(
ThisItem.Allegiance,
"Rebels", nfTheming.Colours.Pink,
"Dark Side", nfTheming.Colours.Teal,
"The Force", nfTheming.Colours.Cream
)
All working as expected:
If we want to use the same logic elsewhere in the app, chances are we’re copying & pasting the same code. All of a sudden that’s a lot of duplication.
Power Apps user defined function: To conditionally format text, text will need to be our input. Our output is going to be a colour value. The formula will then reference the input value to perform the formatting logic.
You can use a number input if you want to apply the same formatting logic over numbers or calculations.
// Conditional formatting logic
udfConditionalFormatting(ValueToFormat:Text):Color =
Switch(ValueToFormat,
"Rebels",nfTheming.Colours.Pink,
"Dark Side",nfTheming.Colours.Teal,
"The Force",nfTheming.Colours.Cream);
Implementing this is super simple; add the function and the text (or number) value to pass in. The function does the rest:
// UDF for conditional Allegiance fill
udfConditionalFormatting(ThisItem.Allegiance)
Pattern matching
Sometimes we need to create custom logic in Power Apps to validate user input. A good example of this is email addresses; get these ever so slightly wrong and users won’t receive important communications.
I’ve built and seen many apps where multiple email fields need validating. There is an out-of-the-box approach using the IsMatch function, however this isn’t the best approach. For more info on that, check out Sancho Harker’s article here. He mentions using Regex for matching instead, which is a great shout.
Using the pattern in his article, we’d typically set up some validation in Power Fx like so:
// Is email address entered correctly
If(
!IsMatch(
txtEmailAddress.Text,
"(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)@{1}(?:([a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9]{2,})"
),
"Unrecognised email format",
"Recognised email format"
)
That’s a decent amount of text, which doesn’t always make for easy reading if it’s embedded inside a larger amount of code. Copying this lots of times for multiple email validations in your app will bloat the amount of visible code too.
Power Apps user defined function: We simply need a text input and output for this matching scenario. This will provide a friendly output to the user:
// Pattern matching - email
udfIsTrueEmail(EmailAddress:Text):Text =
If(
!IsMatch(EmailAddress,
"(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)@{1}(?:([a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9]{2,})"
),
"Unrecognised email format",
"Recognised email format");
An alternative approach is to keep the text input, but use a boolean output instead:
// Pattern matching - email
udfIsTrueEmailBoolean(EmailAddress:Text):Boolean =
IsMatch(EmailAddress,
"(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*)@{1}(?:([a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9]{2,})"
);
Either approach just requires an email address for the parameter. For example, adding either of the following into the Text property of a label:
// Validate email - friendly response
udfIsTrueEmail(txtEmailAddress.Text)
// Validate email - boolean response
udfIsTrueEmailBoolean(txtEmailAddress.Text)
You can use this technique for any other matching scenarios you may have across your app.; NHS numbers, IP addresses, phone numbers, zip/postal codes, URL’s and so on.
Converting Hex values to text
A very common requirement is to convert Hex values to text, so they can be used within SVG’s. SVG code is a large text string, so it won’t accept a colour value anywhere. As per an earlier example, we have theming stored as a named formula. The values are stored as Hex:
// Theming
nfTheming = {
Colours: {
Cream: ColorValue("#FDF5DF"),
Teal: ColorValue("#5EBEC4"),
Pink: ColorValue("#F92C85"),
Grey: ColorValue("#2B2B2B")
}};
Thankfully, returning these values as text is quite simple. We start by converting the value to JSON, using the JSON function:
// Get text output of Hex colour value
JSON(nfTheming.Colours.Pink)
This returns the value as text:
As you can see, the result is bookended with double quotes. If we want to use the value in SVG code, we’ll need to remove those. Let’s wrap the JSON with a Mid function to target the string needed:
// Get text output of Hex colour value, minus double quotes
Mid(JSON(nfTheming.Colours.Pink),2,7)
Sorted, here’s the Hex value as a string:
However, do you want to write that code for every conversion within some SVG code? Let’s take the Power Apps logo as an example. I want to dynamically update the darkest part of the logo. In the SVG code, the highlighted Hex values will need to be replaced:
A function would be a much better idea here so we can streamline this repeated code:
Power Apps user defined function: We’ll need the function to take a colour value and return a text value:
// Convert Hex value to text
udfHexToText(HexInput:Color):Text = Mid(JSON(HexInput),2,7);
Awesome. I do all my theming as Hex values these days and use a lot of SVG’s. This would be a super powerful addition to the kitbag.
Calculating working days
Something I’ve done a lot of in the past is trying to calculate working days between 2 dates. An added complication is factoring in holiday days, as such the Power Fx can be quite lengthy. Something else to streamline with a function.
In this example, I’ve loaded in a bunch of UK holiday dates:
ClearCollect(
colHolidays,
[
"05/06/2024", // Early May bank holiday
"05/27/2024", // Spring bank holiday
"08/26/2024", // Summer bank holiday
"12/25/2024", // Christmas day
"12/26/2024", // Boxing day
"01/01/2025" // New Years Day
]
)
I have two date controls in my app – dtpStartDate and dtpEndDate. Here is the Power Fx to calculate the number of working days between the selected date range:
With(
{
// Start and end dates
tvStartDate: dtpStartDate.SelectedDate,
tvEndDate: dtpEndDate.SelectedDate,
// Weekday no's of start and end
tvStartWeekDay: Weekday(dtpStartDate.SelectedDate),
tvEndWeekDay: Weekday(dtpEndDate.SelectedDate),
// No of days between start and end
tvDaysDiff: DateDiff(
dtpStartDate.SelectedDate,
dtpEndDate.SelectedDate
)
},
With(
{
// Logic for weekends
tvWorkDays: tvDaysDiff + 1 - (2 * (Int(tvDaysDiff / 7) + If(
tvStartWeekDay > tvEndWeekDay,
1,
If(
tvStartWeekDay <= 6 && tvEndWeekDay >= 7,
1,
0
)
)))
},
// Logic for holidays
tvWorkDays - CountRows(
Filter(
colHolidays,
DateValue(Value) >= tvStartDate && DateValue(Value) <= tvEndDate && Weekday(Value) <> 1 && Weekday(Value) <> 7
)
)
)
)
Firstly, I’m sure there’s a more efficient approach – if so please let me know in the comments below if so. But, it’s worked for me so happy days.
Secondly, if you have to do this calculation multiple times across an app, that’s a lot of duplicated code!
Power Apps user defined function: We need two date inputs for start and end date. As we’re calculating number of working days, the function needs to provide a number output. The input properties will be used in the first part of the With function:
// Working days calc inc. holidays
udfWorkingDays(StartDate:Date, EndDate:Date):Number = With(
{
// Start and end dates
tvStartDate: StartDate,
tvEndDate: EndDate,
// Weekday no's of start and end
tvStartWeekDay: Weekday(StartDate),
tvEndWeekDay: Weekday(EndDate),
// No of days between start and end
tvDaysDiff: DateDiff(
StartDate,
EndDate
)
},
With(
{
// Logic for weekends
tvWorkDays: tvDaysDiff + 1 - (2 * (Int(tvDaysDiff / 7) + If(
tvStartWeekDay > tvEndWeekDay,
1,
If(
tvStartWeekDay <= 6 && tvEndWeekDay >= 7,
1,
0
)
)))
},
// Logic for holidays
tvWorkDays - CountRows(
Filter(
colHolidays,
DateValue(Value) >= tvStartDate && DateValue(Value) <= tvEndDate && Weekday(Value) <> 1 && Weekday(Value) <> 7
)
)
)
);
Now, anywhere we need to perform that calculation, call the function and give it two date values:
// UDF to calculate working days between a date range
udfWorkingDays(dtpStartDate.SelectedDate,dtpEndDate.SelectedDate)
As demonstrated below, the chosen 7 day period returns 3 working days. It’s excluding the weekend, Christmas Day and Boxing Day:
Constructing an email body
I recently covered how to send emails from Power Apps. We might need to use this functionality and construct a HTML body to send. This can potentially be duplicated lots of times in an app, so more to maintain if changes are required.
In this example, the app will send an email to ask users to launch another Power App:
Power App user defined function: Making the recipient name and hyperlink dynamic means we’ll need those as input properties. The overall output needs to be text so it’s compatible with an email body. The recipient and hyperlink input properties are then referenced in the HTML:
// Construct email body
udfEmailBody(Recipient:Text, Hyperlink:Hyperlink):Text = $"
Hi {Recipient},
Thanks for using our Power Platform services.
Now you have finished your initial onboarding, please visit our Connectors app to view what is blocked by our Power Platform DLP policies.
Thanks,
Han Solo
";
With a combination of the user details and the hyperlink (saved as a named formula), deploying the function is easy:
// UDF to send email with dynamic recipient name and hyperlink
Office365Outlook.SendEmailV2(
Office365Users.MyProfileV2().mail,
"This is my subject",
udfEmailBody(
Office365Users.MyProfileV2().givenName,
nfAppURL
)
)
This is perfect if you have multiple email-sending scenarios from a single Power App.
As mentioned at the start of the article, user defined functions are currently an experimental feature. I really hope they’re able to be used in production scenarios sooner rather than later, as I see more and more use cases where they’d fit perfectly. I’d love to see these extended too, to include things like optional parameters or better support for working with records/tables.
Have you played around with this experimental feature yet, or have other ideas where it might be useful? Let me know in the comments.
Thanks for reading. If you liked this article and want to receive more helpful tips about Power Platform, don’t forget to subscribe or follow me on socials 😊.
Excellent post!
Do you have a repository with more custom functions?
Nice article!