Showcase Article - Subfiles Part 1
A subfile is the AS/400 equivalent to Windows list boxes. Basically, it is a technique for loading a list of records, displaying the list, and then processing selections from the list.
For this simple subfile program, you must be able to:
Let’s look at a program that will let a user display a list of customers that belong to a salesperson. Figure 1 shows the screen that lists the customers for salesperson # 6004.
The AS/400 defines the subfile as part of the display screen. Because it will be displayed on the screen, this makes sense. What is different is that the data portion of the subfile will contain many records; one for each line that will be displayed. Also, the display screen must define some control values. These values include the number of lines per screen as well as some very important indicators.
The secret to understanding subfiles is to realize that the data is written as a direct access file. You probably have used sequential files and random access files. Subfiles are direct access files that are similar to random access files but with a key that is the actual record number.
So, to read or write records to a direct access file, you tell the AS/400 the record number that you want. Of course, this means that if you are loading the subfile, you will write record number one first, followed by record number two, and then number three. To do this, you must define a variable that holds the record number of the file that you are writing.
Figure 2 has the DDS that defines the display file. The first record in the display file is named ENTSLS. It defines a screen to allow the user to enter the salesperson’s number.
Next in Figure 2 is the record description for the direct access file that will hold the data in the list. The first line defines the name of the record, SFDATA, and uses the important keyword, SFL, to denote that it is a subfile record definition. Then each field is listed. The location for each field is the screen location for the first line of the list. In this case, the list will start on the fourth line.
Following the SFDATA record in Figure 2 is the SFCTL record. This record defines the controlling attributes of the SFDATA subfile. This record is named SFCTL. It has several important keywords. The first keyword, SFLCTL, not only defines this as a subfile control record, but links it to the SFDATA record that was just defined.
The next keyword, SFLPAG, says that we want to show 15 lines of the subfile on the screen. Keyword SFLSIZ defines the space for the subfile. This does not limit the subfile to 45 records; it automatically allocates space for 45 records but will extend the subfile if necessary.
The OVERLAY keyword is necessary because we have to display the command keys at the bottom of the page as a separate record. When it is time to display the subfile, we will first display the command keys at the bottom and then display the subfile and overlay the existing display without destroying it.
The next keyword, SFLCLR, defines the indicator that we will use to tell the AS/400 to clear the subfile. In this case, it is handy to use a NOT condition of indicator 50. This is handy because we are using indicator 50 for the next three keywords. SFLDSP tells the AS/400 that we want to display the SFDATA record. SFLDSPCTL tells the AS/400 that we want to display the SFCTL record also. Finally, SFLEND(*MORE) tells the AS/400 to show the word MORE at the lower right of the screen if there are more records than will fit on a screen.
So, by turning off indicator 50, we can clear the subfile. By turning on indicator 50 we will display the subfile.
Now look at Figure 3 to see the RPG code for the program. Notice the special keywords in the “F” specification for the display file. REC# is the variable that will hold the record number of the subfile.
The main logic of the program is to display the screen for the user to enter the salesperson’s number. Then, execute the subroutines to clear the subfile, load the subfile, and finally show the subfile.
To clear the subfile, subroutine CLRSF turns off indicator 50 and writes a record to the SFCTL file. Since indicator 50 is off, it doesn’t actually write a record; it clears the subfile.
The subroutine LODSFL reads the CUS file for all records that belong to this salesperson. For each record, it increments the record number field, REC#, and writes a record to the subfile.
Displaying an empty subfile will cause a “DEVICE ERROR” condition. To prevent this, we check to make sure that the record number field is not zero. If it is zero, we write a record to the file with “*NO RECORDS*” as the value of the customer name. This way, we avoid the device error and clearly communicate that there are no records for this salesperson.
Figure 1 shows the display of the subfile. With about 50 lines of RPG, we have written a subfile display. You can see how easily you can copy and change this program to create user-friendly subfile lists.
Figure 1: This is the list of customers for salesperson # 6004. Salesperson# 6004 Customer# Name Phone# 012795 JOHN'S ALL AMERICAN SPORTS 2105551234 021365 AAA TERMITE INSPECTORS 9405556666 034598 JONATHANS SPORTS CLUB 2125551212 045654 NICKS DELI 4065551212 085261 ZEBRA COMMUNICATIONS 4055551234 085265 ANYTOWN INSTALLERS 9195551256 097854 WIDGET CORP 8175556565 124569 GOLD COAST LANDSCAPING 5045558654 165432 LAST CHANCE GAS STATION 6455551212 232356 TRM TELECOMMUNICATIONS 8885551211 456215 NICKS RESTAURANT 8175559876 546832 DANBURG CONSLUTING 9728176543 561245 BOYDS CAR REPAIR 9625551256 654654 CARLS REPAIRS 8175559963 856234 ABC COMPANY 4055551122 More.. F3=Exit Figure 2: This is the DDS for the display file to list the customers. A REF(*LIBL/CUS) A PRINT A CA03(03) *---------------------------------------------------------------- A R ENTSLS * * Let user enter a salesperson # so program can show a list * of customers A O 2 20'List Customers for Sls#' A SLSPER R B 2 46EDTCDE(4) *---------------------------------------------------------------- A R SFDATA SFL A CUSNUM R O 4 5 A CUSNAM R O 4 15 A CUSPHN R O 4 50 *---------------------------------------------------------------- A R SFCTL SFLCTL(SFDATA) A SFLPAG(0015) A SFLSIZ(0045) A OVERLAY A N50 SFLCLR A 50 SFLDSP A 50 SFLDSPCTL A 50 SFLEND(*MORE) A 2 4'Salesperson#' A SLSPER R O 2 17EDTCDE(4) A 3 4'Customer#' A 3 15'Name' A 3 50'Phone#' *---------------------------------------------------------------- A R CMDKEYS A 24 40'F3=Exit' *---------------------------------------------------------------- Figure 3: This is the RPG for the subfile program. * Define the subfile and the variable that will hold record # (REC#) FCUSD001 CF E WORKSTN F SFILE(SFDATA:REC#) FCUS IF E K DISK * C *IN03 DOWEQ *OFF * Show screen for user to enter the salesperson's number C EXFMT ENTSLS C *IN03 IFEQ *OFF * Clear the subfile C EXSR CLRSF * Load the subfile C EXSR LODSF * Show the command key footer and then the subfile SFCTL C WRITE CMDKEYS C EXFMT SFCTL C ENDIF C ENDDO C MOVE *ON *INLR C RETURN *--------------------------------------------------------------------- C CLRSF BEGSR * Clear the subfile by writing a SFCTL record with Indicator 50 Off C MOVE *OFF *IN50 C WRITE SFCTL C MOVE *ON *IN50 * Set the record number variable to zero C MOVE *ZERO REC# 4 0 C ENDSR *--------------------------------------------------------------------- C LODSF BEGSR * Start reading the customer file for this salesperson C SLSPER SETLL CUS 10 C *IN10 IFEQ *ON C SLSPER READE CUS 95 C *IN95 DOWEQ *OFF * For every customer found, add 1 to the record # of the subfile * and write that record to the subfile data C ADD 1 REC# C WRITE SFDATA C SLSPER READE CUS 95 C ENDDO C ENDIF * If subfile is empty, write a record that says "*NO RECORDS" C REC# IFEQ *ZERO C ADD 1 REC# C CLEAR SFDATA C MOVEL '*NO RECORDS*'CUSNAM C WRITE SFDATA C ENDIF C ENDSR