Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Power BI is turning 10! Let’s celebrate together with dataviz contests, interactive sessions, and giveaways. Register now.

Reply
WMart_AMS
Frequent Visitor

transform multiple columns into 2 columns (List.Zip, (un)pivot)

Hi Everybody,

 

Hopefully somebody can help me out. I am working with the data set in the image below. basically i have 5 categrories: Scope, Planning, Financien, Capaciteit and Kwaliteit. These categories are provided with an indicator and a comment. Each row contains the indicators and comments of 1 project in one specific period of time, this is represented with the index column.

 

WMart_AMS_0-1742998885140.png

 

My desired result is as following. I tried to work with List.Zip and unpivotting, but it does not give me the correct results. Can somebody help me out? The data table is provided below.

WMart_AMS_1-1742999290230.png

 

IndexProject_codeScope opmerkingenScope indicatorKwaliteit opmerkingenKwaliteit indicatorPlanning opmerkingenPlanning indicatorCapaciteit opmerkingenCapaciteit indicatorFinancien opmerkingenFinancien indicator
17304100171Tekst scope 13Tekst kwaliteit12Tekst planning12Tekst capaciteit12Tekst financien13
17304210056Tekst scope 23Tekst kwaliteit23Tekst planning22Tekst capaciteit22Tekst financien22
17304210032Tekst scope 33Tekst kwaliteit33Tekst planning32Tekst capaciteit32Tekst financien32
17304210053Tekst scope 4nullTekst kwaliteit4nullTekst planning4nullTekst capaciteit4nullTekst financien4null
17304210033Tekst scope 5nullTekst kwaliteit5nullTekst planning5nullTekst capaciteit5nullTekst financien5null
27304100171Tekst scope 63Tekst kwaliteit62Tekst planning62Tekst capaciteit62Tekst financien63
27304210056Tekst scope 73Tekst kwaliteit73Tekst planning72Tekst capaciteit72Tekst financien72
27304210032Tekst scope 83Tekst kwaliteit83Tekst planning82Tekst capaciteit82Tekst financien82
27304210053Tekst scope 9nullTekst kwaliteit9nullTekst planning9nullTekst capaciteit9nullTekst financien9null
27304210033Tekst scope 10nullTekst kwaliteit10nullTekst planning10nullTekst capaciteit10nullTekst financien10null
37304100171Tekst scope 113Tekst kwaliteit112Tekst planning112Tekst capaciteit112Tekst financien113
37304210056Tekst scope 123Tekst kwaliteit123Tekst planning122Tekst capaciteit122Tekst financien122
37304210032Tekst scope 133Tekst kwaliteit133Tekst planning132Tekst capaciteit132Tekst financien132

 

 

 

2 ACCEPTED SOLUTIONS
sevenhills
Super User
Super User

One more simple way:

 

Your Source:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("tZSxTsMwEEB/5ZS5Q+JQuheEijpQkbHq4CaH6yqxIzcpEiPfg8RH8Cd8CVcLQomjKm3MYF3s2C+Xp/Mtl0EUjIJJHF5FYRhNIqBZkuoSKcY0ZljBXmuzRoMyk0rs1nUmaFHuQJcCN1qLDApa+Hx9i4PVqA2kyfyZ57JCWdEzo3GLsEEsDOfZASMVTStYJA+w5wrYGJ5wbWpuJAj8eFfd0EXOlaJ8vpn3CjKEpKprI4zG0qIyTLGgzOFFbu370ugtphV2I294ydOfRFWd5xSmcns4uJg+zoFztaekhRVyWBW1TcF+i36hm3onFVFR/TJtON7LaPP4epD6Dp5n8w3Un/kG6dV8Q+1pPmZexVucb/EW6le8RXoXb6knxLP29TgWf4klB9hWf4Emh9kyf7YhB9jl/fyyc7A9xDe3Y1jFOzgfFe9Ah1e8g/RS8Q61p/iYDW/yf3n/YN5Tr3GQ3s2f7DWrLw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Index = _t, Project_code = _t, Category = _t, Indicator = _t, Comments = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Index", Int64.Type}, {"Project_code", Int64.Type}, {"Category", type text}, {"Indicator", Int64.Type}, {"Comments", type text}})
in
    #"Changed Type"

 

sevenhills_0-1743116214338.png

 

Target:

 

