Excel - Struggling with complex Index/Match/Match lookup - excel

I've got a table with 9 columns and about 6000 rows. Each row has a price as the last column. Some of those prices are 0.00 when they should be a value.
In another worksheet I have the "original" table with about 3700 rows. The prices I need are in those rows. However, the original table has the prices horizontally within the rows, each next to a cell with specific range of gals. Basically the table I have has unique rows for every location/gal range/price combo, the original has all gal range/prices sequentially in single location rows
For example, a row in the original table looks like this:
... / 1-2000 / 2.8383 / 2001-4000 / 2.5382 / ...
Where as in my new table they look like this:
... / 1-2000 / 2.8383
... / 20001-4000 / 2.5382
etc
Everything is the same in my new table and the original table EXCEPT those gal ranges and prices.
What I'm trying to do is use an array multiple criteria Index/Match (based on 3 cells in both my new table and the original) to lookup the row, find the value that matches the range of gals, and then take the price to the right of that gal range cell.
Here is a row I'm trying to get the value for in my new table:
Here is the row with the value I need in the original table:
Here's a closer look at the formula I've constructed:
INDEX(old!$A$2:$Q$3755,MATCH(1,(A29=old!$A$2:$A$3755)*(F29=old!$F$2:$F$3755)*(G29=old!$G$2:$G3755),1),MATCH(H29,old!$J$2:$Q$3755,1)+1)
The first standard Index/Match part works great... I Index the table and Match to find the row. If I just enter a number for the Col (e.g., 1, 2, 3) it'll return the value from the corresponding cell PERFECTLY. However, I can't seem to make the Col match part work... I continuously get REF and N/A errors.
Is there some trick to doing a two way search? It seems like it should be a simple thing to just find that value in the row and take the next cell after if...?
One catch here is that the gal range value I'm looking for is NOT unique... there are at least 20 other references that have the same range (e.g., "1-2000"). Is there a way to limit the col match to just the row I find with the row match?
Any help is GREATLY appreciated.
Thanks,
Rick

