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.
These commands were part of every application we wrote in FoxPro 2.x (and even in earlier versions). We don’t use them the same way in Visual FoxPro because VFP’s buffering capabilities make it unnecessary, but one VFP-only version of the commands can be useful.
SCATTER copies all or part of a record to an array, memory variables or an object. GATHER collects data from an array, variables or an object and sticks it in the current record.
SCATTER [ FIELDS FieldList |
[ LIKE Skeleton1 ] [ EXCEPT Skeleton2 ] ]
MEMVAR | TO ArrayName | NAME ObjectName
[ MEMO ] [ BLANK ]
GATHER [ FIELDS FieldList |
[ LIKE Skeleton1 ] [ EXCEPT Skeleton2 ] ]
MEMVAR | FROM ArrayName | NAME ObjectName
[ MEMO ]
Parameter |
Value |
Meaning |
FieldList |
List of fields |
The fields to include in the command. |
Skeleton1 |
Fieldname with wildcards |
A specification for which fields to include in the command. Wildcards are * and ?. |
Skeleton2 |
Fieldname with wildcards |
A specification for which fields to exclude from the command. Wildcards are * and ?. |
ArrayName |
Name |
An array to hold the scattered data or from which to get the gathered data. SCATTER creates or enlarges the array, as needed, but doesn't shrink it. |
ObjectName |
Name |
An object that has a property corresponding to each specified field. SCATTER creates the object. |
Both the LIKE and EXCEPT clauses can be included in a single command, but they can’t be mixed with an explicit field list.
There are three forms of these commands that differ in where they put or get the data: MEMVAR, TO array and NAME. MEMVAR uses a set of memory variables with the same names as the fields. SCATTER MEMVAR creates the memory variables; GATHER MEMVAR collects data from them.
Using TO or FROM indicates that field data is stored in an array. SCATTER creates or redimensions the array, if necessary. GATHER collects data from the array, matching it element by element with the record.
The NAME clause lets you create an object that has a property for each specified field. SCATTER creates and populates the object. GATHER collects data from the object. Note that objects created this way differ from almost every other object you can create in Visual FoxPro. Unless the table being SCATTERed happens to have such fields, these objects have neither Name nor Class properties. They have no methods or events. Listing memory shows the object as type Object with class “EMPTY.” These “lightweight” objects are ideal candidates to use as parameters, having no visible presence and no surprising behaviors.
The MEMO clause indicates that memo fields should be included in the command. Without it, memos are ignored. When you’re working with arrays and omit MEMO, you need to be careful that you don’t get mixed up about which column refers to which field, since memo fields are skipped. General fields are always skipped, so watch out for those, too.
BLANK says to create the memvars, array or object, but populate it with blank values of the appropriate type. In a FoxPro 2.x application, you’d typically SCATTER MEMVAR BLANK at the beginning of an Add operation, then APPEND BLANK and GATHER MEMVAR when the user asked to save.
Visual FoxPro appears to fix a “by design” bug in older versions. In FoxPro 2.x, if you SCATTER MEMVAR, then call a routine that makes one of the SCATTERed memvars private and GATHER in that routine, if the called routine contains no assignment to the private memvar, FoxPro would find the memvar in the calling routine and GATHER it even though the PRIVATE declaration should have hidden the memvar in the calling routine. Visual FoxPro respects the privacy of the variable. This change should only create a problem for you if you depended on the old behavior.
We don’t use SCATTER and GATHER much in Visual FoxPro. Instead, we use row and table buffering and work with the fields directly. However, we do know people who use the NAME clause to create “record objects” so that they can write more OOP-y code.
* Create an object corresponding to a Customer record
* Assumes the record pointer is on the relevant customer
SCATTER NAME oCust MEMO
* Now you can refer to the fields as properties of the object
? oCust.Company_Name
? oCust.Customer_Id
* After editing, you can:
GATHER NAME oCust