I was presented with an interesting problem last week; how to create running totals in Power Query. There doesn’t appear to be a built in method to do this, so I thought it would make an interesting use case study.
Background
Let’s take a look at the following table, which can be found in the sample file found here (if you’d like to follow along.)
![SNAGHTML1ec4a255 SNAGHTML1ec4a255]()
Now, we could certainly use a Pivot Table to create running totals, but consider the scenario where we want to preserve the original list. Pivot Tables aggregate data and apply running totals to the aggregation, so that might not suit our needs. (In the case of the table above, it would aggregate both records for 1/2/2015 into a single line.)
We could also set up a formula on our table that summed the row about plus the row to the left, for example. Of course that means you MUST land it in the worksheet, which may not be ideal either.
This solution is entirely possible to solve with Power Query, but with no one click feature in the user interface, how do we pull it off?
Creating the Staging Query
The first thing I did is create a query to pull in my data source and land it in a “Staging” table inside Power Query, as per this post. To do that I:
- Selected a cell in the table
- Went to Power Query –> From Table
- Selected the Date column –> Transform –> Data Type –> Date
- Went to Add Column –> Add Index Column –> From 0
At this point the query looks like this:
![image image]()
Next I finalized the staging query. I:
- Changed the table name to “Staging-Sales”
- Went to File –> Close and Load to… –> Only Create Connection
- Right clicked the query in the Workbook Queries pane –> Move to Group –> Staging
Building a Running Total function - Groundwork
With the staging query in place, it was time to tackle the real problem; the method to create running totals in Power Query. That work requires a bit of down and dirty M work, and here’s how I approached this to build up my end solution:
- Right click the “Sales” staging query and choose Edit
This will land you back in the Power Query editor. On the left side of the window, expand the vertical “Queries” window by click on the little arrow until you see this:
![image image]()
With this window expanded, we can begin creating our function:
- Right click “Sales” –> Reference
- Right click “Sales (2)” –> Move to Group –> Create Group –> “Functions”
- Change the name from “Sales (2)” to “fnRunningTotal”
Things should now look as follows:
![image image]()
Perfect. We now have the query set up the way we need to take our next steps. Right now it’s just pointing to our Sales query and pulling the data in, but that will change.
From a logic point of view, here’s what I want to happen:
- I want to take a row from the Sales table
- I want to send a copy of the table to my function
- I want my function to remove all rows where the index is higher than the submitted row
- I want to sum the remaining values
- I want to return that total back to the calling row
So let’s start working through that process… we’ll come back to steps 1 and 2 in a bit… let’s pretend those have already happened, and focus on the rest.
- Select the Sale and Index columns –> Home –> Remove Columns –> Remove Other Columns
- Click the Index column filter –> Number Filters –> Less than or equal to
- We’ll pick an arbitrary starting point like 2 for right now
![image image]()
- Rename the “Sale” column to “Temp”
Now we’re going to take the final step with this data before we convert it into a function. We are going to group it, so go to:
Now, we need to tweak the default a bit to get it right. The very first thing we need to do is remove the “Group By” level that groups by Temp, as we want to group all remaining rows together. To do that, you click the – button beside Temp.
Next we need to set our data correctly. We are going to set it to:
- New column name: RunningTotal
- Operation: Sum
- Column: Temp
And at this point, our output should look like this:
![image image]()
Building a Running Total function – Finalization
With this in place, we now need to turn this into a real function. And to do that, we need to step into the M code itself. So go to View –> Advanced Editor to do that.
Now, at the very top of the M code (before the let line), we are going to insert the following code:
(tbl as table, sumcolumn as text, rowindex as number) =>
This code will allow us to pass in the table, which column we want to sum, and which row we are working with when we call the function.
Next we need to plumb these variable into our code. To do that we will:
- Remove the “Source = Sales,” line of the M query
- Replace every instance of Source in query (there is only one) with the name of our table: tbl
![image image]()
- Replace every instance of “Sale” in the query with the name of the variable which holds our column name; sumcolumn.
![image image]()
Note that we do not need to wrap sumcolumn in quotes, as Power Query knows that it is text based on the parameter definition at the head of the function.
- In the #”Filtered Rows” step, replace the hard coded 2 with the name of the variable which holds our index number; rowindex.
![image image]()
- Place a comma at the end of the #”Grouped Rows” line (to make way for the next step)
- Replace the last two rows with the following to return the single value back to the caller:
RunningTotal = Record.Field(#"Grouped Rows"{0},"RunningTotal")
in
RunningTotal
When complete the function looks as follows:
![image image]()
And now click Done. At this point, your query should flip to appear as a function. This is evident in three ways:
- The icon in the left pane changes to an fx logo
- The table disappears and is replaced with the function parameters and an invoke box
- The Applied Steps collapse to a single line (I wish this didn’t happen)
Commit it by choosing File –> Close and Load
Create Running Totals in Power Query
So now… did it work? Let’s find out.
- Right click the Sales query in the Workbook Queries pane and choose Edit
- Expand the queries pane on the left
- Right click Sales –> Reference
- Right click Sales (2) –> Move to Group –> Other Queries
- Rename Sales (2) to “Landing”
- Go to Add Column –> Add Custom Column
- Call the column “Running Total”
And now we need to enter our formula. The actual formula itself will be:
=fnRunningTotal(Source,"Sale",[Index])
Here’s how it breaks down:
- fnRunningTotal is the name of the function
- Source is the name of the previous step in the Applied Steps section. This allows us to pass the entire table that is generated up to that point
- “Sale” is the name of the column we want to summarize. The quotes here indicated that we are going after the column’s name, not the data in that column’s row.
- [Index] is surrounded in square brackets as we want to pass the value for that row of the index column. That is the row that is then used to filter down the data.
And the result, if you followed along exactly, is this:
![image image]()
So at this point, we can remove the Index column and call it done. You’ll find a complete version here if you’d like to review it.
Final Thoughts
This looks like a very long and cumbersome route, but overall it’s actually not that complicated once you understand it. The key points that I want to highlight here are:
- We started with a simple Staging query
- We used that as a reference and stepped through the process of filtering down the data for one record
- We converted the new query to a function by:
- Defining a line at the beginning to receive 3 variables
- Integrated the variables into the code in place of hard values
- Added an ending to feed back a single value
- We used our function
The first line of the query is essentially just () => and any variables we need go between the brackets. And while I declared there types, you don’t actually even have to do that.
The last line of code before the in is the trickiest part. And here’s a secret… I just come back to a blog post and copy this part:
RunningTotal = Record.Field(#"Grouped Rows"{0},"RunningTotal")
The secret is understanding that the #"Grouped Rows" portion is just the name of the previous step in the M code, and the final “RunningTotal” is the name of the column you want to return. That lets me retrofit it pretty easily into any other function.
So… would it be faster to just flip it into a pivot and add running totals there? Absolutely. Would it be faster to just land the data in a table and create a running total formula down the table? Absolutely. But if those aren’t options, then Power Query may be a viable solution for you. ![:)]()
The post Create Running Totals in Power Query appeared first on The Ken Puls (Excelguru) Blog.