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.

FirstElement, NumberOfElements

These properties mimic one of the coolest (and most underused) features of FoxPro 2.x. When a combo or list box is based on an array, you can control which column of the array and which sequence of rows appear.

Usage

oObject.FirstElement = nFirstElementToShow
nFirstElementToShow = oObject.FirstElement
oObject.NumberOfElements = nNumberToShow
nNumberToShow = oObject.NumberOfElements

These properties apply only when the list or combo has RowSourceType set to 5 (Array) and only when ColumnCount is set to 1. (The latter limit was not documented in earlier versions of VFP, but is now correct in the VFP Help file. We’re quite grateful since we’re very tired of telling people that these properties won’t do what they wanted them to: let them choose a rectangular portion of the array to go into the list.)

In any case, under the right circumstances, what these properties do is pretty cool. Imagine that you have a multi-column array and you want to show the contents of the third column in a list. You could set ColumnCount to 3 and then set ColumnWidths so that the first two don’t show up at all, but why bother? If you only need the one column, just set FirstElement to 3 and only the third column appears.

There’s a more complex way to use FirstElement. The items in an array are numbered in what’s officially known as row-major order. This means you go all the way across one row numbering, then move to the next row. If the value you give FirstElement isn’t in the first row of the array, then not only does it determine which column appears, but it also indicates that the list or combo starts with the specified row. That is, with a three-column array, FirstElement=8 means to show the second column, starting with the third row.

NumberOfElements is pretty simple. It indicates how many rows are included in the list or combo.

It’s at this point that we get a tad disappointed that they didn’t make this work for multi-column lists and combos. We could imagine wanting multiple columns but limiting the display to a subset of the array. Oh well, it’s not that hard to ACOPY() the relevant rows to another array and use that, or to set RowSourceType to 0 and AddItem the elements into the list or combo.

Example

* This example sets up a combo to show last names
* of Employees. It can be set to show only those from
* a specified Country.

* This code goes in the form's Load and assumes
* you've added a property to the form aEmp[1].
* It creates an array of Employees ordered by country.
SELECT Employee_Id, First_Name, Last_Name, Country ;
   FROM Employee ;
   ORDER BY Country ;
   INTO ARRAY ThisForm.aEmp

* Now set a combo's properties in the combo's Init as follows
* to show only the last name column (or make equivalent
* settings in the property sheet):
This.RowSourceType = 5
This.RowSource = "ThisForm.aEmp"
This.FirstElement=3

* In a method on the form, you can change
* the combo to include only Employees from a
* specified Country (cCountry), as follows:
LOCAL nFirst, nFirstRow, nCount
nFirst = ASCAN(ThisForm.aEmp, cCountry)
nFirstRow = ASUBSCRIPT(ThisForm.aEmp, nFirst, 1)
IF nFirst > 0
   nCount = 1
   DO WHILE nFirstRow + nCount <= ALEN(ThisForm.aEmp,1) ;
            AND ThisForm.aEmp[nFirstRow + nCount, 4] = cCountry
      nCount=nCount+1
   ENDDO
ENDIF
* Now set combo properties.
* FirstElement is first occurrence of cCountry - 1
* to get last name
ThisForm.cboEmps.FirstElement = nFirst-1
ThisForm.cboEmps.NumberOfElements = nCount

See Also

ACopy(), AddItem, ColumnCount, ColumnWidths, ComboBox, ListBox, RowSource, RowSourceType