You are on page 1of 23

Introduction to Subfiles

Introduction to Subfiles Basically subfiles are display-file-concept. Whenever we have to display some tabular data we have two options Define as many required fields Here, We can define as many fields as we wish to display at a time. For example if we have to display 15 sets of customer number, customer name at a time, total 30 fields need to be defined. Each field with unique name so the names of fields of screen would typically be $CusNam1, $CusName2....$CusName15. Similarly the customer numbers. This much is fine, we can handle it very easily. But what if the number of rows the table is too large say 1500 instead of 15. In that situation the programming will become a mess!. Use Subfiles Subfiles in a sense are display physical file, with several limitations. However, subfiles do free you up from defining innumerable fields. In the case discussed above, you need to define only two fields $CusName and $CusNo. That's all. Few of the limitations of subfiles as compared to physical files are as under

Subfiles are not objects. They are not files where you store data permanently. A maximum 9999 records can be written to a subfile at a time. A subfile can be used to store data only during runtime. You end the program you clear the subfile data. Several PF opcodes will not work with subfiles. Only READC and CHAIN and UPDATE are allowed opcodes. Subfiles can be CHAINed using record numbers only. You can not DELETE any subfile record. You can only UPDATE it. You need to remove it from subfile, you have to clear the subfile and reload all the records minus the delete record.

Some points in the above discussion might seem foreing to you. But do not mind you will learn each of them when you read the EDITABLE subfiles. Anyway this much is good for starting!

