Namespaced, reusable DAX User-Defined Functions (UDFs) for Power BI. Import functions, call them like built-ins, and keep business logic consistent, documented, and versioned.
A DAX UDF is a reusable function you define in DAX (preview) and call from measures/expressions. Benefits:
- Consistency
- Maintainability
- Context control
DEFINE
FUNCTION <Namespace.FunctionName> = (
param1 : <TYPE> [VAL|EXPR],
...
) => <FunctionBody>
NUMERICSTRINGBOOLEANDATETIMETABLEVARIANTINT64DECIMALDOUBLE
VAL(default): evaluate before call (eager)EXPR: evaluate inside function (lazy, context-aware)
- Power BI Desktop (latest)
- Enable DAX UDF:
- File → Options → Preview features
- Enable "DAX user-defined functions"
- Restart Power BI Desktop
- Open DAX Query View
- Paste the
DEFINE FUNCTIONblock(s) from/src/.../*.dax - Save to model
DEFINE
/// Financial.AddTax(amount: NUMERIC VAL) -> NUMERIC
/// Returns amount with 10% tax.
/// Model Requirements: none
FUNCTION Financial.AddTax = (
amount : NUMERIC
) => amount * 1.10
-- In your model
Total Sales w/ Tax = Financial.AddTax ( [Total Sales] )
DEFINE
FUNCTION Stats.CountAllDates_VAL = ( t: TABLE VAL ) =>
COUNTROWS( CALCULATETABLE( t, ALL('Date') ) )
FUNCTION Stats.CountAllDates_EXPR = ( t: TABLE EXPR ) =>
COUNTROWS( CALCULATETABLE( t, ALL('Date') ) )
Note: With an external 'Date' filter:
VALpreserves the filter at call timeEXPRre-evaluates inside the function and can modify context (e.g.,ALL('Date'))
Each .dax file begins with /// docs including Model Requirements:
- Required tables
- Keys
- Relationships
- Cardinality
- Data quality
/// <Namespace.FunctionName>
/// Summary: <what it does>
/// Params:
/// param (TYPE [VAL|EXPR]): <meaning>
/// Returns: <TYPE>
/// Model Requirements: <tables/columns/relationships>
/// Example:
/// <one-line measure usage>
/// Notes: <edge cases/perf>
Format: <Namespace>.<VerbNoun>
Examples:
Financial.AddTaxDateTime.FiscalYearIndex
-
Be explicit with context:
KEEPFILTERSREMOVEFILTERSALLALLEXCEPT
-
Prefer set-based patterns
- Avoid repeated heavy calculations
- Wrap once in a helper UDF
-
Parameter modes:
- Use
EXPRfor context-sensitive parameters (tables/measures) - Use
VALfor scalars
- Use
- Fork → create feature branch
- Add function under the correct namespace folder in
/src - Include complete
///header:- Summary
- Params with type & mode
- Returns
- Model Requirements
- Example
- Notes
- Validate in a sample model (e.g., Contoso/AdventureWorks)
- Open a PR with:
- Purpose
- Usage
- Trade-offs
- Performance notes (timings/screens if helpful)
- File name = full function name; correct namespace folder
-
///header complete (incl. Model Requirements) - Compiles and runs in a basic model
- No breaking changes (or clearly documented)
When adding a new namespace:
- Include a short
README.mdinside the folder - List all functions
- Document typical model prerequisites