SumProduct in Excel's Power Query

daedalos

New Member
Joined
Oct 5, 2023
Messages
6
Office Version
  1. 365
  2. 2021
Platform
  1. Windows
Dear Excel Gurus,
I am seeking help how to replicate Excel's formula SumProduct in Power Query.
In one table I have payroll data (1), i.e. list of employees with their wage components.
In second table (2) I have information, if the wage component belongs to specific summary or not. Here I am using 3 states: 0 = do not use, 1 = add to summary, -1 = substract from summary. Where in this example I am creating 3 sums: Gross Income, Gross Salary, Net Salary.
My final table (3) has all original data and added summaries.
GTN_Sums.png

Normally I have over 100 wage components and over 4500 employees, so my concern is speed of the query. I believe that the answer is behind one or two List functions, but after 4 hours I gave up for the moment and created a primitive solution: Unpivot wage components. Merge with table with rules. Multiply value from source with value from rules. Summarized per EID and merge with original source. I know that something more elegant has to exist, but I only started learning Power Query 2 weeks ago, so the solution eludes me.
If someone can give me at least a hint which way to go, it would be great. If someone would be willing to create a solution, I am more than happy to buy them a couple of coffees via PayPal.
Thanks in advance to anyone willing to help.
 

Excel Facts

Create a chart in one keystroke
Select the data and press Alt+F1 to insert a default chart. You can change the default chart to any chart type
Cannot manipulate data in a picture. Please reload your samples using XL2BB so that we don't have to retype all your data to test our assumptions for a solution. Without processing, it looks like you will need to Unpivot your data and then do a Group By on the eid. With sample data I can give you actual Mcode.
 
Upvote 0
Hi alansidman, this is my first try with XL2BB so fingers crossed and thanks in advance for your help.
GTN_testing_PQ_v01.xlsx
BCDEFGHIJKLMNOPQRSTUV
2Source of data Rules for creating summariesOriginal tableNewly created summaries
3EIDNameBaseBonusGiftTaxHeaderGross IncomeGross SalaryNet SalaryEIDNameBaseBonusGiftTaxGross IncomeGross SalaryNet Salary
4eid01employee 01200002100500EID000eid01employee 01200002100500221002000019500
5eid02employee 02250002500600Name000eid02employee 02250002500600275002750026900
6eid03employee 032400020002400400Base111eid03employee 032400020002400400284002600025600
7eid04employee 0430002100700Bonus111eid04employee 0430002100700510030002300
8eid05employee 052800Gift100eid05employee 052800280000
9eid06employee 063250035002400500Tax00-1eid06employee 063250035002400500384003600035500
10eid07employee 072000015002100600eid07employee 072000015002100600236002150020900
Data
 
Upvote 0
This is the query I was capable to came up. Nothing fancy and I am afraid what it will do once I try it on real data. I wanted to use something more elegant like List.Accumulate, but I failed so far.
Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    Change_Type = Table.TransformColumnTypes(Source,{{"EID", type text}, {"Name", type text}, {"Base", type number}, {"Bonus", type number}, {"Gift", type number}, {"Tax", type number}}),
    Unpivote_Columns = Table.UnpivotOtherColumns(Change_Type, {"EID", "Name"}, "Attribute", "Value"),
    Merge_Queries = Table.NestedJoin(Unpivote_Columns, {"Attribute"}, Master, {"Header"}, "Master", JoinKind.LeftOuter),
    Expand_Master = Table.ExpandTableColumn(Merge_Queries, "Master", {"Gross Income", "Gross Salary", "Net Salary"}, {"Master.Gross Income", "Master.Gross Salary", "Master.Net Salary"}),
    Add_Custom1 = Table.AddColumn(Expand_Master, "Gross Income", each [Value]*[Master.Gross Income]),
    Add_Custom2 = Table.AddColumn(Add_Custom1, "Gross Salary", each [Value]*[Master.Gross Salary]),
    Add_Custom3 = Table.AddColumn(Add_Custom2, "Net Salary", each [Value]*[Master.Net Salary]),
    Remove_Columns = Table.RemoveColumns(Add_Custom3,{"Name", "Attribute", "Value", "Master.Gross Income", "Master.Gross Salary", "Master.Net Salary"}),
    Group_Rows = Table.Group(Remove_Columns, {"EID"}, {{"Sum Gross Income", each List.Sum([Gross Income]), type number}, {"Sum Gross Salary", each List.Sum([Gross Salary]), type number}, {"Sum Net Salary", each List.Sum([Net Salary]), type number}})
in
    Group_Rows
 
Upvote 0
If the rules table is not going to change then just add three hard-coded columns:

Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"EID", type text}, {"Name", type text}, {"Base", Currency.Type}, {"Bonus", Currency.Type}, {"Gift", Currency.Type}, {"Tax", Currency.Type}}),
    #"Replaced Value" = Table.ReplaceValue(#"Changed Type",null,0,Replacer.ReplaceValue,{"Base", "Bonus", "Gift", "Tax"}),
    #"Added Custom" = Table.AddColumn(#"Replaced Value", "Gross Income", each [Base]+[Bonus]+[Gift]),
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "Gross Salary", each [Base]+[Bonus]),
    #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Net Salary", each [Gross Salary] - [Tax])