How subfiles are handled in ILE RPG IV Subfile processing in ILE RPG IV is a two step process. 1. Loading the subfile: First of all a subfile needs to be loaded before it can be further used in an ILE RPG IV program. By loading we mean adding records to subfile by explicitly WRITEing to the subfile. (There are certain conditions where you can achieve writing in some other way by using SFLINZ keyword.) 2. Displaying the subfile: Once a subfile is loaded with records you are free to use it. The subfile once loaded is ready to be displayed. Display part is important because we have to do lots of work when we process the user inputs. Hence by displaying a subfile we will mean that processing the user inputs. After all their is nothing difficult if we would have to just display a subfile! (EXFMT control Format. That's all!) Types of subfiles Before learning anything else let us learn the types of subfiles. We will learn the subfile concepts of these types one by one. 1. Load all Subfile: All records (Upto 9999) are loaded into subfiles at a time. 2. Expandable Subfile: Records, fitting one page in number, are loaded at a time. They are added to the already loaded records of the subfile. 3. Single Page Subfile: Only that many records are loaded at time which can fit on a sinble page. These records are cleared whenever new records are loaded.

Subfile Terminology
Subfiles structure, Anatomy of a subfile A subfile basically has two parts (Two record Formats) 1. Control Format: As the name suggests, a control format is the record format which controls the behavior of the subfile which it controls. Once control format can be associated with subfile record format only. The control format typically controls the Page size, Subfile Size, Function key definitions, Display control etc. and some optional features like + or More... sign when there're more records in a subfile. 2. Subfile Record Format: A subfile record format consists of the iterating fields. That's all those tabular fields are defined inside the subfile record format. Having known a little about subfiles, let us see a sample record format source of a subfile. Example of a typical subfile of a Display file Basic terms of a subfile Page Size: Page size of a subfile is the number of records which are to be displayed at a time. The page number is specified in the control format of a subfile by keyword SFLPAGE as you can see in the example above. Subfile Size: Subfile size is the initial number of records which are to be loaded in the subfile. The subfile size is specified by SFLSIZ keyword. The numbers of records specified by the subfile size are loaded in contiguous memory location. You may load more records than you specify in subfile size (Upto 9999) however they will not be contiguously placed in memory. Contiguous memory placement of subfile records results in higher performance. ROLLUP: At any time only a limited number of records are displayed on the screen. In a subfile the maximum number of records displayed is equal to the page size of subfile. To view next records we have to press the ROLLUP key. This key sometimes is "Page Up" and sometimes "Page Down". ROLLUP is a keyword also which is defined in control format of a subfile and marks the expandable subfile when defined without ROLLDOWN. ROLLDOWN: To view the previous records after pressing the ROLLUP key, we press the ROLLDOWN key. ROLLDOWN is a keyword also, its explicitly defined in Single Page subfiles along with ROLLUP keyword in control format.

Process a Load All subfile in ILE RPG (RPG IV)


What is a load all subfile? A load all subfile is one in which we generally specify the subfile size as 9999 in the record format itself. However, you may define the subfile size to be less than 9999 in the record format and still load your entire subfile at a time. In that situation the records will not be placed at contiguous memory location. So, conceptually a load all subfile is the one in which all records are loaded at one go before they are displayed. Also, they should occupy contiguous memory locations. Load all subfiles are the easiest concept in subfile. That too when the subfile is display only! Let us now see the example of a load all subfile DDS.
** Declare the name of the record format of the subfile. Notice ** that this time the function SFL has been used to distinguish ** this record format as a subfile A R LOADALLSF SFL ** Declare fields as we would do in case of normal record format. A $CUSNAME 20A 5 10TEXT('Customer Name') A DSPATR(HI) ** A $CUSNO 4Y 0 5 02TEXT('Customer Number') A DSPATR(HI) ** ** 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 LOADALLCF SFLCTL(LOADALLSF) ** Function keys are defined in the record format. A CA01 ** Declare the page size and subfile size A SFLPAG(2) A SFLSIZ(9999) ** 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. A SFLDSP A SFLDSPCTL ** 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' A 4 02'Id' A DSPATR(UL) A 4 10'Customer Name' A DSPATR(UL)

The source code with explanation of the ILE RPG program to process the load all subfile in the above example is given below.
** **Declare the display file which contains the subfile ** FFilename++IPEASF.....L.....A.Device+.Keywords+++++++++++++++++++++++ FLOAD_ALL CF E WorkStn ** ** Declare the relative record number (RRN) for the subfile. Notice ** the keyword used to declare subfile. ** F SFILE(LOADALLSF:W@Rrn1) ** ** Define the RRN of subfile (Typically 4 or 5 length with zero ** decimal places depending on how you handle it. If it's likely to ** reach 10000 then declare the length as 5 otherwise 4.) ** DW@Rrn1 S 4 0 Inz ** CL0N01Factor1+++++++Opcode&ExtExtended-factor2++++++++++++ C DoW *INKA = *Off ** ** Execute subroutine to load the subfile ** C ExSr #LodSfl ** ** ExFmt the CONTROL FORMAT of the subfile. ** C ExFmt LOADALLCF C EndDo ** ** Free up resources and return ** C Eval *InLr = *On C Return ** ** The subroutine #LODSFL ** C #LODSFL BegSr ** ** Clear the subfile. Clearing a subfile involves the following four ** statements. ** 1. Swicth on the SFLCLR indicator ** 2. Write to the control format ** 3. Swicth off the SFLCLR indicator ** 4. Reset the RRN to zero (Or one). ** The fourth statement actually is not related to subfile. However, ** we generally reset this value while clearing the subfile itself. ** C Eval *In(50) = *On C Write LOADALLCF C Eval *In(50) = *Off C Eval W@Rrn1 = *Zeros ** ** Set a looping condition. This condition may be based on anything.

** But in any case just ensure that RRN does not exceed 9999. ** C DoW W@Rrn1 < 9999 ** ** Increment the RRN to mark a new record of subfile. Remember that ** the variable corresponding to RRN should not be less than one (1) a ** nd it should never exceed 9999. ** C Eval W@Rrn1 += 1 ** ** Populate the fields defined in the subfiles. To load a blank subfil ** e we can just intialize the subfile fields. ** C Eval $CusNo = W@Rrn1 ** ** Perform actual write to the subfile. Notice that each write actuall ** y adds a record to the subfile. ** C Write LOADALLSF C EndDo ** C EndSr

Process an Expandable subfile in ILE RPG IV (RPGLE, RPG-ILE)


Expandable subfiles in RPGLE An expandable subfile is one in which ideally one page of records are loaded at a time. Subsequent pages are added to the subfile as per the user demand. In the expandable subfile the subfile size must be atleast one greater than the page size. The ILE RPG program to process an expandable subfile has typically the following flow 1. Load the subfile: Intitially the only the first one page of the subfile is loaded. 2. Display the subfile: The subfile screen is displayed to the user. 3. Rollup: Check if user pressed the rollup key. Many a times no rollup is defined and the next page is loaded with ENTER (RETURN) key only. If ROLLUP key has been pressed, load the next page and display it. Note: In expandable subfiles, we do not need to handle ROLLDOWN. This is handled by the system itself. This is because we do not clear subfile before loading the next page. The next page records are simly added to already existing first page. The following example illustrates how to process an expandable subfile (Some people like to call it extendible subfile because the subfile extends to accomodate the newly written records). Comments have been given at appropriate places to help you understand the flow of the program easily. Notice the ROLLUP function defined in the DDS here. /**** The DDS of the subfile. Notice the newly introduced functions ***/
** ** Declare the name of the record format of the subfile. Notice ** that this time the function SFL has been used to distinguish ** this record format as a subfile ** AAN01N02N03T.Name++++++RLen++TDpBLinPosFunctions++++++++++++++++++ A R EXPANDSF SFL ** ** Declare fields as we would do in case of normal record format. ** A $CUSNAME 20A 5 10TEXT('Customer Name') A DSPATR(HI) ** A $CUSNO 4Y 0 5 02TEXT('Customer Number') A DSPATR(HI) ** ** Control Format of the subfile. Notice the usage of function ** SFLCTL. The name of the subfile has been given here to associate ** this control format with a specific subfile. **

R EXPANDCF SFLCTL(EXPANDSF) ** ** 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. ** A 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 the subfile record number. SFLRCDNBR is a ** hidden filed. This is used here to display the last page ** whenever a new page is loaded. The name and data type of this ** field has been kept same as the RRN of this subfile in the ** program. This ensures that we do not have to explicitly populate ** this field. This field automatically contains the last RRN ** of the subfile which always would be on the last page. ** Caution: SFLRCDNBR variable can not be zero, so ensure that ** you do not display the subfile when it is zero. ** 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)

/**** The program to process the above subfile. Currently only one field is being populated ***/
**

** Declare the display file which contains the expandable subfile ** FFilename++IPEASF.....L.....A.Device+.Keywords+++++++++++++++++++++++ FEXPANDSFL CF E WorkStn ** ** Declare the relative record number (RRN) for the subfile. Notice ** the keyword used to declare subfile. ** F SFILE(EXPANDSF:W@Rrn1) ** ** Define the RRN of subfile (Typically 4 or 5 length with zero ** decimal places depending on how you handle it. If it's likely to ** reach 10000 then declare the length as 5 otherwise 4.) ** DW@Rrn1 S 4 0 Inz ** ** Define a couter variable to keep track of number of record ** to subfile at any time. ** DW@Counter S 2 0 Inz ** ** Execute subroutine to clear the subfile. The subfile is to ** ed everytime the screen is refreshed. ** CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len+ 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 ExpandCF ** C Select C When *INKE = *On ** ** Execute subroutine to load the subfile after clearing it. ** C ExSr #ClrSfl C ExSr #LodSfl ** C When *In(60) = *On ** ** Execute subroutine to load the next page of subfile. ** C ExSr #LodSfl C EndSl ** C EndDo ** ** Free up resources and return ** C Eval *InLr = *On

Return ** ** The subroutine #LODSFL ** ** C #CLRSFL BegSr ** ** Clear the subfile. Clearing a subfile involves the following four ** statements. ** 1. Swicth on the SFLCLR indicator ** 2. Write to the control format ** 3. Swicth off the SFLCLR indicator ** 4. Reset the RRN to zero (Or one). ** C Eval *In(50) = *On C Write ExpandCF C Eval *In(50) = *Off C Eval W@Rrn1 = *Zeros C EndSr C #LODSFL BegSr ** ** Reset the counter ** C Eval W@Counter = *Zeros ** ** Set a looping condition. This condition this time will be based on ** the page size. You can club it with any other condition you require ** However, the number of records loaded at a time should ideally not ** exceed the page size. ** C DoW W@Counter < 15 ** ** 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. Remember that ** the variable corresponding to RRN should not be less than one (1) a ** nd it should never exceed 9999. You may add a check here to confirm ** that the RRN is within the valid range. ** C Eval W@Rrn1 += 1 ** ** Populate the fields defined in the subfiles. To load a blank subfil ** e we can just intialize the subfile fields. ** C Eval $CusNo = W@Rrn1 ** ** Perform actual write to the subfile. Notice that each write actuall ** y adds a record to the subfile. ** C Write ExpandSF C EndDo ** C EndSr

Process a Single Page subfile in ILE RPG IV (RPGLE)


What are single page subfiles A single page subfile is a subfile in the number of records loaded at a time is equal to the maximum number of records which can be displayed at a time. In other words in a single page subfile all loaded records are displayed at a time. We delete all previously loaded records from the subfile whenever we need to load the next page of the subfile. A single page subfile is characterized by equal number of subfile and page sizes. Also, in a single page subfile both ROLLUP and ROLLDOWN keywords must be deined in the DDS of the subfile control format. This is because the ROLLUP and ROLLDOWN activities are handled by the program. After learning the expandable subfile processing with ILE RPG in the previous chapter, a single page subfile should not be very difficult for you. The source code of the DDS and RPG IV program which processes the subfile are given in the example below. Example to process a single page subfile in ILE RPG IV.
** ** Declare the name of the record format of the subfile. Notice ** that this time the function SFL has been used to distinguish ** this record format as a subfile ** AAN01N02N03T.Name++++++RLen++TDpBLinPosFunctions++++++++++++++++++ A R SINGLESF SFL ** ** Declare fields as we would do in case of normal record format. ** A $CUSNAME 20A 5 10TEXT('Customer Name') A DSPATR(HI) ** A $CUSNO 4Y 0 5 02TEXT('Customer Number') A DSPATR(HI) ** ** Control Format of the subfile. Notice the usage of function ** SFLCTL. The name of the subfile has been given here to associate ** this control format with a specific subfile. ** A R SINGLECF SFLCTL(SINGLESF) ** ** Function keys are defined in the record format. ** A CA01 A CA05 ** ** Declare the page size and subfile size ** A SFLPAG(15) A SFLSIZ(15) **

** 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. ** A 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) ** ** Declare the ROLLDOWN key. The number inside the bracket is the ** indicator which would be set on when ROLLDOWN key has been press ** ed. ** A ROLLDOWN(61) ** ** The SFLRCDNBR is the subfile record number. SFLRCDNBR is a ** hidden filed. This is used here to display the last page ** whenever a new page is loaded. The name and data type of this ** field has been kept same as the RRN of this subfile in the ** program. This ensures that we do not have to explicitly popula ** te this field. This field automatically contains the last RRN ** of the subfile which always would be on the last page. ** Caution: SFLRCDNBR variable can not be zero, so ensure that ** you do not display the subfile when it is zero. ** 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)

