DAX Logic and Blanks

A while back I was chatting with Shannon Lindsay on Twitter. She shares lots of useful Power BI tips there. She shared her syntax tip of the & operator being used for concatenation and the && operator being used for boolean AND, which reminded me about implicit conversions and blanks in DAX.

Before you read the below tweet, see how many of these you can guess correctly:

Blank + 5 = ? 
Blank * 5 = ?
5 / Blank = ?
0 / Blank = ?

In DAX, Blank is converted to 0 in addition and subtraction.

What about boolean logic? Do you know the result of the following expressions?

AND(True(), Blank()) = ? 
OR(True(), Blank()) = ? 
AND(False(), Blank()) = ? 
AND(Blank(), Blank()) = ? 

You can see the results as well as a few more permutations in the screenshot below.

Two tables in a Power BI report. The left table shows arithmetic operations involving blanks. For example, Blank + Blank = Blank, 0 * Blank = NaN, 5 * Blank = Blank, 5 / Blank = Infinity. The right table shows boolean operations involving blanks. True and blank = false, true or blank = true, false and blank = false, blank or blank = false
Read the left table as Number1 [operator] Number2, so 5 + Blank = 5. 5 * Blank = Blank. And 5 / Blank = Infinity. Read the right table as Bool1 [operator] Bool2, so True AND Blank = False and True OR Blank = True.

Why does this matter?

You need to understand the impact of blanks in your data. Do you really want to divide by zero when you are missing data? If you are performing a boolean AND, and your data is blank, are you ok with showing a result of False? Remember that your expression may produce undesired results rather than an error.

First, you need to be aware of where it is possible in your data to get a blank input. When you are writing your DAX measures, you may need to handle blanks. DAX offers the IFERROR() function to check if the result of an expression throws an error. There is also an ISBLANK() function that you can use to check for a blank value and a COALESCE() function to provide an alternate value when a blank value is detected.

But adding extra logic in your measures may have a performance impact. For example, the DIVIDE() function can handle divide by zero errors for you. But DIVIDE() may be slower than the / operator. The performance difference is highly dependent on your data. Alternatively, you can use an IF statement to check if an input value is greater than zero using the > operand. This can be quicker than checking for blanks or errors using other functions.

At the end of the day, producing the correct result is more important than fast performance, but we strive to achieve both. If you have any tips for handling blanks in DAX, please share them in the comments.

Contact the Author | Contact DCAC

Stop Letting Accessibility Be Optional In Your Power BI Reports

We don’t talk about inclusive design nearly enough in the Power BI community. I was trying to recall the last time I saw a demo report (from Microsoft or the community) that looked like consideration was made for basic accessibility, and… it’s a pretty rare occurrence.

A woman, man, and another man in a wheelchair next to the Power BI logo.

Part of the reason for this might be that accessibility was added into Power BI after the fact, with keyboard accessible visual interactions being added in 2019 as one of the last big accessibility improvements. But I think the more likely reasons are that inclusive design requires empathy and understanding of how to build reports for people who work differently than ourselves, and Power BI accessibility features take time and effort to implement. While we can never make our reports 100% accessible for everyone, that doesn’t mean we should just not try for anyone.

Population statistics tell us that many of our colleagues have or will have a disability at some point, and many of them will be invisible. So even if you don’t see a report consumer with an obvious disability today, that doesn’t mean an existing user won’t acquire a disability or a new user with a disability won’t come along as people change roles in an organization. In addition to the permanent disabilities we normally think of, there are also temporary and situational disabilities that we should try to accommodate.

In order to start designing more inclusively, we need to increase conversation around accessibility requirements and standards for our reports. I fully understand that it can feel tedious or confusing as you get started. I hope that as Power BI matures, the accessibility features will mature as well to make it even easier to create a more accessible report by default. For now, the only way to make accessible Power BI report design easier for report creators is for us to start forming accessible design habits and to offer feedback to the Power BI team along the way.

My Accessible Report Design Proposal

