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

Score big with last-minute savings on the final tickets to FabCon Vienna. Secure your discount

Reply
work_1111
Helper II
Helper II

Move Data from Columns to Rows and split 1 column data

Hello everyone,

 

I have a huge set of data in a table where a single item has multiple part numbers and prices. See sample below under Current table. I am trying to get the data into more of a pivot like structure while also separating the core part number from the size. See Desired Table. Please share any tips or guidance on how I can achieve this. Thank you!

 

Current table

Item Title  Small_Item Num  Medium_Item Num  Large_Item Num  Small_Price  Medium_Price  Large_Price
Item 1PNTRSMPNTRMDPNTRLG1.572.282.99
Item 1PNTRSMPPNTRMDPPNTRLGP1.812.623.44
Item 2TCHLSMTCHLMDTCHLLG2.653.654.65
Item 2TCHLSMPTCHLMDPTCHLLGP3.224.225.22

 

Desired Table

 

Item Title  Item Number  Item Size  Price
Item 1PNTRSM1.57
Item 1PNTRMD2.28
Item 1PNTRLG2.99
Item 1PNTRSMP1.81
Item 1PNTRMDP2.62
Item 1PNTRLGP3.44
Item 2TCHLSM2.65
Item 2TCHLMD3.65
Item 2TCHLLG4.65
Item 2TCHLSMP3.22
Item 2TCHLMDP4.22
Item 2TCHLLGP5.22
2 ACCEPTED SOLUTIONS
wdx223_Daniel
Super User
Super User

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bc27CoAwDIXhV5HOUmhsvcwKKqgEdZOOjm6+PzaHUged/kPgI8ehxvu8MqNyxcu+bnMccxfH1IdhtKtCSFONNI3y+YdyspwwQ9cGrKSQQlv7arns7TDhsQw8loHHwTgYxEp+KCfLCTMYERjiJN4/", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Item Title" = _t, #"  Small_Item Num" = _t, #"  Medium_Item Num" = _t, #"  Large_Item Num" = _t, #"  Small_Price" = _t, #"  Medium_Price" = _t, #"  Large_Price" = _t]),
    Custom1 = #table({"Item Title","Item Number","Item Size","Price"},List.TransformMany(Table.ToRows(Source),each List.Transform(List.Zip(List.Split(List.Skip(_),3)),each {Text.Start(_{0},4),Text.Range(_{0},4),_{1}}),(x,y)=>{x{0}}&y))
in
    Custom1

View solution in original post

dufoq3
Super User
Super User

Hi, I'm not that skilled as @wdx223_Daniel but I built it my way:

dufoq3_0-1705687253747.png

Change 2nd step YourSource = Source (replace Source with your table reference)

 

//Move Data from Columns to Rows and split 1 column data
//https://community.fabric.microsoft.com/t5/Power-Query/Move-Data-from-Columns-to-Rows-and-split-1-column-data/m-p/3644632#M119982