One way to tackle this case is to use #powerquery.
Please refer to this article to find out how to use Power Query on your version of Excel. It is availeble in Excel 2010 Professional Plus and later versions. My demonstration is using Excel 2016.
The steps are:
Load/Add your old data to the Power Query Editor. My sample data only has one row but it is same for thousands of rows;
Use Merge Columns function under Transform tab to merge the first 7 columns with a delimiter say semicolon ;;
Repeat Merge Columns for each pair of GALLONS and TOTAL PRICES with the same delimiter ;. If you have done it correctly you should have something like the following:
Use Unpivot Columns function under Transform tab to unpivot all the merged columns for GALLONS;TOTAL PRICE, then remove the Attribute column;
Use Split Column function under the Transform tab to split each column by delimiter ;. If you have done it correctly you should have something like the following:
Make a duplicate column of the GALLONS range column (which is the second last column in the above screen-shot), and then split the original GALLONS range column by delimiter -. Then you should have:
Rename the column headers as desired;
Close & Load the new table to a new worksheet (by default) or you can change the default setting and create a connection for the new table and load it to a desired location in your workbook.
The second table is the output table and you can do INDEX+MATCH from this new table which should be much easier than from the old table. If the data are identical but just in different structure then you may just use the output table without worrying about looking up missing prices.
I have added a test line to my source table and here is the Refreshed output with a click of button:
Here are the power query M codes behind the scene for reference only. All steps are performed using built-in functions of the editor which is quite straight forward.
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"IATA", Int64.Type}, {"ST", type text}, {"FUELER", type text}, {"UPDATED", type datetime}, {"RESTRICTIONS", type text}, {"BASEF UEL", type text}, {"NOTES", type any}, {"GALLONS1", type text}, {"TOTAL PRICES1", type text}, {"GALLONS2", type text}, {"TOTAL PRICES2", type text}, {"GALLONS3", type text}, {"TOTAL PRICES3", type text}, {"GALLONS4", type text}, {"TOTAL PRICES4", type text}, {"GALLONS5", type text}, {"TOTAL PRICES5", type text}}),
#"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Changed Type", {{"IATA", type text}, {"UPDATED", type text}, {"NOTES", type text}}, "en-AU"),{"IATA", "ST", "FUELER", "UPDATED", "RESTRICTIONS", "BASEF UEL", "NOTES"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged"),
#"Merged Columns1" = Table.CombineColumns(#"Merged Columns",{"GALLONS1", "TOTAL PRICES1"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.1"),
#"Merged Columns2" = Table.CombineColumns(#"Merged Columns1",{"GALLONS2", "TOTAL PRICES2"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.2"),
#"Merged Columns3" = Table.CombineColumns(#"Merged Columns2",{"GALLONS3", "TOTAL PRICES3"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.3"),
#"Merged Columns4" = Table.CombineColumns(#"Merged Columns3",{"GALLONS4", "TOTAL PRICES4"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.4"),
#"Merged Columns5" = Table.CombineColumns(#"Merged Columns4",{"GALLONS5", "TOTAL PRICES5"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged.5"),
#"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Merged Columns5", {"Merged"}, "Attribute", "Value"),
#"Removed Columns" = Table.RemoveColumns(#"Unpivoted Columns",{"Attribute"}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Removed Columns", "Merged", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Merged.1", "Merged.2", "Merged.3", "Merged.4", "Merged.5", "Merged.6", "Merged.7"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Merged.1", Int64.Type}, {"Merged.2", type text}, {"Merged.3", type text}, {"Merged.4", type datetime}, {"Merged.5", type text}, {"Merged.6", type text}, {"Merged.7", type text}}),
#"Split Column by Delimiter1" = Table.SplitColumn(#"Changed Type1", "Value", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Value.1", "Value.2"}),
#"Changed Type2" = Table.TransformColumnTypes(#"Split Column by Delimiter1",{{"Value.1", type text}, {"Value.2", type text}}),
#"Duplicated Column" = Table.DuplicateColumn(#"Changed Type2", "Value.1", "Value.1 - Copy"),
#"Reordered Columns" = Table.ReorderColumns(#"Duplicated Column",{"Merged.1", "Merged.2", "Merged.3", "Merged.4", "Merged.5", "Merged.6", "Merged.7", "Value.1 - Copy", "Value.1", "Value.2"}),
#"Split Column by Delimiter2" = Table.SplitColumn(#"Reordered Columns", "Value.1", Splitter.SplitTextByDelimiter("-", QuoteStyle.Csv), {"Value.1.1", "Value.1.2"}),
#"Changed Type3" = Table.TransformColumnTypes(#"Split Column by Delimiter2",{{"Value.1.1", Int64.Type}, {"Value.1.2", Int64.Type}}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type3",{{"Merged.1", "IATA"}, {"Merged.2", "ST"}, {"Merged.3", "FUELER"}, {"Merged.4", "UPDATED"}, {"Merged.5", "RESTRICTIONS"}, {"Merged.6", "BASEF UEL"}, {"Merged.7", "NOTES"}, {"Value.1 - Copy", "GALLONS"}, {"Value.1.1", "Min Fuel"}, {"Value.1.2", "Max Fuel"}, {"Value.2", "TOTAL PRICE"}}),
#"Changed Type4" = Table.TransformColumnTypes(#"Renamed Columns",{{"UPDATED", type date}})
in
#"Changed Type4"

This can be done with Index/Match, but you have to keep your cool.
My Screenshot for reference
The formula in cell F7 is
=INDEX(
INDEX(A2:A3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0))
:INDEX(L2:L3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0)),
MATCH(E7,
INDEX(A2:A3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0))
:INDEX(L2:L3,MATCH(B7&C7&D7,INDEX(A2:A3&C2:C3&F2:F3,0),0)),0)
+1)
To explain: First we build an Index on column A finding the row with a concatenation of the three values. That is combined with the union operator : with an Index on column L, using the same Match.
This Index will return one row of data, from column A to L. It is then used as the range argument for another Index/Match, where inside that row of data Match looks for the "g value" and adds 1 to move one to the right of the found cell.
Note that you don't want whole columns in this formula, since it will be very slow to calculate.

Here is another approach, not using Index/Match at all, but Sumproduct instead. in F7:
=SUMPRODUCT($B$2:$L$3,($A$2:$A$3=B7)*($C$2:$C$3=C7)*($F$2:$F$3=D7)*($A$2:$K$3=E7))
Note that the offset of one column is achieved with the first range from B to L and the last range from A to K.

