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 are all properties of a cursor in the Data Environment of a form, report or label. They let you indicate how the table or view the cursor refers to is to be opened.
These properties affect a table or view only if it is opened by the Data Environment, either because AutoOpenTables is .T. or by explicitly calling the OpenTables method. If the table or view is opened in other code, it uses the settings in the USE command and the current SET settings.
ReadOnly also applies to several controls and to the Project’s File object.
frmForm.DataEnvironment.crsCursor.Alias = cAlias
cAlias = frmForm.DataEnvironment.crsCursor.Alias
Alias determines the alias assigned to the table or view. By default, the alias is the name of the table or view. If the name has embedded blanks, the default alias replaces them with underscores (for example, the view “supplier listing” becomes “Supplier_listing”).
frmForm.DataEnvironment.crsCursor.Exclusive = lIsExclusive
lIsExclusive = frmForm.DataEnvironment.crsCursor.Exclusive
Exclusive determines whether the table is opened exclusively or shared. In VFP 5 and later, Exclusive is read-only for views and set permanently to .T. In VFP 3, you can change Exclusive for views, but when you test ISEXCLUSIVE()
, it returns .T. anyway. None of this really matters because views are always sharable. Every user can open the same view (unless offline views are involved).
The tables opened behind the scenes to populate a view are always opened shared, regardless of the view’s Exclusive setting or the current value of SET(“EXCLUSIVE”). On the whole, we think this isn’t awful, though we’d rather have control over it. If you want to be sure these tables are opened the way you want them, add them to the Data Environment before the views that need them and SET EXCLUSIVE
the way you want it for each, or open them explicitly in the BeforeOpenTables or OpenTables method.
frmForm.DataEnvironment.crsCursor.Filter = cFilterString
cFilterString = frmForm.DataEnvironment.crsCursor.Filter
Filter determines the filter applied to the table or view. You can change the cursor’s filter while the form is running and the visible set of records is updated.
In VFP 3, there’s no way to turn the filter off entirely. That is, there’s no equivalent to SET FILTER
TO. This means to make all records visible, you have to resort to a trick like using “.T.” for cFilterString. The problem with this is that you may end up with a filter that isn’t Rushmore optimizable.
In VFP 5 and later, use the Data Environment’s ResetToDefault method to clear the filter or set it to “”.
frmForm.DataEnvironment.crsCursor.Order = cTagName
cTagName = frmForm.DataEnvironment.crsCursor.Order
Order determines the index in effect for the table or view. Like Filter, you can change Order while a form is running.
There's no way to turn off index order. That is, you can't restore the table to natural order by modifying the Order property. We can't even think of a work-around that restores natural record order—ResetToDefault doesn't work. (In fact, you can't reset Order to default in the property sheet, either. How odd!) |
Okay, so we lied. We can think of a way to restore natural record order, but the cure may be worse than the disease. You can SET ORDER TO and the table is displayed in natural order. However, the cursor's Order property still reflects the last order you specified. (Fortunately, ORDER() does correctly return the empty string.) |
Bottom line: If you need to work with records in natural order, you may want to stay away from the Order property in code. Use it in the property sheet to set the initial table order, but make all your changes with SET ORDER
and do all your testing with ORDER()
. (Of course, the main reason to use natural order is because it’s faster for some operations.)
We should probably explain why we say that Order affects views. Although views can’t have index tags stored for them, you can index a view once it’s open. One clever trick is to force OpenTables to open the tables and views prematurely (see DODEFAULT()
for details), then create some index tags for your views. Starting in VFP 7, you can use the AfterOpenTable database event to index a view once you’ve opened it. Once you’ve created the tags, you can SET ORDER
just as you can for a table.
In VFP 7, if you create tags for a view in the AfterOpenTable event, you can set Order to one of those tags in the Property Sheet. Of course, the tags don't appear in the dropdown, but you can just type in the tag name you want. |
Prior to VFP 7, you can’t SET ORDER
for a view in the property sheet—that value gets called on too soon.
frmForm.DataEnvironment.crsCursor.ReadOnly = lIsReadOnly
lIsReadOnly = frmForm.DataEnvironment.crsCursor.ReadOnly
For a cursor, ReadOnly determines whether the table or view is opened in read-only mode. If so, it can’t be changed by the user or in code.
For a control (grid, column, text box, edit box, spinner, check box or combo box), ReadOnly determines whether the user can change the data displayed in the control. Even when ReadOnly is .T., the user can navigate in the control. To disable a control completely, use the Enabled property.
For the file object, ReadOnly is related to source control and indicates whether or not you can change the file at this moment.
* The following assumes you've added the TasTrade
* Customer table to the DE of a form as the first table,
* so the corresponding object is named "Cursor1".
* You'd normally set these properties in the Form Designer,
* but here's the code:
ThisForm.DataEnvironment.Cursor1.Alias="Cust"
ThisForm.DataEnvironment.Cursor1.Exclusive=.T.
ThisForm.DataEnvironment.Cursor1.Filter="country='USA'"
ThisForm.DataEnvironment.Cursor1.Order="company_na"
ThisForm.DataEnvironment.Cursor1.ReadOnly=.F.
You need to set most of these properties at design-time. Otherwise, your changes occur after the tables have been opened, which is too late. You can’t change the cursor properties before opening tables at runtime because the cursor’s Init doesn’t fire until after the tables have been auto-opened. If you really need to, you can change these properties in the BeforeOpenTables or OpenTables methods.
AfterOpenTable, Alias(), Cursor, DataEnvironment, DoDefault(), Enabled, File, Filter(), IsExclusive(), IsReadOnly(), Order(), ResetToDefault, Set Exclusive, Set Filter, Set Order, Use