Power BI Conditional Formatting

How to use DAX and modelling to leverage conditional formatting in Power BI

Начать. Это бесплатно
или регистрация c помощью Вашего email-адреса
Power BI Conditional Formatting создатель Mind Map: Power BI Conditional Formatting

1. Visual layering and transparency masks

1.1. I did not have a use case to recreate this but I've captured a few screenshots as it's an interesting concept

1.1.1. The basic idea is that we have a visual that only makes sense when there are n data points available and we want to replace the chart with a warning message when a slicer reduces below a threshold (16 data points in this example)

1.1.1.1. Here's the visual when over threshold

1.1.1.2. Here's the visual when below the threshold

1.1.1.2.1. To achieve the dynamic changes, backgrounds, font colours and the primary visual measure are all subject to conditional expressions

2. Colour theory

2.1. Choosing optimal font colours for particular backgrounds can be automated in Power BI based on colour theory (a mathematical theory)

2.1.1. Colour theory can be implemented in DAX for conditional formatting, so it's useful to have at least a basic idea of what's going on

2.2. Hex codes are 6 digit codes that specify how much red, green and blue light is in a colour

2.2.1. Hex codes can be converted into RGB codes like this:

2.2.1.1. #70A4BC = RGB(112, 164, 188)

2.3. To determine a colour's brightness, you cannot simply average the RGB values

2.3.1. This is partly due to something known as the non linearity of computer screens, which tends to darken midtone colours

2.3.1.1. A number known as the gamma correction constant can be used to adjust the determination of a colour's brightness

2.3.2. Another factor is the spectral sensitivity of the human eye, which tends to see colours in the middle of the spectrum (green, yello, cyan) as brighter than those on the edges (blue, red, purple)

2.3.2.1. This can be adjusted for using numeric weightings of the RGB values

2.4. Another noteworthy feature of hex codes is that there can be an extra pair of digits appended to represent transparency mask

2.4.1. Adding 00 as the 7th and 8th digits to a hex code means that the colour becomes fully transparent

2.4.1.1. This can be used to show and hide visuals in Power BI

3. Saving theme files and importing into semantic model

3.1. We can start by picking a basic theme and saving it

3.1.1. For this demo, we pick the City park theme and the Colorblind safe theme (i.e. saving both theme files on the local machine)

3.2. Next, we load the themes into the Power BI semantic model via Query Editor

3.2.1. We load in each JSON file, add an Index column starting at 1 and then create a new query named Themes that appends the two theme tables

3.2.1.1. Note that the Theme table is full of hex codes representing colours and row uniqueness is determined by the name and Index columns

3.2.1.1.1. Duplicate the dataColors column so there is an extra column named "dataColors - Copy"

3.2.1.1.2. Rename the Themes "name" column to "Theme"

3.2.1.1.3. Disable the load for the individual theme tables, and then Apply & Close to load the consolidated Themes table into the model

4. Creating a table for hex codes

4.1. Add a table and a slicer to a fresh report page canvas

4.1.1. Drag the Theme column onto the slicer and make it single select

4.1.1.1. Drag dataColor and dataColor - Copy onto the table visual

4.1.1.1.1. Set the background colour of the dataColor column in the table

5. Add Dynamic Font Measure and use for dynamic font colours

5.1. This Dynamic Font Measure was developed by an expert in colour theory called Ilmari Karonen

5.1.1. Dynamic Font Colour = // 1. Grab the background colour for the current row VAR selectedColour = SELECTEDVALUE(Themes[dataColors]) // 2. Extract the hexadecimal value for each digit in each colour couplet, and translate to the decimal representation of that value VAR redDig1 = MID(selectedColour, 2, 1) VAR redDig1Number = SWITCH(redDig1,"0",0,"1",1,"2",2,"3",3,"4",4,"5",5,"6",6,"7",7,"8",8,"9",9,"A",10,"B",11,"C",12,"D",13,"E",14,"F",15) VAR redDig2 = MID(selectedColour, 3, 1) VAR redDig2Number = SWITCH(redDig2,"0",0,"1",1,"2",2,"3",3,"4",4,"5",5,"6",6,"7",7,"8",8,"9",9,"A",10,"B",11,"C",12,"D",13,"E",14,"F",15) VAR greenDig1 = MID(selectedColour, 4, 1) VAR greenDig1Number = SWITCH(greenDig1,"0",0,"1",1,"2",2,"3",3,"4",4,"5",5,"6",6,"7",7,"8",8,"9",9,"A",10,"B",11,"C",12,"D",13,"E",14,"F",15) VAR greenDig2 = MID(selectedColour, 5, 1) VAR greenDig2Number = SWITCH(greenDig2,"0",0,"1",1,"2",2,"3",3,"4",4,"5",5,"6",6,"7",7,"8",8,"9",9,"A",10,"B",11,"C",12,"D",13,"E",14,"F",15) VAR blueDig1 = MID(selectedColour, 6, 1) VAR blueDig1Number = SWITCH(blueDig1,"0",0,"1",1,"2",2,"3",3,"4",4,"5",5,"6",6,"7",7,"8",8,"9",9,"A",10,"B",11,"C",12,"D",13,"E",14,"F",15) VAR blueDig2 = MID(selectedColour, 7, 1) VAR blueDig2Number = SWITCH(blueDig2,"0",0,"1",1,"2",2,"3",3,"4",4,"5",5,"6",6,"7",7,"8",8,"9",9,"A",10,"B",11,"C",12,"D",13,"E",14,"F",15) // 3. Assign the value of the Gamma exponent VAR gamma = 2.2 // 4. Calculate the RGB values and normalize VAR redNumber = ((redDig1Number * 16) + redDig2Number) / 255 VAR greenNumber = ((greenDig1Number * 16) + greenDig2Number) / 255 VAR blueNumber = ((blueDig1Number * 16) + blueDig2Number) / 255 // 5. Apply calculation as per Stack Exchange answer VAR luminance = (0.2126 * POWER(redNumber, gamma)) + (0.7152 * POWER(greenNumber, gamma)) + (0.0722 * POWER(blueNumber, gamma)) // 6. If the luminance is greater than 0.5, return "Black". Else return "White". RETURN IF(luminance > 0.5, "Black", "White")

