![]() |
|
Published 1997-07-01 Printer-friendly version
"You're restricted!"
Fortunately, I don't have to say that to my teenagers too often, but for data entry screens, I want to enforce that discipline on users to ensure their input is valid and makes logical sense.
As we all know, list boxes, combo boxes, and drop-down lists offer choices for user input. We can restrict entry selections with record filters and range limits to display appropriate data choices. Sometimes the set of selections for a particular data field depends on the selected value of a related field on the same form. This article explores how to dynamically display appropriate choices for related data fields on a form.
The FileDropCombo Control template is a user-friendly mechanism designed to display valid choices for data fields based on values in a separate related file. To demonstrate its use and functionality, let's set up a data dictionary for an application that will log calls received at the fictitious Help Desk Headquarters for the Generally Defective Company, a small household appliance manufacturer. (The dictionary, named HELPDESK.DCT, is included in the solution set for this article.)
| CallLog | ||
| LogID | ULONG | Primary, Unique Key, Auto Num, No Pop |
| CustomerName | STRING(30) | |
| ProductID | USHORT | Key, Must be in Product File, No Pop << - - > Product file |
| DefectID | USHORT | Key, Must be in Defect File, No Pop << - -> > Defect file |
| Product | Do Not Populate File | |
| ProductID | USHORT | Primary, Unique Key, Auto Num, No Pop < - - > > Defect file |
| ProductDescription | STRING(25) | Unique Key |
| Defect | Do Not Populate File | |
| ProductID | USHORT | Key, No Pop |
| DefectID | USHORT | Unique Key, Auto Num, No Pop |
| DefectDescription | STRING(25) | Key |
| ResolutionScript | MEMO |
Now generate an application from this dictionary using the Application Wizard. For simplicity's sake, only generate procedures for the CallLog file. (In the Application Wizard, uncheck the box labeled "Generate Procedures for all files in my dictionary", then select the CallLog file in the Select Files to Use dialog.) Compile and run your application to see the default behavior generated from our dictionary.
Browse the CallLog file. Press the + button on the toolbar to insert a new CallLog record. Once you enter a customer's name, you're faced with making a decision on what product id to enter. Don't know one? Well, if the cursor is placed in the entry field for ProductID and you press Enter, a selection listing of the Product file pops up. Select a product by double-clicking on it. Then, you're faced with another decision - the choice of the defect id on the product. The selection listing of the Defect file pops up, you make your selection, and your record entry flies into the CallLog file. Whew! That will definitely be confusing for our users. Let's list where we can make some improvements in the way we ask for valid data from our users:
Let's improve our UpdateCallLog screen. In the Window formatter, delete the ProductID and DefectID entry fields. Let's repopulate these fields with file drop combos which display intuitive data choices to our users:
Populate the file drop combo for LOG:DefectID in a similar manner with an appropriate local data description, the description from the Defect file in the list box and correct Fill From and Target fields in the Control Template. Compile your app and check out your changes.
The results of our efforts show: The selection lists are more intuitive for the user. We are still displaying all of the possible product defects in the drop for the defect id. I know.. your instincts tell you to put a record filter on the Defect file drop of DEF:ProductID = LOG:ProductID. Your instincts are correct... partially. Go ahead and make that change, compile and run, and you'll find that your filter works great in an ChangeRecord situation, but on InsertRecord, your selection list is empty. Why is that? Well, I'm glad you asked.
Here's where we need to put the drop list template in the spotlight and understand its default behavior on a window. Drop lists are loaded at the time that the window is opened. Our range limit worked fine in the ChangeRecord situation, because we had a value already in LOG:ProductID to limit the records. In an Insert scenario, we have no value in LOG:ProductID, so none of the records in the Defect file fit the criteria, and we were left with a blank drop list. But don't worry, we can easily make it do exactly what we want it to do.
We need to have the program remember the ProductID that the user has entered, so that when a new ProductID has been entered, we will want to fill the Defect drop list. To achieve this, declare a local variable named LocalHoldProdID (USHORT), and put the following code into the embed labeled Window Event Handling, Open Window:
!Hold the Prod description if a change, otherwise set to invalid value
CASE(LocalRequest)
OF InsertRecord
HoldProductDesc = '' !Invalid Prod Description - forces input
OF ChangeRecord
PRO:ProductID = LOG:ProductID !Prime product id
GET(Product,PRO:KeyProductID)
IF Errorcode( )
HoldProductDesc = ''
END
HoldProductDesc = PRO:ProductDescription
LocalProduct = HoldProductDesc
?ButtonSeeText{PROP:disable} = False
END
Right click on the UpdateCallLog procedure in the application tree, and select Source to view the source code. Do a search for 'FillList Routine' (no quotes in your search). You will find two routines that are called upon opening the Form window which fill the queues for the two file drop combos. Find the routine that fills the Defect file drop and note its name. (FLDx::FillList, where x designates the field number.)
To execute this code when a product has been entered on the CallLog form, add the following code on the embed on Accepted of ?LocalProduct in Control Event Handling, after generated code:
!Fill the Defect FDC with associated values for the product !just selected
IF CLIP(HoldProductDesc) <> CLIP(LocalProduct)
HoldProductDesc = LocalProduct
LOG:DefectID = 0
LocalDefect = ''
?ButtonSeeText{PROP:Disable} = True
DO FLD6::FillList
DISPLAY( )
END

Now that we have related data validation built into our procedure, we can look at another option for our users at input time:
Sometimes, the appropriate choice for entry is not present in the dropped list. Generally Defective Company wants to allow the Help Desk engineers to update the Defect file with additional data they gather from callers. To achieve this functionality, select the UpdateCallLog procedure > Window Formatter. Select the Defect file drop combo, right click, select Actions > Update Behavior tab. Check the Allow Updates box, and select the UpdateDefect procedure from the drop list. Upon entering the update procedure, the value of ProductID in the Defect file should be primed to the value that has been chosen on the CallLog form. On the Procedure Properties screen of UpdateDefect, press the Field Priming on Insert button, and then Insert the Field to Prime: DEF:ProductID, and Initial Value: LOG:ProductID.
We're done! You can clean up the unused procedures in your application tree, renumber modules, recompile, and deliver your program. Generally Defective Company's Help Desk is now automated to insure valid, logical data entry, thanks to our related, limited file drops. Now maybe they can concentrate on improving their products, and we can concentrate on trying to make logical sense of our teenagers. <G>
Disclaimer: Any resemblance of Generally Defective Company to "real" companies, profitable or not, is purely coincidental. The fictitious Generally Defective Company was created by the author and friends strictly for demonstration and entertainment purposes.
Copyright © 1999-2008 by CoveComm Inc. All Rights Reserved. Reproduction in any form without the express written consent of CoveComm Inc., except as described in the subscription agreement, is prohibited.
Clarion Magazine ISSN 1718-9942
One year: $189
(includes all back issues since '99)
Renewals from $139
Two years: $289
Renewals from $239