The SCAN command
2007-08Aug-31
I've seen lots of FoxPro programs that use GO TOP before a SCAN loop and SELECT just before the ENDSCAN and before every LOOP statement. These statements aren't required anymore. Yet, many developers use them as a safety belt. So what does SCAN really do? Here are a number of observations:
On the first pass, SCAN moves the cursor to the top of the file. Subsequent calls just skip by one record. This even true when the table changes in between. Hence, the following code skips through records 1-3 of Customers, and records 2-4 of Products. The total number of iterations is six, even though this would impossible with the FOR condition in just one table.
The NEXT clause is implemented as an independent counter. If you add NEXT 4 to the SCAN command above, the total number of iterations is four, not four for each table.
The FOR clause is bound to the SCAN statement which invalidates a filter when you switch tables:
When you run this code you see that VFP evaluates the FOR condition for the first record of Customers.DBF, all matching records in Customers (17, 55, and 65) and exactly the same records (17, 55, and 65) in the Products table. In other words, VFP is using the Rushmore bitmap for Customers on the Products table. Because Rushmore involves a record validation, the SCAN loop itself is only executed for the Customers table.
Reusing Rushmore bitmaps this way is a subtle source for errors. If you changed the condition from UPPER(City)="A" to UPPER(City)="W", you would end up with a "Record out of range" error message. The records with "W" as the city in Customers.dbf are record 43 and 91. The Products table, however, only has 77 records.
Select 4
Use Northwind\customers
Scan for Recno() < 5
? Select(), Evaluate(Field(1))
If Used("Customers") and Recno() >= 3
Use Northwind\Products
EndIf
Select 99
Endscan
The NEXT clause is implemented as an independent counter. If you add NEXT 4 to the SCAN command above, the total number of iterations is four, not four for each table.
The FOR clause is bound to the SCAN statement which invalidates a filter when you switch tables:
Clear
_screen.Cls()
ln = 0
Select 4
Use Northwind\customers
Scan for Iif(;
_Screen.Print(Alias()+Transform(Recno())+Chr(13));
,.t.,.t.) and Upper(city)="A"
? " *"
ln = ln+1
If Used("Customers") and ln> 2
Use Northwind\Products
EndIf
lnRecNo = Recno()
endscan
When you run this code you see that VFP evaluates the FOR condition for the first record of Customers.DBF, all matching records in Customers (17, 55, and 65) and exactly the same records (17, 55, and 65) in the Products table. In other words, VFP is using the Rushmore bitmap for Customers on the Products table. Because Rushmore involves a record validation, the SCAN loop itself is only executed for the Customers table.
Reusing Rushmore bitmaps this way is a subtle source for errors. If you changed the condition from UPPER(City)="A" to UPPER(City)="W", you would end up with a "Record out of range" error message. The records with "W" as the city in Customers.dbf are record 43 and 91. The Products table, however, only has 77 records.