Process an Editable subfile in ILE RPG IV (RPGLE, RPG-ILE)
So far we have dealt with display only subfiles. Now we will learn the subfiles which can accept user input and process it.
Generally the following are the steps in which we can display and process an input capable subfile. The editable subfiles are very much similar to the display-only subfiles except the last two steps where these subfiles are read (USING READC Or CHAIN) and updated (Using UPDATE). The steps to process an editable subfile in RPG IV are as given below.
- Load the subfile: We populate the subfile records as in case of any display only subfile. If we do not have any records earlier we may write blank records to subfile.
- Display the subfile: Display the subfile by ExFmt or continuous WRITE and READ operations.
- User edits the subfile: User edits the displayed subfile by changing the field values and presses any function key.
- Read Subfile: Read the subfile for the changed value. Optionally validate the user input and process it. Here, to read a subfile we use the keyword CHAIN or the keyword READC.
Difference between CHAIN and READC (CHAIN Vs READC)
The opcodes CHAIN and READC both are used to read a subfile record. However, there're a few differences between them. The opcode CHAIN requires a parameter, the relative record number (RRN) of the specific record you wish to read. So, here to process user input, we have to to CHAIN the subfile from RRN 1 to the maximum RRN. CHAINing a subfile is equivalent to CHAINing any other physical file, except the constraint mentioned (RRN). However, the opcode READC is used to read only those records which have been changed by the user. The opcode READC does not require any parameter. You begin doing READC in a loop based on the data indicator (EQ). The indicator at EQ place is set on if no more changed records are there in a subfile. This means that, if we displayed 1000 records to user and user changed only one record, READC will read only that changed record unlike CHAIN. With chain we will have to read all the thousand records and determine which record was changed.
Note: The READC will read those records also where user pressed the spacebar or the tab button.
When to use CHAIN and When the READC?
The answer to this question is that if your users are connected to the main AS400 system directly through LAN connection, they will not feel any difference whether you are using CHAIN or READC. Off course using CHAIN requires more CPU time as you read the subfile record by record. Here is a few guidelines which you may find helpful to make up your mind.
- Whenever possible use READC. This significantly reducess CPU time if the number of records in the subfile is in thousands. However, If you are not comfortable using READC. You can go for CHAIN.
- Always use READC when you know beforehand that your users might not be directly connected to the AS400 server using LAN. If the application you are writing is to be used over internet, even a small fraction of time saved means a lot.
- If you are not so comfortable with using READC and you do not expect your subfile to contain more than 100, 200 records. You can opt for CHAIN.
- There are times when there are no alternative to CHAIN. Like when you decide to CHAIN the last record of the single page subfile to load the next page of subfile. However, use CHAIN as scarcly as possible. That's use CHAIN when you specifically know the record number(RRN) of the record you are interested in.
Note:- Lots of programs in RPG III use CHAIN only. But we can almost always find an elegant alternative to CHAIN.
Example of an Editable subfile Processing in RPG IV.
OK, in the example below we will be using the same subfile DDS we have been using in our examples thruoghout this book. However, there will be a few modifications needed to make the subfile editable. For this, we change the field types to Both.
In the example below, we will be using READC only. No CHAIN. This is to help you understand and RETAIN the concept of READC. We may write a separate program to demonstarate CHAIN for the sake of completion of subfile Tutorial. (And also for a few (very few in fact) cases where READC might not be used)
Here is the source code of DDS of the subfile. The changes from a trivial subfile has been written in bold.
AAN01N02N03T.Name++++++RLen++TDpBLinPosFunctions+++++++++++++++++++
A R EDITSF SFL
A 56 SFLNXTCHG
**
** Declare fields as we would do in case of normal record format.
**
A $CUSNO 4Y 0B 5 02TEXT('Customer Number')
A 30 DSPATR(RI PC)
**
A $CUSNAME 20A B 5 10TEXT('Customer Name')
A 31 DSPATR(RI PC)
**
** Control Format of the subfile. Notice the usage of function
** SFLCTL. The name of the subfile has been given here to associa
** this control format with a specific subfile.
**
A R EDITCF SFLCTL(EDITSF)
**
** Function keys are defined in the record format.
**
A CA01
A CA05
**
** Declare the page size and subfile size
**
A SFLPAG(15)
A SFLSIZ(16)
**
** Declare the function SFLCLR. We need this function to clear a
** subfile.
**
A 50 SFLCLR
**
** The SFLDSP and SFLDSPCTL functions are necessary to display
** subfile. This time the SFLDSP function is indicator based. This is
** to handle the situation when no record is loaded into the subfile.
**
A 40 SFLDSP
A SFLDSPCTL
**
** Declare the ROLLUP key. The number inside the bracket is the
** indicator which would be set on when ROLLUP key has been press
** ed.
**
A ROLLUP(60)
**
** The SFLRCDNBR is required to display the last loaded screen.
**
A W@RRN1 4 0H SFLRCDNBR
**
** Define the control format fields. Generally the heading and
** subfile specific instructions are given here.
**
A 1 26' Customer Display '
A DSPATR(RI)
A 2 02'F1=Exit F5=Refresh'
A 4 02'Id'
A DSPATR(UL)
A 4 10'Customer Name'
A DSPATR(UL)
About the program: This program is supposed to the followings.
- Read a file and display all the availabe records in an expandable subfile.
- The subfile is to be editable
- The user will be allowed to change the values in the subfile record. Program will validate the changed records for blanks and zeros.
- Program will reverse image the records in error.
- All records will be updated at one go, when there are no errors in any of the changed records.
For the time being we are not displaying the specific error messages. We will do that after we read the message subfiles and how to process messages in an RPG IV program.
But... but... but...
Before we go to the source code of the RPG IV program, let us learn the SFLNXTCHG function.
SFLNXTCHG: This function is read as "Subfile next change"... indicator. Actually we associate an indicator with this function. This associtated indicator is set on by the AS400 system whenever, a subfile record is changed. Actually our READC reads only those subfile records for which the SFLNXTCHG indicator is set on. The READC operation set off this indicator.
The SFLNXTCHG indicator is of extreme use when we are dealing a subfile with READC. This concept is actually all you should try to master. You learn the concept of SFLNXTCHG and you are done with subfiles! We can also force the AS/400 system to read a specific subfile record. We can achieve this by setting the indicator associated with any record to on.
Another important point about SFLNXTCHG indicator, you can safely assume that for each subfile record we have a separate indicator. You can switch off or on this indicator as per your wish, but to associate an indicator's present value (On or Off) with any specific record, you need to UPDATE that subfile record. The UPDATE of subfile is exactly similar to that of a Physical file or logical file and hence to UPDATE a subfile you must have successfully read a record of that record (Using CHAIN or READC).
Now, the actual program source,
**
** Declare the customer master file.
**
FFilename++IPEASF.....L.....A.Device+.Keywords++++++++++++++++++++++
FCustMast UF E Disk
**
FEDITABLESFCF E WorkStn
**
** Declare the relative record number (RRN) for the subfile.
**
F SFILE(EDITSF:W@Rrn1)
**
DW@Rrn1 S 4 0 Inz
**
** Variable to store the last RRN of the subfile (Maximum RRN).
**
DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++
DW@LstRrn S 4 0 Inz
**
** Define a couter variable to keep track of number of records written
** to subfile at any time.
**
DW@Counter S 2 0 Inz
**
** Indicator to indicate whether the first page is to be loaded.
**
DW@FstPage S 1 Inz('1')
**
** Indicator to indicate whether the last record has been displayed.
**
DW@LstRcd S 1
**
** Error flag
**
DW@Error S 1 Inz('N')
**
** Execute subroutine to clear the subfile. The subfile is to be clear
** ed everytime the screen is refreshed.
**
C ExSr #ClrSfl
**
** Load the first page of the subfile.
**
C ExSr #LodSfl
**
C DoW *INKA = *Off
**
** ExFmt the CONTROL FORMAT of the subfile.
**
C ExFmt EditCF
CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+
C Select
C When *INKA = *On
C Iter
**
C When *INKE = *On
**
** Execute subroutine to load the subfile after clearing it.
**
C ExSr #ClrSfl
**
C Eval W@FstPage = *On
**
C ExSr #LodSfl
**
C When *In(60) = *On
C If W@LstRcd = *Off
**
** Execute subroutine to load the next page of subfile.
**
C ExSr #LodSfl
C EndIf
**
** When enter has been pressed to update the database with screen
** values
**
C Other
C If W@Rrn1 > *Zeros
C ExSr #Validate
**
C If W@Error <> 'Y'
C ExSr #Update
**
C Eval W@FstPage = *On
C ExSr #ClrSfl
C ExSr #LodSfl
C EndIf
**
C EndIf
**
C EndSl
**
C EndDo
**
C Eval *InLr = *On
C Return
********************************************************************
**
** The subroutine #LODSFL
**
C #CLRSFL BegSr
**
** Clear the subfile.
**
C Eval *In(50) = *On
C Write EditCF
C Eval *In(50) = *Off
C Eval W@Rrn1 = *Zeros
C Eval W@LstRrn = *Zeros
C EndSr
*********************************************************************
C #LODSFL BegSr
**
** Reset the counter
**
C Eval W@Counter = *Zeros
C Eval W@Rrn1 = W@LstRrn
**
** Set the cursor to read the first record of the physical file. If
** the subfile is to be loaded for the first time.
**
C If W@FstPage = *On
C 1 SetLl CustMast01
C Read CustMast01 90
C EndIf
**
C DoW W@Counter < 15 And *In(90) = *Off
**
** Increment the counter to keep track of number of record written at
** a time to the subfile. This count should not exceed the page size.
**
C Eval W@Counter += 1
**
** Increment the RRN to mark a new record of subfile.
**
C Eval W@Rrn1 += 1
**
** Populate the fields defined in the subfiles.
**
C Eval $CusNo = CustNo
C Eval $CusName = CustName
**
** Perform actual write to the subfile. Notice that each write actuall
** y adds a record to the subfile.
**
C Write EditSF
**
** Read the next record from the physical file.
**
C Read CustMast01 90
C EndDo
**
** The subfile is never to be displayed if no records are loaded into
** it. For this purpose, the SFLDSP indicator is set on only if some
** record has been written to it (W@Rrn1 > *Zeros).
**
C If W@Rrn1 = *Zeros
C Eval *In(40) = *Off
C Else
C Eval *In(40) = *On
C EndIf
**
C Eval W@LstRcd = *In(90)
C Eval W@LstRrn = W@Rrn1
**
C EndSr
***********************************************************************
C #Validate BegSr
C Eval W@Error = 'N'
C ReadC EDITSF 90
**
C DoW *In(90) = *Off
**
C If $CusNo = *Zeros
C Eval *In(30) = *On
C Eval W@Error = 'Y'
C EndIf
**
C If $CusName = *Blanks
C Eval *In(31) = *On
C Eval W@Error = 'Y'
C EndIf
**
C Eval *In(56) = *On
C Update EDITSF
C Eval *In(30) = *Off
C Eval *In(31) = *Off
CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+HiLoEq
C ReadC EDITSF 90
C EndDo
**
C EndSr
***********************************************************************
C #Update BegSr
C ReadC EDITSF 90
C DoW *In(90) = *Off
C W@Rrn1 Chain CustMast01
C Eval CustNo = $CusNo
C Eval CustName = $CusName
C Update CustMast01
C ReadC EDITSF 90
C EndDo
C EndSr
****************** End of data ****************************************
- 7267 reads
