Power Query how to combine multiple ranges and their subtotal information into one range

Guitarmageddon

Board Regular
Joined
Dec 22, 2014
Messages
159
I have a very messy report output that Im trying to consolidate with power query. In its old form, this report was a bunch of summary ranges for different suppliers. It is dynamic and basically just lists a bunch of tables (in range form) of data. The finance folks have just revised the report to now add a supplier number between each table. The users would like to have that supplier brought down into the range of data, for which we will then combine into one table in typical power query fashion. How would I go about doing that?

Here is a snapshot of what it looks like. What I get is some version of the ranges on the left. Various dynamic collections by supplier. The tables nested within could be any number of rows, as you can see. What I am aiming to clean the data into would be the example on the right. Any thoughts?

1687281888418.png
 

Excel Facts

Ambidextrous Undo
Undo last command with Ctrl+Z or Alt+Backspace. If you use the Undo icon in the QAT, open the drop-down arrow to undo up to 100 steps.
With range A1:D20 named Data

Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name = "Data"]}[Content],
    lst = List.Zip(List.Skip(List.Accumulate(Source[Column1], {{0,-1}}, (s,c)=> let ll = List.Last(s) in 
        if c=null then if Number.IsEven(ll{1}) then s & {{ll{0}+1, ll{1}+1}} else s & {{ll{0}, ll{1}+1}} else s & {ll}))){0},
    Custom1 = Table.FromColumns(Table.ToColumns(Source) & {lst}),
    tbl = Table.Group(Custom1, {"Column5"}, {{"All", each _}}),
    tbl1 = Table.TransformColumns(tbl, {"All", each 
        let 
            tbl2 = Table.SelectRows(_, each ([Column1] <> null)),
            tbl3 = Table.AddColumn(tbl2, "Supplier", each tbl2[Column2]{0}),
            tbl4 = Table.AddColumn(tbl3, "Supplier Number", each tbl2[Column2]{1}),
            tbl5 = Table.Skip(tbl4,3),
            tbl6 = Table.RemoveColumns(tbl5,{"Column5"}),
            tbl7 = Table.ReorderColumns(tbl6,{"Supplier", "Supplier Number", "Column1", "Column2", "Column3", "Column4"})
        in 
            Table.RenameColumns(tbl7,{{"Column1", "Color"}, {"Column2", "Description"}, {"Column3", "Cost"}, {"Column4", "Retail"}})
    }),
    Result = Table.Combine(tbl1[All])
in
    Result

produces the table in G1:G7

delme.xlsx
ABCDEFGHIJKLM
1SupplierSupplier ASupplierSupplier NumberColorDescriptionCostRetail
2Supplier Number1234Supplier A1234RedABC12
3Supplier B2345BlueDEF23
4ColorDescriptionCostRetailSupplier B2345GreenGHI58
5RedABC12Supplier B2345YellowJKL35
6Supplier C3456GreyMNO23
7SupplierSupplier BSupplier C3456RedPQR58
8Supplier Number2345
9
10ColorDescriptionCostRetail
11BlueDEF23
12GreenGHI58
13YellowJKL35
14
15SupplierSupplier C
16Supplier Number3456
17
18ColorDescriptionCostRetail
19GreyMNO23
20RedPQR58
21
Sheet5
 
Upvote 0
A little simpler version

Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name = "Data"]}[Content],
    AddIndex = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
    AddCustom = Table.AddColumn(AddIndex, "Custom", each if [Column1]="Supplier" then [Index] else null),
    FillDown = Table.FillDown(AddCustom,{"Custom"}),
    tbl = Table.Group(FillDown, {"Custom"}, {{"All", each _}}),
    tbl1 = Table.TransformColumns(tbl, {"All", each 
        let 
            tbl2 = Table.SelectRows(_, each ([Column1] <> null)),
            tbl3 = Table.AddColumn(tbl2, "Supplier", each tbl2[Column2]{0}),
            tbl4 = Table.AddColumn(tbl3, "Supplier Number", each tbl2[Column2]{1}),
            tbl5 = Table.Skip(tbl4,3),
            tbl6 = Table.RemoveColumns(tbl5,{"Index", "Custom"}),
            tbl7 = Table.ReorderColumns(tbl6,{"Supplier", "Supplier Number", "Column1", "Column2", "Column3", "Column4"})
        in 
            Table.RenameColumns(tbl7,{{"Column1", "Color"}, {"Column2", "Description"}, {"Column3", "Cost"}, {"Column4", "Retail"}})
    }),
    Result = Table.Combine(tbl1[All])
in
    Result
 