Related

Can Power Query tabularize data with different levels of sub-total detail?

I am a proficient Excel user but new to Power Queries - they seem powerful, but I am hung up tabularizing a Quickbooks report.
In short, the data includes several columns of hierarchy all expanded to the lowest node and includes sub-headers and sub-totals. I need to tabularize this data, but when one section has detail 3 columns deep and the next section only goes 2 columns deep, "Fill Down" (in the 3rd column) incorrectly fills sub-headers in a different section.
If this does not make sense, I put together a screenshot that hopefully illustrates this question a little better:
Thank you in advance,
Dillon
This is a PivotTable right?
Go to "Design" -> drop down "Report Layout" -> Show in Tabular Form
If what you are showing is not a pivot table, but rather the output from Quicken, then you can:
Fill Down Column 1 only
Group by Column 1
Use a custom aggregation to Fill down column 2 in each subtable
Then expand the subtables
Remove the Amount rows that contain null
reset the data types
let
//cahnge table name in next line to the real table name in your workbook
Source = Excel.CurrentWorkbook(){[Name="Table3"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{
{"Column1", type text}, {"Column2", type text}, {"Item", type text}, {"Amount", Currency.Type}}),
//Fill down the main group
#"Filled Down" = Table.FillDown(#"Changed Type",{"Column1"}),
//group by Column 1; then fill down subgroup in column 2
group = Table.Group(#"Filled Down","Column1",{
{"subGroup", each Table.FillDown(_,{"Column2"})}
}),
#"Expanded subGroup" = Table.ExpandTableColumn(group, "subGroup", {"Column2", "Item", "Amount"}, {"Column2", "Item", "Amount"}),
#"Filtered Rows" = Table.SelectRows(#"Expanded subGroup", each ([Amount] <> null)),
#"Changed Type1" = Table.TransformColumnTypes(#"Filtered Rows",{{"Column2", type text}, {"Item", type text}, {"Amount", Currency.Type}})
in
#"Changed Type1"

Writing a query that can have excel fill in and consolidate unpopulated fields within a group of duplicates?

