Forum Discussion

PythonMaster11's avatar
PythonMaster11
Regular Visitor
4 years ago
Solved

Loop function based on keyword

Hello all,

 

I'm trying to find the duration of each job my robot is doing. Process Operations vary from 3 - 50+ so I figured the best way to calculate the duration was to identify the keyword "Write Material Information" and assign the corresponding Start Time to variable t1. Then search for the vary next instance of "Update Material Position" and assign the corresponding Start Time/End time to variable t2 (FYI, Start Time & End Time are always the same value at the end of each job). After that, create a custom column to calculate the Job Duration via T=t2-t1. Then the function would repeat to find the next keyword "Write Material Information" and start all over (there are 20,000+ rows to go through). Here's a little picture to help. I'm new to VBA and Power Query so thanks in advance.

 

 

  • BA_Pete's avatar
    BA_Pete
    4 years ago

    Hi PythonMaster11 ,

     

    Try pasting this into a new blank query:

     

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("jZA9C8IwFEX/imTukJe0Nc0mTg5CQcShdAiaaECbEuPgvzf247W42PWcB/feV1Xk5G3Qq70K2lt1X+0a4/xDBesakhBgkuYyy0mdVKT17gwDXEsqEDKEQBHyAQpJoYPH9qLmSaV72lmMkNDf/SsEfB4DEwSEOUXKeEdV48JN+zJKVCld0CveZWxRL16Ml98KQvQ0peP+qw5bZ4zWk5j+mhdIhx1vHTa/paNlfUQnDuFlDBouFsyJd1mcXX8A", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [robotAction = _t, startTime = _t]),
        chgTypes = Table.TransformColumnTypes(Source,{{"robotAction", type text}, {"startTime", type time}}),
        addRandomBatchID = Table.AddColumn(chgTypes, "randomBatchID", each if [robotAction] = "Write Material Information" then List.Random(1) else {null}),
        expandRandomBatchID = Table.TransformColumns(addRandomBatchID, {"randomBatchID", each if _ = null then null else Text.Combine(List.Transform(_, Text.From)), type text}),
        replaceBlanks = Table.ReplaceValue(expandRandomBatchID,"",null,Replacer.ReplaceValue,{"randomBatchID"}),
        fillDownBatchID = Table.FillDown(replaceBlanks,{"randomBatchID"}),
        groupBatchID = Table.Group(fillDownBatchID, {"randomBatchID"}, {{"data", each _, type table [robotAction=nullable text, startTime=nullable time, randomBatchID=nullable text]}, {"minStart", each List.Min([startTime]), type nullable time}, {"maxStart", each List.Max([startTime]), type nullable time}}),
        expandDataColumn = Table.ExpandTableColumn(groupBatchID, "data", {"robotAction", "startTime"}, {"robotAction", "startTime"})
    in
        expandDataColumn

     

     

    It's a bit messy, and does rely on your data being in the correct order, but will hopefully inspire a cleaner solution if required.

     

    Summary:

    1) addRandomBatchID = adds a 1 item list of random numbers next to each process start (to identify a process batch)

    2) expandRandomBatchID = expand list created in 1)

    3) replaceBlanks = switch blanks for nulls - was lazy here!

    4) fillDownBatchID = fill down our random number to the rest of each batch - this is why it's important original data is in the correct order beforehand

    5) groupBatchID = group on our new batch ID, creatin All Rows, MIN, MAX, aggregate columns

    6) expandDataColumn = expand the nested tables in [data] to get our original info back

     

    Based on your actual data, you would probably shortcut this and just add a SUM of [Start to End] at the Group By stage along with an All Rows to get the original data back.

     

    This gives the following output:

     

    Pete

8 Replies

  • Hi PythonMaster11 ,

     

    I'm sure I already know the answer to this, but just in case: Are there other columns that give a robot ID and an 'Action Batch' ID?

     

    Pete

    • PythonMaster11's avatar
      PythonMaster11
      Regular Visitor

      Unfortunately, there are not. Besides a Date field, all I have are the columns you see in the picture. 

      • BA_Pete's avatar
        BA_Pete
        Icon for Super User rankSuper User

        Hi PythonMaster11 ,

         

        Try pasting this into a new blank query:

         

        let
            Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("jZA9C8IwFEX/imTukJe0Nc0mTg5CQcShdAiaaECbEuPgvzf247W42PWcB/feV1Xk5G3Qq70K2lt1X+0a4/xDBesakhBgkuYyy0mdVKT17gwDXEsqEDKEQBHyAQpJoYPH9qLmSaV72lmMkNDf/SsEfB4DEwSEOUXKeEdV48JN+zJKVCld0CveZWxRL16Ml98KQvQ0peP+qw5bZ4zWk5j+mhdIhx1vHTa/paNlfUQnDuFlDBouFsyJd1mcXX8A", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [robotAction = _t, startTime = _t]),
            chgTypes = Table.TransformColumnTypes(Source,{{"robotAction", type text}, {"startTime", type time}}),
            addRandomBatchID = Table.AddColumn(chgTypes, "randomBatchID", each if [robotAction] = "Write Material Information" then List.Random(1) else {null}),
            expandRandomBatchID = Table.TransformColumns(addRandomBatchID, {"randomBatchID", each if _ = null then null else Text.Combine(List.Transform(_, Text.From)), type text}),
            replaceBlanks = Table.ReplaceValue(expandRandomBatchID,"",null,Replacer.ReplaceValue,{"randomBatchID"}),
            fillDownBatchID = Table.FillDown(replaceBlanks,{"randomBatchID"}),
            groupBatchID = Table.Group(fillDownBatchID, {"randomBatchID"}, {{"data", each _, type table [robotAction=nullable text, startTime=nullable time, randomBatchID=nullable text]}, {"minStart", each List.Min([startTime]), type nullable time}, {"maxStart", each List.Max([startTime]), type nullable time}}),
            expandDataColumn = Table.ExpandTableColumn(groupBatchID, "data", {"robotAction", "startTime"}, {"robotAction", "startTime"})
        in
            expandDataColumn

         

         

        It's a bit messy, and does rely on your data being in the correct order, but will hopefully inspire a cleaner solution if required.

         

        Summary:

        1) addRandomBatchID = adds a 1 item list of random numbers next to each process start (to identify a process batch)

        2) expandRandomBatchID = expand list created in 1)

        3) replaceBlanks = switch blanks for nulls - was lazy here!

        4) fillDownBatchID = fill down our random number to the rest of each batch - this is why it's important original data is in the correct order beforehand

        5) groupBatchID = group on our new batch ID, creatin All Rows, MIN, MAX, aggregate columns

        6) expandDataColumn = expand the nested tables in [data] to get our original info back

         

        Based on your actual data, you would probably shortcut this and just add a SUM of [Start to End] at the Group By stage along with an All Rows to get the original data back.

         

        This gives the following output:

         

        Pete

  • Anonymous's avatar
    Anonymous
    Not applicable

    You could filter your rows to include only the Rows with Update and Write. Sort by StartTime. Then you could use Table.Split(PriorStepName, 2). This will give you a column of nested two row tables, and you can now add a column like:

     

    = List.Transform(PriorStep, "Duration" each Table.AddColumn( _, [StartTime]{1} - [StartTime]{0}))

     

    Now you can expand the list of tables, and go back to the step before we filter, and join on that step as the table name, your last step name as the right table, with Robot Action and Start Time as your join columns.

     

    --Nate

     

    --Nate