L is for Loop
FileMaker scripting provides the features of any structured programming language. Conditional and looping structures are key features.
Conditional structures like the If / End If in FileMaker scripting allow for different subroutines to run on the evaluation of a condition. See our previous blog article on If statements.
A loop is a series of instructions that are continuously executed until a condition is reached. A simple example is working through a set of records performing certain operations until the last record is reached.
Loops in everyday life
We often perform repetitive processes. These can be considered to be loops with an exit condition.
For example, if you had to peel a bag of potatoes, you would prepare by getting the equipment required and opening the bag. You pick up a potato, peel it, rinse it and place it in a bowl. Then you check for more potatoes. If there are more, you pick up the next one and repeat – peel, rinse, place. When all the potatoes are gone, you finish and clean up.
Loop steps in FileMaker scripting
The basic loop script steps in FileMaker scripting are Loop and End Loop. The script steps placed between (‘inside the loop’) form the looping operation. Any loop is expected to have two components:
- procedures to be carried out each time through the loop
- an exit condition which, when true, will exit the loop
Infinite loops are bad
A loop without a valid exit condition is called an infinite loop – it will continue without ever exiting. This is not something you want in a script.
In many cases, there are steps before the loop to set up the environment. For example, if the loop is going to work through a set of records, you may ensure it goes to the first record of the found set before entering the loop.
Example: Loop creating new records from a list
Sometimes you have a list of values that you want to turn into a list of records.
In this example, we have a list of children’s names in a global field. A scripted button will create records related to the current parent.
The screenshot above shows the Parent layout. In the Children section, the names are in a global text field. Child records will display in a portal at the right. The relationship is a simple one to many from Parent to Child.
Why would you be doing this?
Good question. Sometimes it is easier for users to enter a list of data than to create new records. This may be by pasting from another source. Then you provide an easy process to create the required records.
The looping script will work through the child values creating a new record for each. The challenge here is that we do not know ahead of time how many children will be in the list. So the script will count the names to know how many times to repeat the loop.
The pseudocode for the looping script is:
Store the parent ID and the child list Count the child records required Set loop counter Go to the child table Enter the loop Create new record for nth child in list Exit loop if last child processed Else increment counter Return to the parent table
Here is the script:
How does it work?
The first four steps are setting variables to store required values:
- primary key of the parent record
- list of children from the global field
- count of the children
- loop counter initialised to 1
Then we go to the Child layout to create new records in the loop.
Inside the loop, the first step is to create a new record. Two Set Field steps are used to set the foreign key (ID parent) and the child’s name. The child’s name is extracted from the child list using the GetValue function and the $counter to know which one to take.
GetValue ( $children ; $counter )
The loop will then exit if the $counter is greater than or equal to the $childcount i.e. if the required number of child records has been created. If the loop does not exit, it continues on to increment (add 1 to) the $counter and then loop back to the start where it creates another new record.
When the loop exits, the script returns to the original layout (where it started).
Q. Moving script steps around
Consider what might be the positive effects of moving the Exit Loop If step to line 7 – being the first step in the loop.
[see the end of the article for a suggested answer]
Anything else needed?
This script is bare bones. At a minimum, you will probably also check that the user is happy to proceed and error trap to stop the script if no child names exist. You may also choose to clear the global field if the loop ends successfully.
The above example shows the simple structure of a looping process with:
- setup before the loop
- doing things in the loop
- checking the exit condition
- returning to the start
There are many times that a loop will be the right thing to do. However, you need to be aware of alternative methods and possible speed implications of looping scripts.
For example, if you need to loop through a found set of records and set fields according to some conditions, then consider using the Replace Field Contents script step.
If a looping script ‘touches’ every record on the way through, that may slow the process. Consider the methods to avoid opening and closing records, and even jumping to key records in the set. A Freeze Window script step before the loop may result in speed improvements.
A. Moving script steps around
If you move the Exit Loop If step to the start of the loop, this will have the positive effect that a new record would not be created unless needed. Since the $counter has been set to 1 before entering the loop, if there are no values in the children list ($childcount = 0), the loop will exit immediately.
What do you use loops for?
Feel free to leave a comment below.