A real world example of using a UDF in Dax

Getting started
The user-defined tasks feature was introduced as a first preview version in September 2025 Delent.
This feature enables us to integrate business logic into functions, which can be called by other standard functions.
In this piece, I will show how to use this feature with a real-world example: calculating a forecast based on prices.
You will see how you can build a simple task and handle a more complex situation.
The status quo
Let's imagine a company that wants to forecast its earnings in price simulations.
They want to simulate how different rates of inflation affect monthly income.
For simplicity, we ignore imports and use the last month's final sales figure to calculate future revenue for the entire year.
The user should be able to set the number of increments and see how the numbers change.
Configure the data model
Now, it depends on whether I start with a new BI power file and load the data or add this functionality to the existing one.
The first thing to do is to activate the preview feature:
You may be forced to restart BI Desktop after enabling it.
To find an existing BIB BI file, we need to set the appropriate compatibility level to create user-defined functions (UDFS).
You can create a dummy function, which will automatically improve the compatibility level, or use the table editor to set it to at least 1702:

You can enter 1702 in the marked field and save it.
I will show how to create a simple UDF later in this part.
Please go to the Microsoft documentation to learn more about creating a new UDF in Power Bi Desktop. You can find a link in the reference section at the end of this article.
Adding Level Selection
Since the user should be able to choose the inflation rate, I added a parameter to the data model:

After clicking on “Numeric Range” I fill out the form:

Since I want to control the percentage, I set the range to -0.02 to 0.05, which corresponds to 2% to 5%.
After a few seconds, the new slicer was automatically added to the report page.
But it only shows decimal numbers.
I need to change the number format to see percentages:

Now the slider shows the number as needed:

Now it is ready to use.
Write the first function
First, let's create a UDF to retrieve the selected measure.
I prefer writing in a tabular editor, because its DAX editor is much faster than Power Bi Desktop.
But you can build it in the DAX query view in Power BI Desktop.
In the Tabular Editor, I go to login functions, right-click on it, and select “new user-defined function”:

Now I can put a name.
This is the first time, I set “Return”.
This is the function code:
(
Rate : DECIMAL VAL
)
=>
Rate
Inside the parentheses, I define the input parameter.
After => I can put the dax code of the function.
In this case, I return the input parameter.
Now, I create an estimate to use this function:
Get Inflation rate = ReturnRate([Inflation rate Value])
Average [Inflation rate Value] was created when I created a parameter to select the rate of increase in values.
When I add a card and assign a new rating to it, I will see the selected value from the slicer:

Ok, this is the first work, but it's just to show how it works.
Write a real job
You may have seen the keyword val in the parameter definition.
As you can read in the two articles below in more detail, we have two ways to pass parameters:
- VAL: Pass the contents of the parameter as is.
- Expr: Pass a parameter as an expression, which can be used inside a function as a standard expression.
In the following work, I use both.
Here is the complete code for the function MonthlyInflation:
(
Rate : DECIMAL VAL
,InputVal : EXPR
)
=>
VAR CurrentMonth = MAX( 'Date'[MonthKey] )
VAR LastMonthWithData = CALCULATE(
LASTNONBLANK( 'Date'[MonthKey]
, InputVal
)
, ALLEXCEPT( 'Date', 'Date'[Year] )
)
VAR LastValueWithData = CALCULATE(InputVal
,ALLEXCEPT('Date', 'Date'[Year])
,'Date'[MonthKey] = LastMonthWithData
)
VAR MonthDiff = CurrentMonth - LastMonthWithData
VAR Result = IF(MonthDiff<=0
,InputVal
,(1 + ( Rate * MonthDiff ) ) * LastValueWithData
)
RETURN
Result
The first parameter works as before.
The second parameter will be the input rate word.
Inside the function, I can use the parameter name to change the filter context and other things. I have to set the parameter as EXPR When I need to work this way within a function.
The function performs the following steps:
- I find the highest moon and keep it in transition
CurrentMonth
The content is the month of the current filter context in the form of values YYYYMM. - I get the latest month of the current year by a value from an input parameter (scale) and store it as a vaction
LastMonthWithData - I subtract the current month from the last month and the data to find the difference. This will be something to calculate the rate of increase in prices. The result is saved in the transition
MonthDiff - If MonthDIff is less than or equal to 0, then the filter context (month) contains the value from the input variable
- Otherwise, the filter context (month) is in the future, and we can calculate the result.
What I'm doing here is multiplying the selected inflation rate by the number of months from the previous month in the data (LastMonthWithData).
Now, I can create a monthly power calculation based on the selected power up value:
Online Sales With Inflation =
MonthlyInflation([Inflation rate Value], [Sum Online Sales])
This is the result of an inflation rate of 3%:

The months marked in blue contain the actual data, and the months in red are calculated based on the selected zoom level.
The beauty is that I can pass any dax expression to the measurement I want.
For example, I can increase internet sales by selling merchandise:

Average of the following:
Total Sales With Inflation =
MonthlyInflation([Inflation rate Value], [Sum Online Sales] + [Sum Retail Sales])
Yes, it's very easy.
I know the calculation is oversimplified, but I used this example to show what can be done with UDFS.
What is the point?
So, that's the point with UDFS?
Most of the things shown here can also be done in counting groups.
Yes, that is true.
But using a UDF is much easier than using a calculator.
In addition, we can write model-ready UDFs and reuse them across multiple models.
Check out extending BI capabilities with DAX lib.
This is a growing collection of UDFs that represent UDFs that contain logic that can be used in any data model.
Some points of difference between UDFs and counters are:
- UDFs cannot be partitioned, but counters can be organized into counter groups.
- Counters have no parameters.
- A UDF can be called directly like any other DAX function.
Try it to learn more about the possibilities of UDFs.
Lasting
A great addition to the Power Bi tools and fabric.
I'm sure it will be very important to know how to work with UDFs, as their power will become more apparent over time.
Since we are in the early stages of launching this feature, we need to stay tuned to see what Microsoft will do next to improve it.
There are some limitations to this feature. You find them here: considerations and limitations of DAX user-defined functions.
There is ample room for improvement.
Let's take a look at what's next.
Progress
Here, Microsoft's documentation for user-defined functions: Using user-defined functions (preview) – power bi | Microsoft Read.
This is a SQL BI article that describes the feature in good detail: Introduce user-defined functions in DAX – SQLBI.
A free collection of model-independent UDF implementations: Extend the power of bi with dax lib.
Like my previous articles, I am using the Contoso sample data. You can download the contosoretaildw dataset for free from Microsoft here.
Contoso data can be freely used under the MIT license, as described in this document. I changed the dataset and removed the information from modern days.