let
    Source = Table,
    #"Replaced Value" = Table.ReplaceValue(Source,null,-99999,Replacer.ReplaceValue,{"Indicator"}),
    #"Replaced Value1" = Table.ReplaceValue(#"Replaced Value","null","-9999990",Replacer.ReplaceValue,{"Comments"}),
    #"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Replaced Value1", {"Index", "Project_code", "Category"}, "Attribute", "Value"),
    #"Merged Columns" = Table.CombineColumns(#"Unpivoted Columns",{"Category", "Attribute"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"Merged"),
    #"Pivoted Column" = Table.Pivot(#"Merged Columns", List.Distinct(#"Merged Columns"[Merged]), "Merged", "Value"),
    #"Changed Type" = Table.TransformColumnTypes(#"Pivoted Column",{{"Scope Indicator", type text}, {"Scope Comments", type text}, {"Kwaliteit Indicator", type text}, {"Kwaliteit Comments", type text}, {"Planning Indicator", type text}, {"Planning Comments", type text}, {"Capaciteit Indicator", type text}, {"Capaciteit Comments", type text}, {"Finacien Indicator", type text}, {"Finacien Comments", type text}}),
    #"Replaced Value2" = Table.ReplaceValue(#"Changed Type","-99999",null,Replacer.ReplaceValue,{"Scope Indicator", "Kwaliteit Indicator", "Planning Indicator", "Capaciteit Indicator", "Finacien Indicator"}),
    #"Replaced Value3" = Table.ReplaceValue(#"Replaced Value2","-9999990",null,Replacer.ReplaceValue,{"Scope Comments", "Kwaliteit Comments", "Planning Comments", "Capaciteit Comments", "Finacien Comments"})
in
    #"Replaced Value3"

Output:

sevenhills_1-1743116234458.png

 

I used replace with some standard value for nulls and after the format achieved, replaced back to nulls. 

 

Hope this helps!

 

View solution in original post

I tried this out and it worked! Thanks!

View solution in original post

8 REPLIES 8
dufoq3
Super User
Super User

Hi @WMart_AMS, query for your sample data:

Output

dufoq3_0-1743165762811.png

let
    Source = Table.TransformColumns(Table.FromColumns(List.Split(Text.Split("1,1,1,1,1,2,2,2,2,2,3,3,3,7304100171,7304210056,7304210032,7304210053,7304210033,7304100171,7304210056,7304210032,7304210053,7304210033,7304100171,7304210056,7304210032,Tekst scope 1,Tekst scope 2,Tekst scope 3,Tekst scope 4,Tekst scope 5,Tekst scope 6,Tekst scope 7,Tekst scope 8,Tekst scope 9,Tekst scope 10,Tekst scope 11,Tekst scope 12,Tekst scope 13,3,3,3,,,3,3,3,,,3,3,3,Tekst kwaliteit1,Tekst kwaliteit2,Tekst kwaliteit3,Tekst kwaliteit4,Tekst kwaliteit5,Tekst kwaliteit6,Tekst kwaliteit7,Tekst kwaliteit8,Tekst kwaliteit9,Tekst kwaliteit10,Tekst kwaliteit11,Tekst kwaliteit12,Tekst kwaliteit13,2,3,3,,,2,3,3,,,2,3,3,Tekst planning1,Tekst planning2,Tekst planning3,Tekst planning4,Tekst planning5,Tekst planning6,Tekst planning7,Tekst planning8,Tekst planning9,Tekst planning10,Tekst planning11,Tekst planning12,Tekst planning13,2,2,2,,,2,2,2,,,2,2,2,Tekst capaciteit1,Tekst capaciteit2,Tekst capaciteit3,Tekst capaciteit4,Tekst capaciteit5,Tekst capaciteit6,Tekst capaciteit7,Tekst capaciteit8,Tekst capaciteit9,Tekst capaciteit10,Tekst capaciteit11,Tekst capaciteit12,Tekst capaciteit13,2,2,2,,,2,2,2,,,2,2,2,Tekst financien1,Tekst financien2,Tekst financien3,Tekst financien4,Tekst financien5,Tekst financien6,Tekst financien7,Tekst financien8,Tekst financien9,Tekst financien10,Tekst financien11,Tekst financien12,Tekst financien13,3,2,2,,,3,2,2,,,3,2,2", ","), 13), {"Index", "Project_code", "Scope opmerkingen", "Scope indicator", "Kwaliteit opmerkingen", "Kwaliteit indicator", "Planning opmerkingen", "Planning indicator", "Capaciteit opmerkingen", "Capaciteit indicator", "Financien opmerkingen", "Financien indicator"}), {}, each if _ = "" then null else _),
    Transformed = Table.FromRows(List.TransformMany(Table.ToRows(Source),
        each List.Split(List.Skip(_, 2), 2),
        (x,y)=> {x{0}, x{1}} & y ), {"Index", "Project_code", "Category", "Indicator"})
