You know that looping can be an important part of any workflow. Getting data from a SharePoint list, web service or database needs to be parsed so you can use it in your business process. Nintex Workflow for Office 365 has had looping actions in it since its inception. But as we always do, we strive to make things easier for everyone. This time, we have the For Each action.
There are many reasons for how awesome this action is, but I will focus on a few of them.
1. Simple iteration through each value in a dictionary of data
2. You can stop the iteration once a condition is met
3. No chance of an infinite loop
Note: See also “Stepping through a dictionary variable” in the help.
Iterating through Data
One easy way to get data iterate through, is to query a list. In this example, I created a list called Countries. The result of the query will go into a Dictionary variable, called dictCountries.
Notice in the above image that we have a few requirements. The Target Dictionary is the variable that would contain the result from the Query List action. The other requirement is the Output field. Here, you select the variable that will store the output of this action. NOTE: this action is going through each item in the dictionary. Which means that with each iteration, the "textCountry" variable will contain a different country name.
So if the original list looked like this:
then to iterate through this list, each time through we get would one of the above country names.
The other thing I am storing in the above example is the "Key value". That's just for my own debugging in the example, and can be ignored for this example. I'll talk more about this later.
The workflow example for this looks like this:
The end result of this, is each value in the dictionary is then logged to the workflow history:
Sometimes, a simple collection of data is not all you get back. On occasion, you'll be query for multiple sets of data.
eg. Give me a list of countries and their populations
The following examples is really an extension of the above workflow.
This time, I've actually added the other field (Population) and I'm also storing the "Fields XML" into another Dictionary variable that I've called "dictAllData".
What this means, is that in the For Each, where I'm iterating through the first Dictionary, I now have another location where I can pull the other field data.
The first thing to note, is that the Fields XML is actually a dictionary of XML objects. Each XML object representing an item that came back from the Query List action. Now here's the golden nugget that you need to be aware of. As we are going through the dictCountries Dictionary via the For Each action, store the Key into a text variable. Why??? Because that key is what you will be using to get the XML for that item in the dictAllData Dictionary.
Here is what the For Each looks like again:
Notice the textKeyValue variable. That contains the key. Inside the For Each action, add the Get an Item from a Dictionary action. This is what the configuration looks like.
This actions lets us pull out the appropriate XML object from the dictAllData Dictionary and store it in textAllData. This gives us the ability to query that data and pull out any field that we need (as long as we requested in in the Query List action).
I don't want to harp on much about this action, because really, the focus of this post is about the ability to use the For Each. But since I got caught out on this, if you're going to use this type of functionality, make sure your XPath query is correct.
If you're pulling out a number, make sure the XPath expression looks like this :
If you're querying for text, it should look like this :
Stop Processing a Dictionary
The nice addition to the For Each action that allows you to stop processing is awesome. It definitely won't be used all the time, but it definitely has it's place in good workflow design. Especially if performance and efficiency are important to you. (they should be!!).
Lets take an example where you're querying a list that have 10,000 items in it. In part of your workflow, you need to find a particular item. XPath in this case is not really an option here, so you use a For Each to iterate through each item until you find the one you need. Once found, you pull out the data from the XML for the other fields and you're set. Except for the fact that the For Each continues to process all the other items. If it had found the item you need at the beginning of the dictionary, the For Each still has a majority of the 10,000 items to go through. Not very efficient.
To mitigate this, a Boolean variable can be used. I like to call it "boolStopProcessing" and then use a Set a Variable action to set it to No. In the For Each, for the Stop Processing option, I select my boolStopProcessing variable.
One other addition is needed inside the For Each. Add a Run If action that checks for a specific condition. In my example, I check whether the country found in the For Each is "UK". If it is, I get the population and then set the boolStopProcessing to Yes.
If it evaluates to True, inside the Run If, add a Set a Variable action to set the boolStopProcessing to Yes so that the For Each knows to stop processing the data.
No Chance of an Infinite Loop
I did want to comment on this. The Loop with Condition action has the potential of going into an infinite loop, based on the condition that is configured with. eg. Loop while 1 is equal to 1
This is not an option with the For Each action, because it is going through a finite number of items in the Dictionary.
On that note, I'm going to call it a day. I'll attach each of the workflows mentioned above to this post, so that you can download and have a look at them. If you have any comments or thoughts, please feel free to add to this comments section.