In the world of green-screen programming, one basic function a program has is dealing with information that the user enters on the screen, including changes to data.
On a simple screen, processing user-entered changes can be straightforward--editing, validating, and then processing. On more sophisticated screens, it is not as straightforward.
In my position, I write many subfile programs. In any program, I can give the user several options for positioning and filtering the subfile. I may also give the user Option 1=Add lines. These functions usually involve validation and rebuilding the subfile.
So why should I check what the user enters on the screen? If the data hasn't changed from the last time the user pressed Enter (or another function key), I really don't want to re-validate the data or rebuild the subfile. That would be redundant.
One way to check for changes in screen data is to use the CHANGE keyword for display file DDS. The syntax is CHANGE(nn), where nn is an indicator. This can be a record-level keyword to apply to all input-capable fields in the format, or it can be a field-level keyword. If the user types into a field that is affected by this keyword, then indicator nn is set on.
All your program needs to do is check that indicator to see if the data in the field has changed.
OK. Whoa. Back up the iSeries delivery truck. That last statement is not entirely accurate. CHANGE sets on the indicator if the user has typed into the field. That does not mean that the data in the field has changed. The user could type into a blank field and then blank out the field again. Or the user could type in a new value for the field, change his mind, and type in the original value again.
This doesn't work for me. If the user does something like this, and the indicator comes back to my program set on, I could end up rebuilding my subfile when I don't really need to (possibly confusing the user in the process). Or I could do a validation routine again when it is not needed--not good if the routine is extensive and/or I/O intensive.
So I rarely use CHANGE. I've come up with a different approach to see if screen data actually changes.
I keep a list of fields I want to check for user-entered change in my RPG program. Here's an example:
D S1 DS
D S1WO
D S1WO2
D S1NO
D S1DESC
D S1LOCATION
D S1REQLOC
D S1@WO // Option 1=Add fields...
D S1@NO
D S1@DESC
D P1 S like(S1)
The data structure S1 lists all the fields from my screen format that I want to check. It will contain the values of the fields from the last read of the screen. Note the field P1, which is defined like S1. This will contain the previous values of the screen fields. It is fine as a standalone field for the most part. Defining it with LIKEDS can also be useful if I need to check for changes in individual fields.
I also have some switches:
D |
D ChgFound N
D ForceChg N inz(*off)
ChgFound will be set on if any of the fields have had data changed. I use ForceChg if I want to make the program think there is a screen data change, regardless if there is any or not. I often use ForceChg when my program is changing screen data itself, such as in F5=Refresh processing.
Now, here's the main screen processing routine:
begsr $Screen1;
// Main Screen
// ================================================================
exsr $Show;
|
|
|
if CmdKey = F5;
exsr $ClrAdd;
ForceChg = TRUE;
endif;
exsr $ScreenChange;
if ErrFound OR ChgFound;
exsr $Edit;
if ErrFound;
leavesr;
endif;
endif;
|
|
|
exsr $Process;
endsr;
First, the F5=Refresh processing forces a change. Since I'm refreshing, I may be changing screen data myself (clearing out subfile filter or position-to fields or Option 1=Add fields, for example), and I would need to rebuild the subfile.
Then, I execute a routine to check for screen changes, using the list defined earlier:
begsr $ScreenChange;
// ================================================================
ChgFound = ForceChg OR (S1 <> P1);
ForceChg = FALSE;
P1 = S1;
endsr;
If there is a change (actual or forced), ChgFound is set on.
Now, if the user did make a change (or there are still errors from the last time the validation routine $Edit was run), the edit routine $Edit is run.
begsr $S1Edit;
// ================================================================
ErrFound = FALSE;
inError = *ALL'0';
dou Once;
// Edits go here
enddo;
// --------------------------------
ErrFound = (inError <> *ALL'0');
exsr $Clear;
if NOT ErrFound;
exsr $Load;
endif;
endsr;
This is the routine that validates the user-entered data and rebuilds the subfile. And it is run only when the user actually changes data on the screen (or a change is forced).
This is a relatively simple technique for checking if data coming in from a screen has actually been changed, rather than using CHANGE, which merely tells if a field has been typed into. You may use this technique, or, ahem, change it as you see fit.
Doug Eckersley is the chief iSeries developer at Dominion Homes in Dublin, Ohio. He has over 16 years of application development experience. He is the co-author of Brainbench’s RPG IV certification test. This year, his family is hosting a boy from Germany, while supporting their Hong Kong boy through his sophomore year at the University of Dayton.
LATEST COMMENTS
MC Press Online