NOTE
Tabular Editor 3 includes day 0 support for both new semantic model objects introduced at FabCon Europe 2025: DAX User-Defined Functions and Custom Calendars.Step 1: New Compatibility Level – 1702
NOTE
Compatibility Level is the TOM object term for enabling release-specific behaviors in the Analysis Service engine. For more information refer to Microsoft documentation on compatibility levels.
UDFs are currently only available in Power BI Desktop and the Power BI/Fabric Service. Compatibility level 1702 is not available on SSAS and Azure AS.
Additionally, compatibility level 1701 and higher also includes support for custom calendars. Check back soon for an article on these.
You update the compatibility level on an existing model by going to the TOM Explorer, selecting the top model object and under its properties locating the Compatibility level.
Here is a small example of how that would look:

Step 2: Create a Function
As we saw in the previous section, UDFs introduce a new folder inside the TOM Explorer called Functions. This is where you create and store all the model’s functions. To create a new function, you can either:
- Go to the Model menu and select “Add User-Defined Function” or
- Right-click in the TOM Explorer on functions and choose Create -> User-Defined Function.

Step 3: Starting from an empty Expression Editor
It’s very simple to make the function, but just like measures, you need to fill it with DAX and business logic for it to be valuable.
Now on to write some DAX into that empty Expression Editor or? Well, not quite first we need to learn a little new syntax that is required when creating functions:


Step 4: Writing DAX UDFs
The function is there, the code action has given us a quick start on the UDF syntax, where do we go from here? A good place to start is to look through your model and identify a DAX pattern that you reuse across several measures.
Here is an example of a measure that calculates a comparison related to a specific target measure. Here, the Orders Target is used to calculate the delta with the [Net Orders], and then a percentage difference calculation is done.

This pattern is used several times in the model. It is thus a prime candidate to use a function instead in order to centralize your business logic, making it easy to reuse and maintain across your model.
In the following demo, we create a function that can replace the code in the measure with our new function.
One thing to do before writing DAX is to give your new function a meaningful name. Giving your function a good name is the first step to you and others knowing how to use it. In this case, we will call it Comparison.RelativeToTarget

TIP
Creating a naming standard for your functions will help with maintenance throughout your development process. One current best practice is to use a [Area].[SubArea].[FunctionName] naming standard.

Step 5: Using UDF in a measure

UDF Code Example
If you want to try out how to set up this function yourself we have included the code for it here:
‘’’DAX
// Compare to a target and return the relative percent
// Example usage: Comparing sales to budget or forecast to get relative performance
// Examples:
// - 9/10 is -10% or -1
// - 11/10 is +10% or +1
(
// The actual value that you are measuring
actualMeasure : SCALAR NUMERIC VAL,
// The target that you are comparing to
target : SCALAR NUMERIC VAL
)
=>
VAR _Actual = actualMeasure
VAR _Target = target
VAR _Delta = _Actual - _Target
VAR _Percentage = DIVIDE ( _Delta, _Target )
RETURN
_Percentage
‘‘‘