Upvote 2
Solution
A little simpler version

Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name = "Data"]}[Content],
    AddIndex = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
    AddCustom = Table.AddColumn(AddIndex, "Custom", each if [Column1]="Supplier" then [Index] else null),
    FillDown = Table.FillDown(AddCustom,{"Custom"}),
    tbl = Table.Group(FillDown, {"Custom"}, {{"All", each _}}),
    tbl1 = Table.TransformColumns(tbl, {"All", each
        let
            tbl2 = Table.SelectRows(_, each ([Column1] <> null)),
            tbl3 = Table.AddColumn(tbl2, "Supplier", each tbl2[Column2]{0}),
            tbl4 = Table.AddColumn(tbl3, "Supplier Number", each tbl2[Column2]{1}),
            tbl5 = Table.Skip(tbl4,3),
            tbl6 = Table.RemoveColumns(tbl5,{"Index", "Custom"}),
            tbl7 = Table.ReorderColumns(tbl6,{"Supplier", "Supplier Number", "Column1", "Column2", "Column3", "Column4"})
        in
            Table.RenameColumns(tbl7,{{"Column1", "Color"}, {"Column2", "Description"}, {"Column3", "Cost"}, {"Column4", "Retail"}})
    }),
    Result = Table.Combine(tbl1[All])
in
    Result
This is very good!
 
Upvote 0
@JGordon11 Thanks so much for working on this solution. So In my efforts to provide a simple skeleton of the source data I think I may not have done it justice, having a bit of trouble implementing your solution. Now that I have figured out the XL2BB add-in, I think I can provide a much better analog for what the data is. I have included a small sampling below. As you can see, there is the "supplier or party" and the location type info about each little range of data. And this goes on for dozens of variable-length suppliers throughout this sheet...Also a lot of annoying merged cells, but that is easy enough to clear with PQ.
Here is that sample in raw form. The cells 51 and up to the beginning are mostly junk and I would be clearing them out with the query.
InvoiceAging_Payables Invoice Aging Report Excel.xlsx
ABCDEFGHIJKLMNOPQRSTUVWXYZ
52CurrencyUSD
53
54
55Supplier or PartySUPPLIER A SAMPLE
56
57Supplier Number1234
58
59SiteDALLASDALLASTX
60
61Invoice NumberDue DateDaysPercentageRemaining1 Month2 Months3 MonthsOver 3 Months
62DueUnpaidAmountOverdueOverdueOverdueOverdue
63
64123456/1/2319100-225.00-225.000.000.000.00
65
66
67Total for Site DALLAS-225.00-225.000.000.000.00
68100 %0 %0 %0 %
69
70
71Supplier or PartySUPPLIER B SAMPLE
72
73Supplier Number12948
74
75SiteDALLAS2DALLASTX
76
77Invoice NumberDue DateDaysPercentageRemaining1 Month2 Months3 MonthsOver 3 Months
78DueUnpaidAmountOverdueOverdueOverdueOverdue
79
80CN8579596/15/235100-45.00-45.000.000.000.00
81
82CN8584056/15/235100-45.00-45.000.000.000.00
83
84
85Total for Site DALLAS2-90.00-90.000.000.000.00
86100 %0 %0 %0 %
87
88
89Supplier or PartySUPPLER C
90
91Supplier Number291010
92
93SiteDALLAS3DALLASTX
94
95Invoice NumberDue DateDaysPercentageRemaining1 Month2 Months3 MonthsOver 3 Months
96DueUnpaidAmountOverdueOverdueOverdueOverdue
97
98CN8580446/15/235100-40.00-40.000.000.000.00
99
100
101Total for Site DALLAS3-40.00-40.000.000.000.00
102100 %0 %0 %0 %
103
104
105Supplier or PartySUPPLIER D
106
107Supplier Number303030
108
109SiteCHICAGOCHICAGOIL
110
111Invoice NumberDue DateDaysPercentageRemaining1 Month2 Months3 MonthsOver 3 Months
112DueUnpaidAmountOverdueOverdueOverdueOverdue
113
1149876/7/22378100-129.720.000.000.00-129.72
115
11698766/9/22376100-51.980.000.000.00-51.98
117
118987656/22/22363100-82.600.000.000.00-82.60
119
120109876.16676/22/22363100-923.440.000.000.00-923.44
121
122158765.16677/8/22347100-573.150.000.000.00-573.15
123
124207654.16677/11/22344100-256.080.000.000.00-256.08
125
126232098.66677/29/22326100-372.340.000.000.00-372.34
127
128280987.66678/9/22315100-171.090.000.000.00-171.09
129
130329876.66678/25/22299100-103.650.000.000.00-103.65
131
132354321.166710/3/22260100-122.810.000.000.00-122.81
133
134
135Total for Site CHICAGO-12,325.770.000.000.00-12,325.77
1360 %0 %0 %100 %
137
138
Sheet1


And just a quick screen snip to show you how it looks up to the start of the data....
1687347215178.png
 
