Forum Discussion

Anonymous's avatar
Anonymous
Not applicable
4 years ago

Insert previous rows with calculated columns

Hi,

Can you please help me on this. I am expecting output similar to the one outlined in the chart below under the heading "Expected output". Please see the chart below for more info.

My requirements are:

1) Take number of rows from where combination of the respective ID & Code is maximum for Assignment & AssignmentDesc is not null for column Mode='BER' and insert those rows for column Mode='AER'.
2) Newly inserted rows for column Mode="AER" should carry Assignment,AssignmentDesc, AllCost column values from their copied/previous rows. Here ALLCost is a "calculated column".
3) Newly inserted rows for column Mode="AER" should have the existing values as it is for ID, Code, Mode columns and cost value as null/blank.

 

Current Data      
IDCodeAssignmentAssignmentDescCostModeAllCost
20010  250BER285
2001034JDC120.19BER145.19
2001018OB 58.88BER65
2001051FFY82.42BER89
20020  320BER340
2002032AOL45.34BER78
20030  1084.51AER2000
30010  500BER560
3001034JDC235.67BER300
3001023LPT456.34BER500
30040  700BER756
3004051FFY340BER370
3004045KT290BER300
3004018OB 2345.78BER2587
30090  1000AER1200
       
       
Expected Output      
IDCodeAssignmentAssignmentDescCostModeAllCost
20010  250BER285
2001034JDC120.19BER145.19
2001018OB 58.88BER65
2001051FFY82.42BER89
20020  320BER340
2002032AOL45.34BER78
20030  1084.51AER2000
2003034JDC AER145.19
2003018OB  AER65
2003051FFY AER89
30010  500BER560
3001034JDC235.67BER300
3001023LPT456.34BER500
30040  700BER756
3004051FFY340BER370
3004045KT290BER300
3004018OB 2345.78BER2587
30090  1000AER1200
3009051FFY AER370
3009045KT AER300
3009018OB  AER2587

 

Thanks,

Bobhy

