In my last post, we looked at creating an IF statement using Power Query. This time we’re going to go a bit deeper and look at a scenario where we need to choose between several options.
The base scenario
In the last post I talked about my billing code setup. As a reminder, it’s a 10 digit code that is constructed as follows:
- Char 1 – Alpha – Indicates the division (G = Golf, F = Fitness, M = Marina)
- Char 2 – Alpha – Indicates the billing type (D = Dues, S = Pass, A = Annual Moorage, P = Periodic Moorage)
- Char 3-4 – Numeric – Indicates the number of months of coverage for the product (1-12)
- Char 5-6 – Numeric – Indicates the start month (and subsequent anniversary) for the customer’s product
- Char 7-8 – Variable – Slip length (in feet) for a boat in the case of marina customers, or SG, CP or CS for golf (indicating single, couple primary or couple spouse)
- Char 9 – Text – A variety of single letter codes indicating specific things we want to know. (Outlined below)
- Char 10 – Text – Indicates the payment method (F = Financed, P = Paid up front, C = Comp/Honorary)
(Note that the sample data only includes records for Marina data)
Sample file
If you’d like to follow along, download the sample file here.
Multi condition logic – Using IF
So, building on my previous two posts (using text functions and creating IF statements), we could easily break the first character into pieces by nesting 2 IF tests together:
=if Text.Start([BillingCode],1)=”G” then “Golf” else “two options left”
=if Text.Start([BillingCode],1)=”F” then “Fitness” else “Marina”
into
if Text.Start([BillingCode],1)=”G” then “Golf” else if Text.Start([BillingCode],1)=”F” then “Fitness” else “Marina”
Not too hard really. In fact, we can even build each IF statement separately, then just copy the second to replace the “two options left” part without making any other changes at all. No parentheses or anything needed.
More than 3 options
But what if you have a whole bunch of options that you need to work with? Let’s look at the 9th character in our billing code. I haven’t given the details yet for that one, but here are the options:
E = Employee, S = Yacht Club, N = Non-Taxable, R = Restricted, I = Inactive, L = Social, M = Medical, U = Regular
Wow. That’s a whole lot of possibilities, and would make for one monster nested IF statement. That wouldn’t be a lot of fun to write, nor maintain. So how would we deal with it?
In Excel proper, we would probably separate these options into a separate table, then use VLOOKUP to pull the appropriate value into the table. So we just need a Power Query VLOOKUP function… except there isn’t one.
We actually have a couple of different methods to deal with this. We could either:
- Split the first character into one column, create an Excel table with the first letter in column 1 and the appropriate match in column 2, then merge the two using Power Query’s merge function. (Maybe I’ll write a future post on it.)
- Build our own CHOOSE function inside Power Query (or SWITCH if you prefer Power Pivot’s DAX version.) This is way more fun, so let’s do that.
Building a CHOOSE function
This actually isn’t too hard once you know the basic structure. It basically goes like this:
function_name = (input) => let
values = {
{result_1, return_value_1},
{input, “Undefined”}
},
Result = List.First(List.Select(values, each _{0}=input)){1}
in
Result,
The key parts to recognize here are:
- We can change the “function_name” part to be whatever we want/need,
- result_1 is the first of the possibilities that we may pass TO the function
- return_value_1 is the value that we’d like to return if the first value is result_1
- if we need more values, we just insert another comma after the value_1 section and put in a value_2 section
- we can keep adding as many values as we need.
- the “Undefined” value will return the text “Undefined” if the value you pass isn’t in your provided list of options (it’s the Else portion of the CHOOSE statement)
Using this structure, we could write a CHOOSE function for our scenario as follows:
fnChoose_CustCode = (input) => let
values = {
{“E”, “Employee”},
{“S”, “SCYC”},
{“N”, “Non-Taxable”},
{“R”, “Restricted”},
{“I”, “Inactive”},
{“L”, “Social”},
{“M”, “Medical”},blah
{“U”, “Regular”},
{input, “Undefined”}
},
Result = List.First(List.Select(values, each _{0}=input)){1}
in
Result,
Notice that I changed a couple of things:
- I gave the function a name so that I can recognize it, and also so that I can create more than one function with different names. This one is fnChoose_CustCode.
- I created a list of all the options I needed.
Implementing the CHOOSE function
Okay, so now we have this, how do we use it? Again, we’ve got two options. I’ll focus on the other option at some other time, but for this scenario I want to build this right into an existing query. So here’s how I do it.
First I created a brand new query that just pulls my table into Power Query, resulting in the following:
Let’s go and inspect the code that pulls this in. We need to click View –> Advanced Editor. That will bring up the following code:
let
Source = Excel.CurrentWorkbook(){[Name="Customers"]}[Content]
in
Source
Not too complicated (yet). Let’s paste in our code just before the Source = line:
let
fnChoose_CustCode = (input) => let
values = {
{“E”, “Employee”},
{“S”, “SCYC”},
{“N”, “Non-Taxable”},
{“R”, “Restricted”},
{“I”, “Inactive”},
{“L”, “Social”},
{“M”, “Medical”},blah
{“U”, “Regular”},
{input, “Undefined”}
},
Result = List.First(List.Select(values, each _{0}=input)){1}
in
Result,Source = Excel.CurrentWorkbook(){[Name="Customers"]}[Content]
in
Source
Perfect. And yet it doesn’t exactly look like much. In fact, beyond adding a new line in the Steps section of the Editor, we don’t see any changes:
So what good did that do then?
As it turns out, we’ve only pasted in our function to make it available to the Power Query engine. We haven’t actually told Power Query to do anything with it. So why don’t we do that now?
Using our new CHOOSE function
You’re going to be amazed how easy this is…
First we’re going to add a new column (Add Column –> Add Custom Column). When the dialog pops up, we’ll create a formula to return the letter we want to pass to the function:
=Text.Range([BillingCode],8,1)
And that gives us the following result (assuming we provided the column name of Status):
Cool stuff. Now, let’s amp this up and use our function. We’ll click the gear next to the Status step and wrap the existing formula with our function call. (Don’t forget the extra parenthesis needed at the end):
=fnChoose_CustCode(Text.Range([BillingCode],8,1))
Which gives us the following:
The end effect
You’ll find that all the sample codes in the data work just fine, and that nothing comes back as undefined. If you’d like to see how the query reacts to different items, go back to the Customers table and try changing the second to last letter to something else. When you refresh the table, you’ll find that it will evaluate the new character and return the appropriate result.
Caveat
It should be noted that the function as written above is case sensitive, meaning that a code of MP010450uP would return “Undefined”. This is expected in my case, as valid codes are made up of upper case letters.
If I wanted to accept either case I would need to modify my Text.Range function to force it to upper case. This would result in a function call that reads as follows:
=fnChoose_CustCode(Text.Upper(Text.Range([BillingCode],8,1)))
Which would work, as you can see here:
The post Power Query – Multi Condition Logic appeared first on The Ken Puls (Excelguru) Blog.