DAX: A Breadcrumb Pattern

Table of Contents

Overview

Breadcrumbs are a powerful element adding context to your reports. Effectively, when a user applies filters, breadcrumbs establish context for quick reference. You can see an example below or by going to this article: Financial Modeling in Power BI (Filter Page and Breadcrumbs), Analytical Ants.

Pattern Overview

The output of this pattern looks something like below:

Category [ Attribute: list, … ] …

The intent is that a developer defines category sections which logically group filters. An example might be a ‘Calendar’ category with the following attributes: Year, Month, date, etc. The output is supposed to be dynamic in that unselected categories and attributes simply don’t show – only relevant information is presented.  

The general pattern is below. The key components are:

  • Categories: These are the developer designed sections.
  • Attributes: These are the attributes users select.
  • Delimiter: This is the separator between attributes
Breadcrumbs = 
VAR __Delimiter = "; "
VAR __Category = 
    VAR __Attribute1 = IF ( ISFILTERED ( Table[Column] ) , "Year(s): " & CONCATENATEX ( VALUES ( Table[Column] ) , [Column] , ", " ) )
    VAR __Attribute2 = IF ( ISFILTERED ( Table[Column] ) , "Year(s): " & CONCATENATEX ( VALUES ( Table[Column] ) , [Column] , ", " ) )
    ...
    RETURN CONCATENATEX ( FILTER ( UNION ( {__Attribute1} , {__Attribute2} , ... ) , [Value] <> Blank() ) , [Value] , __Delimiter ) 
VAR __Category_2 = ...
VAR __BreadCrumbTable = 
	Generate ( /*Categories*/ {"Category1", "Category2" , "..." }
		, ROW ( 
			"Data" , 
				SWITCH(
					TRUE() , 
					[Value] = "Category1", __Category , 
					[Value] = "Category2" , __Category_2 , 
					...
				)
			)
		)
RETURN CONCATENATEX( FILTER ( __BreadCrumbTable , [Data] <> Blank() ) , [Value] & " [" & [Data] & "] " )

Examples with DAX.do

The following example is based on this senario:

  • Categories: Calendar and Product
  • Attributes: Calendar [Year, Month, Date] and Product[Category, Subcategory]

Here is the full Breadcrumb code:

Example 1: Users selects May and June for 2009

1DEFINE
2    VAR __FilterYear = TREATAS ( {"FY 2009"} , 'Date'[Fiscal Year] )
3    VAR __FilterMonth = TREATAS ( {"May", "June"} , 'Date'[Fiscal Month] )
4    VAR __FilterDate = TREATAS ( {"2009-05-01"} , 'Date'[Date] )
5    VAR __FilterCategory = TREATAS ( {"Computers"} , 'Product'[Category] )
6    VAR __FilterSubcategory = TREATAS ( {"Laptops"} , 'Product'[Subcategory] )
7    
8EVALUATE 
9SELECTCOLUMNS (
10SUMMARIZECOLUMNS(
11    ------------
12    /*Please ignore; simply selecting a non-relevant single value*/ 'Currency'[Currency] , TREATAS ( {"US Dollar"} , 'Currency'[Currency] )
13    ------------
14    , __FilterYear
15    , __FilterMonth
16    //, __FilterDate
17    //, __FilterCategory 
18    //, __FilterSubcategory
19    , "Bread Crumbs" ,  
20        VAR __Delimiter = "; "
21        VAR __Calendar = 
22            VAR __Year = IF ( ISFILTERED ( 'Date'[Fiscal Year] ) , "Year(s): " & CONCATENATEX ( VALUES ( 'Date'[Fiscal Year] ) , [Fiscal Year] , ", " ) )
23            VAR __Month = IF ( ISFILTERED ( 'Date'[Fiscal Month] ) , "Month(s): " & CONCATENATEX ( VALUES ( 'Date'[Fiscal Month] ) , [Fiscal Month] , ", " ) )
24            VAR __Date = IF ( ISFILTERED ( 'Date'[Date] ) , "Day(s): " & CONCATENATEX ( VALUES ( 'Date'[Date] ) , [Date] , ", " ) )
25            RETURN CONCATENATEX ( FILTER ( UNION ( {__Year} , {__Month} , {__Date}) , [Value] <> Blank() ) , [Value] , __Delimiter ) 
26        VAR __Product =
27            VAR __Category = IF ( ISFILTERED ( 'Product'[Category] ) , "Category(s): " & CONCATENATEX ( VALUES ( 'Product'[Category] ) , [Category] , ", " ) )
28            VAR __SubCategory = IF ( ISFILTERED ( 'Product'[Subcategory] ) , "Subcategory(s): " & CONCATENATEX ( VALUES ( 'Product'[Subcategory] ) , [Subcategory] , ", " ) )
29            RETURN CONCATENATEX ( FILTER ( UNION ( {__Category} , {__SubCategory} ) , [Value] <> Blank() ) , [Value] , __Delimiter ) 
30        VAR __BreadCrumbTable = 
31         Generate ( /*Categories*/ {"Calendar", "Product" }
32 , ROW ( 
33 "Data" , 
34 SWITCH(
35 TRUE() , 
36 [Value] = "Calendar", __Calendar , 
37 [Value] = "Product" , __Product
38 )
39 )
40 )
41 RETURN CONCATENATEX( FILTER ( __BreadCrumbTable , [Data] <> Blank() ) , [Value] & " [" & [Data] & "] " )
42), [Bread Crumbs] ) 
Bread Crumbs
Calendar [Year(s): FY 2009; Month(s): May, June]