5.1.1.1. Use this to apply conditional formatting to the font colour of the [dataColors - Copy] column

5.1.1.1.1. Now we can see the contrast in font colours, with the [dataColors - Copy] column going white or black depending on background

6. Add custom icons to theme files

6.1. The theme files we export from Power BI Desktop are pretty basic but we can add custom sections to it.

6.1.1. First create an icons template section in your theme file, right below the "name" property

6.1.1.1. In this example, we're going to add 3 custom icons to represent positive, negative and neutral sentiment in our reports

6.2. There are built in icons available in Power BI but the choice is limited, and there are millions of freely available icons at sites like flaticon.com

6.2.1. To demonstrate the process, we can go to www.flaticon.com and search for "cloudy weather", "stormy weather" and "sunny weather", choose associated icons and download these

6.2.1.1. Note that to make use of these in websites, you have to give attribution to the content creators

6.2.1.1.1. Weather icons created by iconixar - Flaticon

6.2.1.1.2. Storm icons created by Freepik - Flaticon

6.2.1.1.3. Weather icons created by Freepik - Flaticon

6.3. In order to use custom icons in our Power BI theme, we must convert them to Base 64 format

6.3.1. A good site for this is www.base64-image.de

6.3.1.1. Upload the icon files and click the "copy image" buttons

6.3.1.1.1. Paste these into the theme file under the "url" attribute

6.4. To use the custom icons, we need to import the custom theme into our report, using Power BI Desktop

6.4.1. Go to the View menu, expand themes and click "Browse for themes"

6.4.1.1. Select the custom theme file and click to import it; all being well you should get a confirmation message

6.5. Having imported the custom theme, we have access to the custom icons and can use these to add conditional formatting

6.5.1. Pick some measure in a visual that you want to add icons to, then click Conditional formatting > Icons

6.5.1.1. We can set up rules, using the new icons

6.5.1.1.1. And now we can see the custom icons in our report

6.6. Rather than settling for the built-in conditional formatting rules for the custom icons, we can get a more flexible solution using DAX

6.6.1. As a pre requisite for this solution, we need to import our custom theme file using Query Editor so that a transformed version pertaining to the icons becomes available in the model for the DAX to reference

6.6.1.1. After an initial import of the JSON file, a certain amount of transformation will be done for us, but we must follow that with a series of further steps

6.6.1.1.1. 1. Remove all columns apart from the name and the icons columns

6.6.1.1.2. 2. Select all the icons columns and choose "Unpivot columns"

6.6.1.1.3. 3. Choose "Remove rows" | "Remove duplicates"

6.6.1.1.4. 4. Select Attribute column and choose "Split column" | "By delimiter"

6.6.1.1.5. 5. Delete the Attribute.1 and Attribute.3 columns, leaving just Attribute.2 (the incon name)

6.6.1.1.6. 6. "Add Column" | "Index column" | "From 0"

6.6.1.1.7. 7. With new Index columns selected, choose "Transform" | "Standard" | "Modulo" and then enter "2" for the value

6.6.1.1.8. 8. With the modulo index column selected, choose "Transform" | "Pivot column" and select "Value" as the Values column

6.6.1.1.9. 9. Rename columns to "Theme", "Icon Name", "Sentiment" and "Icon URL"

6.6.1.1.10. 10. Rename the table to "Icons" and then Close & Apply to load this into our model

6.6.2. Now we can add measures for custom icon display using DAX, such as the following example:

6.6.2.1. Sales Quarterly Diff Icon Field Value = VAR Icon = SWITCH( TRUE(), [Total Sales Increase/Decrease From Last Quarter] >= 50000, CALCULATE( MAX( 'Icons'[Icon URL] ), 'Icons'[Sentiment] = "Positive" ), [Total Sales Increase/Decrease From Last Quarter] >= 0, CALCULATE( MAX( 'Icons'[Icon URL] ), 'Icons'[Sentiment] = "Neutral" ), CALCULATE( MAX( 'Icons'[Icon URL] ), 'Icons'[Sentiment] = "Negative" ) ) VAR Result = IF( HASONEVALUE( 'Dates'[Date] ), Icon, BLANK() ) RETURN Result

6.6.2.1.1. Note that the HASONEVALUE use is just to avoid an icon being added to the Totals for the measure, and the value passed into it will depend on the table visual you are putting your measure into

6.6.2.1.2. Before dragging the measure onto our table visual, we need to set its data category to image URL

6.6.3. Although we can achieve the same thing via conditional formatting rules in this example, we can imagine how much more sophisticated we can make the logic using this DAX method, so it's worth the extra effort

6.6.3.1. We also get the flexibility of varying the image sizes