Logo

Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.

For Each

This command, introduced in VFP 5, is a variation on the traditional counted FOR loop. It lets you go through all the elements in an array or collection without having to figure out up front how many there are. Unlike a regular FOR loop, FOR EACH can handle some changes in the size of the array or collection inside the loop.

Usage

FOR EACH uRef IN aGroup
   [ Commands ]
   [ EXIT ]
   [ LOOP ]
ENDFOR | NEXT

Parameter

Value

Meaning

uRef

Variable

A variable that takes on the value of each element of the array or collection in turn.

aGroup

Array or Collection

The array or collection to be processed.

Commands

Any Visual FoxPro commands

The command(s) to be executed each time through the loop.

One annoying feature of a FOR loop is that you have to figure out ahead of time where it ends. For arrays, this often means using ALEN(). The flip side of this is that the endpoint is calculated once, on the way into the loop, and if the array’s size changes inside the loop, either the loop bombs (because the array got shorter) or it simply doesn’t process the new items. FOR EACH is the solution to this problem. Rather than using an explicit counter, you tell it to process every member of an array or collection. The loop continues until each element has been touched, even if the array grows or shrinks inside the loop.

Beware, though—FOR EACH processes the elements in order. If you insert new items into the middle of an array, and the loop has already passed that point, the new elements are not processed and some old elements may be handled more than once. Similarly, if you remove items in the middle of a loop (using ADEL() or by removing items from a collection), some items may not get processed. Although you don’t have to keep a counter, FOR EACH uses one internally and does process each element in order.

The variable uRef takes on the value of each item of the array or collection in turn. This is especially handy when you’re processing a collection; in that case, uRef gives you an object reference to a member of the collection. For example, if you use a FOR EACH loop on a form’s Controls collection, uRef provides an object reference to each control in the collection in turn, and you can manipulate that object’s properties and call its methods using the reference.

Be careful, however, when you’re processing an array that doesn’t contain object references. uRef gets the value of the element, not a pointer to it. This means that changes to uRef do not affect the array itself. Also, uRef is created as a private variable if it has not already been explictly declared. Good programming practices dictate you should always be declaring your variables and their scope. This is one of those situations where a LOCAL or PUBLIC declaration could prove essential.

LOOP and EXIT behave here the same as they do for regular FOR loops—they let you jump out from the middle. LOOP sends you on to the next item, while EXIT ends the loop altogether.

In VFP 6 and earlier, if you use FOR EACH to process an array of strings and one of the strings has more than 255 characters, you get a "String too long to fit" error. This bug was fixed in VFP 7.

Example

* Get a list of all the open forms in the main VFP window and
* minimize those that are maximized.
ACTIVATE SCREEN
FOR EACH oForm IN _SCREEN.Forms
   ? oForm.Caption
   IF oForm.WindowState = 2
      oForm.WindowState = 1
   ENDIF
ENDFOR

See Also

For, Local