This is what I would like to see from report creators in the community as well as within Microsoft. I’ll define what I mean by accessible report design in the next section.

  • Before publishing a report, implement accessible design techniques as thoroughly as possible.
  • For demonstrations of report design/UI techniques where you are providing a finished product at the end, implement accessible design techniques as thoroughly as possible.
  • For demonstrations of things that are not inherently visual, implement bare minimum accessibility or add a disclaimer to the report.
    Example: “Here’s a cool DAX technique that I just threw into a quick table or bar chart to show you the results. It hasn’t been cleaned up and made accessible (alt text, color contrast, etc.), but I would do that before publishing.”
  • For demonstrations of report design/UI techniques where you show only part of the process, implement bare minimum accessibility or add a disclaimer to the report. 
    Example: “This is the part of the report creation process about creating bookmarks, and before I publish to an audience, I want to make sure I’m following good design practices including accessibility.”

Power BI Report Accessibility

I have a full list of things to check here. That is the checklist that I use to ensure my report designs are generally accessible, when I have no specific compliance requirements or knowledge or any specific disabilities that need to be accommodated. In my opinion, this is what we should be doing in all of our reports because we want everyone in our intended audience to be able use our reports. You’ll find a very similar checklist on Microsoft Docs.

If you need to start smaller, you can go with my bare minimum accessibility and work your way up to the full list.

Bare Minimum Accessibility

This is the short list of the most impactful (according to me) accessibility changes you can make in your report. Use this because you have to start somewhere, but realize there is more we should be doing.

  1. Ensure text and visual components have sufficient color contrast
  2. Use descriptive, purposeful chart titles
  3. Avoid using color as the only means of conveying information
  4. Set tab order on all visuals in each page
  5. Remove unnecessary jargon and acronyms from all charts

Give It a Try

I just learned that the Power BI Community Featured Data Stories Gallery theme for September is Accessibility. So here’s your chance to win a free t-shirt and internet bragging rights by showing off your accessible design skills. You need to submit your report to the Data Stories Gallery by September 30th in order for your submission to be considered. But a well designed, accessible Power BI report added to the gallery is appreciated any time of year!

Contact the Author | Contact DCAC

Fun with Power BI and Color Math

I recently published my color contrast report in the Power BI Data Stories Gallery. It allows you to enter two hex color values and then see the color contrast ratio and get advice on how the two colors should be used together in an accessible manner.

Screenshot of the Color Contrast calculator Power BI report. The report headline reads "How shoudl I use these colors together in my Power BI report?". There are 2 slicers that allow you to select colors by hex value. A contrast ratio is shown along with advice generated on how to use the colors.
Color contrast calculations in a Power BI report

I could go on for paragraphs about making sure your report designs are accessible and useful for your intended audience. But this post focuses on how I made this report.

The Calculations

Color contrast (as calculated in the WCAG 2.1 success criteria) is dependent on luminance. Luminance is the relative brightness of any point in a color space, normalized to 0 for darkest black and 1 for lightest white. In order to calculate color contrast you must first get the luminance of each color.

As an example, I have colors #F3F2F1 and #007E97. In this hex notation, often explained as #RRGGBB, the first two digits represent red, the second two digits are green, and the last two digits are blue. Each two digits is a value that represents the decimal numbers 0 to 255 in hexadecimal notation. The same red, green, and blue values can be represented in decimal notation as integers, and this is what is used to calculate luminance. #F3F2F1 is RGB(243, 242, 241), and #007E97 is RGB(0,126,151).

On a side note, there are places in Power BI where we can change the transparency of the color which is referred to as RGBA (where A represents opacity/transparency). But whenever you copy a hex color value out of the color palette in Power BI, you will just see the 6 digits without the A because the A is stored separately in the UI. When you set colors using DAX formulas, you can specify the A value.

The sRGB color space is non-linear. It compensates for humans’ non-linear perception of light and color. If images are not gamma-encoded, they assign too many bits or too much bandwidth to highlights that humans can’t distinguish, and too few bits to shadows to which humans are sensitive and would require more bits to maintain the same visual quality. To calculate luminance we have to linearize the color values.

