Formatting DAX code
Before we continue explaining the DAX language, we would like to cover an important aspect of DAX—that is, formatting the code. DAX is a functional language, meaning that no matter how complex it is, a DAX expression is like a single function call. The complexity of the code translates into the complexity of the expressions that one uses as parameters for the outermost function.
For this reason, it is normal to see expressions that span over 10 lines or more. Seeing a 20-line DAX expression is common, so you will become acquainted with it. Nevertheless, as formulas start to grow in length and complexity, it is extremely important to format the code to make it human-readable.
There is no “official” standard to format DAX code, yet we believe it is important to describe the standard that we use in our code. It is likely not the perfect standard, and you might prefer something different. We have no problem with that: find your optimal standard and use it. The only thing you need to remember is: format your code and never write everything on a single line; otherwise, you will be in trouble sooner than you expect.
To understand why formatting is important, look at a formula that computes a time intelligence calculation. This somewhat complex formula is still not the most complex you will write. Here is how the expression looks if you do not format it in some way:
IF(CALCULATE(NOT ISEMPTY(Balances), ALLEXCEPT (Balances, BalanceDate)),SUMX (ALL(Balances [Account]), CALCULATE(SUM (Balances[Balance]),LASTNONBLANK(DATESBETWEEN(BalanceDate[Date], BLANK(),MAX(BalanceDate[Date])),CALCULATE(COUNTROWS(Balances))))),BLANK())
Trying to understand what this formula computes in its present form is nearly impossible. There is no clue which is the outermost function and how DAX evaluates the different parameters to create the complete flow of execution. We have seen too many examples of formulas written this way by students who, at some point, ask for help in understanding why the formula returns incorrect results. Guess what? The first thing we do is format the expression; only later do we start working on it.
The same expression, properly formatted, looks like this:
IF ( CALCULATE ( NOT ISEMPTY ( Balances ), ALLEXCEPT ( Balances, BalanceDate ) ), SUMX ( ALL ( Balances[Account] ), CALCULATE ( SUM ( Balances[Balance] ), LASTNONBLANK ( DATESBETWEEN ( BalanceDate[Date], BLANK (), MAX ( BalanceDate[Date] ) ), CALCULATE ( COUNTROWS ( Balances ) ) ) ) ), BLANK () )
The code is the same, but this time it is much easier to see the three parameters of IF. Most important, it is easier to follow the blocks that arise naturally from indenting lines and how they compose the complete flow of execution. The code is still hard to read, but now the problem is DAX, not poor formatting. A more verbose syntax using variables can help you read the code, but even in this case, the formatting is important in providing a correct understanding of the scope of each variable:
IF ( CALCULATE ( NOT ISEMPTY ( Balances ), ALLEXCEPT ( Balances, BalanceDate ) ), SUMX ( ALL ( Balances[Account] ), VAR PreviousDates = DATESBETWEEN ( BalanceDate[Date], BLANK (), MAX ( BalanceDate[Date] ) ) VAR LastDateWithBalance = LASTNONBLANK ( PreviousDates, CALCULATE ( COUNTROWS ( Balances ) ) ) RETURN CALCULATE ( SUM ( Balances[Balance] ), LastDateWithBalance ) ), BLANK () )
You can find the website at www.daxformatter.com. The user interface is simple: just copy your DAX code, click FORMAT, and the page refreshes showing a nicely formatted version of your code, which you can then copy and paste in the original window.
This is the set of rules that we use to format DAX:
Always separate function names such as IF, SUMX, and CALCULATE from any other term using a space and always write them in uppercase.
Write all column references in the form TableName[ColumnName], with no space between the table name and the opening square bracket. Always include the table name.
Write all measure references in the form [MeasureName], without any table name.
Always use a space following commas and never precede them with a space.
If the formula fits one single line, do not apply any other rule.
If the formula does not fit a single line, then
Place the function name on a line by itself, with the opening parenthesis.
Keep all parameters on separate lines, indented with four spaces and with the comma at the end of the expression except for the last parameter.
Align the closing parenthesis with the function call so that the closing parenthesis stands on its own line.
These are the basic rules we use. A more detailed list of these rules is available at http://sql.bi/daxrules.
If you find a way to express formulas that best fits your reading method, use it. The goal of formatting is to make the formula easier to read, so use the technique that works best for you. The most important point to remember when defining your personal set of formatting rules is that you always need to be able to see errors as soon as possible. If, in the unformatted code shown previously, DAX complained about a missing closing parenthesis, it would be hard to spot where the error is. In the formatted formula, it is much easier to see how each closing parenthesis matches the opening function call.