in
    Transformed

Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

AntrikshSharma
Super User
Super User

@WMart_AMS 

let
    Source = Table,
    Transform = Table.TransformRows (
        Source,
        (Row) =>
            let
                ColumnValues = List.Skip ( Record.ToList ( Row ), 2 ),
                ColumnNames = List.Skip ( Record.FieldNames ( Row ), 2 ),
                Comments = List.Alternate ( ColumnValues, 1, 1, 1 ),
                Indicator = List.Alternate ( ColumnValues, 1, 1 ),
                Category = List.Distinct (
                    List.Transform ( ColumnNames, ( x ) => Text.BeforeDelimiter ( x, " " ) )
                ),
                ColumnsCombined = Table.FromColumns (
                    { { Row[Index] } }
                        & { { Row[Project_code] } }
                        & { Category }
                        & { Indicator }
                        & { Comments },
                    type table [
                        Index = Int64.Type,
                        Project Code = Int64.Type,
                        Category = text,
                        Indictory = Int64.Type,
                        Commments = text
                    ]
                ),
                FillDownColums = Table.FillDown ( ColumnsCombined, { "Index", "Project Code" } )
            in
                FillDownColums
    ),
    CombineTables = Table.Combine ( Transform )
in
    CombineTables

 

sevenhills
Super User
Super User

One more simple way:

 

Your Source:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("tZSxTsMwEEB/5ZS5Q+JQuheEijpQkbHq4CaH6yqxIzcpEiPfg8RH8Cd8CVcLQomjKm3MYF3s2C+Xp/Mtl0EUjIJJHF5FYRhNIqBZkuoSKcY0ZljBXmuzRoMyk0rs1nUmaFHuQJcCN1qLDApa+Hx9i4PVqA2kyfyZ57JCWdEzo3GLsEEsDOfZASMVTStYJA+w5wrYGJ5wbWpuJAj8eFfd0EXOlaJ8vpn3CjKEpKprI4zG0qIyTLGgzOFFbu370ugtphV2I294ydOfRFWd5xSmcns4uJg+zoFztaekhRVyWBW1TcF+i36hm3onFVFR/TJtON7LaPP4epD6Dp5n8w3Un/kG6dV8Q+1pPmZexVucb/EW6le8RXoXb6knxLP29TgWf4klB9hWf4Emh9kyf7YhB9jl/fyyc7A9xDe3Y1jFOzgfFe9Ah1e8g/RS8Q61p/iYDW/yf3n/YN5Tr3GQ3s2f7DWrLw==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Index = _t, Project_code = _t, Category = _t, Indicator = _t, Comments = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Index", Int64.Type}, {"Project_code", Int64.Type}, {"Category", type text}, {"Indicator", Int64.Type}, {"Comments", type text}})
in
    #"Changed Type"

 

sevenhills_0-1743116214338.png

 

Target:

 

let
    Source = Table,
    #"Replaced Value" = Table.ReplaceValue(Source,null,-99999,Replacer.ReplaceValue,{"Indicator"}),
    #"Replaced Value1" = Table.ReplaceValue(#"Replaced Value","null","-9999990",Replacer.ReplaceValue,{"Comments"}),
    #"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Replaced Value1", {"Index", "Project_code", "Category"}, "Attribute", "Value"),
    #"Merged Columns" = Table.CombineColumns(#"Unpivoted Columns",{"Category", "Attribute"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"Merged"),
    #"Pivoted Column" = Table.Pivot(#"Merged Columns", List.Distinct(#"Merged Columns"[Merged]), "Merged", "Value"),
    #"Changed Type" = Table.TransformColumnTypes(#"Pivoted Column",{{"Scope Indicator", type text}, {"Scope Comments", type text}, {"Kwaliteit Indicator", type text}, {"Kwaliteit Comments", type text}, {"Planning Indicator", type text}, {"Planning Comments", type text}, {"Capaciteit Indicator", type text}, {"Capaciteit Comments", type text}, {"Finacien Indicator", type text}, {"Finacien Comments", type text}}),
    #"Replaced Value2" = Table.ReplaceValue(#"Changed Type","-99999",null,Replacer.ReplaceValue,{"Scope Indicator", "Kwaliteit Indicator", "Planning Indicator", "Capaciteit Indicator", "Finacien Indicator"}),
    #"Replaced Value3" = Table.ReplaceValue(#"Replaced Value2","-9999990",null,Replacer.ReplaceValue,{"Scope Comments", "Kwaliteit Comments", "Planning Comments", "Capaciteit Comments", "Finacien Comments"})
