(Power) Pivot - show true/false and calculate at the same time - excel

I have the following data source:
My pivot rows are Team => Project Name with "Value" column in the Values. I am calculating the % ration of all projects that have value "True" compared to all projects that have a value (disregarding those without values). Here's the formula I use in PowerPivot:
=CALCULATE(COUNTROWS(),'Table'[Value]=TRUE()) / CALCULATE(COUNTROWS(), ('Table'[Value]=FALSE() || 'Table'[Value]=TRUE()), ISLOGICAL('Table'[Value]))
The formula works, however I only need to see this percentage on the "Team" level, the expanded projects should still have "True/False" values. Is this possible? Preferably, without VBA.

Format your code. If you like reading very long lines, that's fine, but use DAX Formatter for the rest of us.
True vs All =
CALCULATE(
COUNTROWS( 'Table' ) // It's considered a best practice
// to explicitly name the table in
// COUNTROWS()
,'Table'[Value]=TRUE()
) / CALCULATE(
COUNTROWS( 'Table' )
// You can remove the test for [Value] = TRUE() ||
// [Value] = FALSE()
,ISLOGICAL('Table'[Value])
)
ConditionalDisplay =
IF(
ISFILTERED( 'Table'[Project] )
&& HASONEVALUE( 'Table'[Project] )
,VALUES( 'Table'[Value] )
,[True vs All]
)
[True vs All] is a cleaned up version of your existing measure.
[ConditionalDisplay] does what its name says. Displays a different value based on conditions.
We check for ISFILTERED() to cover the edge case where a given value of [Team] has only a single project. We check for HASONEVALUE() to cover the case where an explicit filter (slicer or filter) exists on [Project], but more than one is in context (grand total level).
When the two are true, we return VALUES( 'Table'[Value] ), the column made up of the distinct values in [Value]. This is only evaluated when we already know there's exactly one distinct value. A 1x1 table is implicitly converted to scalar in DAX.
When there's more than one distinct value of [Value] or it's not filtered, then we return your original measure.
[ConditionalDisplay] will fail if you have two rows for the same value of [Project] with multiple values of [Value].

Related