For each color component (R,G,and B), we first divide our integer value by 255 to get a decimal value between 0 and 1. Then we apply the linearization formula:

  • if R sRGB <= 0.03928 then R = R sRGB /12.92 else R = ((R sRGB +0.055)/1.055) ^ 2.4
  • if G sRGB <= 0.03928 then G = G sRGB /12.92 else G = ((G sRGB +0.055)/1.055) ^ 2.4
  • if B sRGB <= 0.03928 then B = B sRGB /12.92 else B = ((B sRGB +0.055)/1.055) ^ 2.4

Then we plug those values in to calculate luminance:

L = 0.2126 * R + 0.7152 * G + 0.0722 * B

The luminance of #F3F2F1 is .8891. The luminance of #007E97 is .1716.

The final calculation is color contrast:

(L1 + 0.05) / (L2 + 0.05), where

  • L1 is the relative luminance of the lighter of the foreground or background colors, and
  • L2 is the relative luminance of the darker of the foreground or background colors.

The color contrast between #F3F2F1 and #007E97 is 4.24, and we usually write this as 4.24:1. You can check my math here.

The Dataset

The source data for the report is generated entirely in Power Query. It starts with a simple list of the integers 0 through 255. I placed this in a query called Values.

let
    Source = List.Numbers(0,256),
    #"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Changed Type" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", Int64.Type}})
in
    #"Changed Type"

My linearization function is called ColorConvert.

(colornum as number) =>
let 
    Source = if colornum < .04045 then colornum/12.92 else  Number.Power(((colornum+0.055)/1.055),2.4)
in
    Source

My main query is called color 1. This is where all the calculations through luminance are done.

let
    //Get values 0 - 255
    Source = Values,
    //Call that column R for Red
    #"R Dec" = Table.RenameColumns(Source,{{"Column1", "R Dec"}}),
    //Crossjoin to Values to get Green values 0 - 255
    #"G Dec" = Table.AddColumn(#"R Dec", "Custom", each Values),
    #"Expanded G Dec" = Table.ExpandTableColumn(#"G Dec", "Custom", {"Column1"}, {"G Dec"}),
    //Crossjoin to Values to get Blue values 0 - 255
    #"B Dec" = Table.AddColumn(#"Expanded G Dec", "B", each Values),
    #"Expanded B Dec" = Table.ExpandTableColumn(#"B Dec", "B", {"Column1"}, {"B Dec"}),
    //Get hexidecimal values for R,G,B
    #"R Hex" = Table.AddColumn(#"Expanded B Dec", "R Hex", each Text.End("00" & Number.ToText([R Dec], "x"),2)),
    #"G Hex" = Table.AddColumn(#"R Hex", "G Hex", each Text.End("00" & Number.ToText([G Dec], "x"),2)),
    #"B Hex" = Table.AddColumn(#"G Hex", "B Hex", each Text.End("00" & Number.ToText([B Dec], "x"),2)),
    //Concatenate to get full 6-digit Hex color value
    #"Changed Hex Type" = Table.TransformColumnTypes(#"B Hex",{{"R Hex", type text}, {"G Hex", type text}, {"B Hex", type text}}),
    #"Full Hex" = Table.AddColumn(#"Changed Hex Type", "Hex", each [R Hex] & [G Hex] & [B Hex]),
    //Convert integers to decimals and linearize
    #"R Lin" = Table.AddColumn(#"Full Hex", "R Lin", each ColorConvert(([R Dec]/255))),
    #"G Lin" = Table.AddColumn(#"R Lin", "G Lin", each ColorConvert(([G Dec]/255))),
    #"B Lin" = Table.AddColumn(#"G Lin", "B Lin", each ColorConvert(([B Dec]/255))),
    //Calculate luminance with the linearized values
    #"Luminance" = Table.AddColumn(#"B Lin", "Luminance", each 0.2126 * [R Lin] + 0.7152 * [G Lin] + 0.0722 * [B Lin]),
    #"Changed Luminance Type" = Table.TransformColumnTypes(#"Luminance",{{"Luminance", type number}}),
    //Create a column for hexidecimal value with the hash/pound at the beginning
    #"Hex Dup" = Table.DuplicateColumn(#"Changed Luminance Type", "Hex", "Hex With Hash"),
    #"Hex with Hash" = Table.TransformColumns(#"Hex Dup", {{"Hex With Hash", each "#" & _, type text}}),
    //Remove Hex and linearized RGB columns to keep model under 1 GB limit for Pro license
    #"Removed Columns" = Table.RemoveColumns(#"Hex with Hash",{"R Hex", "G Hex", "B Hex", "R Lin", "G Lin", "B Lin", "Hex"}),
    //Rename Hex with Hash to Hex
    #"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Hex With Hash", "Hex"}})