in
    #"Replaced Value3"

Output:

sevenhills_1-1743116234458.png

 

I used replace with some standard value for nulls and after the format achieved, replaced back to nulls. 

 

Hope this helps!

 

I tried this out and it worked! Thanks!

SundarRaj
Solution Supplier
Solution Supplier

Hi @WMart_AMS , here's another solution you could possibly look at. I'll leave the images of the output, the source and text of code used. Thanks!

SundarRaj_0-1743058682266.png

SundarRaj_1-1743058714452.png

SundarRaj_2-1743058759718.png

 

let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],


#"Changed Type" = Table.TransformColumnTypes(Source,{{"Index", Int64.Type}, {"Project_code", Int64.Type}, {"Scope opmerkingen", type text}, {"Scope indicator", Int64.Type}, {"Kwaliteit opmerkingen", type text}, {"Kwaliteit indicator", Int64.Type}, {"Planning opmerkingen", type text}, {"Planning indicator", Int64.Type}, {"Capaciteit opmerkingen", type text}, {"Capaciteit indicator", Int64.Type}, {"Financien opmerkingen", type text}, {"Financien indicator", Int64.Type}}),


Custom1 = List.Split(List.Skip(Table.ToColumns(#"Changed Type"),2),2),


Custom2 = List.Transform(Custom1, each Table.FromColumns(_)),


Custom3 = List.Transform(Custom2, each Table.AddIndexColumn(_,"Project_Code",0,1)),


Custom4 = List.Transform(Custom3, each Table.TransformColumns(_, {"Project_Code", each #"Changed Type"[Project_code]{_}})),


Custom5 = List.Transform(Custom4, each Table.AddIndexColumn(_,"Index",0,1)),


Custom6 = List.Transform(Custom5, each Table.TransformColumns(_, {"Index", each #"Changed Type"[Index]{_}})),


Custom7 = Table.Combine(Custom6),


#"Reordered Columns" = Table.ReorderColumns(Custom7,{"Index", "Project_Code", "Column1", "Column2"}),


#"Grouped Rows" = Table.Group(#"Reordered Columns", {"Index","Project_Code"}, {{"All", each _, type table [Index=number, Project_Code=number, Column1=nullable text, Column2=nullable number]}})[All],


Custom8 = List.Transform(#"Grouped Rows", each Table.AddIndexColumn(_, "Category",0,1)),


Custom9 = {"Scope","Kwaliteit","Planning","Capaciteit","Financien"},


Custom10 = List.Transform(Custom8, each Table.TransformColumns(_,{"Category", each Custom9{_}})),


Custom11 = Table.Combine(Custom10),


#"Reordered Columns1" = Table.ReorderColumns(Custom11,{"Index", "Project_Code", "Category", "Column2", "Column1"}),


#"Renamed Columns" = Table.RenameColumns(#"Reordered Columns1",{{"Column2", "Indicators"}, {"Column1", "Comments"}})


in


#"Renamed Columns"

Sundar Rajagopalan
slorin
Super User
Super User

Hi @WMart_AMS 

 

A solution with List.TransformMany

let
Source = Your_Source,
ColumnNames = Table.ColumnNames(Source),
Data = Table.ToRows(Source),
Transform = List.TransformMany(Data, each {1..5},
(x,y) => List.FirstN(x,2) & {Text.BeforeDelimiter(ColumnNames{y*2+1}, " ")} & List.Reverse(List.Range(x,y*2,2))),
Result = Table.FromRows(Transform, {"Index", "Project_code", "Category", "Indicator", "Comment"})
in
Result

or

let
Source = Your_Source,
ColumnNames = List.Distinct(List.Transform(
List.RemoveFirstN(Table.ColumnNames(Source),2),
each Text.BeforeDelimiter(_, " "))),
Data = Table.ToRows(Source),
Transform = List.TransformMany(Data, each {1..5},
(x,y) => List.FirstN(x,2) & {ColumnNames{y-1}} & {x{y*2+1}} & {x{y*2}}),
Result = Table.FromRows(Transform, {"Index", "Project_code", "Category", "Indicator", "Comment"})
in
Result

 

 

Stéphane

jgeddes
Super User
Super User

Maybe something like this may work...

let
    Source = 
    Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("fdRNioNAEAXgq4ReZ2F1Rdu5x+yCCxEnNJGOEIe5fiKZrv6pKpe+F8KHFu96NWDOxmFzgaYBtz98z/fndnpOj3U+7c9I2f1vXPw2+22PLcXrMobgw61Mp3EdJ+HXPz6MYfJz+Pz3cE4E+za0XUWwMqGMI8EqBCsTPnFNQFsRUCagSECFgDIBRUKLFeHyfg6/y8IVrIkQViQLq4hDDXsptahVRayJIlYkEatI1OYie3SsnfyZOvFYyzRBypwUHR2rNQfH6mRCGUeCUwhOJji6lJzAjrWXCb1I6BVCLxN6kcCO9Us9DdZECCuShVXEoYa9lFoEjUriFe0Za7JNY13atSZn4eG8avuqDKy6sNrEpo1Fc3C2oIwsyCsL2syCsrOQhjZ3sNsFZWlBnlrQthaUsf3Ph+EF", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Index = _t, Project_code = _t, #"Scope opmerkingen" = _t, #"Scope indicator" = _t, #"Kwaliteit opmerkingen" = _t, #"Kwaliteit indicator" = _t, #"Planning opmerkingen" = _t, #"Planning indicator" = _t, #"Capaciteit opmerkingen" = _t, #"Capaciteit indicator" = _t, #"Financien opmerkingen" = _t, #"Financien indicator" = _t]),
    set_types = 
    Table.TransformColumnTypes(
        Source,
        {
            {"Index", Int64.Type}, {"Project_code", Int64.Type}, {"Scope opmerkingen", type text}, {"Scope indicator", Int64.Type}, {"Kwaliteit opmerkingen", type text}, {"Kwaliteit indicator", Int64.Type}, {"Planning opmerkingen", type text}, {"Planning indicator", Int64.Type}, {"Capaciteit opmerkingen", type text}, {"Capaciteit indicator", Int64.Type}, {"Financien opmerkingen", type text}, {"Financien indicator", Int64.Type}
        }
    ),
    indicator_columns = 
    List.Select(
        Table.ColumnNames(set_types), 
        each Text.Contains(_, "indicator")
    ),
    opmerkingen_columns = 
    List.Select(
        Table.ColumnNames(set_types), 
        each Text.Contains(_, "opmerkingen")
    ),
    columns_list = 
    List.Transform(
        opmerkingen_columns, 
        each Text.BeforeDelimiter(_, " ")
    ),
    group_rows = 
    Table.Group(
        set_types, 
        {"Index", "Project_code"}, 
        {
            {"AllRows", each List.Zip({columns_list, Record.ToList(Table.SelectColumns(_, indicator_columns){0}), Record.ToList(Table.SelectColumns(_, opmerkingen_columns){0})}), type list}
        }
    ),
    expand_nested = 
    Table.ExpandListColumn(
        group_rows, 
        "AllRows"
    ),
    extract_text = 
    Table.TransformColumns(
        expand_nested, 
        {
            {"AllRows", each Text.Combine(List.Transform(List.ReplaceValue(_, null, "", Replacer.ReplaceValue), each Text.From(_)), "|")}
        }
    ),
    split_column = 
    Table.SplitColumn(
        extract_text, 
        "AllRows", 
        Splitter.SplitTextByDelimiter("|", QuoteStyle.Csv), 
        {"Category", "Indicator", "Comment"}
    )
in
    split_column

jgeddes_0-1743020118762.png

 





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!





ToddChitt
Super User
Super User

You might be able to do this with five separate queries, where each one does an UNPIVOT of one pair of columns. Then have a final query that does a big UNION of the five.




Did I answer your question? If so, mark my post as a solution. Also consider helping someone else in the forums!

Proud to be a Super User!





Helpful resources

Announcements
June 2025 Power BI Update Carousel

Power BI Monthly Update - June 2025

Check out the June 2025 Power BI update to learn about new features.

June 2025 community update carousel

Fabric Community Update - June 2025

Find out what's new and trending in the Fabric community.

Top Solution Authors