let
    Source = Table.TransformColumnNames(Table.PromoteHeaders(Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bc1BCoMwFATQq0jWIpgmra5baAsqn+pOpEgbJGA2ovdvMoZYwdVMJjx+27LnrEzU6HlULGZRVJt+HN8Yq8VgKtVXL2a/Ff00qP20Spr0R/2zbVjN+u5ifzm1X1Q1r7r0pbz5UtxtSRN5scETniHy/IhSsBQwQWcp2JnbOCVCbNotzfVR4LArOOwKDlsjYRDCxQGlYClgAuMcDCFddN0P", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"(blank)" = _t, #"(blank).1" = _t, #"(blank).2" = _t, #"(blank).3" = _t, #"(blank).4" = _t, #"(blank).5" = _t, #"(blank).6" = _t])), Text.Trim),
    YourSource = Source,
    ColNameContains = Table.FromList(List.Distinct(List.Transform(List.Select(Table.ColumnNames(YourSource), each Text.Contains(_, "_Item", Comparer.OrdinalIgnoreCase)), (r)=> Text.BeforeDelimiter(r, "_"))), Splitter.SplitByNothing(), {"ColName"}),
    #"Added Index" = Table.AddIndexColumn(ColNameContains, "Index", 1, 1, Int64.Type),
    Ad_SizeTables = Table.AddColumn(#"Added Index", "Size Tables", each
    [v_sizeTables = Table.SelectColumns(YourSource, {"Item Title"} & List.Select(Table.ColumnNames(YourSource), (r)=> Text.Contains(r, [ColName]))),
     v_adIndex =Table.AddIndexColumn(v_sizeTables, "InnerIndex", [Index], Table.RowCount(v_sizeTables)),
     v_toColumns = Table.ToColumns(v_adIndex)
    ][v_toColumns]),
    toTable =   [v_combinedLists = List.Transform(List.Zip(Ad_SizeTables[Size Tables]), each List.Combine(_)),
   v_table = Table.FromColumns(v_combinedLists, {"Item", "Item Number", "Price", "Index"})
  ][v_table],
    #"Split Column by Positions" = Table.SplitColumn(toTable, "Item Number", Splitter.SplitTextByPositions({0, 4}), {"Item Number", "Item Size"}),
    #"Sorted Rows" = Table.Sort(#"Split Column by Positions",{{"Index", Order.Ascending}}),
    #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Index"})
in
    #"Removed Columns"

 


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

View solution in original post

11 REPLIES 11
work_1111
Helper II
Helper II

Hello - thanks for the help you've all provided. My requirements have slightly changed and I am seeking assistance. I still need to split the data but instead of splitting the columns by position, I need to split the column based on a  value in another column. I have a custom column "Common_Item_Num that finds the common value between 3 columns and provides that value. I would like to the split to happen based on this column since the lengths of the item num can vary.

 

Item Title  Small_Item Num  Medium_Item Num  Large_Item NumCommon_Item_Num  Small_Price  Medium_Price  Large_PriceManufacturer    Location
PantsPNTRSMPNTRMDPNTRLGPNTR1.572.282.99Company AHouston
PantsPNTRSMPPNTRMDPPNTRLGPPNTR1.812.623.44Company AHouston
ShirtsTCHLSMTCHLMDTCHLLGTCHL2.653.654.65Supplier 3Dallas
ShirtsTCHLSMPTCHLMDPTCHLLGPTCHL3.224.225.22Supplier 3Dallas
Socks9315RSM9315RMD9315RLG9315R0.540.650.77Supplier 4Phoenix

 

dufoq3
Super User
Super User

Hi @bkwok, try this:

dufoq3_0-1706386886027.png

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("hc4xC4MwEIbhvyKZJZCYtDoWBS1oOaqbODg4FKIJVYf++56nZKnQ6f0C4eHalt2XYQwECxk8mmddHaPKjlHmOATXV4zkMqYkCSa1o+unT3DDXdh1XuzEuvAHBC+CJ4HMWBB2kZiIK/XP3P41aVHSkdugI7dBR6KkSaKoPfXqnHkN7yDCR9Yb089nIHgRPAmESUkYRe85Nbsv", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Item Title" = _t, #"Small_Item Num" = _t, #"Medium_Item Num" = _t, #"Large_Item Num" = _t, Small_Price = _t, Medium_Price = _t, Large_Price = _t, Manufacturer = _t, Location = _t]),
    YourSource = Source,
    ColNameSizeTable = Table.FromList(List.Distinct(List.Transform(List.Select(Table.ColumnNames(YourSource), each Text.Contains(_, "_Item", Comparer.OrdinalIgnoreCase)), (r)=> Text.BeforeDelimiter(r, "_"))), Splitter.SplitByNothing(), {"ColName"}),
    ColNameOtherList = List.Select(Table.ColumnNames(YourSource), each not List.ContainsAny(Text.SplitAny(_," _-/|:,;[]{}()"), ColNameSizeTable[ColName])),
    StepBack = ColNameSizeTable,
    #"Added Index" = Table.AddIndexColumn(StepBack, "Index", 1, 1, Int64.Type),
    Ad_SizeTables = Table.AddColumn(#"Added Index", "Size Tables", each
    [v_sizeTables = Table.SelectColumns(YourSource, ColNameOtherList & List.Select(Table.ColumnNames(YourSource), (b)=> Text.Contains(b, [ColName]))),
     v_adIndex =Table.AddIndexColumn(v_sizeTables, "InnerIndex", [Index], Table.RowCount(v_sizeTables)),
     v_toColumns = Table.ToColumns(v_adIndex)
    ][v_toColumns]),
    toTable =   [v_combinedLists = List.Transform(List.Zip(Ad_SizeTables[Size Tables]), each List.Combine(_)),
   v_table = Table.FromColumns(v_combinedLists, ColNameOtherList & {"Item Number", "Price", "Index"})
  ][v_table],
    #"Split Column by Positions" = Table.SplitColumn(toTable, "Item Number", Splitter.SplitTextByPositions({0, 4}), {"Item Number", "Item Size"}),
    #"Sorted Rows" = Table.Sort(#"Split Column by Positions",{{"Index", Order.Ascending}}),
    #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Index"})
in
    #"Removed Columns"

 


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

@dufoq3 I've tried your updated formula but it still doesn't pull in the newly added columns. Also, the gear icon disappeared from the YourSource step.

@work_1111, use my latest code here.

  1. Import your data and name your query as MyData
  2. Edit 2nd step YourSource = Source and change Source to MyData

Now, my query is refering to your data table called MyData, so you can delete first step Source in my query (but it is not necessary - PowerQuery will ignore that step).

dufoq3_0-1706631411643.png


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

dufoq3
Super User
Super User

Hi, I'm not that skilled as @wdx223_Daniel but I built it my way:

dufoq3_0-1705687253747.png

Change 2nd step YourSource = Source (replace Source with your table reference)

 

//Move Data from Columns to Rows and split 1 column data
//https://community.fabric.microsoft.com/t5/Power-Query/Move-Data-from-Columns-to-Rows-and-split-1-column-data/m-p/3644632#M119982

let
    Source = Table.TransformColumnNames(Table.PromoteHeaders(Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bc1BCoMwFATQq0jWIpgmra5baAsqn+pOpEgbJGA2ovdvMoZYwdVMJjx+27LnrEzU6HlULGZRVJt+HN8Yq8VgKtVXL2a/Ff00qP20Spr0R/2zbVjN+u5ifzm1X1Q1r7r0pbz5UtxtSRN5scETniHy/IhSsBQwQWcp2JnbOCVCbNotzfVR4LArOOwKDlsjYRDCxQGlYClgAuMcDCFddN0P", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"(blank)" = _t, #"(blank).1" = _t, #"(blank).2" = _t, #"(blank).3" = _t, #"(blank).4" = _t, #"(blank).5" = _t, #"(blank).6" = _t])), Text.Trim),
    YourSource = Source,
    ColNameContains = Table.FromList(List.Distinct(List.Transform(List.Select(Table.ColumnNames(YourSource), each Text.Contains(_, "_Item", Comparer.OrdinalIgnoreCase)), (r)=> Text.BeforeDelimiter(r, "_"))), Splitter.SplitByNothing(), {"ColName"}),
    #"Added Index" = Table.AddIndexColumn(ColNameContains, "Index", 1, 1, Int64.Type),
    Ad_SizeTables = Table.AddColumn(#"Added Index", "Size Tables", each
    [v_sizeTables = Table.SelectColumns(YourSource, {"Item Title"} & List.Select(Table.ColumnNames(YourSource), (r)=> Text.Contains(r, [ColName]))),
     v_adIndex =Table.AddIndexColumn(v_sizeTables, "InnerIndex", [Index], Table.RowCount(v_sizeTables)),
     v_toColumns = Table.ToColumns(v_adIndex)
    ][v_toColumns]),
    toTable =   [v_combinedLists = List.Transform(List.Zip(Ad_SizeTables[Size Tables]), each List.Combine(_)),
   v_table = Table.FromColumns(v_combinedLists, {"Item", "Item Number", "Price", "Index"})
  ][v_table],
    #"Split Column by Positions" = Table.SplitColumn(toTable, "Item Number", Splitter.SplitTextByPositions({0, 4}), {"Item Number", "Item Size"}),
    #"Sorted Rows" = Table.Sort(#"Split Column by Positions",{{"Index", Order.Ascending}}),
    #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Index"})
in
    #"Removed Columns"

 


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

@dufoq3 thank you! I was able to apply this query to get my data in the format I needed. I was able to understand each step and make additional adjustments as needed. I just have one question, if I needed to added a few more columns to my table would I just  update this part of the query by adding _t, #"(blank).7" and so on?

HI @work_1111, you can use this code and edit Sample Data with gear icon:

 

dufoq3_0-1706166095064.png

 

Use this code please. I've splitted 1st step to 3. Now you are able to use gear icon. You should still refer to your data in step YourSource as I mentioned before.

 

To answer your question. No, it is not eddnough by adding _t..., because you should not edit this step in Advanced Editor - that step (Source) is just sample data.

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bc1BCoMwFATQq0jWIpgmra5baAsqn+pOpEgbJGA2ovdvMoZYwdVMJjx+27LnrEzU6HlULGZRVJt+HN8Yq8VgKtVXL2a/Ff00qP20Spr0R/2zbVjN+u5ifzm1X1Q1r7r0pbz5UtxtSRN5scETniHy/IhSsBQwQWcp2JnbOCVCbNotzfVR4LArOOwKDlsjYRDCxQGlYClgAuMcDCFddN0P", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"(blank)" = _t, #"(blank).1" = _t, #"(blank).2" = _t, #"(blank).3" = _t, #"(blank).4" = _t, #"(blank).5" = _t, #"(blank).6" = _t]),
    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
    TrimmedColumnNames = Table.TransformColumnNames(#"Promoted Headers", Text.Trim),
    YourSource = TrimmedColumnNames,
    ColNameContains = Table.FromList(List.Distinct(List.Transform(List.Select(Table.ColumnNames(YourSource), each Text.Contains(_, "_Item", Comparer.OrdinalIgnoreCase)), (r)=> Text.BeforeDelimiter(r, "_"))), Splitter.SplitByNothing(), {"ColName"}),
    #"Added Index" = Table.AddIndexColumn(ColNameContains, "Index", 1, 1, Int64.Type),
    Ad_SizeTables = Table.AddColumn(#"Added Index", "Size Tables", each
    [v_sizeTables = Table.SelectColumns(YourSource, {"Item Title"} & List.Select(Table.ColumnNames(YourSource), (r)=> Text.Contains(r, [ColName]))),
     v_adIndex =Table.AddIndexColumn(v_sizeTables, "InnerIndex", [Index], Table.RowCount(v_sizeTables)),
     v_toColumns = Table.ToColumns(v_adIndex)
    ][v_toColumns]),
    toTable =   [v_combinedLists = List.Transform(List.Zip(Ad_SizeTables[Size Tables]), each List.Combine(_)),
   v_table = Table.FromColumns(v_combinedLists, {"Item", "Item Number", "Price", "Index"})
  ][v_table],
    #"Split Column by Positions" = Table.SplitColumn(toTable, "Item Number", Splitter.SplitTextByPositions({0, 4}), {"Item Number", "Item Size"}),
    #"Sorted Rows" = Table.Sort(#"Split Column by Positions",{{"Index", Order.Ascending}}),
    #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Index"})
in
    #"Removed Columns"

 


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

@dufoq3 I'ved followed your steps the 2 additional columns are showing in my updated source, but not in the final table output. See image below for the 2 additional columns:

tem Title  Small_Item Num  Medium_Item Num  Large_Item Num  Small_Price  Medium_Price  Large_PriceManufacturer    Location
Item 1PNTRSMPNTRMDPNTRLG1.572.282.99Company AHouston
Item 1PNTRSMPPNTRMDPPNTRLGP1.812.623.44Company AHouston
Item 2TCHLSMTCHLMDTCHLLG2.653.654.65Supplier 3Dallas
Item 2TCHLSMPTCHLMDPTCHLLGP3.224.225.22Supplier 3Dallas
spinfuzer
Solution Sage
Solution Sage

Just replace source with whatever your actual source is.  The json binary thing is just a manual table created when you Press "Enter Data" in the Power Query Editor.  You can edit this manual table by clicking on the COG in the Source applied step.

 

 

 

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bc27CoAwDIXhV5HOUmhsvcwKKqgEdZOOjm6+PzaHUged/kPgI8ehxvu8MqNyxcu+bnMccxfH1IdhtKtCSFONNI3y+YdyspwwQ9cGrKSQQlv7arns7TDhsQw8loHHwTgYxEp+KCfLCTMYERjiJN4/", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Item Title" = _t, #"  Small_Item Num" = _t, #"  Medium_Item Num" = _t, #"  Large_Item Num" = _t, #"  Small_Price" = _t, #"  Medium_Price" = _t, #"  Large_Price" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Item Title", type text}, {"  Small_Item Num", type text}, {"  Medium_Item Num", type text}, {"  Large_Item Num", type text}, {"  Small_Price", type number}, {"  Medium_Price", type number}, {"  Large_Price", type number}}),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Item Title"}, "Attribute", "Value"),
    #"Added Index" = Table.AddIndexColumn(#"Unpivoted Other Columns", "Index", 0, 1, Int64.Type),
    #"Grouped Rows" = Table.Group(#"Added Index", {"Item Title", "Index"}, 
    {{"Rows", 
        each Table.FromColumns(List.Split(_[Value],3), {"Item Num", "Price"})
    }}, 
    GroupKind.Local, 
    (x,y) => Byte.From(x[Index] + 6 = y[Index])
    ),
    #"Expanded Rows" = Table.ExpandTableColumn(#"Grouped Rows", "Rows", {"Item Num", "Price"}, {"Item Num", "Price"}),
    #"Split Column by Position" = Table.SplitColumn(#"Expanded Rows", "Item Num", Splitter.SplitTextByPositions({0, 4}, false), {"Item Num.1", "Item Num.2"}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Position",{{"Item Num.1", type text}, {"Item Num.2", type text}})
in
    #"Changed Type1"

 

Key here is

1) Unpivot Other Columns than the 1st column

2) Add index from 0

3) Group By Item Title and Index

4) Group by Add 4th parameter GroupKind.Local

5) Group by 5th parameter.  custom grouping (x,y) =>(x,y) => Byte.From(x[Index] + 6 = y[Index])

