When an end user sees a strange value in a Power BI report, their first reaction is usually to want to see the detail-level data from the underlying table. Power BI’s drillthrough feature is a great way of letting them do this, but it only returns meaningful results if you use it on measures that do simple aggregations such as sums or counts; if you have more complex calculations then usually what the drillthrough returns won’t be the rows that go to make up the value the user has clicked on.
Here’s an example. Say you have a simple Power BI model with a Sales table that contains the following data:
There is also a Date table with date and month columns, and the entire model looks like this:
Let’s say you create a measure called Sales Value that sums up the contents of the Sales column:
Sales Value = SUM('Sales'[Sales])
You could use this in a column chart to show sales by month, like so:
If the user wants to see the underlying data for one of the bars in this chart, drillthrough will work well – you just need to create another page (called, in this case, Month Drillthrough), put a table on it that displays the full contents of the Sales table:
[It’s important to note that it’s the Date column from the Sales table that’s shown here, not the Date column from the Date table]
Then drag the Month column from the Date table into the Drillthrough filter area:
…and you will be able to drillthrough from one of the columns in the chart, in this case the bar for May 2018:
…and that filter will be passed over to the Date Drillthrough page, so you only see the row in the table showing sales for May 5th 2018:
But what happens if you want to display year-to-date values in your column chart? If you create the following measure:
YTD Sales = CALCULATE([Sales Value], DATESYTD('Date'[Date]))
…and use it in the bar chart, you will see the following:
The problem comes when the user does the same drillthrough on May 2018 – which now shows the value 16 – and gets exactly the same table that they did before, showing only the sales transactions for May:
In this case, because the user clicked on the year-to-date value for May 2018 they would expect to see all the rows from the Sales table that went to make up that YTD value for May, that’s to say all the rows from the Sales table where the date was in the range January 2018 to May 2018.
The solution is to use some DAX that takes the month filter passed by the drillthrough and ensures that it filters the table shown not by the selected month, but all months in the year-to-date (similar to, but not exactly the same as, what I describe here).
Here’s a measure that does the job:
SalesIgnoringDate = var CurrentDateFromSales = CALCULATE( SELECTEDVALUE('Sales'[Date]), CROSSFILTER( 'Date'[Date], Sales[Date], None ) ) return IF( CONTAINS( DATESYTD('Date'[Date]), 'Date'[Date], CurrentDateFromSales ), CALCULATE( [Sales Value], CROSSFILTER( 'Date'[Date], Sales[Date], None) ) )
What this does is:
- Uses the DAX Crossfilter() function to disable the relationship between the Date and Sales table, and then use the SelectedValue() function to find the date from the Sales table shown on the current row of the table on the drillthrough report page, and store it in the CurrentDateFromSales variable.
- Constructs a table using the DatesYTD() function and the Date column of the Date table, which contains all of the dates from the beginning of the current year up to and including the last date in the filter context – which will be the last date in the month selected in the drillthrough.
- Uses the Contains() function to see if the date saved in the CurrentDateFromSales appears in the table returned in the previous step.
- If it does appear, return the value of the Sales Value measure. Once again, this needs to have the relationship between the Sales and Date table disabled using the CrossFilter() function.
This measure can be used in the table on the drillthrough page instead of the Sales Value measure. Last of all, since your users will not want to see a measure called SalesIgnoringDate in their report, you can rename the SalesIgnoringDate column on the table to Sales Value.
Here’s the end result (in this case I created a new drillthrough page called YTD Drillthrough with the new measure on):
You can download the sample pbix file here.
This is just one example, and different types of calculation on your source page will require vastly different DAX measures on your drillthrough page to ensure that a meaningful set of rows is returned. The basic concepts will remain the same whatever the calculation, though: you need to create a measure that ignores the filter applied by the drillthrough and instead returns a value when you want a row to appear in your drillthrough table and returns a blank value when you don’t want a row to appear.
It’s a shame that drillthrough in the SSAS Tabular sense is not available in Power BI, because being able to set a the Detail Rows Expression property on a measure in Power BI would make this problem a lot easier to solve.