Saving Field Rules in Xbasic

by Dr. Peter Wayne

You may have some carefully constructed field rules that you want your Xbasic program to respect. Can you keep those field rules, or are they lost?

One of Alpha Five's great strengths is its large collection of field rules, which let you do everything from case conversion to posting. When you open a table with Xbasic, however, you override all of Alpha Five's field rules except for the validation-level field rules and autoincrement rules. But what if you don't want to rewrite the transformation rules or posting rules? Can you make your script obey the table's field rules?
Let me illustrate the problem with a simplified inventory application with 2 sample tables, stock and sales_from_stock. The stock table has 2 fields, item, C3 and on_hand, N4. The sales_from_stock table also has 2 fields, item, C3 and sold, N2. As sales are recorded in the sales_from_stock table, the on_hand quantity is automatically decremented by the amount recorded in sold. The automatic updating of the on_hand quantity is done with a simple Posting field rule in the sales_from_stock table:
posting field rule
Figure 1. Creating a Posting rule for the sold field.

The full posting rule is:

Posting Option Value
Table stock.dbf
Field Stock->on_hand
Target Linking Key Item
Source Linking Key Item
Operation Subtract
Condition (none)
Undo on Delete Yes

Table 1. Options for Posting field rule.

Let's enter a few items into the stock table:Stock table entries
Figure 2. Entries in stock.dbf.
Now we'll create a form for sales_from_stock and make an entry:Entry into sales from stock
Figure 3. An entry in sales_from_stock.dbf: the Sales_from_stock form.
After this entry is saved, the posting rule on sold will reduce the on_hand field in the first record in stock from 30 to 27.
What if we need to make entries into sales_from_stock from an Xbasic program? This script is a fairly straightforward way to make the same entry as shown in Figure 3:

dim sales as p
sales=table.open("sales_from_stock")
sales.enter_begin()
	sales.item="001"
	sales.sold=3
sales.enter_end(.t.)
sales.close()

Script 1. Table-level entry into sales_from_stock.
The problem with Script 1 is that our posting rule is no longer enforced. We would have to explicitly code the posting to the stock table. In this example, it would not be a very big effort to code the post, but under other circumstances it could be burdensome:

  1. we could have multiple, complex posting rules
  2. if we change the posting rules in the field rules, we have to remember to change them in all the scripts as well

Wouldn't it be simpler if we could just make the Xbasic script recognize the field rules? Well, we can. If we use the form-level entry methods, then Alpha Five believes that our Xbasic script is simply another user. We'll write an Xbasic script to open the Sales_from_stock form, make a new record, and close the form:

f=form.load("Sales from stock")
f.new_record()

f:item.value="001"
f:sold.value=3
f.commit()
f.close()

Script 2. Form-level script to enter a new sale.

Compare Script 2 to Script 1. If you run Script 2 you will see that it physically displays the form, fills it out, and then closes it. When this script runs, the posting rule is executed.
You may find the temporary displaying and filling out of the Sales from stock form distracting (I do!). You can eliminate most of the distraction by using the command, ui_freeze(.t.), which prevents the display from being updated. Here is the final script:

ui_freeze(.t.)

f=form.load("Sales from stock")
f.new_record()

f:item.value="001"
f:sold.value=3
f.commit()
f.close()
ui_freeze(.f.)

Script 3. Enter a new sale and prevent display of the form.
There is still a bit of screen flicker at the ui_freeze(.f.) command, but the Sales from stock form is not displayed.

Alpha Five v. 4 enforces field rules differently.

Now for the good news. In Alpha Five v. 4, it won't be necessary to use the form-level new_record() and commit() methods to enforce field rules. You can use the table-level record entry methods, enter_begin() and enter_end(), with any table that has an associated form. So we can rewrite Script 3 as

dim f as p
dim sales as p
f=form.load("Sales from stock")
sales=:Sales_from_stock:Tables:Sales_from_stock.this
sales.enter_begin()
	sales.item"001"
	sales.sold=3
sales.enter_end(.t.)
f.close()

Script 4. An Alpha Five version 4 script that respects field rules
In the second line of Script 4, the first :Sales_from_stock: refers to the form which has been loaded. That form in turn contains a :Tables: object, which is in itself a container for the Sales_from_stock table. Adding the final this attaches the sales pointer to the sales_from_stock table.
It's not just posting field rules that can be enforced by these techniques. By writing to an invisible form or by accessing the tables associated with an invisible form, you can force Alpha Five to execute transformation rules (such as case conversion), default value rules, and even custom record and field-level event scripts. Now that is power!

7/24/98 - pkw

Don't forget, we need your feedback to make this site better!

Return to home