in
    #"Renamed Columns"

In order to allow users to choose two colors, I made a reference query to Color 1 called Color 2.

let
    Source = #"Color 1"
in
    Source

If you are interested in these Power Query scripts, you can get them from this Gist.

DAX Calculations

The color contrast calculation is a DAX measure because it is dynamically calculated based upon the colors selected in the report.

Color Contrast = 
If( Max('Color 1'[Luminance]) > MAX('Color 2'[Luminance]),
    Divide((Max('Color 1'[Luminance]) + 0.05) , (Max('Color 2'[Luminance]) + 0.05)),
    Divide((Max('Color 2'[Luminance]) + 0.05) , (Max('Color 1'[Luminance]) + 0.05))
)

The advice given based upon the color contrast ratio is also a DAX measure.

Advice =
IF (
    [Color Contrast] < 3,
    "Not enough contrast for text or non-text content, use only for decorative items",
    IF (
        [Color Contrast] < 4.5,
        "Appropriate for large text at least 18pt, bold text at least 14 pt, or non-text content",
        IF (
            'Color 1'[Color Contrast] >= 4.5,
            "Appropriate for any size text and any non-text content"
        )
    )
)

The example charts showing the two colors as foreground and background are SVG measures.

Chart 1 =
VAR Bkgrnd =
    MAX ( 'Color 1'[Hex] )
VAR Frgrnd =
    MAX ( 'Color 2'[Hex] )
VAR chart = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 24 24' style='background-color:" & Bkgrnd & "'><path fill= '" & Frgrnd & "' d='M7 19h-6v-11h6v11zm8-18h-6v18h6v-18zm8 11h-6v7h6v-7zm1 9h-24v2h24v-2z'/></svg>"
RETURN
    chart
Chart 2 =
VAR Bkgrnd =
    MAX ( 'Color 2'[Hex] )
VAR Frgrnd =
    MAX ( 'Color 1'[Hex] )
VAR chart = "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 24 24' style='background-color:" & Bkgrnd & "'><path fill= '" & Frgrnd & "' d='M7 19h-6v-11h6v11zm8-18h-6v18h6v-18zm8 11h-6v7h6v-7zm1 9h-24v2h24v-2z'/></svg>"
RETURN
    chart

The check or x mark to indicate whether the colors can be used together in a graph or in text is created using Unicode characters.

UseInGraph =
IF ( [Color Contrast] < 3, "✗", "✔" )
UseInText =
IF ( [Color Contrast] < 4.5, "✗", "✔" )

The RGB value shown for each color in the report is a DAX measure because storing it in the model made the model size larger than 1 GB, which would have prohibited me from deploying the report and publishing it to the web.

RGB1 =
VAR R =
    SELECTEDVALUE ( 'Color 1'[R Dec] )
VAR G =
    SELECTEDVALUE ( 'Color 1'[G Dec] )
VAR B =
    SELECTEDVALUE ( 'Color 1'[B Dec] )
RETURN
    R & "," & G & "," & B

Check Out the Report

This post was an enjoyable combination of color, Power BI, and a bit of math. It was fun to make the report since it brought together my interests in accessibility and Power BI model optimization. At the least I’m hoping this gives you some exposure to how accessibility guidelines are applied to reports. If you are like me, you’ll find the color math fascinating and go down that rabbit hole.

Take a few seconds, pick some colors, and give the report a try.

Contact the Author | Contact DCAC

I’m Speaking at Virtual PASS Summit 2020