Example 2: User adds the following filters: Category = Computers and Subcategory = Laptops

1DEFINE
2    VAR __FilterYear = TREATAS ( {"FY 2009"} , 'Date'[Fiscal Year] )
3    VAR __FilterMonth = TREATAS ( {"May", "June"} , 'Date'[Fiscal Month] )
4    VAR __FilterDate = TREATAS ( {"2009-05-01"} , 'Date'[Date] )
5    VAR __FilterCategory = TREATAS ( {"Computers"} , 'Product'[Category] )
6    VAR __FilterSubcategory = TREATAS ( {"Laptops"} , 'Product'[Subcategory] )
7    
8EVALUATE 
9SELECTCOLUMNS (
10SUMMARIZECOLUMNS(
11    ------------
12    /*Please ignore; simply selecting a non-relevant single value*/ 'Currency'[Currency] , TREATAS ( {"US Dollar"} , 'Currency'[Currency] )
13    ------------
14    , __FilterYear
15    , __FilterMonth
16    //, __FilterDate
17    , __FilterCategory 
18    , __FilterSubcategory
19    , "Bread Crumbs" ,  
20        VAR __Delimiter = "; "
21        VAR __Calendar = 
22            VAR __Year = IF ( ISFILTERED ( 'Date'[Fiscal Year] ) , "Year(s): " & CONCATENATEX ( VALUES ( 'Date'[Fiscal Year] ) , [Fiscal Year] , ", " ) )
23            VAR __Month = IF ( ISFILTERED ( 'Date'[Fiscal Month] ) , "Month(s): " & CONCATENATEX ( VALUES ( 'Date'[Fiscal Month] ) , [Fiscal Month] , ", " ) )
24            VAR __Date = IF ( ISFILTERED ( 'Date'[Date] ) , "Day(s): " & CONCATENATEX ( VALUES ( 'Date'[Date] ) , [Date] , ", " ) )
25            RETURN CONCATENATEX ( FILTER ( UNION ( {__Year} , {__Month} , {__Date}) , [Value] <> Blank() ) , [Value] , __Delimiter ) 
26        VAR __Product =
27            VAR __Category = IF ( ISFILTERED ( 'Product'[Category] ) , "Category(s): " & CONCATENATEX ( VALUES ( 'Product'[Category] ) , [Category] , ", " ) )
28            VAR __SubCategory = IF ( ISFILTERED ( 'Product'[Subcategory] ) , "Subcategory(s): " & CONCATENATEX ( VALUES ( 'Product'[Subcategory] ) , [Subcategory] , ", " ) )
29            RETURN CONCATENATEX ( FILTER ( UNION ( {__Category} , {__SubCategory} ) , [Value] <> Blank() ) , [Value] , __Delimiter ) 
30        VAR __BreadCrumbTable = 
31         Generate ( /*Categories*/ {"Calendar", "Product" }
32 , ROW ( 
33 "Data" , 
34 SWITCH(
35 TRUE() , 
36 [Value] = "Calendar", __Calendar , 
37 [Value] = "Product" , __Product
38 )
39 )
40 )
41 RETURN CONCATENATEX( FILTER ( __BreadCrumbTable , [Data] <> Blank() ) , [Value] & " [" & [Data] & "] " )
42), [Bread Crumbs] ) 
Bread Crumbs
Calendar [Year(s): FY 2009; Month(s): May, June] Product [Category(s): Computers; Subcategory(s): Laptops]

Conclusion

This breadcrumb pattern provides a robust and adjustable code to dynamically show relevant filters for users exploring reports. This code can easily be adjusted for formatting purposes. Stay connected for any additional updates!

Note: for additional information on robust DAX filter context displays, see the following articles: Displaying filter context in Power BI Tooltips, SQLBI and Displaying a list of selected months, SQLBI.


About the Author:
William Rodriguez is the founder and principal consultant of Analytical Ants, an analytics company focused on procuring insights via data engineering, data science, and data analysis. William has led multi-million-dollar construction projects, acted as financial controller managing million-dollar monthly check productions, and built and deployed BI infrastructures at companies large ($30B Revenue) and ‘small’ ($60M Revenue). Academically, he has his master’s in business, two undergraduate business degrees, four active Microsoft certifications, and over 70 accredited SQLBI training hours. William loves spending time with his amazing family and knows that he would be nowhere without Christ.

Reach out to Analytical Ants LLC for all your data/analytical needs. We specialize in #DataEngineering #DataScience, and #DataAnalysis.

Shopping Cart