7 Replies

  • If I understand your logic, the following might work

    • Group by ID
    • Then use a custom function to 
      • Group by Code
      • Determine which Code has the maximum number of rows
      • Use the rows from that code to create the rows to be inserted

    Custom Function

     

    //rename fnInsertAERrows
    
    (tbl as table)=>
    
    let
        //assuming only a single AER code
        #"AER Code" = Table.SelectRows(tbl, each [Mode]="AER")[Code]{0},
       
        #"BER Rows" = Table.SelectRows(tbl, each [Mode] = "BER" and [Assignment] <> null),
       
        #"Code Count" = Table.Group(#"BER Rows",{"Code"},{
            {"Count", each Table.RowCount(_), Int64.Type}               
                    }),
        #"Code with Max Rows" = Table.SelectRows(#"Code Count", each [Count] = List.Max(#"Code Count"[Count]))[Code],
       
        #"Full Rows to Insert" = Table.SelectRows(#"BER Rows", each List.Contains(#"Code with Max Rows", [Code])),
       
        #"Modified Rows to Insert" = Table.FromRecords(Table.TransformRows(#"Full Rows to Insert", (r) =>
            Record.TransformFields(r,
            {{"Mode", each "AER"},
             {"Cost", each null},
             {"Code", each #"AER Code"}
             }))),
       
        #"Insert the rows" = Table.Combine({tbl,#"Modified Rows to Insert"})
       
    in
        #"Insert the rows"

     

     

    Main Code

     

    let
        Source = Excel.CurrentWorkbook(){[Name="Table22"]}[Content],
        #"Changed Type" = Table.TransformColumnTypes(Source,{
            {"ID", Int64.Type}, {"Code", Int64.Type}, {"Assignment", Int64.Type}, {"AssignmentDesc", type text}, 
            {"Cost", Currency.Type}, {"Mode", type text}, {"AllCost", Currency.Type}}),
        
        #"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {
            {"added Rows", each fnInsertAERrows(_), 
                type table [ID=Int64.Type, Code=Int64.Type, Assignment=Int64.Type, AssignmentDesc=nullable text, Cost=Currency.Type, Mode=nullable text, AllCost=Currency.Type]}}),
        
        #"Expanded added Rows" = Table.ExpandTableColumn(#"Grouped Rows", "added Rows", 
            {"Code", "Assignment", "AssignmentDesc", "Cost", "Mode", "AllCost"})
    in
        #"Expanded added Rows"

     

     

    Original Data

    Results

     

     

     

    • Anonymous's avatar
      Anonymous
      Not applicable

      It's not working as I have multiple "AER" codes. Please see the chart below for more info. As I am new to M code, how to incorporate the Main Code and the Custom Function?

      Thanks

       

      Current Data      
      IDCodeAssignmentAssignmentDescCostModeAllCost
      20010  250BER285
      2001034JDC120.19BER145.19
      2001018OB 58.88BER65
      2001051FFY82.42BER89
      20020  320BER340
      2002032AOL45.34BER78
      20060  500AER600
      20030  1084.51AER2000
      30010  500BER560
      3001034JDC235.67BER300
      3001023LPT456.34BER500
      30040  700BER756
      3004051FFY340BER370
      3004045KT290BER300
      3004018OB 2345.78BER2587
      30090  1000AER1200
             
             
      Expected Output      
      IDCodeAssignmentAssignmentDescCostModeAllCost
      20010  250BER285
      2001034JDC120.19BER145.19
      2001018OB 58.88BER65
      2001051FFY82.42BER89
      20020  320BER340
      2002032AOL45.34BER78
      20060  500AER600
      2006034JDC AER145.19
      2006018OB  AER65
      2006051FFY AER89
      20030  1084.51AER2000
      2003034JDC AER145.19
      2003018OB  AER65
      2003051FFY AER89
      30010  500BER560
      3001034JDC235.67BER300
      3001023LPT456.34BER500
      30040  700BER756
      3004051FFY340BER370
      3004045KT290BER300
      3004018OB 2345.78BER2587
      30090  1000AER1200
      3009051FFY AER370
      3009045KT AER300
      3009018OB  AER2587
      • ronrsnfld's avatar
        ronrsnfld
        Super User

        When your example does not reflect the variability in your actual data, and your description is unclear and incomplete, I am not surprised.

        Given your new data, it is merely a matter of changing the custom function to account for more than one "AER" row.

        The main function remains the same:

        Custom Function

         

        //rename fnInsertAERrows
        
        (tbl as table)=>
        
        let
            #"AER Rows" = Table.SelectRows(tbl, each [Mode]="AER"),
        
            #"All BER Rows" = Table.SelectRows(tbl, each [Mode]="BER"),
            #"BER Rows" = Table.SelectRows(tbl, each [Mode] = "BER" and [Assignment] <> null),
           
            #"Code Count" = Table.Group(#"BER Rows",{"Code"},{
                {"Count", each Table.RowCount(_), Int64.Type}               
                        }),
            #"Code with Max Rows" = Table.SelectRows(#"Code Count", each [Count] = List.Max(#"Code Count"[Count]))[Code],
           
            #"Full Rows to Insert" = Table.SelectRows(#"BER Rows", each List.Contains(#"Code with Max Rows", [Code])),
           
            #"Modified Rows to Insert" = List.Accumulate(List.Numbers(0,Table.RowCount(#"AER Rows")),{#"All BER Rows"},(state, current)=>
            state & {Table.FromRecords({#"AER Rows"{current}}) & 
            Table.FromRecords(Table.TransformRows(#"Full Rows to Insert", (r) =>
                Record.TransformFields(r,
                {{"Mode", each "AER"},
                 {"Cost", each null},
                 {"Code", each #"AER Rows"[Code]{current}}})))}
                 
            ),
           
            #"Insert the rows" = Table.Combine(#"Modified Rows to Insert")
           
        in
            #"Insert the rows"

         

        Main Function

         

        let
        
        //Change next line to reflect your actual data source
            Source = Excel.CurrentWorkbook(){[Name="Table22"]}[Content],
        
        //set the data types
            #"Changed Type" = Table.TransformColumnTypes(Source,{
                {"ID", Int64.Type}, {"Code", Int64.Type}, {"Assignment", Int64.Type}, {"AssignmentDesc", type text}, 
                {"Cost", Currency.Type}, {"Mode", type text}, {"AllCost", Currency.Type}}),
            
        //group rows by ID and aggregate using the Custom function
            #"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {
                {"added Rows", each fnInsertAERrows(_), 
                    type table [ID=Int64.Type, Code=Int64.Type, Assignment=Int64.Type, AssignmentDesc=nullable text, Cost=Currency.Type, Mode=nullable text, AllCost=Currency.Type]}}),
        
        //Expand the resultant tables
            #"Expanded added Rows" = Table.ExpandTableColumn(#"Grouped Rows", "added Rows", {"Code", "Assignment", "AssignmentDesc", "Cost", "Mode", "AllCost"})
        in
            #"Expanded added Rows"

         

         

        Source Data (your modified data in last post)

         

        Results

        The code would be pasted as separate queries into the Query (Power Query) Advanced Editor.

        Please read the comments in the code for important changes you will need to make in the pasted code and query name.

         

  • Anonymous's avatar
    Anonymous
    Not applicable

    I got the error with the same data that I posted.  The only difference is that my source is SQL server table with the same data that I have provided you. Yes, the error returned at the #"Group Rows" step. Please see the screenshot below for more info. Thanks.

     

     

    • ronrsnfld's avatar
      ronrsnfld
      Super User

      As I wrote, I cannot see what you have done to adapt the code to your environment. Without that and without being able to reproduce the error, all I can do is suggest you recheck the code you have copied. My guess is that the error is coming from the custom function, and is due to a typo or mis-copy.  Even that's hard to say since you did not show the status at the #"Grouped Rows" step in your screenshot.

       

      PS I just tried again, this time using Power BI Desktop instead of Excel, and also obtained the results without errors.