Forum Discussion
Converting Excel Formulas to DAX
- 10 years ago
Didn't have time to read the whole thread, but your WHB is impossible in DAX as you've got it defined. Luckily we can redefine it in a much more reasonable way (in terms of fields being accessed). Here are all the measures in clean DAX for you. It should be a good exercise in observing row vs filter context.
DAX isn't really the tool of choice for this, though. This sort of data munging should be done before the model is loaded. Unless you want these as measures, in which case, most of the ALL()s should be replaced with ALLSELECTED(), and the raw column references will have to be wrapped in SUM()s.
Steve = DIVIDE( SomeDamnTable[Fred], SomeDamnTable[Allen] ) // All row context Sysco = DIVIDE( SomeDamnTable[Fred] + SomeDamnTable[X] // All row context ,SomeDamnTable[Allen] ) Mary = IF( SomeDamnTable[Fred] >= SomeDamnTable[Allen] // All row context ,0 ,SomeDamnTable[Allen] - SomeDamnTable[Fred] ) Impact = CALCULATE( // Do this whole thing in a filter context made up of the entire table DIVIDE( SUM( SomeDamnTable[Fred] ) ,SUM( SomeDamnTable[Allen] ) ) ,ALL( SomeDamnTable ) ) - DIVIDE( CALCULATE( // this CALCULATE is in a filter context of the entire table SUM( SomeDamnTable[Fred] ) ,ALL( SomeDamnTable ) ) + SomeDamnTable[Mary] // This is row context ,CALCULATE( // this calculate is in the filter context of the whole table SUM( SomeDamnTable[Allen] ) ,ALL( SomeDamnTable ) ) ) Bob = IF( // all row context ( SomeDamnTable[Fred] + SomeDamnTable[X] ) >= SomeDamnTable[Allen] ,0 ,SomeDamnTable[Allen] - SomeDamnTable[Fred] - SomeDamnTable[X] ) WHB =
CALCULATE(
DIVIDE(
SUM( SomeDamnTable[Fred] )
,SUM( SomeDamnTable[Allen] )
)
,ALL( SomeDamnTable )
) - CALCULATE(
SUM( SomeDamnTable[Impact] )
,FILTER(
ALL( SomeDamnTable )
,SomeDamnTable[Index] <= EARLIER( SomeDamnTable[Index] )
)
)You should try to do this sort of thing before your data hits your model. Here's some Power Query to get you there. You can examine all this in the .pbix here.
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSAWMDMI7ViVYywhAxxhAxwRAxxRAxwxAxxxCxwBCxxBAxNIAKGSKEDFGFYgE=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Product = _t, Allen = _t, Fred = _t, X = _t]), #"Changed Type" = Table.TransformColumnTypes(Source,{{"Product", Int64.Type}, {"Allen", Int64.Type}, {"Fred", Int64.Type}, {"X", Int64.Type}}), Steve = Table.AddColumn(#"Changed Type", "Steve", each [Fred] / [Allen]), Sysco = Table.AddColumn(Steve, "Sysco", each ( [Fred] + [X] ) / [Allen]), Mary = Table.AddColumn(Sysco, "Mary", each if [Fred] >= [Allen] then 0 else [Allen] - [Fred]), Impact = Table.AddColumn(Mary, "Impact", each ( List.Sum( Mary[Fred] ) / List.Sum( Mary[Allen] ) ) - ( ( List.Sum( Mary[Fred] ) + [Mary] ) / List.Sum( Mary[Allen] ) )), Bob = Table.AddColumn(Impact, "Bob", each if ( [Fred] + [X] ) >= [Allen] then 0 else [Allen] - [Fred] - [X]), Index = Table.AddIndexColumn(Bob, "Index", 1, 1), WHB = Table.AddColumn(Index, "WHB", each let CurrentRow = [Index] ,Base = ( List.Sum( Index[Fred] ) / List.Sum( Index[Allen] ) ) ,SumImpact = List.Sum( Table.Column( Table.SelectRows( Index , each [Index] <= CurrentRow ) ,"Impact" ) ) ,WHB = Base - SumImpact in WHB), #"Removed Columns" = Table.RemoveColumns(WHB,{"Index"}), #"Changed Type1" = Table.TransformColumnTypes(#"Removed Columns",{{"Impact", Currency.Type}, {"WHB", type number}, {"Mary", Int64.Type}, {"Sysco", Int64.Type}, {"Steve", Int64.Type}, {"X", Int64.Type}, {"Fred", Int64.Type}, {"Allen", Int64.Type}, {"Product", Int64.Type}, {"Bob", Int64.Type}}) in #"Changed Type1"
greggyb fbrossard Thank you both for the suggestions. I have moved the majority of my former measures upstream to where it calculates before it hits the data model. For now, I am only using Steve, Sysco, Impact, and WHB as measures in the data model.
I have also created an index column to handle the sorting, however, I get a semantic error for the WHB formula:
WHB =
CALCULATE(
DIVIDE(
SUM( SomeDamnTable[Fred] )
,SUM( SomeDamnTable[Allen] )
)
,ALL( SomeDamnTable )
) - CALCULATE(
SUM( SomeDamnTable[Impact] )
,FILTER(
ALL( SomeDamnTable )
,SomeDamnTable[Index] <= EARLIER( SomeDamnTable[Index] )
)
)
"Earlier/Earliest refers to an earlier row context which doesn't exist."
However, the sorting can be done manually as long as the WHB formula works.
Thanks in advance
WHB was defined as a calculated column in my model. That error indicates you're using it as a measure.
Use MAX(), which will be evaluated in the filter context of the visualization, rather than EARLIER() which depends, as the error indicates, on a row context that cannot exist in the top level of a measure evaluation in a visualization.
I've not put much thought toward using these as measures, but I can't see much issue. Subtotals will be calculated as of the item in that subtotal with the greatest value for [Index].