Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
Anonymous
Not applicable

Calculate Subtotals based on column value in Power Query M

I have been trying to find a solution for this, but I just can't get my head around it.

 

I want to do a kind of SUMIFS in Power Query Editor using M-Language.

 

 

So I have a table like this:

IndexRow typeValue
1Header 
1.1Value100
1.2Value200
2Header 
2.1Value200
2.2Value400

 

Now I would like to add another temporary column which would summarize the Value column on the rows with type "Value" based on the start of index.

 

So for example. Index "1.1" and "1.2" they start with "1" so on the first row I would like to see the summary of rows with index "1.1" and "1.2".

 

The result would be something like this:

 

 

IndexRow typeValueSum
1Header 300
1.1Value100100
1.2Value200200
2Header 600
2.1Value200200
2.2Value400400

 

So basically I want to see the subtotals of each group. How can I do this?

 

So I can do it like this:

 

= Table.AddColumn(#"PREVIOUS_STEP", "Sum", each List.Sum(Table.SelectRows(#"PREVIOUS_STEP", each Text.StartsWith([Index], "1"))[#"Value"]))

That adds a new column and nicely gives me a subtotal of all the rows that start with "1". But how can make this so that instead of hard coding the "1" in the code I can use the Index value in the current row?

 

I have tried something like this:

= Table.AddColumn(#"PREVIOUS_STEP", "Sum", each List.Sum(Table.SelectRows(#"PREVIOUS_STEP", each Text.StartsWith([Index], Record.Field(_, "Index")))[#"Value"]))

But that doesn't work, it just returns the total sum of all value columns in each row.

 

 

 

5 REPLIES 5
AnkitBI
Solution Sage
Solution Sage

Try below. Might not be the best solutionn but gets the work done. Will Recheck for simpler approach.

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUfJITUxJLQIylGJ1gCJ6ILGwxJzSVCBtaGAAFTVCEjWCihph6DZC0Q1Xh6LbBCQaCwA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Index = _t, #"Row type" = _t, Value = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Index", type text}, {"Row type", type text}, {"Value", Int64.Type}}),
    #"Split Column by Character Transition" = Table.SplitColumn(#"Changed Type", "Index", Splitter.SplitTextByCharacterTransition({"0".."9"}, (c) => not List.Contains({"0".."9"}, c)), {"Index.1", "Index.2"}),
    #"Grouped Rows" = Table.Group(#"Split Column by Character Transition", {"Index.1"}, {{"sum", each List.Sum([Value]), type number}, {"AllRows", each _, type table [Index.1=text, Index.2=text, Row type=text, Value=number]}}),
    #"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom", each Table.AddIndexColumn([AllRows],"NewIndex",1,1)),
    #"Expanded Custom" = Table.ExpandTableColumn(#"Added Custom", "Custom", {"Index.2", "Row type", "Value", "NewIndex"}, {"Index.2", "Row type", "Value", "NewIndex"}),
    #"Removed Columns" = Table.RemoveColumns(#"Expanded Custom",{"AllRows"}),
    #"Added Custom1" = Table.AddColumn(#"Removed Columns", "Sum", each if [NewIndex] = 1 then [sum] else [Value]),
    #"Removed Columns1" = Table.RemoveColumns(#"Added Custom1",{"sum", "NewIndex"}),
    #"Merged Columns" = Table.CombineColumns(#"Removed Columns1",{"Index.1", "Index.2"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Index")
in
    #"Merged Columns"

Hi - Earlier solution is better if we don't have any Row Type Column. For your case, we can also use below.

 

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUfJITUxJLQIylGJ1gCJ6ILGwxJzSVCBtaGAAFTVCEjWCihph6DZC0Q1Xh6LbBCQaCwA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Index = _t, #"Row type" = _t, Value = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Index", type text}, {"Row type", type text}, {"Value", Int64.Type}}),
    #"Split Column by Character Transition" = Table.SplitColumn(#"Changed Type", "Index", Splitter.SplitTextByCharacterTransition({"0".."9"}, (c) => not List.Contains({"0".."9"}, c)), {"Index.1", "Index.2"}),
    #"Grouped Rows" = Table.Group(#"Split Column by Character Transition", {"Index.1"}, {{"SumRows", each List.Sum([Value]), type number}, {"AllRows", each _, type table [Index.1=text, Index.2=text, Row type=text, Value=number]}}),
    #"Expanded AllRows" = Table.ExpandTableColumn(#"Grouped Rows", "AllRows", {"Index.2", "Row type", "Value"}, {"Index.2", "Row type", "Value"}),
    #"Added Custom" = Table.AddColumn(#"Expanded AllRows", "Custom", each if [Row type] = "Header" then [SumRows] else [Value]),
    #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"SumRows"}),
    #"Merged Columns" = Table.CombineColumns(#"Removed Columns",{"Index.1", "Index.2"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Index")
in
    #"Merged Columns"

Thanks

Ankit Jain

Do Mark it as solution if the response resolved your problem. Do like the response if it seems good and helpful.

Anonymous
Not applicable

Thanks @AnkitBI for your solutions, but not exactly what I was looking for.

 

I simplified my problem too much 🙂 My indexes are way more complicated than that.

 

So I also have indexes like:

 

IndexRow typeValueSum
1Header 300
1.1Value100100
1.2Value200200
2Header 1100
2.1Value200200
2.2Value400400
2.3Header 500
2.3.1Value150150
2.3.2Header 350
2.3.2.1Value350350

 

So I don't have any set maximum of how long the indexes can be... At the moment my biggest index is:

1.1.1.1.1.1 But I don't want to make a code that is limited to certain index size, it should be able to handle any size index. That's why using something like "StartsWith" would be ideal because it would just simply summarize all the values on rows who's index starts with the index on current row. (it can summarize header rows too, because they are blank / zero)

 

 

 

Ok.. Solution was based on your sample data and assumption of not having multiple dots in Indexes.

I will check other options including 'StartsWith'.

Meanwhile you can try reach out to @ImkeF.
Nathaniel_C
Super User
Super User

@Anonymous ,

I would use an if statement to return either of the two different values depending on whether the value of the decimal zero or not.

 

If this solves your issues, please mark it as the solution, so that others can find it easily. Kudos are nice too.
Nathaniel





Did I answer your question? Mark my post as a solution!

Proud to be a Super User!




Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors
Top Kudoed Authors