powerquerypowerbi-desktop

PowerQuery Syntax: Dynamically populating rows based on text match with column header


I am trying to populate columns with a True/False Value. If a field has a value that matches the column Header it is true, if not it is false or null.

I need to cycle through the values in the field: e.g. POWERAPPS_VIRAL, POWERAPPS_INDIVIDUAL_USER, SPE_F5_SECCOMP, SPE_F1, POWER_BI_STANDARD and 'tick' each column where the header is the same as a given value in the description. Note: The values are not ordered, so I must parse the field rather than just expand it.

Thus far I have only been able to return cartesian product and have been unable to parse the description field uniquely.

Here's an example of the output I am getting, all row values apart from License Details start off as nulls. (Note: there are around 50 possible values and I have not included them all):

License Details DYN365_BUSCENTRAL_ESSENTIAL_ISVEMB DYN365_ENTERPRISE_CUSTOMER_SERVICE DYN365_ENTERPRISE_FIELD_SERVICE DYN365_FINANCE DYN365_HUMAN_RESOURCES_ATTACH DYN365_PROJECT_OPERATIONS_ATTACH DYN365_SCM DYN365_SCM_ATTACH Dynamics_365_Field_Service_Enterprise_viral_trial
D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE, DYN365_SCM_ATTACH [List] [List] [List] [List] [List] [List] [List] [List] [List]
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_SCM_ATTACH, [List] [List] [List] [List] [List] [List] [List] [List] [List]
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE, DYN365_SCM_ATTACH [List] [List] [List] [List] [List] [List] [List] [List] [List]
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE [List] [List] [List] [List] [List] [List] [List] [List] [List]
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE [List] [List] [List] [List] [List] [List] [List] [List] [List]

The only bit of code I have managed to get half working is as follows (it produces the result above, where List is populated with all the column values):

let
    Source = ExpandedUserTable,
    _Lookups = List.Buffer(Table.ColumnNames(LicenceLookUpFinal)),
// LicenceLookUpFinal is the result of scanning a file to produce a row for every unique Licence type in Licence Description
 
   #"Replaced Value" = Table.ReplaceValue(
        Source,
        null,
        _Lookups,
        Replacer.ReplaceValue, _Lookups 
    )
in
    #"Replaced Value"

(excuse the idiosyncratic indentation but anything else kicks of my ADHD) which shows the result above.

What I'm trying to get to is this (example with not all possible columns appearing):

License Details DYN365_BUSCENTRAL_ESSENTIAL_ISVEMB DYN365_ENTERPRISE_CUSTOMER_SERVICE DYN365_ENTERPRISE_FIELD_SERVICE DYN365_FINANCE DYN365_HUMAN_RESOURCES_ATTACH DYN365_PROJECT_OPERATIONS_ATTACH DYN365_SCM DYN365_SCM_ATTACH Dynamics_365_Field_Service_Enterprise_viral_trial
D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE, DYN365_SCM_ATTACH Null Null Null Y Null Null Null Y Null
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_SCM_ATTACH, Null Null Null Null Null Null Null Null Null
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE, DYN365_SCM_ATTACH Null Null Null Y Null Null Null Y Null
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE Null Null Null Null Null Null Null Null Null
D365_CUSTOMER_SERVICE_ENT_ATTACH, D365_FIELD_SERVICE_ATTACH, DYN365_FINANCE Null Null Null Y Null Null Null Null Null

I have tried introducing 'each' into the statement, but after I remove any syntax errors I get a bewildering set of run time error codes. Like: 'We cannot apply an index of type List', or I am supplying too many arguments to a function.

After hours of trying to resolve, I am wondering: a) Is this possible at all? b) Am I approaching the problem from the right direction (I am a self-taught early-intermediate in Powerquery - so this is definitely an option)


Solution

  • I am assuming that your raw data starts with just the first column of what you have posted:
    enter image description here

    If that is the case, this code should produce your desired output:

    let
        Source = Excel.CurrentWorkbook(){[Name="Table2"]}[Content],
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"License Details", type text}}),
        #"Trim Commas" = Table.TransformColumns(#"Changed Type", {"License Details", each Text.Trim(_,",")}),
        #"Remove Spaces" = Table.ReplaceValue(#"Trim Commas"," ","",Replacer.ReplaceText,{"License Details"}),
     
        //create unique list of Licenses
        #"License List" = 
            List.Distinct(
                List.Combine(
                    List.Transform(#"Remove Spaces"[License Details], 
                        each Text.Split(_,",")))),
                   
    
    //add a column for each License type 
        #"Add Columns" = List.Accumulate(
            #"License List",
            #"Remove Spaces",
            (s,c)=> Table.AddColumn(s, c,each null, type nullable text)),
        
    //Add ticks to appropriate column if License exists in the first column
        #"Add Ticks" = List.Accumulate(
            List.Numbers(0, List.Count(#"License List")),
            #"Add Columns",
            (s,c)=> 
                Table.ReplaceValue(
                s,
                each [License Details],
                Character.FromNumber(Expression.Evaluate("0x2714")),
                (x,y,z) as nullable text=> if List.Contains(Text.Split(Text.Remove(y," ")  ,","),#"License List"{c}) then z else x   ,
                {#"License List"{c}})
            )
    in
        #"Add Ticks"
    

    enter image description here

    Note that the License Details column of the final table is the "cleaned up" version where the spaces and leading/trailing commas have been removed. If you require the original column, a few lines of code could be added or changed