The RPG IV (ILE RPG) program which processes the above subfile is given below. Notice that the function key F5 to refresh the page (Meaning reloading the subfile from beginning) has not been implemented. You can try it as an excercise.
** ** Declare the display file which contains the SINGLE PAGE subfile **

FFilename++IPEASF.....L.....A.Device+.Keywords++++++++++++++++++++++ FSingleSFL CF E WorkStn ** ** Declare the relative record number (RRN) for the subfile. Notice ** the keyword used to declare subfile. ** F SFILE(SINGLESF:W@Rrn1) ** ** Define the RRN of subfile (Typically 4 or 5 length with zero ** decimal places depending on how you handle it. If it's likely to ** reach 10000 then declare the length as 5 otherwise 4.) ** DW@Rrn1 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 ** ** Define the variable to store the last displayed value ** DW@LastVal S 4 0 Inz ** ** Load the first page of the subfile. ** CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+HiLoEq C ExSr #NextPage ** C DoW *INKA = *Off ** ** ** ExFmt the CONTROL FORMAT of the subfile. ** C ExFmt SINGLECF ** C Select ** ** Indicator 60 is set on by the as400 system when ROLLUP is pressed ** C When *In(60) = *On ** ** Execute subroutine to load the next page of subfile ** C ExSr #NextPage ** ** Indicator 60 is set on by the as400 system when ROLLDOWN is pressed ** C When *In(61) = *On ** ** Execute subroutine to load the next page of subfile, if this is not ** the first page of the subfile. ** C If W@LastVal > 15 C ExSr #PrevPage C EndIf ** C EndSl

EndDo ** ** Free up resources and return ** C Eval *InLr = *On C Return ** ** The subroutine #CLRSFL to clear the subfile and reset the RRN ** C #CLRSFL BegSr ** ** Clear the subfile. Clearing a subfile involves the following four ** statements. ** 1. Swicth on the SFLCLR indicator ** 2. Write to the control format ** 3. Swicth off the SFLCLR indicator ** 4. Reset the RRN to zero (Or one). ** C Eval *In(50) = *On C Write SINGLECF C Eval *In(50) = *Off C Eval W@Rrn1 = *Zeros C EndSr ** ** Subroutine to process the ROLLUP key. ** C #NextPage BegSr ** ** The subfile is to be cleared every time a new page is loaded. ** C ExSr #ClrSfl ** ** Reset the counter ** C Eval W@Counter = *Zeros ** ** Set a looping condition. This condition will be based on the page ** size. You can club it with any other condition you require, However ** , the number of records loaded at a time should ideally not exceed ** the page size. ** C DoW W@Counter < 15 ** ** 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. Remember that ** the variable corresponding to RRN should not be less than one (1) a ** nd it should never exceed 9999. You may add a check here to confirm ** that the RRN is within the valid range. ** C Eval W@Rrn1 += 1 ** ** In single page subfiles, the last and first values of a subfile are

**

** are very important to keep track of the records currently being ** displayed. Here, we are storing the last value only. We will subtr** act 15 to get the first record ** C Eval W@LastVal += 1 ** ** Populate the fields defined in the subfiles. To load a blank subfil ** e we can just intialize the subfile fields. ** C Eval $CusNo = W@LastVal ** ** Perform actual write to the subfile. Notice that each write actuall ** y adds a record to the subfile just like in case of any other type ** of subfile! ** C Write SINGLESF C EndDo C EndSr ** ** Load the previous page of the subfile. ** C #PrevPage BegSr ** ** The subfile is to be cleared every time a new page is loaded. ** C ExSr #ClrSfl ** ** Reset the counters, Retrieve the value of the first record of the ** subfile. Here we are sutracting the page size from the last value. ** This is OK here, but in practical situation where we do not have ** such straight-forward relationship we do the followings ** 1. Store the key values in variables each time the subfile is loded ** 2. Chain the first record of the subfile and retrieve the required ** value. ** C Eval W@Counter = 15 C Eval W@LastVal -= 15 ** C DoW W@Counter > 0 And W@LastVal > 0 ** C Eval W@Counter -= 1 ** C Eval W@Rrn1 += 1 ** ** Populate the fields defined in the subfiles. We populate the custom ** er number by the last displayed value - the RRN. ** C Eval $CusNo = W@LastVal - W@Counter ** ** Perform actual write to the subfile. Notice that each write actuall ** y adds a record to the subfile. ** C Write SINGLESF C EndDo ** C EndSr

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. 1. 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. 2. Display the subfile: Display the subfile by ExFmt or continuous WRITE and READ operations. 3. User edits the subfile: User edits the displayed subfile by changing the field values and presses any function key. 4. 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. 1. 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. 2. 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. 3. 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. 4. 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. 1. Read a file and display all the availabe records in an expandable subfile. 2. The subfile is to be editable 3. The user will be allowed to change the values in the subfile record. Program will validate the changed records for blanks and zeros. 4. Program will reverse image the records in error.

5. 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 C C C C C C C C C C C ** Other If ExSr If ExSr Eval ExSr ExSr EndIf EndIf EndSl EndDo W@Rrn1 > *Zeros #Validate W@Error <> 'Y' #Update W@FstPage = *On #ClrSfl #LodSfl

**

** ** ** **

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. **

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 C

ReadC EndDo

EDITSF

90

** 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 ****************************************