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

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now! Learn more

Reply
JustCraig
Frequent Visitor

Need Assistance - M Code adding two Custom Columns with relevant calculations

Good day,

 

Trust you're all well. Totally new to M.

I require some assistance in creating a step in Power Query that creates two custom columns which rely on values from the current and previous rows respectively. Essentially the intention is as follows, as one would easily do in Excel (C and D):

 ABCD
1xy0(C1+A1)-B1
2xyD1(C2+A2)-B2
3xyD2(C3+A3)-B3

 

Some Sample Data:

SiteNameDateSubmittedReceived_BinsSorted_BinsIndex
MEN2024/06/19 22:5480801
MEN2024/06/20 17:2797902
MEN2024/06/20 22:2365603
MEN2024/06/21 10:2370704
MEN2024/06/21 17:001031105
MEN2024/06/22 11:5275706
MEN2024/06/22 16:091061007
MEN2024/06/23 15:5697978
MEN2024/06/23 22:3465709

 

 

JustCraig_1-1723641039917.png

 

Intended Outcome: 2 additional Columns added 'Opening' and 'Closing'

SiteNameDateSubmittedReceived_BinsSorted_BinsIndexOpeningClosing
MEN2024/06/19 22:548080100
MEN2024/06/20 17:279790207
MEN2024/06/20 22:2365603712
MEN2024/06/21 10:23707041212
MEN2024/06/21 17:001031105125
MEN2024/06/22 11:5275706510
MEN2024/06/22 16:0910610071016
MEN2024/06/23 15:56979781616
MEN2024/06/23 22:34657091611

 

 

JustCraig_0-1723641007102.png

 

Reason it needs to happen in Power Query is due to the fact that the table needs to be unpivoted in the last step prior to being applied. 

 

Any assistance would be greatly appreciated

2 ACCEPTED SOLUTIONS
dufoq3
Super User
Super User

Hi @JustCraig, check this:

 

Output