in
    #"Added Custom2"
 
Upvote 0
If the rules table is not going to change then just add three hard-coded columns:

Power Query:
let
    Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"EID", type text}, {"Name", type text}, {"Base", Currency.Type}, {"Bonus", Currency.Type}, {"Gift", Currency.Type}, {"Tax", Currency.Type}}),
    #"Replaced Value" = Table.ReplaceValue(#"Changed Type",null,0,Replacer.ReplaceValue,{"Base", "Bonus", "Gift", "Tax"}),
    #"Added Custom" = Table.AddColumn(#"Replaced Value", "Gross Income", each [Base]+[Bonus]+[Gift]),
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "Gross Salary", each [Base]+[Bonus]),
    #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Net Salary", each [Gross Salary] - [Tax])
in
    #"Added Custom2"
Hi JGordon11, rules table is changing constantly. Either new wage codes are added, or the rules itself change (e.g. what wasn't in gross income, now is). This is why i have rule/master table, so my colleagues can easily add new wage types or change rules (in the case I did it incorrectly in the first place :D)
When I was searching for an answer, I stumble on you reply
Matrix match across identical tables in Power Query
I tried to understand it, but it is way above my pay grade.
 
Upvote 0
My original idea was to pivot my rule table. So I have two same tables with same headers. Then do matrix multiplication between them. Each time for separate summary, but I failed so hard
I checked one dataset I have and there I have almost 300 wage types, plus 4500 employees and 4 different summaries, where even the sumproduct can crunch a while.
To all of willing souls, thanks for your help.
 
Upvote 0
Power Query:
let
    Data = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    Rules = Table.Buffer(Excel.CurrentWorkbook(){[Name="Rules"]}[Content]),
    ChangeType = Table.TransformColumnTypes(Data,{{"EID", type text}, {"Name", type text}, {"Base", Currency.Type}, {"Bonus", Currency.Type}, {"Gift", Currency.Type}, {"Tax", Currency.Type}}),
    ReplaceValue = Table.Buffer(Table.ReplaceValue(ChangeType,null,0,Replacer.ReplaceValue,{"Base", "Bonus", "Gift", "Tax"})),
    Result = List.Accumulate(List.Skip(Table.ColumnNames(Rules)), ReplaceValue, (s,c)=> Table.AddColumn(s,c, each 
            let  
                Rules1 = Table.SelectRows(Rules, (x)=> Record.Field(x, c) <>0),
                cols = Rules1[Header],
                mlist = Table.Column(Rules1, c),
                zip = List.Buffer(List.Zip({cols,mlist}))
            in 
                List.Sum(List.Transform(zip, (y)=> Record.Field(_, y{0})*y{1}))
    ))
in
    Result

add cols.xlsm
ABCDEFGHIJKLMNOPQRSTU
1DataRulesQuery Output
2EIDNameBaseBonusGiftTaxHeaderGross IncomeGross SalaryNet SalaryEIDNameBaseBonusGiftTaxGross IncomeGross SalaryNet Salary
3eid01employee 01200002100500EID000eid01employee 012000002100500221002000019500
4eid02employee 02250002500600Name000eid02employee 022500025000600275002750026900
5eid03employee 032400020002400400Base111eid03employee 032400020002400400284002600025600
6eid04employee 0430002100700Bonus111eid04employee 04030002100700510030002300
7eid05employee 052800Gift100eid05employee 050028000280000
8eid06employee 063250035002400500Tax00-1eid06employee 063250035002400500384003600035500
9eid07employee 072000015002100600eid07employee 072000015002100600236002150020900
10
Sheet1
 
Upvote 1
Solution
Power Query:
let
    Data = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    Rules = Table.Buffer(Excel.CurrentWorkbook(){[Name="Rules"]}[Content]),
    ChangeType = Table.TransformColumnTypes(Data,{{"EID", type text}, {"Name", type text}, {"Base", Currency.Type}, {"Bonus", Currency.Type}, {"Gift", Currency.Type}, {"Tax", Currency.Type}}),
    ReplaceValue = Table.Buffer(Table.ReplaceValue(ChangeType,null,0,Replacer.ReplaceValue,{"Base", "Bonus", "Gift", "Tax"})),
    Result = List.Accumulate(List.Skip(Table.ColumnNames(Rules)), ReplaceValue, (s,c)=> Table.AddColumn(s,c, each
            let 
                Rules1 = Table.SelectRows(Rules, (x)=> Record.Field(x, c) <>0),
                cols = Rules1[Header],
                mlist = Table.Column(Rules1, c),
                zip = List.Buffer(List.Zip({cols,mlist}))
            in
                List.Sum(List.Transform(zip, (y)=> Record.Field(_, y{0})*y{1}))
    ))
in
    Result
This is unbelievable. Working like a charm. Now I just need to understand the code, so I can replicate it for similar scenarios :biggrin:
How can I buy you a coffee?
 
Upvote 0
Glad it's working. No coffee needed, I enjoy an interesting PQ challenge.
 
Upvote 0

Forum statistics

Threads
1,224,812
Messages
6,181,096
Members
453,021
Latest member
Justyna P

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