Upvote 0
And once brought into power query, initially you can see how all those nasty merged columns shake out. Lots of nulls but in places where filtering a null in one column would omit the data in others... Here I have chunked out the first few examples of data, with the blue being that "header" portion. Im hoping this helps clarify. The columns referencing the months overdue extend well out to the right to columns 27 or so.
1687347982007.png
 
Upvote 0
Try this.
I edited @JGordon11's beautiful query to adapt the solution to your actual data structure. All credits goes to @JGordon11.

"Data" named range for the sample data: A1:W136
Since many merged cells are in the source file, this might look confusing, but it entirely uses the main logic in @JGordon11's solution. Any change in the data range might make this code unusable.

Notes:
  • I also added the Site column as it looks like it is necessary.
  • Skipped 54 rows at the beggining according to the new data structure.

Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name = "Data"]}[Content],
    SkipRows = Table.Skip(Source, 54),
    SkipColumns = Table.RemoveColumns(SkipRows,{"Column22", "Column23"}),
    AddIndex = Table.AddIndexColumn(SkipColumns, "Index", 0, 1, Int64.Type),
    AddCustom = Table.AddColumn(AddIndex, "Custom", each if [Column1]="Supplier or Party" then [Index] else null),
    FillDown = Table.FillDown(AddCustom,{"Custom"}),
    tbl = Table.Group(FillDown, {"Custom"}, {{"All", each _}}),
    tbl1 = Table.TransformColumns(tbl, {"All", each 
        let 
            tbl2 = Table.SelectRows(_, each ([Column1] <> null and not Text.Contains(Text.From([Column1]), "Total"))),
            tbl3 = Table.AddColumn(tbl2, "Supplier or Party", each tbl2[Column4]{0}),
            tbl4 = Table.AddColumn(tbl3, "Supplier Number", each tbl2[Column4]{1}),
            tbl5 = Table.AddColumn(tbl4, "Site", each tbl2[Column4]{2}),
            tbl6 = Table.Skip(tbl5,4),
            tbl7 = Table.RemoveColumns(tbl6,{"Index", "Custom"})
        in 
            tbl7
    }),
    CombineAll = Table.Combine(tbl1[All]),
    RenameColumns = Table.RenameColumns(CombineAll,{{"Column1", "Invoice Number"}, {"Column2", "Due Date"}, {"Column3", "Days Due"}, {"Column5", "Percentage Update"}, {"Column8", "Remaining Amount"}, {"Column12", "1 Month Overdue"}, {"Column14", "2 Months Overdue"}, {"Column17", "3 Months Overdue"}, {"Column21", "Over 3 Months Overdue"}}),
    RemoveColumns = Table.RemoveColumns(RenameColumns,{"Column4", "Column6", "Column7", "Column9", "Column10", "Column11", "Column13", "Column15", "Column16", "Column18", "Column19", "Column20"}),
    ReorderColumns = Table.ReorderColumns(RemoveColumns,{"Supplier or Party", "Supplier Number", "Site", "Invoice Number", "Due Date", "Days Due", "Percentage Update", "Remaining Amount", "1 Month Overdue", "2 Months Overdue", "3 Months Overdue", "Over 3 Months Overdue"}),
    Result = Table.TransformColumnTypes(ReorderColumns,{{"Supplier or Party", type text}, {"Supplier Number", type text}, {"Site", type text}, {"Invoice Number", type text}, {"Due Date", type date}, {"Days Due", Int64.Type}, {"Remaining Amount", Currency.Type}, {"1 Month Overdue", Currency.Type}, {"2 Months Overdue", Currency.Type}, {"3 Months Overdue", Currency.Type}, {"Over 3 Months Overdue", Currency.Type}, {"Percentage Update", type number}})     
in
    Result
 
Upvote 1
Wow! Superstars @smozgur and @JGordon11

Playing with this implementation and will maybe have a question or two momentarily...... Digging in to the "skip columns" thing now, as there seems to be some data at the end of the spreadsheet I did not see. But I suspect that could be an unneeded totals column down at the very very end of the data
 
Upvote 0
I only made simple edits in the existing query while @JGordon11 was not around :) There is only one superstar in this thread - @JGordon11!

Playing with this implementation and will maybe have a question or two momentarily...... Digging in to the "skip columns" thing now, as there seems to be some data at the end of the spreadsheet I did not see. But I suspect that could be an unneeded totals column down at the very very end of the data
In the meantime, please don't forget to mark the initial answer (post #3) as the solution to this question as it will also help future readers.
 
Upvote 1
Ok I went in and happily marked that as a solution. This is going to be something very powerful to use when I have really annoying grouped source data in this fashion. And there are others...

Using the indexing function with the grouping like you did taught me a lot, thats huge! Thanks again.
 
Upvote 0

Forum statistics

Threads
1,215,105
Messages
6,123,118
Members
449,096
Latest member
provoking

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top