function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Bob Lloyd 2Bob Lloyd 2 

Nested Loops in flow

I'm trying to compare 2 lists using flow. I'm not an apex developer and would prefer to do this entirely with clicks. I've tried to do this using 2 fast lookups and then nesting one loop inside the other. The first lookup grabs a set selection of contacts and places into an sobject collection. The second grabs a set of account records and places into a separate sobject. I then start a loop through the contacts and a loop through the accounts. If the accountid=account.id I check a condition. If that condition is true I go to the next contact. If false, it adds the record to new collection variable. If the accountid<>account.id, I loop to the next account.
For me, I call that a "nested loop".
What I'm finding is the inside loop (the one through the accounts) isn't restarting when I go back to next contact. I've turned on debug and I see the iteration of the account loop doesn't restart. Even with ordering the original collections by the accountid/account.id, I'm not getting the desired results.
My questions are: 1) is there a better way to do this type of check? (I want to be able to use nested loops in other items too) and 2) is there a way to get the loop to restart from the original iteration.
Restrictions: there will be more than 100 records, so I will run into limits.
Here's an example of the flow. Please note that HH is the "account" object for me.
Flow with nested loop

 
Jonathan LaRosaJonathan LaRosa
In case you didn't already solve this, I think this should help: https://salesforcesidekick.com/2016/05/23/how-to-use-a-loop-inside-a-loop-in-flow/
Personally my problem was that I also had my 2 Fast Lookups outside of the 2 Loops. When I put one of the Fast Lookups inside the Loop, it worked.
Tim Shores 7Tim Shores 7
I ran into the same type of problem: inner loop does not happen after an initial iteration. I figured out that we aren't allowed to "break" out of a Flow Loop.

Many programming languages provide a way to break out of a loop -- when you're searching for one member of a list, why bother continuing to search once you've found it? I've read that it's not a best practice, but it sure is useful in practical applications, and it seems more sensible and efficient.

That's what you're doing in this Flow diagram. When Loop HH Next Element goes to Decision, if HH != Contact then it returns to Loop HH for the Next Element. If HH never = Contact, then Loop HH reaches End of Loop. Success!

However, if HH = Contact, it goes to Decision Is Primary Set. That branch provides no way to return to Loop HH, and Loop HH will remain stuck in a non-End state. Loop Contacts will return to Loop HH, but Loop HH won't respond correctly. The debug log or email will show that Loop HH is invoked, but without any contents, and the entire transaction is likely to halt with an error. Ouch!

Here's an earlier version of my Flow, which caused the same problem.
Depiction of Flow with broken loop

Outer loop: Fetch Campaign
Inner Loop: Sift Campaign Members.

These two loops look for matching Contacts among Campaign Members from multiple Campaigns. I needed one of two things to happen: create a Campaign Member, or update a Campaign Member.

For each Campaign, if I find no match, the inner loop ends, the Flow creates a Campaign Member, and returns to the outer loop. That's the blue word balloon.

If I find a match, I break the loop and update the Campaign Member. That's the red word balloon.

The way this looked in testing was interesting and took a while to find the pattern. If I had two Campaigns and they both had matches, the Flow failed. Otherwise, it worked. If I had three or more Campaigns, the Flow failed only when matches were in adjacent Campaigns! So if Campaigns 1 and 3 had a match, but Campaign 2 did not, then the Flow worked. This is because in Campaign 2, the broken loop just moves right to End of Loop, which creates a Campaign Member. Since the loop reached the End it was ready for the next iteration of the outer loop. That isn't "correct" but in testing it created many combinations that appeared correct, so it was difficult to understand the problem.

The Solution
I wonder if there's a more elegant way to do this, but I recognized that no matter what, I had to let my inner loop reach the End every time it ran.

Flow for successful nested looping

Here's what this Flow does different from my earlier version:
  1. Before each invocation of the inner loop, an Assign sets a Campaign Member sObject variable to the value of another sObject variable (since Flow doesn't allow you to directly set a variable to NULL). Why?
  2. ... Because, when it finds a match, it Assigns to an sObject variable instead of invoking a Record Update directly.
  3. If it doesn't find a match it goes directly back to the inner loop for the Next Iteration.
  4. At the End of the inner loop, a Decision tests the sObject variable for NULL and either Updates or Creates, then returns to the outer loop.
  5. My Campaign Member sObject variable retains its value, and that's why I need to clear it as I do in step 1.
Bob Lloyd 2Bob Lloyd 2
Thanks, Tim. I see the error about not returning to the HH loop. There is no way of you knowing this, but there's a 1:1 relationship with the "primary" and the HH. Nevertheless, that would cause a problem. I spent some time looking at your DETAILED reply. Thumbs up for that. I was trying to keep the number of fast lookups down, so I didn't do the full lookup in the inner loop. I do like the idea of the assignment. I'm going to have to spend some more time on that. I thought I had issues referencing an assigned sobject collection value and referencing it later. If memory serves me correctly, this had me build my first (and only one of verry few) pieces of APEX. 
Stephen Long 6Stephen Long 6
Tim... Thankyou! I have spent hours trying to figure this out for my Flow.