Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
6 years ago
Solved

Hierarchy Transformations - Level to Title

To the experts.. I'm having some trouble conceptualizing my Power Query transformation steps for the current challenge I have. I have a table that list a project, with an employee that's responsible for the project and then their tiered-leaders (Leader #1, Leader#2, etc). The tiering table includes names and titles.

What I need though is to transform that tiered table into a table that shows the projects with its responsible person and then their leaders by TITLE, not position number. I know there will be some form of any or all of PIVOT, UNPIVOT, TRANSPOSE, and the like, I just can't quite get my head around the steps. Attached is a snapshot of my initial table on top and my desired end result. Any help would be greatly appreciated.

PS: if it wasn't clear, I want to do these transformations strictly in M Code (Power Query).

Thank you in advance,
-Nate

ProjectPersonPerson IDLEADER 1 NameLEADER 1 IDLEADER 1 TitleLEADER 2 NameLEADER 2 IDLEADER 2 TitleLEADER 3 NameLEADER 3 IDLEADER 3 TitleLEADER 4 NameLEADER 4 IDLEADER 4 Title
T555555Joe1234John2345DirectorJim3456Vice PresidentJill4567PresidentJeff5678CEO
T777777Paul4321Carl5432SupervisorGabe6543ManagerJose7654DirectorTodd8765Vice President
T999999Joe7408Jack8519ManagerStacey9630DirectorLindsay10741Vice PresidentLauren11852President
T122222Bill10495Sandy11606DirectorDoug12717Vice PresidentLandon13828PresidentJoseph14939CEO
               
               
   Title Title Title Title Title Title 
ProjectPersonPerson IDSupervisorSupervisorIDManagerManagerIDDirectorDirectorIDVice PresidentVice PresidentIDPresidentPresidentIDCEOCEOID
T555555Joe1234    John2345Jim3456Jill4567Jeff5678
T777777Paul4321Carl5432Gabe6543Jose7654Todd8765    
T999999Joe7408  Jack8519Stacey9630Lindsay10741Lauren11852  
T122222Bill10495    Sandy11606Doug12717Landon13828Joseph14939
  • Anonymous's avatar
    Anonymous
    6 years ago

    UPDATE: After doing some transformation to get my titles normalized, like I showed in the example, I solved this by just creating custom columns for each title looking at all of the leaders titles and placing their name in the proper column if their normalized title matched the column title I needed. Here are some advanced editor examples... pretty easy in reality.

     

     Director = Table.AddColumn(VP, "DIRECTOR", each if [#"SUP_1_TITLE-Groomed"] = "DIRECTOR" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "DIRECTOR" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "DIRECTOR" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "DIRECTOR" then [SUP_4_Name] else "TBD"),
     
    Manager = Table.AddColumn(Director, "MANAGER", each if [#"SUP_1_TITLE-Groomed"] = "MANAGER" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "MANAGER" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "MANAGER" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "MANAGER" then [SUP_4_Name] else "TBD"),

     

  • Anonymous 

    try this:

    let
        Source = Table.FromRecords(Json.Document(Binary.Decompress(Binary.FromText("hdRPb4IwGAbwr0J69kDLn4K3TcyyhW1kml3MDh1UZcPWFFhiln33FRaxllfXm09eH82P8q6+UabkB88bNEXLoD9ogjKuail09CD58NG5T9AUE8+foHR+k8xfHOw8sR3vx7YCGXE3qQcDI1qWTdWNJqXSvybVaZwMLeXOTLsS3REa0bHktcy5kylelwUXzelL3qmqqsy469JV1IiOXUCNP9Tw9dqMuxrdEhnRsWY2f0Y/kzNO2h+TM2Ntde7pewSPPWdMVbZnoEcBz0W75+qrrEHRO/bObdJQFwGkj0ywDVeQpay5bUl1C2A5frgD5VIWhU0Z6RqA0nq6lmrcn6uXlPpuBFxSln/aqFGAYwB1hDGILhqW84NtGoeeC5iOOQbUtBRFzQ62K3apjwHYSxd+4E1Zq7iwgTGOAgIIX8TFpDsm7u3fm2SuANePgzHvgoniYPtiHLohAHxlCySy3di+mFBMAeB/90Cq/5QUI2UvIhGgfHUV6Ldgvx0B+7EXA8D9Nnj7BQ==", BinaryEncoding.Base64),Compression.Deflate))),
        fd = Table.ColumnNames(Source),
       
        fx = (rec)=>
             let fnField = (txt)=> Record.Field(rec, List.Select(Record.FieldNames(rec), each Text.EndsWith(_, txt)){0})
             in  Record.AddField(Record.AddField([],fnField("Title"),fnField("Name")),fnField("Title")&"ID",fnField("ID")),
             
        recs = Table.TransformRows(
                  Source, 
                  (r)=> Record.SelectFields(r, List.FirstN(fd,3))&
                        Record.Combine(List.Transform(List.Split(List.Skip(fd,3),3), each fx(Record.SelectFields(r, _))))),
        toTbl = Table.FromRecords(recs, Record.FieldNames(Record.Combine(recs)), 2),
        ref_order = {"S", "M", "D", "V", "P", "C"},
        nfd = List.Sort(
                 List.Skip(Table.ColumnNames(toTbl), 3), 
                 {{each List.PositionOf(ref_order, _, 0, (x,y)=>Text.StartsWith(y,x)), 0}, {Text.Length, 0}}
              ),
        result = Table.ReorderColumns(toTbl, nfd)
    in
        result

7 Replies

  • ziying35's avatar
    ziying35
    Impactful Individual

    Hi, Anonymous 

    Your problem shouldn't be too hard to solve, but I'm too slow to get this data into the table from the screenshot you provided. Can you upload your example table to the cloud, and then share the link here?

    • Anonymous's avatar
      Anonymous
      Not applicable

      Thank you for your response. I added the table-concepts to the post. I think they can be copy and pasted from there

       

  • Anonymous's avatar
    Anonymous
    Not applicable

    UPDATE: After doing some transformation to get my titles normalized, like I showed in the example, I solved this by just creating custom columns for each title looking at all of the leaders titles and placing their name in the proper column if their normalized title matched the column title I needed. Here are some advanced editor examples... pretty easy in reality.

     

     Director = Table.AddColumn(VP, "DIRECTOR", each if [#"SUP_1_TITLE-Groomed"] = "DIRECTOR" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "DIRECTOR" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "DIRECTOR" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "DIRECTOR" then [SUP_4_Name] else "TBD"),
     
    Manager = Table.AddColumn(Director, "MANAGER", each if [#"SUP_1_TITLE-Groomed"] = "MANAGER" then [SUP_1_Name] else if [#"SUP_2_TITLE-Groomed#(cr)#(lf)"] = "MANAGER" then [SUP_2_Name] else if [#"SUP_3_TITLE-Groomed"] = "MANAGER" then [SUP_3_Name] else if [#"SUP_4#(cr)#(lf)_TITLE-Groomed"] = "MANAGER" then [SUP_4_Name] else "TBD"),

     

    • Icey's avatar
      Icey
      Community Support

      Hi Anonymous ,

       

      Glad to hear that the problem has been solved. Please accept your reply as the solution.

      In addition, I can't reproduce your results. Could you share us more details or just a dummy .pbix file? I really want to know how you did it. Your contribution is highly appreciated.😀

       

       

       

      Best regards

      Icey

  • ziying35's avatar
    ziying35
    Impactful Individual

    Anonymous 

    try this:

    let
        Source = Table.FromRecords(Json.Document(Binary.Decompress(Binary.FromText("hdRPb4IwGAbwr0J69kDLn4K3TcyyhW1kml3MDh1UZcPWFFhiln33FRaxllfXm09eH82P8q6+UabkB88bNEXLoD9ogjKuail09CD58NG5T9AUE8+foHR+k8xfHOw8sR3vx7YCGXE3qQcDI1qWTdWNJqXSvybVaZwMLeXOTLsS3REa0bHktcy5kylelwUXzelL3qmqqsy469JV1IiOXUCNP9Tw9dqMuxrdEhnRsWY2f0Y/kzNO2h+TM2Ntde7pewSPPWdMVbZnoEcBz0W75+qrrEHRO/bObdJQFwGkj0ywDVeQpay5bUl1C2A5frgD5VIWhU0Z6RqA0nq6lmrcn6uXlPpuBFxSln/aqFGAYwB1hDGILhqW84NtGoeeC5iOOQbUtBRFzQ62K3apjwHYSxd+4E1Zq7iwgTGOAgIIX8TFpDsm7u3fm2SuANePgzHvgoniYPtiHLohAHxlCySy3di+mFBMAeB/90Cq/5QUI2UvIhGgfHUV6Ldgvx0B+7EXA8D9Nnj7BQ==", BinaryEncoding.Base64),Compression.Deflate))),
        fd = Table.ColumnNames(Source),
       
        fx = (rec)=>
             let fnField = (txt)=> Record.Field(rec, List.Select(Record.FieldNames(rec), each Text.EndsWith(_, txt)){0})
             in  Record.AddField(Record.AddField([],fnField("Title"),fnField("Name")),fnField("Title")&"ID",fnField("ID")),
             
        recs = Table.TransformRows(
                  Source, 
                  (r)=> Record.SelectFields(r, List.FirstN(fd,3))&
                        Record.Combine(List.Transform(List.Split(List.Skip(fd,3),3), each fx(Record.SelectFields(r, _))))),
        toTbl = Table.FromRecords(recs, Record.FieldNames(Record.Combine(recs)), 2),
        ref_order = {"S", "M", "D", "V", "P", "C"},
        nfd = List.Sort(
                 List.Skip(Table.ColumnNames(toTbl), 3), 
                 {{each List.PositionOf(ref_order, _, 0, (x,y)=>Text.StartsWith(y,x)), 0}, {Text.Length, 0}}
              ),
        result = Table.ReorderColumns(toTbl, nfd)
    in
        result
    • Anonymous's avatar
      Anonymous
      Not applicable

      I just applied this in a blank query and am astonished at how simple the transformations are. I don't know M well enought to know what you did here but it's definitely simpler than what I came up with

      • ziying35's avatar
        ziying35
        Impactful Individual

        Anonymous 

        In short, my code is to take the value of each person's job field from the three information fields, and use this value to rename all the information fields belonging to him, while deleting his original job field, and finally sort all the fields of the table according to the rank of the position.

        My code used in some of the syntax in the official documentation which can not necessarily be found, see my code requires some time and experience, I hope you help!