Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
3 years ago
Solved

Specific rows to column

I have a report in Excel that has information in specific rows that I need to convert to a column. I have tried group/pivot/unpivot in many different ways and I can't seem to figure it out. Here is what the source data looks like:

 

department AlocationsNew YorkWashingtonArizona
department Aposition Aremotein officein office
department Aposition Bremote remote
department Aposition Cin officein office 
department BlocationsNew YorkWisconsin 
department Bposition Aremotein office 
department Bposition Bremotein office 
department ClocationsCaliforniaNevada 
department Cposition Dremoteremote 
department DlocationsTexasArizona 
department Dposition Ain officein office 

 

I need to take the rows for "locations" and convert them to a column for each department/position. Any ideas? Here is what the final output should look like:

 

DepartmentLocationPositionstatus
department ANew Yorkposition Aremote
department ANew Yorkposition Bin office
department ANew Yorkposition Cin office
department AWashingtonposition Aremote
department AWashingtonposition Cin office
department AArizonaposition Ain office
department AArizonaposition Bremote
department BNew Yorkposition Aremote
department BNew Yorkposition Bremote
department BWisconsinposition Ain office
department BWisconsinposition Bin office
department CCaliforniaposition Dremote
department CNevadaposition Dremote
department DTexasposition Ain office
department DArizonaposition Ain office
  • OK, full Advanced Editor Code here:

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("jZBBDsIgEEWvQlj3Ei2sXZkY03QxoZBMbJkGiBpPL3ShSARd8Yfk8YY/jnzWG7iwahtYzzu+kceAZPfB6ZWCjgEtI2NQfeapq+NDjrP30GJE1ZSeKMgkWEhBIn3MB31jZ3KXGE/oVbxEW+N+f7KNDX9jothSwIKGnEXYV77CDDXsZZO5Leu0YGShOuo7pLN3+CD7VSPLLhrtT08=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"department A" = _t, locations = _t, #"New York" = _t, Washington = _t, Arizona = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"department A", type text}, {"locations", type text}, {"New York", type text}, {"Washington", type text}, {"Arizona", type text}}),
        #"Demoted Headers" = Table.DemoteHeaders(#"Changed Type"),
        #"Grouped Rows" = Table.Group(#"Demoted Headers", {"Column1"}, {{"all", each _, type table [Column2=nullable text, Column3=nullable text, Column4=nullable text, Column5=nullable text]}}),
        #"Added Custom1" = Table.AddColumn(#"Grouped Rows", "Custom1", each Table.PromoteHeaders([all])),
        #"Removed Columns1" = Table.RemoveColumns(#"Added Custom1",{"all"}),
        #"Added Custom2" = Table.AddColumn(#"Removed Columns1", "Custom2", each Table.RemoveColumns([Custom1], Table.ColumnNames ([Custom1]) {0} )),
        #"Removed Columns2" = Table.RemoveColumns(#"Added Custom2",{"Custom1"}),
        #"Added Custom" = Table.AddColumn(#"Removed Columns2", "Custom", each Table.UnpivotOtherColumns([Custom2], {"locations"}, "Attribute", "Value")),
        #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Custom2"}),
        #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns", "Custom", {"locations", "Attribute", "Value"}, {"Custom.locations", "Custom.Attribute", "Custom.Value"}),
        #"Changed Type1" = Table.TransformColumnTypes(#"Expanded Custom",{{"Column1", type text}, {"Custom.locations", type text}, {"Custom.Attribute", type text}, {"Custom.Value", type text}}),
        #"Filtered Rows" = Table.SelectRows(#"Changed Type1", each ([Custom.Value] <> " ")),
        #"Sorted Rows" = Table.Sort(#"Filtered Rows",{{"Column1", Order.Ascending}, {"Custom.Attribute", Order.Ascending}, {"Custom.locations", Order.Ascending}})
    in
        #"Sorted Rows"

    Some of these steps could possibly be neatened up but sometimes it's easier to add a column at each stage so that I can compare it to the previous stage easily.  Then I remove the old column and move on.

    The algorithm is basically :

    Group the table by department and create a mini-table on each row.

    Within each row, do some tidying to make all mini-tables have the same column names.

    and Unpivot the Geographic column names.

    Expand the mini-tables.

    Remove the rows with blank values.

    ---

    See how you get on with your test data and then try the full set.

    --

    I think there is a mistake in the provided desired table :

    department A New York position B in office

     

     

    ---

    let me know how you get on.

     

10 Replies

  • HotChilli's avatar
    HotChilli
    Community Champion

    OK, full Advanced Editor Code here:

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("jZBBDsIgEEWvQlj3Ei2sXZkY03QxoZBMbJkGiBpPL3ShSARd8Yfk8YY/jnzWG7iwahtYzzu+kceAZPfB6ZWCjgEtI2NQfeapq+NDjrP30GJE1ZSeKMgkWEhBIn3MB31jZ3KXGE/oVbxEW+N+f7KNDX9jothSwIKGnEXYV77CDDXsZZO5Leu0YGShOuo7pLN3+CD7VSPLLhrtT08=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"department A" = _t, locations = _t, #"New York" = _t, Washington = _t, Arizona = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"department A", type text}, {"locations", type text}, {"New York", type text}, {"Washington", type text}, {"Arizona", type text}}),
        #"Demoted Headers" = Table.DemoteHeaders(#"Changed Type"),
        #"Grouped Rows" = Table.Group(#"Demoted Headers", {"Column1"}, {{"all", each _, type table [Column2=nullable text, Column3=nullable text, Column4=nullable text, Column5=nullable text]}}),
        #"Added Custom1" = Table.AddColumn(#"Grouped Rows", "Custom1", each Table.PromoteHeaders([all])),
        #"Removed Columns1" = Table.RemoveColumns(#"Added Custom1",{"all"}),
        #"Added Custom2" = Table.AddColumn(#"Removed Columns1", "Custom2", each Table.RemoveColumns([Custom1], Table.ColumnNames ([Custom1]) {0} )),
        #"Removed Columns2" = Table.RemoveColumns(#"Added Custom2",{"Custom1"}),
        #"Added Custom" = Table.AddColumn(#"Removed Columns2", "Custom", each Table.UnpivotOtherColumns([Custom2], {"locations"}, "Attribute", "Value")),
        #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Custom2"}),
        #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns", "Custom", {"locations", "Attribute", "Value"}, {"Custom.locations", "Custom.Attribute", "Custom.Value"}),
        #"Changed Type1" = Table.TransformColumnTypes(#"Expanded Custom",{{"Column1", type text}, {"Custom.locations", type text}, {"Custom.Attribute", type text}, {"Custom.Value", type text}}),
        #"Filtered Rows" = Table.SelectRows(#"Changed Type1", each ([Custom.Value] <> " ")),
        #"Sorted Rows" = Table.Sort(#"Filtered Rows",{{"Column1", Order.Ascending}, {"Custom.Attribute", Order.Ascending}, {"Custom.locations", Order.Ascending}})
    in
        #"Sorted Rows"

    Some of these steps could possibly be neatened up but sometimes it's easier to add a column at each stage so that I can compare it to the previous stage easily.  Then I remove the old column and move on.

    The algorithm is basically :

    Group the table by department and create a mini-table on each row.

    Within each row, do some tidying to make all mini-tables have the same column names.

    and Unpivot the Geographic column names.

    Expand the mini-tables.

    Remove the rows with blank values.

    ---

    See how you get on with your test data and then try the full set.

    --

    I think there is a mistake in the provided desired table :

    department A New York position B in office

     

     

    ---

    let me know how you get on.

     

    • Anonymous's avatar
      Anonymous
      Not applicable

      This worked great, thanks! I have a similar issue with another table which is a little more complicated but I think the principal is the same so I'll post it here. Here is my source table from an Excel report:

       

      Column1Column2Column3Column4Column5Column6Column7Column8Column9Column10Column11
      department AApplication NameProcess A  Process B  Process C  
      department A StatusRTORPOStatusRTORPOStatusRTORPO
      department AApp ACritical4 hours1 hourCritical4 hours1 hourAncillary12 hours2 hours
      department AApp BAncillary72 hours24 hoursCritical1 hour0 hoursAncillary5 days24 hours
      department AApp CCritical4 hours1 hourAncillary24 hours4 hoursCritical4 hours1 hour
      department BApplication NameProcess D  Process E  Process F  
      department B StatusRTORPOStatusRTORPOStatusRTORPO
      department BApp DCritical2 hours0 hoursAncillary24 hours4 hoursCritical4 hours1 hour
      department BApp ECritical2 hours0 hoursAncillary24 hours4 hoursAncillary12 hours12 hours
      department BApp FAncillary24 hours12 hoursCritical4 hours1 hourCritical4 hours1 hour

       

      As you can see now I have 2 different rows need to be converted into columns, with this as the final output:

       

      DepartmentApplicationProcessStatusRTORPO
      department AApp AProcess ACritical4 hours1 hour
      department AApp AProcess BCritical4 hours1 hour
      department AApp AProcess CAncillary12 hours2 hours
      department AApp BProcess AAncillary72 hours24 hours
      department AApp BProcess BCritical1 hour0 hours
      department AApp BProcess CAncillary5 days24 hours
      department AApp CProcess ACritical4 hours1 hour
      department AApp CProcess BAncillary24 hours4 hours
      department AApp CProcess CCritical4 hours1 hour
      department BApp DProcess DCritical2 hours0 hours
      department BApp DProcess EAncillary24 hours4 hours
      department BApp DProcess FCritical4 hours1 hour
      department BApp EProcess DCritical2 hours0 hours
      department BApp EProcess EAncillary24 hours4 hours
      department BApp EProcess FAncillary12 hours12 hours
      department BApp FProcess DAncillary24 hours12 hours
      department BApp FProcess ECritical4 hours1 hour
      department BApp FProcess FCritical4 hours1 hour

       

      I tried using your previous method (which worked like a charm) but i think the blank values in Column2 are causing issues. Any ideas? 

  • HotChilli's avatar
    HotChilli
    Community Champion

    Select the first 2 columns and 'Unpivot other columns'

    • Anonymous's avatar
      Anonymous
      Not applicable

      That didn't work. I should have mentioned the source data didn't have any column headers, so technically it looks like this in Power Query:


      Column1Column2Column3Column4Column5
      department AlocationsNew YorkWashingtonArizona
      department Aposition Aremotein officein office
      department Aposition Bremote remote
      department Aposition Cin officein office 
      department BlocationsNew YorkWisconsin 
      department Bposition Aremotein office 
      department Bposition Bremotein office 
      department ClocationsCaliforniaNevada 
      department Cposition Dremoteremote 
      department DlocationsTexasArizona 
      department Dposition Ain officein office 
  • HotChilli's avatar
    HotChilli
    Community Champion

    "That didn't work" - In the spirit of cooperation, tell me what happened.  Error messages? Syntax correct but not the desired result?  Also please paste the line of Power Query code that was generated when you Unpivoted the columns.

    • Anonymous's avatar
      Anonymous
      Not applicable

      line in Power Query is  Table.UnpivotOtherColumns(Source, {"Column1", "Column2"}, "Attribute", "Value")

      here was the result:


      Here is the desired result (entered manually)

       

  • HotChilli's avatar
    HotChilli
    Community Champion

    Right, I see that the original table is really made up of mini-tables for each department.

    Is this the final table or are there more departments in a real table?

    ---

    I'll have a look at a generic solution.

    A quick, semi-manual solution would be to make 4 versions of the original table (each one filtered to a single, different department).

    Promote the headers. Then do the Unpivot.

    You could then append the 4 tables together.

     

    • Anonymous's avatar
      Anonymous
      Not applicable

      The full table includes 30 departments and roughly a dozen locations, with up to 10 positions for each department/location. I am able to get the table to show department/position or department/location but I can't figure out how to get them all in one table with 4 columns (Department, Location, Position, Status)

  • HotChilli's avatar
    HotChilli
    Community Champion

    Can we rely on there being 11 columns maximum?
    So we could make 3 queries from this one -  

    1st one -> Columns 1,2,3,4,5

    2nd one -> Columns 1,2,6,7,8

    3rd one -> Columns 1,2,9,10,11

    We can do this manually in the first instance.

    Rename the Columns to be 1,2,3,4,5 in each query then Append all 3 tables together.

    Then a bit of manipulation to get the final result.

    Let me know if that is a good plan.

    • Anonymous's avatar
      Anonymous
      Not applicable

      Thank you so much for all of your help with this!

      I have 2 tables that are similarly structured, one with 32 columns total & the other is 17 columns. The only difference would be the 17-column cable would result in 5 columns, and the 32-column table results in 7