Last week i had a question on my ask a question page, Sasha wanted to do the following:
How to define the date I want to see as “open items”.
E.g. Open Items by 25.05.2010
Item 1: Posting Date: 20.05.2010 Clearingdate: 28.05.2010 Value 100 EUR
Item 2: Posting Date: 22.05.2010 Clearingdate: 27.05.2010 Value 200 EUR
Item 3: Posting Date: 23.05.2010 Clearingdate: 24.05.2010 Value 300 EUR
Result will be 300 EUR (Item 1 + 2) Postingdate 25.05.2010 OR Clearingdate = 00.00.0000).
But how to select the 25.05.2010 for this calculation. I have not a date like 25.05.2010 in my Pivottable?
We have two challenges here:
- Create a between like measure using dax
- Get values from a slicer to be used inside this calculation, the data from this slicer mustn’t effect the data inside the pivottable
I have created the following simplified scenario to recreate sasha’s question. I started with a dataset:
I want to get the sum of amount where my slicer is between values a and b. The first thing i want to solve is how to get a value from a slicer inside my calculation.
To do this i created a new dataset with the values i wanted to use in my slicer, since i might want to use a value that is not inside my powerpivot data. I loaded this into PowerPivot:
This made sure of two things: i have the data i want inside a slicer and because i didn’t create a relationship between this data and the fact table nothing will happen when i select data from the slicer.
Because the data from the slicer isn’t connected to my main fact table doesn’t mean we cannot get data from it. The slicer will make sure the table i just loaded will be “sliced” to the value we want.
When we create the pivottable we seen the following:
Because we didn’t create a relationship PowerPivot keeps reminding us a relationship might be needed, because this is pretty annoying we can turn this off by clicking on the Detection button:
So we are good to go, to get the value of the slicer we can now do sum(aantal[aantal]) in our measure. A measure that uses the value from the slicer would be:
Slicer measure=if(COUNTROWS(aantal) = 1, sum(aantal[aantal]), BLANK())
This will check if we have only one value selected, and if that is the case return the sum of the column. This results in the single value because the table has one row (it is sliced to one row). Otherwise return BLANK(). This will look like:
We now have the value of the slicer in our pivottable and we can use it to create a measure that will give us the sum of amount where the value of our slicer is between a and b.
What we are going to do use sumx to sum Table1[amount] over a filtered table, this table will filter the values where the value of slicer aantal between column a and b. This will look like:
=IF(COUNTROWS(aantal) = 1 , SUMX(FILTER(Table1, Table1[a] <= sum(aantal[aantal]) && sum(aantal[aantal]) <= Table1[b] ) ,Table1[amount]) , BLANK())
step by step:
- Check if we have selected only one value in our slicer, if more return blank
- Do a sum of Table1[amount] over a filtered table, more on sumx at this blog post of Rob Collie.
- Use filter to return a dataset of specific values from a table, in this case return all rows where value of column a <= value of the slicer and value of the slicer <= value of column b
This will look like this in our Pivottable, as we can see we only have the rows where our slicer measure is between a and b:
When we remove a and b from the pivottable we see the total sum:
This again shows you the amazing power of DAX, a lot is possible. But a word of caution is at his place, SUMX and FILTER are two of the most CPU consuming functions in PowerPivot, it creates a new dynamic in memory table for every cell in the pivot where FILTER is used. I tried a similar function at a Pivottable based on Contoso and it took me a lot of CPU. Check out this blog post of Rob Collie on the use of filter. SUMX and FILTER are amazing giving you all kinds of possibility's but you need to think where to use what as you can read in Rob's blog post.