dufoq3_0-1723641160272.png

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dY8xDsMwCEWvgjxHCmADNXvH9gJR7n+Ngq1kqJzlDZ+nj/5xlM/7W7bCyG1H3akDs0uL6IUT5/YvMQKZs0XUBx6kaOIakUpiKREQTslwYi2ZY94JUyVaagxELpw18tgVkjr20aWDS60CiYveC20txcLaroX58PwB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [SiteName = _t, DateSubmitted = _t, Received_Bins = _t, Sorted_Bins = _t]),
    ChangedType = Table.TransformColumnTypes(Source,{{"SiteName", type text}, {"DateSubmitted", type datetime}, {"Received_Bins", type number}, {"Sorted_Bins", type number}}),
    Buffered = List.Buffer(Table.ToRows(Table.SelectColumns(ChangedType,{"Received_Bins", "Sorted_Bins"}))),
    GeneratedOpeningClosing = Table.FromRecords(List.Generate(
        ()=> [ x = 0, Opening = 0, Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
        each [x] < List.Count(Buffered),
        each [ x = [x]+1, Opening = [Closing], Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
        each [[Opening], [Closing]]
)),
    ChangedType2 = Table.TransformColumnTypes(GeneratedOpeningClosing,{{"Opening", type number}, {"Closing", type number}}),
    StepBack = ChangedType,
    Combined = Table.FromColumns(Table.ToColumns(StepBack) & Table.ToColumns(ChangedType2), Value.Type(StepBack & ChangedType2))
in
    Combined

Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

View solution in original post

Hi, with my solution you doesn't need [Index] column. Try this - this will calculate Opening and Closing for each SiteName:

 

 

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dY8xDsMwCEWvgjxHCmADNXvH9gJR7n+Ngq1kqJzlDZ+nj/5xlM/7W7bCyG1H3akDs0uL6IUT5/YvMQKZs0XUBx6kaOIakUpiKREQTslwYi2ZY94JUyVaagxELpw18tgVkjr20aWDS60CiYveC20txcLaroX58PwB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [SiteName = _t, DateSubmitted = _t, Received_Bins = _t, Sorted_Bins = _t]),
    ChangedType = Table.TransformColumnTypes(Source,{{"SiteName", type text}, {"DateSubmitted", type datetime}, {"Received_Bins", type number}, {"Sorted_Bins", type number}}),
    GroupedRows = Table.Group(ChangedType, {"SiteName"}, {{"FnTransform", each 
        [ Buffered = List.Buffer(Table.ToRows(Table.SelectColumns(_,{"Received_Bins", "Sorted_Bins"}))),
          GeneratedOpeningClosing = Table.FromRecords(List.Generate(
                ()=> [ x = 0, Opening = 0, Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
                each [x] < List.Count(Buffered),
                each [ x = [x]+1, Opening = [Closing], Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
                each [[Opening], [Closing]]
        )),
          ChangedType2 = Table.TransformColumnTypes(GeneratedOpeningClosing,{{"Opening", type number}, {"Closing", type number}}),
          StepBack = _,
          Combined = Table.FromColumns(Table.ToColumns(StepBack) & Table.ToColumns(ChangedType2), Value.Type(StepBack & ChangedType2))
        ][Combined]
    , type table}}),
    Combined = Table.Combine(GroupedRows[FnTransform])
    
in
    Combined

 


Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

View solution in original post

7 REPLIES 7
Greg_Deckler
Community Champion
Community Champion

@JustCraig 

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dY8xDsQgDAS/gqgjxTbYBPcp7z4Q8f9vBDviipPTjNBqtHivK3/Ob94yAdUdZMeeiJTrjA5YwDy2f5EgYVNqM+oOEykWZyOVGQkbTCyRiAnhERss1BexKfhlYDqivTlSKSEqk9Xx6pQXURS6d4rTb4jUkpCV5bfccMTiXF7qWu6f9zzGDQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [SiteName = _t, DateSubmitted = _t, Received_Bins = _t, Sorted_Bins = _t, Index = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"SiteName", type text}, {"DateSubmitted", type datetime}, {"Received_Bins", Int64.Type}, {"Sorted_Bins", Int64.Type}, {"Index", Int64.Type}}),
    #"Added Custom1" = Table.AddColumn(#"Changed Type", "Opening", each let
  Index = [Index],
  MyTable = Table.SelectRows( #"Changed Type", each [Index] < Index),
  Received = List.Sum( Table.SelectColumns( MyTable,"Received_Bins")[Received_Bins]),
  Sorted = List.Sum( Table.SelectColumns( MyTable, "Sorted_Bins")[Sorted_Bins]),
  Result = Received - Sorted + 0
in
  Result),
    #"Added Custom" = Table.AddColumn(#"Added Custom1", "Closing", each let
  Index = [Index],
  MyTable = Table.SelectRows( #"Added Custom1", each [Index] <= Index),
  Received = List.Sum( Table.SelectColumns( MyTable,"Received_Bins")[Received_Bins]),
  Sorted = List.Sum( Table.SelectColumns( MyTable, "Sorted_Bins")[Sorted_Bins]),
  Result = Received - Sorted
in
  Result)
in
    #"Added Custom"


Follow on LinkedIn
@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
DAX For Humans

DAX is easy, CALCULATE makes DAX hard...

Thank you for your time and solution @Greg_Deckler, very much appreciated. I had to change the Index to run per Group (SiteName) which suited your proposed solution but the Opening and Closing calcs were off for some reason. I'll try it again in due course

dufoq3
Super User
Super User

Hi @JustCraig, check this:

 

Output

dufoq3_0-1723641160272.png

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dY8xDsMwCEWvgjxHCmADNXvH9gJR7n+Ngq1kqJzlDZ+nj/5xlM/7W7bCyG1H3akDs0uL6IUT5/YvMQKZs0XUBx6kaOIakUpiKREQTslwYi2ZY94JUyVaagxELpw18tgVkjr20aWDS60CiYveC20txcLaroX58PwB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [SiteName = _t, DateSubmitted = _t, Received_Bins = _t, Sorted_Bins = _t]),
    ChangedType = Table.TransformColumnTypes(Source,{{"SiteName", type text}, {"DateSubmitted", type datetime}, {"Received_Bins", type number}, {"Sorted_Bins", type number}}),
    Buffered = List.Buffer(Table.ToRows(Table.SelectColumns(ChangedType,{"Received_Bins", "Sorted_Bins"}))),
    GeneratedOpeningClosing = Table.FromRecords(List.Generate(
        ()=> [ x = 0, Opening = 0, Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
        each [x] < List.Count(Buffered),
        each [ x = [x]+1, Opening = [Closing], Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
        each [[Opening], [Closing]]
)),
    ChangedType2 = Table.TransformColumnTypes(GeneratedOpeningClosing,{{"Opening", type number}, {"Closing", type number}}),
    StepBack = ChangedType,
    Combined = Table.FromColumns(Table.ToColumns(StepBack) & Table.ToColumns(ChangedType2), Value.Type(StepBack & ChangedType2))
in
    Combined

Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

Thank you @dufoq3 

It works perfectly! Very much appreciated.

What I've subsequently had to do now on the table is group it by SiteName and reapply the Index. So every new Site would start the Index over. 

 

JustCraig_0-1723670246520.png

 

How can one incorporate an 'each index < [index]' within the List.Generate so that it starts over each time the index does?

 

Hi, with my solution you doesn't need [Index] column. Try this - this will calculate Opening and Closing for each SiteName:

 

 

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dY8xDsMwCEWvgjxHCmADNXvH9gJR7n+Ngq1kqJzlDZ+nj/5xlM/7W7bCyG1H3akDs0uL6IUT5/YvMQKZs0XUBx6kaOIakUpiKREQTslwYi2ZY94JUyVaagxELpw18tgVkjr20aWDS60CiYveC20txcLaroX58PwB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [SiteName = _t, DateSubmitted = _t, Received_Bins = _t, Sorted_Bins = _t]),
    ChangedType = Table.TransformColumnTypes(Source,{{"SiteName", type text}, {"DateSubmitted", type datetime}, {"Received_Bins", type number}, {"Sorted_Bins", type number}}),
    GroupedRows = Table.Group(ChangedType, {"SiteName"}, {{"FnTransform", each 
        [ Buffered = List.Buffer(Table.ToRows(Table.SelectColumns(_,{"Received_Bins", "Sorted_Bins"}))),
          GeneratedOpeningClosing = Table.FromRecords(List.Generate(
                ()=> [ x = 0, Opening = 0, Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
                each [x] < List.Count(Buffered),
                each [ x = [x]+1, Opening = [Closing], Closing = Opening + Buffered{x}{0} - Buffered{x}{1} ],
                each [[Opening], [Closing]]
        )),
          ChangedType2 = Table.TransformColumnTypes(GeneratedOpeningClosing,{{"Opening", type number}, {"Closing", type number}}),
          StepBack = _,
          Combined = Table.FromColumns(Table.ToColumns(StepBack) & Table.ToColumns(ChangedType2), Value.Type(StepBack & ChangedType2))
        ][Combined]
    , type table}}),
    Combined = Table.Combine(GroupedRows[FnTransform])
    
in
    Combined

 


Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

Thank you, works perfectly! Much appreciated again

You're welcome 😉


Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

Helpful resources

Announcements
November Power BI Update Carousel

Power BI Monthly Update - November 2025

Check out the November 2025 Power BI update to learn about new features.

Fabric Data Days Carousel

Fabric Data Days

Advance your Data & AI career with 50 days of live learning, contests, hands-on challenges, study groups & certifications and more!

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.