This can be accomplished by
- Modify previous answer to related question to be used as a
Function
- Groupby Company, then run the function against each subtable
Edited to add extra year if there is only one in the data for a company
and to fill in blank year when no product sold
Custom Function
paste into blank query
//Name query "fnProcessTable"
(myTable as table)=>
let
//create yearly table pairs
yearList = {List.Min(myTable[Year])..List.Max(myTable[Year])},
//test for no profits reported and just one year
years = if List.Count(yearList) > 1 then yearList else
{yearList{0}-1..yearList{0}},
tables = List.Generate(
()=>[t=Table.ExpandTableColumn(
Table.NestedJoin(
Table.SelectRows(myTable, (ft)=>ft[Year]=years{0}), "Product",
Table.SelectRows(myTable, (ft)=>ft[Year]=years{1}), "Product",
"Joined", JoinKind.FullOuter),"Joined",
{"Company","Product","Profit","Year"},{"Company1","Product1","Profit1","Year1"}),
idx=0],
each [idx] < List.Count(years)-1,
each [t=Table.ExpandTableColumn(
Table.NestedJoin(
Table.SelectRows(myTable, (ft)=>ft[Year]=years{[idx]+1}),"Product",
Table.SelectRows(myTable, (ft)=>ft[Year]=years{[idx]+2}), "Product",
"Joined", JoinKind.FullOuter),"Joined",
{"Company","Product","Profit","Year"},{"Company1","Product1","Profit1","Year1"}),
idx=[idx]+1],
each Table.InsertRows(
Table.FillDown(Table.FillUp([t],{"Year", "Year1"}),{"Year","Year1"}),
Table.RowCount([t]),
{[Company="", Product="", Profit=null, Year=null, Company1=null, Product1="", Profit1=null, Year1=null]})
),
#"Converted to Table" = Table.FromList(tables, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandTableColumn(#"Converted to Table", "Column1",
{"Company", "Product", "Profit", "Year", "Company1", "Product1", "Profit1", "Year1"}),
//Fill in the blank company and products
#"Fill in blanks" = Table.FromRecords(
Table.TransformRows(#"Expanded Column1",
(r)=> Record.TransformFields(r,{
{"Company", each if _ = null then r[Company1] else _},
{"Product", each if _ = null and List.Count(yearList) > 1 then r[Product1] else _},
{"Product1", each if _ = null then r[Product] else _},
{"Year", each if _ = null then r[Year1]-1 else _}
} ))),
#"Removed Columns" = Table.RemoveColumns(#"Fill in blanks",{"Company1"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Removed Columns",{{"Company", type text}, {"Product", type text}, {"Profit", Int64.Type}, {"Year", Int64.Type}, {"Product1", type text}, {"Profit1", Int64.Type}, {"Year1", Int64.Type}})
in
#"Changed Type1"
Main Code
let
Source = Excel.CurrentWorkbook(){[Name="Table13"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Company", type text}, {"Product", type text}, {"Profit", Int64.Type}, {"Year", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"Company"}, {
{"tbl", each fnProcessTable(_)}
}),
#"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"Company"}),
#"Expanded tbl" = Table.ExpandTableColumn(#"Removed Columns", "tbl",
{"Company", "Product", "Profit", "Year", "Product1", "Profit1", "Year1"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Expanded tbl",{{"Company", type text}, {"Product", type text}, {"Profit", Int64.Type}, {"Year", Int64.Type}, {"Product1", type text}, {"Profit1", Int64.Type}, {"Year1", Int64.Type}}),
//irrelevant rows generated by companies that show no year over year profit to be removed
#"Added Custom" = Table.AddColumn(#"Changed Type1", "Selector", each [Product]=null and [Product1]=null),
#"Filtered Rows" = Table.SelectRows(#"Added Custom", each ([Selector] = false)),
#"Remove Selector Column" = Table.RemoveColumns(#"Filtered Rows",{"Selector"}),
//remove bottom row which is an extra null row
#"Removed Bottom Rows" = Table.RemoveLastN(#"Remove Selector Column",1)
in
#"Removed Bottom Rows"
Source

Results