Max(If( equivalent in DAX PowerPivot

This question has been asked and answered before, however the solutions I've found don't seem to work for my current situation.
My table looks like:
I want to return the highest value in column B for all instances of it's match in column A in power pivot.
With a standard excel function, I would use =max(if(a2=a:a,b:b)) in column C.
I've tried =CALCULATE(max(Table1[B]),filter(Table1,Table1[A]=Table1[A])) but this is the result
Any help would be appreciated!
Table1[A] always equals Table1[A] so your condition is always true and thus doesn't do any meaningful filtering.
What you're looking for is to filter by the earlier row context (from the original table, not the FILTER iterator function):
CALCULATE (
MAX ( Table1[B] ),
FILTER ( Table1, Table1[A] = EARLIER ( Table1[A] ) )
)
Another way to do this is to use a variable to grab the row context before you're inside of the FILTER.
VAR CurrRowA = Table1[A]
RETURN
CALCULATE ( MAX ( Table1[B] ), Table1[A] = CurrRowA )

Using FILTER with VALUES (multiple rows error)

I am learning DAX on the Contoso database provided for The Definitive Guide to DAX book.
I am trying to understand filter context and I wrote this measure:
CountColor:= COUNT ( 'Product'[Color] )
I put it into the pivot table where 'Product'[Color] is added to the rows section, here is the result:
Row Labels
CountColor
Azure
14
Black
602
Blue
77
...
...
This shows that the filter context in each row is defined by the Color of that row.
When I am writing the following measure, I am anticipating that VALUES only return a unique value of the one color that is currently available in the row of the pivot table and it gets automatically converted to a scalar value:
CountColorValues:= CALCULATE (
COUNT ( 'Product'[Color] ),
FILTER ( 'Product',
'Product'[Color] = VALUES ( 'Product'[Color] )
)
)
But putting this measure to the same table, I get the error:
"Calculation error in measure 'Product'[CountColorValues]: A table of multiple values was supplied where a single value was expected."
I created another measure to test if VALUES really return a single value:
CountrowsValues:= COUNTROWS ( 
  CALCULATETABLE ( VALUES ( 'Product'[Color] )
  )
    )
The result:
Row Labels
CountrowsValues
Azure
1
Black
1
Blue
1
...
...
What am I missing when I am trying to make VALUES work in FILTER?
In this case, VALUES gets a distinct list of items, so in the following:
CountColorValues:= CALCULATE (
COUNT ( 'Product'[Color] ),
FILTER ( 'Product',
'Product'[Color] = VALUES ( 'Product'[Color] )
)
)
'Product'[Color] is trying to equal a list of {'Azure', 'Black' , 'Blue'}, so in affect you are trying to make the rows of 'Azure' equal to a table of the distinct values
For this to work it needs to be changed to an IN, is the [color] value IN the list, not equal to a list.
CountColorValues:= CALCULATE (
COUNT ( 'Product'[Color] ),
FILTER ( 'Product',
'Product'[Color] IN VALUES ( 'Product'[Color] )
)
)
The issue is supposingly caused by the Grand Total of the pivot table.
The context is different there, no color filter is present so VALUES returns every colors, thus the measure is giving the mentioned multiple row error.
Turning off the Grand Totals on the pivot table does not solve the problem, error keeps coming up.
Conclusion is that you have to write your measure Grand Total-compatible even if you are willing to supress it.

Optional FILTER in CALCULATE in DAX

Similarly to the Basket Analysis DAX pattern model, I have 1 fact for Sales, 1 dimension for Product and an extra dimension for Filter Product.
I want to use the Filter Product dimension to exclude products chosen by the user. I made it work with this DAX formula:
Sales =
CALCULATE (
SUM ( Sales['Sales'] ),
FILTER (
Product,
NOT ( 'Product'['ProductName'] IN VALUES ( 'FilterProduct'['ProductName'] ) )
)
)
This works as long as the user has already chosen a Product to exclude on FilterProduct slicer. But if nothing has been selected, the calculation will show blank, rather than just show everything. I wonder if there's a way to handle this gracefully. An idea I had was to create a variable and see if FilterProduct ISFILTERED(). If so, copy&paste the above with the FILTER() on SWITCH statement, if not, just skip the FILTER(). But this isn't great, because it duplicates code, and if I was to add another optional filter (e.g. SalesRegion), I'd had to pre-calculate all the combinations (e.g. SalesRegion & Product, just SalesRegion, just Product, none).
I think you can use the ISFILTERED function, but not exactly how you were suggesting. Try inserting it into you measure like this:
Sales =
CALCULATE (
SUM ( Sales['Sales'] ),
FILTER (
Product,
NOT ( ISFILTERED('FilterProduct'['ProductName']) ) ||
NOT ( 'Product'['ProductName'] IN VALUES ( 'FilterProduct'['ProductName'] ) )
)
)

How to compare one row to others in DAX in Excel

I have this table which has foreign keys from several other keys:
Basically, this table shows which students registered in which module run by which teacher in what term.
I want to query the following:
How many students have registered for more than one module run by a given tutor?
It will look something like this:
For example, Vasiliy Kuznetsov runs two modules: FunPro and NO. If one student registers for both of them, he is counted as one.
My sql oriented mind is telling me this: Count all the rows in which student_id and tutor_id are the same. For example, in one row student_id is 5 and tutor_id is 10, and the same is true for the third row. Then, I count it as one.
How can I do that with DAX formulas?
RowCount:=
COUNTROWS( ModuleRegistration )
StudentsWithTwoOrMoreRegistrations:=
COUNTROWS(
FILTER(
VALUES( ModuleRegistration[Student_ID] )
,[RowCount] >= 2
)
)
I refer to arguments positionally, thus the first argument to a function is (1), the second (2), and so on.
So, [RowCount] is trivial.
[StudentsWithTwoOrMoreRegistrations] is a bit more involved. DAX, being a functional language, is best understood inside-out.
FILTER() takes a table expression in (1) and evaluates a boolean predicate, (2), for each row in (1). It returns all rows from (1) for which (2) evaluates to true.
Our FILTER()'s (1) is VALUES( ModuleRegistration[Student_ID] ). VALUES() returns the unique rows from a field based on current filter context (it respects slicers and filters in the pivot table). Thus, we will return some subset of the unique list of [Student_ID]s.
Our FILTER()'s (2) is [RowCount] >= 2. For each [Student_ID] in (1), we'll evaluate [RowCount], checking how many times that student appears in ModuleRegistration. [RowCount] is evaluated in the combination of filter context from the pivot table (the [Faculty Name] field in your sample pivot provides filter context) and row context from FILTER()'s (1). Thus it counts how many times the student appears in ModuleRegistration for the [Faculty Name] on the pivot table row.
We check that [RowCount] is >= 2.
You've not indicated if your measure needs to handle grand totals, or how you might want to see that. If you need more help for the grand total to get it to behave the way you like, let me know.
Edit for grand total
There are a few ways you might want to handle grand totals. I'm gong to assume that you want a unique count of students.
StudentsWithTwoOrMoreRegistrations:=
COUNTROWS(
SUMMARIZE(
FILTER(
SUMMARIZE(
ModuleRegistration
,ModuleRegistration[Tutor_ID]
,ModuleRegistration[Student_ID]
)
,[RowCount] >= 2
)
,ModuleRegistration[Student_ID]
)
)
WTF happened to our measure?
Let's examine:
Starting with the innermost SUMMARIZE(). SUMMARIZE() navigates relationships outward from the table in (1) and groups by the columns listed in (2)-(N) (these don't have to be from the table in (1), but must be reachable by navigating relationships).
This is equivalent to the following in SQL:
SELECT
mr.Tutor_ID
,mr.Student_ID
FROM ModuleRegistration mr
We use FILTER() on this table like earlier. [RowCount] is evaluated in the combination of filter context from the pivot table and the row in the table, defined by our SUMMARIZE() above.
Now our row context is instead of just a student, a student-tutor pair. This pair will have a [RowCount] >= 2 when the student has taken more than one module from a tutor.
Our FILTER() returns the pairs which have a [RowCount] >= 2. This output table has two fields, [Tutor_ID] and [Student_ID], but we want to count distinct [Student_ID]s out of this.
Thus, we use the table from FILTER() as our (1) in the outer SUMMARIZE(). We group only by the values of [Student_ID]. We then count the rows of this table.
When only one [Faculty_Name] is in context, e.g. on a pivot table row, then our inner SUMMARIZE() is grouping by a single value of [Tutor_ID] and whatever [Student_ID]s are associated with it. This is identical to our earlier measure.
When we have many [Tutor_ID]s in context, like in the grand total, then we'll see the appropriate behavior of only counting each [Student_ID] once.

Calculated Measure Based on Condition in Dax

I have a requirement in Power Pivot where I need to show value based on the Dimension Column value.
If value is Selling Price then Amount Value of Selling Price from Table1 should display, if Cost Price then Cost Price Amount Should display, if it is Profit the ((SellingPrice-CostPrice)/SellingPrice) should display
My Table Structure is
Table1:-
Table2:-
Required Output:-
If tried the below option:-
1. Calculated Measure:=If(Table[Category]="CostPrice",[CostValue],If(Table1[category]="SellingPrice",[SalesValue],([SalesValue]-[CostValue]/[SalesValue])))
*[CostValue]:=Calculate(Sum(Table1[Amount]),Table1[Category]="CostPrice")
*[Sales Value]:=Calculate(Sum(Table1[Amount]),Table1[Category]="SellingPrice")
Tried this in both Calculated Column and Measure but not giving me required output.
Cost:=
CALCULATE(
SUM( Table1[Amount] )
,Table1[Category] = "CostPrice"
)
Selling:=
CALCULATE(
SUM( Table1[Amount] )
,Table1[Category] = "SellingPrice"
)
Profit:=
DIVIDE(
[Selling] - [Cost]
,[Selling]
)
ConditionalMeasure:=
IF(
HASONEFILTER( Table2[Category] )
,SWITCH(
VALUES( Table2[Category] )
,"CostPrice"
,[Cost]
,"SellingPrice"
,[Selling]
,"Profit"
,[Profit]
)
,[Profit]
)
HASONEFILTER() checks that there is filter context on the named field and that the filter context includes only a single distinct value.
This is just a guard to allow our SWITCH() to refer to VALUES( Table2[Category] ). VALUES() returns a table of all distinct values in the named column or table. So, a 1x1 table can be implicitly converted to a scalar, which we need in SWITCH().
SWITCH() is a case statement.
Our else condition in the IF() is just returning [Profit]. You might want something else, but it's unclear what should happen at the grand total level. You can leave this off, and the measure will be blank in IF()'s else condition.
I was thinking about this a little. I'm not sure why you have your categories on rows. Usually the data set would have columns like: item | CostPrice | SellingPrice | Profit. Then you can just use the columns to define your fields. The model becomes easier and more maintainable.

Resources