6) Expand and split by 4 characters

work_1111
Helper II
Helper II

@wdx223_Daniel Is there another way to accomplish this without the binary portion?

wdx223_Daniel
Super User
Super User

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bc27CoAwDIXhV5HOUmhsvcwKKqgEdZOOjm6+PzaHUged/kPgI8ehxvu8MqNyxcu+bnMccxfH1IdhtKtCSFONNI3y+YdyspwwQ9cGrKSQQlv7arns7TDhsQw8loHHwTgYxEp+KCfLCTMYERjiJN4/", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Item Title" = _t, #"  Small_Item Num" = _t, #"  Medium_Item Num" = _t, #"  Large_Item Num" = _t, #"  Small_Price" = _t, #"  Medium_Price" = _t, #"  Large_Price" = _t]),
    Custom1 = #table({"Item Title","Item Number","Item Size","Price"},List.TransformMany(Table.ToRows(Source),each List.Transform(List.Zip(List.Split(List.Skip(_),3)),each {Text.Start(_{0},4),Text.Range(_{0},4),_{1}}),(x,y)=>{x{0}}&y))
in
    Custom1

Helpful resources

Announcements
August Power BI Update Carousel

Power BI Monthly Update - August 2025

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

August 2025 community update carousel

Fabric Community Update - August 2025

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

Top Solution Authors