!ForEach Variable Not Resetting

UI.Vision RPA v6.2.8

If I interrupt a foreach loop, the !foreach variable doesn’t reset if i re-enter the same foreach at a later point in the macro. Instead it picks up where it left off.

Built some sample code below and output below. It loops 5 times on a foreach loop. The foreach loops on an array [A,B,C,D]. It jumps out of the foreach when it finds a ‘C’. Then when it re-enters the foreach, it picks up where it left off at letter D. Then on the next loop into the foreach, it goes back to the start of the array. I would have thought it should restart the array every time it enters the foreach…

Output:
This is loop number 1
Entering the ForEach…
ArrayValue = A !foreach = 0
ArrayValue = B !foreach = 1
ArrayValue = C !foreach = 2
This is loop number 2
Entering the ForEach…
ArrayValue = D !foreach = 3
This is loop number 3
Entering the ForEach…
ArrayValue = A !foreach = 0
ArrayValue = B !foreach = 1
ArrayValue = C !foreach = 2
This is loop number 4
Entering the ForEach…
ArrayValue = D !foreach = 3
This is loop number 5
Entering the ForEach…
ArrayValue = A !foreach = 0
ArrayValue = B !foreach = 1
ArrayValue = C !foreach = 2

Code:

{
  "Name": "foreach",
  "CreationDate": "2021-12-15",
  "Commands": [
    {
      "Command": "executeScript_Sandbox",
      "Target": "return ['A','B','C','D']",
      "Value": "myarray",
      "Description": ""
    },
    {
      "Command": "times",
      "Target": "5",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "This is loop number ${!times}",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "Entering the ForEach...",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "forEach",
      "Target": "myarray",
      "Value": "arrayvalue",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "ArrayValue = ${arrayvalue}  !foreach = ${!foreach}",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "gotoIf_v2",
      "Target": "${arrayvalue} == \"C\"",
      "Value": "exit",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "label",
      "Target": "exit",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    }
  ]
}

That is interesting. I think your issue happens because you should not use GotoIF to jump out of the loop. The proper way to end a loop is using the break command.

However, after rewriting your macro I discovered that there is a bug in the break command! In a nested loop, a break statement only stops the loop it is placed in. Therefore, if a break is placed in the inner loop, the outer loop still continues. Only if the break is placed in the outer loop, all of the looping stops.

However, here the break is in the inner loop and all looping stops. That seems to be a bug => I created a ticket for it and will update this post once I know more.

Your macro rewritten with BREAK:

{
  "Name": "break",
  "CreationDate": "2021-12-15",
  "Commands": [
    {
      "Command": "executeScript_Sandbox",
      "Target": "return ['A','B','C','D']",
      "Value": "myarray",
      "Description": ""
    },
    {
      "Command": "times",
      "Target": "5",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "This is loop number ${!times}",
      "Value": "green",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "Entering the ForEach...",
      "Value": "blue",
      "Description": ""
    },
    {
      "Command": "forEach",
      "Target": "myarray",
      "Value": "arrayvalue",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "ArrayValue = ${arrayvalue}  !foreach = ${!foreach}",
      "Value": "orange",
      "Description": ""
    },
    {
      "Command": "if_v2",
      "Target": "${arrayvalue} == \"C\"",
      "Value": "break",
      "Description": ""
    },
    {
      "Command": "break",
      "Target": "",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "comment",
      "Target": "label // exit",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    }
  ]
}

BREAK test macro:

{
  "Name": "loop",
  "CreationDate": "2021-12-15",
  "Commands": [
    {
      "Command": "times",
      "Target": "3",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "times",
      "Target": "3",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "echo",
      "Target": "inner loop ${!times}",
      "Value": "green",
      "Description": ""
    },
    {
      "Command": "break",
      "Target": "",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    },
    {
      "Command": "end",
      "Target": "",
      "Value": "",
      "Description": ""
    }
  ]
}

Thanks for the feedback. I do agree using the ifgoto to break out of a loop is not best practice in any language. :innocent: My actual code was checking an array variable for the existence of a value. If found, needed it to continue on; but if not found in the array I needed the macro to error. Originally the throwerror was after the foreach end. i.e. if the goto occurred then the error would not be thrown.

I already rewrote it to use a boolean and set it to true if the value was found and then break. Then check the boolean after the end to determine to continue and/or throw error. Was just being lazy and didn’t want the extra steps. But figured I would report the behavior since the documentation didn’t explicitly say don’t do that. :rofl:

1 Like