PASS Summit has gone virtual this year, but that isn’t keeping PASS from delivering a good lineup of speakers and activities. I’m excited to be presenting a pre-con and two regular sessions this year. I know virtual delivery changes the interaction between audience and speaker, and I’m going to do everything I can to make my sessions more than just standard lecture and demo to keep things interesting.

Building Power BI Reports that Communicate Insights and Engage People (Pre-Con)

If you are into Power BI or data visualization, check out my pre-con session. It’s called Building Power BI Reports that Communicate Insights and Engage People. Unless we’ve had data visualization training, the way we learn to make reports is by copying reports that others have made. But that assumes other people were designing intentionally for human consumption. Another issue is that we often mimic example reports from tool vendors. That can be very helpful with the technical aspects of getting content on the page, but we often overlook the design aspects of reports that can make or break their usability and effectiveness in communicating information. My pre-con will begin with discussion on how humans interpret data visualizations and how you can use that to your advantage to make better, more consumable visualizations. We’ll take those lessons and apply them specifically to Power BI and then add on some tips and tricks. Throughout the day, there will be hands-on exercises and opportunities for group conversation. And you’ll receive some resources to take with you to help you continue to improve your report designs.

Agenda slide from my pre-con session: 1) Defining Success, 2) Message & Story, 3) Designing a Visual, 4) Refine Your Report 5) Applied Power BI 6) Power BI Tricks 7) Wrap-Up
Agenda for my PASS Summit pre-con titled Building Power BI Reports that Communicate Insights and Engage People

This session is geared toward people that have at least basic familiarity with Power BI Desktop (if you can populate a bar chart on a report page, that’s good enough). If you have never opened Power BI Desktop, we might move a little fast, but you are welcome to join us and give it a try. If you are pretty good with Power BI Desktop, but you want to improve your data visualization skills, this session could also be a good fit for you. I hope you’ll register and join my pre-con.

Implementing Data-Driven Storytelling Techniques in Power BI

Data storytelling is a popular concept, but the techniques to implement storytelling in Power BI can be a bit elusive, especially when you have data values that change as the data is refreshed. In this session, we’ll talk about what is meant by story. Then I’ll introduce you to tool-agnostic techniques for data storytelling and show you how you can use them in Power BI. We’ll also discuss the visual hierarchy within a page and how that affects your story. You can view my session description here.

Inclusive Presentation Design

I’m also delivering a professional development session for those of us that give presentations. Most speakers have good intentions and are excited to share their knowledge and perspective, but we often exclude audience members with our presentation design. Join me in this session to discuss how to design your presentation materials with appropriate content formatted to maximize learning for your whole audience. You’ll gain a better understanding of how to enhance your delivery to make an impact on those with varying abilities to see, hear, and understand your presentation. You can view my presentation description here.

Other Pre-Cons from My Brilliant Co-Workers

If you aren’t into report design, my DCAC coworkers are delivering pre-cons that may interest you.

Denny Cherry is doing a pre-con session on Microsoft Azure Platform Infrastructure.

John Morehouse is talking about Avoiding the Storms When Migrating to Azure.

I hope you’ll join one of us for a pre-con as well as our regular sessions. With PASS Summit being virtual, the lower price and removal of travel requirements may make this conference more accessible to some who haven’t been able to attend in past years. Be sure to get yourself registered and spread the word to colleagues.

Contact the Author | Contact DCAC
1 2 3

Video

Globally Recognized Expertise

As Microsoft MVP’s and Partners as well as VMware experts, we are summoned by companies all over the world to fine-tune and problem-solve the most difficult architecture, infrastructure and network challenges.

And sometimes we’re asked to share what we did, at events like Microsoft’s PASS Summit 2015.

Awards & Certifications

Microsoft Partner   Denny Cherry & Associates Consulting LLC BBB Business Review    Microsoft MVP    Microsoft Certified Master VMWare vExpert
INC 5000 Award for 2020    American Business Awards People's Choice    American Business Awards Gold Award    American Business Awards Silver Award    FT Americas’ Fastest Growing Companies 2020   
Best Full-Service Cloud Technology Consulting Company       Insights Sccess Award    Technology Headlines Award    Golden Bridge Gold Award    CIO Review Top 20 Azure Solutions Providers