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.

Scan

This loop command is designed for sequentially processing the records in a table. It automatically moves the record pointer forward each time through the loop and stops when it reaches the end of the table.

Usage

SCAN [ Scope ] [ FOR lForCondition ] [ WHILE lWhileCondition ]
     [ NOOPTIMIZE ]
        Commands
        [ LOOP ]
        [ EXIT ]
ENDSCAN

The default scope for SCAN is ALL, so if no other scope is specified and there’s no WHILE clause, processing starts with the first record in the current order. When there’s a WHILE clause, processing starts with the current record. (For an explanation of Scope, FOR and WHILE clauses, see “Scope, FOR, WHILE and Santa Clauses” in “Xbase Xplained.”)

SCAN processes records in the current index order. With a FOR clause, you’ll get better performance by setting ORDER TO 0 before the loop. There’s also a gotcha involving loops and indexes. If you’re processing records in an index order and you change the value of the index key in the loop, the record immediately moves to its new position in the index and you may process some records twice or some not at all. Bottom line is, don’t change the key of the current index order inside a loop.

SCAN replaces any loop that looks like:

DO WHILE .NOT. EOF()
   * Do some processing
   SKIP
ENDDO

We tested empty loops, just going through a table from top to bottom, and found SCAN to be about twice as fast as the equivalent DO WHILE. Your mileage may vary.

SCAN always reselects the right work area (the one the loop started in) when it reaches ENDSCAN, so you don't need to reselect even if you've changed work areas inside the loop. We know a lot of people who do so anyway. There doesn't appear to be a performance penalty for this, so if you're the belt-and-suspenders type, go right ahead.

LOOP and EXIT let you duck out before the show ends. LOOP short-circuits the current pass through the loop, going directly to ENDSCAN without executing any commands in between. EXIT cuts out of the loop entirely, going on to the command after ENDSCAN. Since you can avoid LOOP with IF and you can add a WHILE condition to avoid EXIT, we can’t see too many reasons for using either of these in a SCAN loop. Both LOOP and EXIT violate structured programming guidelines.

You can probably ignore NOOPTIMIZE. We’ve never found a use for it. But, if you really want to know about it, check out SET OPTIMIZE. NOOPTIMIZE is the local equivalent.

We don’t use many SCAN loops because most of the table-processing commands accept Scope, FOR and WHILE clauses, which allow us to do the same thing in a single command. The best time to use a loop is when you have several things to do to each record or when you need to do something complex.

Example

USE Company
* Loop through, printing fax if available and phone
* number otherwise
SCAN
   IF EMPTY(Fax)
      ? Phone
   ELSE
      ? Fax
   ENDIF
ENDSCAN

See Also

Do While, Exit, For, For Each, Loop, Set Optimize