I have a contact info dataset (large) that contains lots of semi-duplicate rows that I'd like to condense into as little rows as possible. Attached is a sample of what I'm talking about.
The blue table on the left is smaller scale example of what I'm currently working with. The orange table on the right is what I would like the table to look like.
I want to write a query that will be able to select an ID that has multiple rows, and within that selection, assess whether values can be moved into a parent row that has unpopulated cells (see ID "4" and how I condensed those three rows of data into one by filling in blanks and consolidating duplicates).
An important point of emphasis is how to perform this task without it being a blanket statement for all duplicates in the entire worksheet. Ultimately I want to perform this task for the entire worksheet, but I want excel to first isolate a single ID and then execute the aforementioned task, rather than evaluating the criteria based on all duplicate IDs. ((If that makes sense))
One other condition I would like to have is for certain columns where multiple rows under the same ID have different values, is to allocate that data into a subsequent column (see Tags & Tags2 columns under ID "1") instead of overriding a cell.
I only want to do this ^ for 2 columns; for the others, have it keep them as separate rows.
This sounds like a task for Power Query, but my knowledge is limited in that realm. Any help on how to construct a query that accomplish this task is much appreciated. Thanks.
This seems to work fine
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Title", type text}, {"Company", type text}, {"Phone", type text}, {"Phone2", type any}, {"Street Address", type any}, {"City", type text}, {"Tags", type text}}),
// group, then unpivot, remove duplicates
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {{"Data", each Table.Distinct(Table.UnpivotOtherColumns(_, {"ID"}, "Attribute", "Value"), {"Attribute", "Value"}), type table}}),
// combine all the tags into one cell for later splitting
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom", each Table.Group([Data], {"ID", "Attribute"}, {{"Data", each Text.Combine([Value],","), type text}})),
#"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom", "Custom", {"Attribute", "Data"}, {"Attribute", "Data.1"}),
// replace null with Title to preserve rows with no data
#"Replaced Value" = Table.ReplaceValue(#"Expanded Custom",null,"Title",Replacer.ReplaceValue,{"Attribute"}),
#"Removed Columns" = Table.RemoveColumns(#"Replaced Value",{"Data"}),
#"Pivoted Column" = Table.Pivot(#"Removed Columns", List.Distinct(#"Removed Columns"[Attribute]), "Attribute", "Data.1"),
// split the Tags column into any number of columns as needed
#"Replaced Value1" = Table.ReplaceValue(#"Pivoted Column",null,"xxx",Replacer.ReplaceValue,{"Tags"}),
DynamicColumnList = List.Transform({1 ..List.Max(Table.AddColumn(#"Replaced Value1","Custom", each List.Count(Text.PositionOfAny([Tags],{","},Occurrence.All)))[Custom])+1}, each "Tags." & Text.From(_)),
#"Split Column by Delimiter" = Table.SplitColumn( #"Pivoted Column", "Tags", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), DynamicColumnList)
in #"Split Column by Delimiter"
You can get your desired output from Power Query using just the Table.Group function.
I have assumed:
Output columns are only as you show
Input columns don't have anything in Phone2 and Tags2
If that is not the case, simple modifications are possible
If there are more distinct entities that columns for the output, they will be output in a single column concatenated.
In other words, if you had three tags; the first one would be in the Tags column and the second and third concatenated with a comma in the Tags 2 column.
I did it this way because, since you show no examples, I'm not quite sure how you want things lined up if you have, for example, multiple phones and multiple tags.
Note: If you want to restrict this to just one ID, just insert a filtering step at the beginning
M Code
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Title", type text}, {"Company", type text}, {"Phone", type text}, {"Phone2", type any}, {"Street Address", type text}, {"City", type text}, {"Tags", type text}, {"Tags2", type any}}),
//Group by ID then
//Depending on how many columns available in results table, will
//either concatenate, multiple non-duplicate rows, or put them in separate columns
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {
{"Title", each Text.Combine(List.Distinct([Title]),", ")},
{"Company", each Text.Combine(List.Distinct([Company]),", ")},
{"Phone", each try List.RemoveNulls([Phone]){0} otherwise null},
{"Phone 2", each Text.Combine(List.RemoveFirstN(List.RemoveNulls(List.Distinct([Phone])),1),", ")},
{"City", each Text.Combine(List.Distinct([City]),", ")},
{"Tags", each try List.RemoveNulls([Tags]){0} otherwise null},
{"Tags 2", each Text.Combine(List.RemoveFirstN(List.RemoveNulls(List.Distinct([Tags])),1),", ")}
})
in
#"Grouped Rows"

How to consolidate rows of data in excel

I am trying to consolidate rows when they have the same ID, Order, and Class. However, the consolidated row needs sum the length, AND input the correct begin and end. So the consolidated row will have the begin value of the first row, and the end value of the last row Please check the image to see what I mean.
I'm pretty sure I can achieve the summing of the length using SUMIF, but I can't figure out how to input the correct begin and end values into the consolidated row.
Is this even possible with excel? I can't use pivot tables because I'm not simply trying sum the length, I want the columns to remain the same, just to consolidate the rows accordingly. Any help will be much appreciated!
The left is what I have, the right is what I am trying to achieve:
In your example, it seems the begin and end that you want are the min and max respectively, and I used that in the approach.
Relatively simple to do with Power Query, which is available in Excel 2010+.
Select the ID, Order and Class columns
Group By
For Aggregations have min of begin; max of end; and sum of length
Move the Class column back to the end
Voila!
This can all be done quickly from the UI
M-Code
let
Source = Excel.CurrentWorkbook(){[Name="Table7"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Order", Int64.Type}, {"begin", Int64.Type}, {"end", Int64.Type}, {"length", Int64.Type}, {"class", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID", "Order", "class"}, {{"Begin", each List.Min([begin]), type number}, {"End", each List.Max([end]), type number}, {"Length", each List.Sum([length]), type number}}),
#"Reordered Columns" = Table.ReorderColumns(#"Grouped Rows",{"ID", "Order", "Begin", "End", "Length", "class"})
in
#"Reordered Columns"
For completeness: If, perchance, you really need to use the First and Last Rows within each group for Begin and End, instead of Min/Max, you can use the following code.
In the group by step, instead of aggregating begin/end by max/min, you choose an aggregation of All Rows. This will create a table which includes the begin and end entries for each group. You can then extract the first and last entries using the List.First and List.Last functions.
The code for the custom columns:
List.First(Table.Column([#"Start/End"],"begin"))
List.Last(Table.Column([#"Start/End"],"end"))
M-Code
let
Source = Excel.CurrentWorkbook(){[Name="Table7"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Order", Int64.Type}, {"begin", Int64.Type}, {"end", Int64.Type}, {"length", Int64.Type}, {"class", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID", "Order", "class"}, {{"Length", each List.Sum([length]), type number}, {"Start/End", each _, type table [ID=number, Order=number, begin=number, end=number, length=number, class=number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Begin", each List.First(Table.Column([#"Start/End"],"begin"))),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "End", each List.Last(Table.Column([#"Start/End"],"end"))),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom1",{"Start/End"}),
#"Reordered Columns" = Table.ReorderColumns(#"Removed Columns",{"ID", "Order", "Begin", "End", "Length", "class"})
in
#"Reordered Columns"
By the way, you can come pretty close with a regular Pivot Table (especially if you can use Min/Max for the begin/end). It's not as flexible, though, and I don't think you can order the columns the way you have shown.
Below is a simple pivot table.
You drag ID, Order and class to the Rows area.
You drag Begin, End and Length to the Values area applying Min, Max and Sum.
Then Show the layout in Tabular form; turn off the grand totals and subtotals, and you have:
Option with formulas - in the simplest way, copy the table to a new location and use Remove duplicates to leave unique values in the Id, Order, and Class columns. Next fill the columns with the following formulas:
Begin (array formula):
{=INDEX($C$2:$C$9,MIN(IF(($A$2:$A$9=H2)*($B$2:$B$9=I2)*($F$2:$F$9=M2),ROW($A$2:$A$9)-MIN(ROW($A$2:$A$9))+1)),0)}
End (array formula):
{=INDEX($D$2:$D$9,MAX(IF(($A$2:$A$9=H2)*($B$2:$B$9=I2)*($F$2:$F$9=M2),ROW($A$2:$A$9)-MIN(ROW($A$2:$A$9))+1)),0)}
Length (conventional formula):
=SUMPRODUCT($E$2:$E$9*($A$2:$A$9=H2)*($B$2:$B$9=I2)*($F$2:$F$9=M2))
Array formulas after editing is confirmed by pressing ctrl + shift + enter

How do we aggregate time series in Excel?

Given the following time series of cashflow, how can I aggreate them into a cumulative time series of cashflow in Excel, ideally by using array formula only and without VBA macro?
Specifically, I was given this time series of cashflow for each transaction:
Given the inputs (in column F) for the number of transactions in each period, I would like to be able to calculate the aggregated time series of total cashflow (in column G, highlighted in yellow), ideally by using array formula only and without VBA macro?
Note: Column H to J are for illustrations only to show how column G should be calculated, I don't want to have them in my final spreadsheet.
Thank you very much for your help!
I believe you can do it by formula - most easily by reversing the cash flows and multiplying by the current and previous 5 transactions:
=SUMPRODUCT(INDEX(F:F,MAX(ROW()-5,3)):F16*INDEX(C:C,MAX(11-ROW(),3)):$C$8)
in G3.
This is an ordinary non-array formula.
OK Put this array formula in G3:
=IFERROR(SUMPRODUCT(INDEX($B$2:$B$7,N(IF({1},MODE.MULT(IF(INDEX(F:F,MAX(ROW()-5,3)):F3>0,(ROW()-ROW(INDEX(F:F,MAX(ROW()-5,3)):F3)+1)*{1,1}))))),INDEX(INDEX(F:F,MAX(ROW()-5,3)):F3,N(IF({1},MODE.MULT(IF(INDEX(F:F,MAX(ROW()-5,3)):F3>0,(ROW(INDEX(F:F,MAX(ROW()-5,3)):F3)-MIN(ROW(INDEX(F:F,MAX(ROW()-5,3)):F3))+1)*{1,1})))))),0)
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode. Then copy down.
Once Microsoft relaeases FILTER and SEQUENCE it can be shortened:
=IFERROR(SUMPRODUCT(INDEX($B$2:$B$7,FILTER(SEQUENCE(ROW()-MAX(ROW()-5,3)+1,,ROW()-MAX(ROW()-5,3)+1,-1),INDEX(F:F,MAX(ROW()-5,3)):F3>0)),FILTER(INDEX(F:F,MAX(ROW()-5,3)):F3,INDEX(F:F,MAX(ROW()-5,3)):F3>0)),0)
This can also be done in Power Query.
Please refer to this article to find out how to use Power Query on your version of Excel. It is available in Excel 2010 Professional Plus and later versions. My demonstration is using Excel 2016.
Steps are:
Load both tables being the time series of cash-flow and your 2-column output table to the power query editor, then you should have:
For the first table, merged the Period column with Cashflow column with semicolon ; as the delimiter;
Transpose the column/table, then merge the columns with comma , as the delimiter;
Add a custom column use this formula ="Connector" which will fill the column with the word Connector, then you should have:
For the second table, also add a custom column use the same formula ="Connector" which will fill the column with the word Connector;
Merge the second table with the first table using the Custom column as the connection, then expand the new column to show the Merged column from the first table, then you should have:
Remove the Custom column, then split the Merged column by delimiter comma , and put the results into Rows;
Split the Merged column again by delimiter semicolon ; to separate the Period and Cashflow from the first table;
Add a custom column to calculate the New Period being =[Period]+[Merged.1];
Add another custom column to calculate the Cashflow being =[#"# Tran"]*[Merged.2], then you should have something like the following:
Group/sum the Cashflow column by New Period.
Once done you can Close & Load the result to a new worksheet (by default). If you want to show the # Trans column in the final output, you can make a duplicate of your second table before making any changes, and then merge it with the final output table by the Period column to show the corresponding number of transactions.
Here are the power query M codes for the first table:
let
Source = Excel.CurrentWorkbook(){[Name="Tbl_CFS"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Period", Int64.Type}, {"Cashflow", Int64.Type}}),
#"Merged Columns1" = Table.CombineColumns(Table.TransformColumnTypes(#"Changed Type", {{"Period", type text}, {"Cashflow", type text}}, "en-AU"),{"Period", "Cashflow"},Combiner.CombineTextByDelimiter(";", QuoteStyle.None),"Merged"),
#"Transposed Table" = Table.Transpose(#"Merged Columns1"),
#"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Transposed Table", {{"Column1", type text}, {"Column2", type text}, {"Column3", type text}, {"Column4", type text}, {"Column5", type text}, {"Column6", type text}}, "en-AU"),{"Column1", "Column2", "Column3", "Column4", "Column5", "Column6"},Combiner.CombineTextByDelimiter(",", QuoteStyle.None),"Merged"),
#"Added Custom" = Table.AddColumn(#"Merged Columns", "Custom", each "Connector")
in
#"Added Custom"
And here are the codes for the second table:
let
Source = Excel.CurrentWorkbook(){[Name="Tbl_Total"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Period", Int64.Type}, {"# Tran", Int64.Type}}),
#"Added Custom" = Table.AddColumn(#"Changed Type", "Custom", each "Connector"),
#"Merged Queries" = Table.NestedJoin(#"Added Custom", {"Custom"}, Tbl_CFS, {"Custom"}, "Tbl_CFS", JoinKind.LeftOuter),
#"Expanded Tbl_CFS" = Table.ExpandTableColumn(#"Merged Queries", "Tbl_CFS", {"Merged"}, {"Merged"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded Tbl_CFS",{"Custom"}),
#"Split Column by Delimiter" = Table.ExpandListColumn(Table.TransformColumns(#"Removed Columns", {{"Merged", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), let itemType = (type nullable text) meta [Serialized.Text = true] in type {itemType}}}), "Merged"),
#"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Merged", type text}}),
#"Split Column by Delimiter1" = Table.SplitColumn(#"Changed Type1", "Merged", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), {"Merged.1", "Merged.2"}),
#"Changed Type2" = Table.TransformColumnTypes(#"Split Column by Delimiter1",{{"Merged.1", Int64.Type}, {"Merged.2", Int64.Type}}),
#"Added Custom1" = Table.AddColumn(#"Changed Type2", "New Period", each [Period]+[Merged.1]),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Cashflow", each [#"# Tran"]*[Merged.2]),
#"Grouped Rows" = Table.Group(#"Added Custom2", {"New Period"}, {{"Sum", each List.Sum([Cashflow]), type number}})
in
#"Grouped Rows"
All steps are using built-in functions so should be straight forward and easy to execute. Let me know if there is any question. Cheers :)

Need Pivot Table for Columns that Have Comma Separated Values

So, I found a couple other solutions to similar questions I have, but not quite exact. I am interpreting survey results in Excel where the survey tool (Qualtrics) has placed responses from multiple select questions ("select all that apply") in a single cell, comma separated. I need counts of the individual responses calculated in a Pivot Table, where I will also take totals from some respondent demographics I'm going to add to the response spreadsheet. What I am trying to do is very similar to this:
Split comma separated entries to new rows
However my sheet will have multiple columns with comma separated responses, like this:
....and I need it in column format so I can Pivot and count. As I mentioned I am going to add in some attribute data (HR data, and that's why I cannot import it into Qualtrics - can't send outside the company), so I'll still need to pair up the person with the response. However, if there is a script or command that can run and split this out for me, I'm not sure how it would handle differing numbers of response from column to column to create the needed rows (Like Bill and Karen in the example). Would I need to have the column with the longest csv cell first and so on? However, it would look something like this:
Is there something I can do to accomplish this?
your desired layout is actually not fit for proper pivot tables, either. You need a really flat table structure, so you can filter on likes without simultaneously hiding dislikes.
You can easily transform your data with Power Query. Load the data into the Power Query Editor, then split each question column by the delimiter ", " (comma followed by space). This will split each answer into its own column, with the question in the header appended by .1, .2 etc.
Then select the name column and click "Unpivot other columns". The question headers will now be in the attribute column. Split that attribute column by the delimiter "." (dot) and delete the column with the split off numbers.
Finally, rename the columns to Question and Answer.
Here is the M code that is generated when doing that.
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Name", type text}, {"like", type text}, {"dislike", type text}}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Changed Type", "dislike", Splitter.SplitTextByDelimiter(", ", QuoteStyle.Csv), {"dislike.1", "dislike.2", "dislike.3", "dislike.4", "dislike.5"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"dislike.1", type text}, {"dislike.2", type text}, {"dislike.3", type text}, {"dislike.4", type text}, {"dislike.5", type text}}),
#"Split Column by Delimiter1" = Table.SplitColumn(#"Changed Type1", "like", Splitter.SplitTextByDelimiter(", ", QuoteStyle.Csv), {"like.1", "like.2", "like.3", "like.4"}),
#"Changed Type2" = Table.TransformColumnTypes(#"Split Column by Delimiter1",{{"like.1", type text}, {"like.2", type text}, {"like.3", type text}, {"like.4", type text}}),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type2", {"Name"}, "Attribute", "Value"),
#"Split Column by Delimiter2" = Table.SplitColumn(#"Unpivoted Other Columns", "Attribute", Splitter.SplitTextByDelimiter(".", QuoteStyle.Csv), {"Attribute.1", "Attribute.2"}),
#"Changed Type3" = Table.TransformColumnTypes(#"Split Column by Delimiter2",{{"Attribute.1", type text}, {"Attribute.2", Int64.Type}}),
#"Removed Columns" = Table.RemoveColumns(#"Changed Type3",{"Attribute.2"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Attribute.1", "question"}, {"Value", "Answer"}})
in
#"Renamed Columns"
The resulting table looks like this:
If your original data receives more rows, just refresh the query.
Now you have a table that can be used in pivots without compromising any data.
Not sure exactly what do you want to achieve (may be too many things at once), at least for the first part of your question: Count of response per category you can do this:
For each response column, create a count column, for example:
Name, Response_column_a, count_a, ...
The formula for count: count of comma + 1
In excel it can be acchieved with the following formula:
You now have:
1) count of responses
2) can generate total count of responses per category, for example count of Response A for Karen.

Resources