MC Press Online

Monday, Feb 20th

Last updateSun, 19 Feb 2017 12pm

You are here: Home ARTICLES Programming RPG AS/400 Subfile Programming, Part I: Foundation

Programming / RPG

AS/400 Subfile Programming, Part I: Foundation

SUPPORT MC PRESS - VISIT OUR SPONSORS

NEW BOOK!

IBM i Security Administration and Compliance


ORDER YOUR COPY

*******************

Click for this Month's

Bookstore Special Deals

Part 1 Subfile Foundations: (July 1992) Complete understanding of any subject begins with a starting point to build upon. Laying the foundation for subfile usage requires familiarization with underlying concepts and basic definitions. As a prelude to the specific code used to implement a subfile, this article lays out a basic understanding of what a subfile is, how one is implemented and why subfiles exist in the first place.

Part 2 Basic Subfile Coding: (August 1992) We begin examining the coding of the display file and HLL program along with the logic and structure of typical subfile programs. The article uses an example of a subfile with "Position to" capability and presents the techniques and logic changes required to code a Modified Load-All, Expanding or Page-at-a-Time subfile.

Part 3 Increased Functionality: (Sept. 1992) In this article, you learn to hone your coding skills for effective use of subfiles. The specific subfile techniques and keywords discussed will allow you to put expanded control and capability into the subfiles introduced in the previous article. Additionally, the article examines the difference between input and output subfiles and the special logic requirements for coding them.

Part 4 Fine-Tuning Your Subfiles: (Oct. 1992) You'll learn to customize subfiles for peak performance. This article examines the coding required to write effective subfiles and present them on-screen without clearing the lines behind the subfile. It further discusses cursor control, determination of cursor position and the coding of a point-and-shoot type of interface to AS/400 programs.

Demystify subfiles with a firm grasp of underlying concepts.

Imagine being able to display lists of similar entries using a HLL program, but without having to write code to handle multiple lines of identical fields or the roll keys. Imagine doing this without using arrays or multiple occurrence data structures. Subfiles let you do all of this and a whole lot more!

Subfiles are a way of displaying a list of information on the screen. What makes them special is the interface built into the display file. Rather than having to control the list from a HLL program, the control elements, such as rolling forward and backward, are handled by the display file using special Data Description Specifications (DDS) keywords.

Subfiles are ideal for displaying a list of codes (such as state abbreviations) and allowing the user to select the one he wants. They also work well for columnar data entry such as the detail lines of a purchase order. Other applications that lend themselves to subfiles include: invoice history inquiry, multiple line order entry, inventory availability, customer alpha search and credit code lookup.

1 illustrates a very simple subfile. The screen provides a window into the list of state abbreviations. The data entry field at the left allows the user to select the correct state. Depending on how the subfile is designed, all 50 states may be loaded at once (a reasonable way to handle a short list like the states) or the subfile may be filled in portions, one portion at a time. This loading of the subfile is separate from the display function, and that separation defines to a large extent why subfiles are so effective.

Figure 1 illustrates a very simple subfile. The screen provides a window into the list of state abbreviations. The data entry field at the left allows the user to select the correct state. Depending on how the subfile is designed, all 50 states may be loaded at once (a reasonable way to handle a short list like the states) or the subfile may be filled in portions, one portion at a time. This loading of the subfile is separate from the display function, and that separation defines to a large extent why subfiles are so effective.

The records to be displayed, the order of the records and the number of records to be loaded at once are handled by the HLL program. The information that can be displayed at any one time is completely a function of the display file.

A subfile format defined in a display file describes the information to be displayed in a list. The display file deals with the basic management of that list. It handles displaying the list one screenful at a time. It deals with the roll keys. It determines when to show the + (or More... under V2R2) to indicate that more records exist. It also marks the records that have been changed or selected by the user while the screen was displayed.

The HLL program selects records from the database file and loads them into the subfile. It may use some control indicators to determine when the list is to be displayed or purged or affected by any of the other functions of which a subfile is capable. The HLL program also determines when the display file will return records that have been "touched" by the user. The subfile is associated with the display file and the program will load into the subfile the records in which the user is interested.

Control then passes to the display file so that the list of records can be shown to the user. The display file shows the list to the user and handles any roll key presses to allow the user to roll through the records stored in the subfile. When the user eventually presses an action key on the keyboard, the display file will return any associated indicators and, possibly, screen fields back to the program.

Subfile Varieties

There are three basic flavors of subfiles (very Neapolitan). The simplest form is a load-all subfile. In this form, the program loads all the records from a database file into the subfile and then passes control to the display file. The display file handles all scrolling while the subfile is in use. This sort of subfile is very easy to code and works well when you are dealing with a small look-up table such as credit card types or state abbreviation codes. It eliminates any programming to handle paging through the list.

The second subfile variety is an expanding subfile. In this case, the program loads a portion of the records-a page or more-into the subfile and passes control to the display file in which the ROLLUP (PAGEDOWN) keyword is coded. If the user asks for a page beyond those initially contained in the subfile, the display file passes control back to the program and tells it to feed more records to the subfile-it's hungry. The program appends an additional page(s) of records to the subfile and passes control back to the display file.

The display file handles all scrolling within the subfile. With expanding subfiles, only the load logic has to be coded in the HLL program. No roll back logic is required. It works well on larger files where the load-all subfile would create too long of a delay before the subfile could be displayed to the user, or where users will start a search within a few pages of where they expect to find their information.

The third variety is a page-at-a-time subfile. In this form, the number of records shown on one screen is equal to the number of records held in the subfile, and only one page of records can be stored or displayed at a time. Typically, both the ROLLUP and ROLLDOWN keys are coded; each time one is pressed, the display file passes control to the program. The program then purges the subfile and loads the next appropriate page of records. The page- at-a-time subfile is most appropriate when the data is of a volatile nature and should be refreshed on the screen frequently, or when you really want to give the user the freedom to roam all over the file with the roll keys. It is very similar to program-controlled lists as we used to code them on the S/36.

Subfile Size and Page

The initial number of records that can be stored in the subfile is described with DDS keywords in the display file. You specify this number, called the subfile size, based upon the number of records that you want the subfile to hold. Note that this is the initial number of records to hold. Subfiles are extendible; if the user requests records to be added, the subfile expands beyond its initial size to accommodate the additional records.

Subfile records are not just stored in the ether, but indeed occupy memory. An equivalent amount of space is set aside for the size of the subfile in the Process Access Group (PAG) just as it is for other program variables and arrays. In order for the AS/400 to perform some portion of your program when you press the Enter key, both that portion of the program and the PAG must reside in memory. Getting them there may mean paging other things out of memory. If the PAG is large, OS/400 winds up hammering a lot of other pages out of the way to respond to your request.

On the flip side, if the initially defined subfile is too small, it may have to be expanded several times. This leads to the same type of performance issues we have always had with files that have non-contiguous portions to them. The system spends extra processing time to deal with the separate extents.

The number of records to show on the screen at one time is also specified in the DDS for the display file and is referred to as the subfile page. While the choice you make for the subfile page is pretty well fixed based upon the size of the screen and visual presentation, the choice for subfile size is more arbitrary. An informed choice for subfile size is as follows: for a load-all subfile, the size should be large enough to hold all of the records to be loaded. For an expanding subfile, the size should be large enough to handle the typical number of pages it will take for the user to find what he wants. For a page-at-a-time subfile, the size is by definition coded as one page worth.

Subfile Record Management

For all intents, a subfile is managed as a file where records are accessed by their record number rather than by key or sequentially. Within the HLL program, a program variable is assigned to the subfile. During load or update operations, the content of that field will determine the record number being written to the subfile. During read operations the field contains the number of the last record read. If you are familiar with direct file processing, this is the same concept.

The following operations are valid for subfile records:

Records can be written to the subfile.

Records can be updated within the subfile.

Records can be retrieved from the subfile.

Within a HLL program, these things are done with the standard I/O operation codes or verbs. Standard rules of file I/O apply. If you try to write a record that already is in the subfile or if you try to update a record that is not in the subfile, the mean-ugly error message monster will rear its bulbous pate.

The Display File

Two record formats must be defined for a subfile. The first format de-scribes the fields to be held on the subfile records and is referred to as the subfile record format.

The second record format is the subfile control record format. As its name implies, it controls the subfile. This format is linked to the subfile record format by a DDS keyword. It also has keywords that describe the subfile size and page size, as well as other optional keywords (some conditioned by indicators) to control clearing, displaying, initializing and deleting the subfile.

The subfile record format is the storage format for the records-records are written into this format and changes are read back from it. The control record format is used to perform all user interaction and to manage the records in the subfile. To display the subfile contents to the user, you write the records to be displayed into the subfile records, set the proper indicators and write the control record format to display them to the user.

The control format may have information of its own to display to the user (e.g., headings for the subfile fields), or it may simply be a vehicle to control the display of the list and have nothing to display itself. If the control format contains information to display, it can appear either above or below the subfile, but not in both locations.

The control format has two or more record level keywords. Depending on the kind of subfile, these keywords may be associated with indicators that are used to control the information stored in the subfile and its presentation. These indicators are typically used to determine when to show the information in the subfile, when to show the control format, when to empty the subfile, or when to show the '+' (or More...) at the bottom of the panel.

The HLL Program

Certain things must be coded in the HLL program to take advantage of the subfile definition coded in the externally described display file. The following associations are made in the file definition portion of the HLL program: the file is identified, the subfile format is identified to the program and a field is assigned to the subfile that will act as its relative record number pointer, although not all HLLs require all of these associations. For example, in PL/I the relative record number (RRN) variable is not specific to the file.

Logic in the program handles the loading, purging, display and processing of the subfile records. Typical logic will include the following:

Clear: Purge any existing information from the subfile and reset the record pointer.

Position: Position the input database file to the point where we want to begin loading records.

Load: Load information from the database into the subfile records.

Display: Display the subfile records to the user for perusal.

Process: Determine which records the user is interested in, and perform the required action.

All the Pieces

Let's see if we can now get a handle on all the pieces that come together to successfully implement a simple load-all subfile. We will begin with the display file itself and then follow with the components that are required in the HLL program. Here are the pieces:

1. A display file that has a subfile record format along with its associated control record format. The subfile will contain the information from the database that we want to display on the screen.

2. A DDS keyword in the control record to set the subfile size large enough to hold all the records from the database file.

3. Another DDS keyword that indicates how many of the subfile records to show at once on the screen.

4. More DDS keywords in the control record, which let you control when to display the subfile records and the subfile control record itself.

5. An HLL program which does all the work of pulling information from the database and moving it into the subfile. The program needs to identify the subfile within the display file.

6. Load the subfile by entering a loop that reads a database record and writes it to a subfile record, using an (RRN) work variable. You must increment this RRN yourself.

7. Present the loaded subfile to the user by writing to the screen the subfile control record and, if not empty, the subfile itself.

Load-All Example

Just so that we don't end this first article with the proverbial baited breath, I have included an example of the simplest form of subfile. It is here to give you the sense of the code involved. We will not be dealing with keyword specifics in this article; that will come next month.

Let's use the example in 1 where we have a table of state abbreviation codes (2 contains the DDS for the state file) that we wish to place on the screen so that a user can scroll and verify abbreviation codes. The list will appear as we have shown in 3. Three record formats are involved in the display. The first starts at the top and goes down through the column headings of the list. This will serve as our subfile control record format. The second is the list itself, which is the subfile record format. The third contains output constants that indicate the available function keys. These formats were built using SDA. First we added a format and indicated that we wanted a subfile, and the prompts led us through the rest of the subfile definition.

Let's use the example in Figure 1 where we have a table of state abbreviation codes (Figure 2 contains the DDS for the state file) that we wish to place on the screen so that a user can scroll and verify abbreviation codes. The list will appear as we have shown in Figure 3. Three record formats are involved in the display. The first starts at the top and goes down through the column headings of the list. This will serve as our subfile control record format. The second is the list itself, which is the subfile record format. The third contains output constants that indicate the available function keys. These formats were built using SDA. First we added a format and indicated that we wanted a subfile, and the prompts led us through the rest of the subfile definition.

In 4 you can see the DDS that was generated by SDA: a couple of command keys, database references, the subfile proper, the control format with subfile keywords and the trailer format. The subfile/control formats and the trailer must occupy the screen at the same time, so the OVERLAY keyword was used to lay the control format over the trailer.

In Figure 4 you can see the DDS that was generated by SDA: a couple of command keys, database references, the subfile proper, the control format with subfile keywords and the trailer format. The subfile/control formats and the trailer must occupy the screen at the same time, so the OVERLAY keyword was used to lay the control format over the trailer.

Figures 5 and 6 have the RPG and COBOL source required to complete the program. During file definition specifications, a file extension or clause identifies the subfile and associates the RRN field with it to act as the relative record pointer. A load loop loads all of the records in the XRD001PF file into the subfile. A safety test determines if there are any records to display and sets the SFLDSP controlling indicator if there are. (The ugly error monster loves it when you try to display an empty subfile!) The last loop displays the control format until the user screams "uncle." That's it! As you can see from the examples, the HLL code required for a working subfile is simple and concise.

The intent of subfiles is to provide a simple-to-code, columnar type of screen-the type of screen that typifies the AS/400 interface; the coding has truly been made easy. In our next article, we will look at the subfile keywords in detail and begin to explore the coding required for the various types of subfiles. Y'all come back now, y'hear.

A Historical Perspective

The concept of subfiles evolved as designers of the S/38, predecessor to the AS/400, chose to provide a simple technique for displaying a list of entries on a screen so that a user could pick an entry. This relieved the user from having to remember codes or use a paper listing. The designers also wanted to provide a simple way of coding the tabular entry screens commonly used in batch transaction entry (remember the days of rows of 3741s and data entry clerks?). The traditional array or direct file techniques in use at that time required a less-than-elementary programming ability to achieve.

Over the years, the S/3X zealots-gluttons for punishment that we are-found new and unique ways to utilize these techniques and continuously asked the planners for new capabilities. As we have come to expect, the techniques and capabilities grew over the years until now the subject is quite formidable, especially in the small shop which does not have a lot of master or journeyman programmers to teach apprentices.

A subfile is a technique to hold and present on a display screen a set of records, row by row, in a columnar fashion. Subfiles cannot be used in producing printed output. You define a subfile in a display file source member using Data Description Specifications (DDS). This definition is then compiled to create a display device file, (more commonly referred to as a display file).

All of our HLLs have extensions unique to the AS/400 platform to take advantage of our highly integrated database manager. These extensions allow us to reference data that was previously defined to the database manager. During early implementation of these external definitions, the developers realized that, to a HLL program, there is no significant difference between database files and communications or screen or printer files. They all involve similar input/output buffer definition, and after that we use pretty much the same read and write operations to access these files. It was decided to expand the data definition language to define these other types of files-referred to in OS/400 lingo as device files-in addition to database files.

External definition of the database removes the concerns of the physical characteristics of the data from the everyday worries of the programmer; i.e., the programmer no longer needs to know record lengths, field lengths or attributes, key lengths or key positions. External definition of device files removes the need to know the specific physical characteristics of the device- i.e., supported screen sizes, field display attributes, printer type, and so forth. In essence, the program writes to the device file, and the device file handles the characteristics of the device.

As it relates to our discussion of subfiles, HLL programs communicate with their display device files by sending/receiving data through I/O buffers. A set of up to 99 logical switches (indicators) is also passed to/from the display. The indicators are either included in the I/O buffers or optionally in a separate buffer. These indicators allow the HLL program to control when to perform some of the functions described in the display device file. They also provide a mechanism for the display to pass back to the program which keys were pressed or when screen data was modified.

Subfiles are simply an extension of the ability to externally define a display device file. The basic functions of displaying a list of information, allowing the user to roll backwards and forwards, and indicating if more information is available to be displayed are not dependent on the type of processing being done in the HLL program. By making these functions part of the definition for the display device file, the developers took the responsibility for managing these basic functions away from the programmer. This allows the programmer to concentrate on the specific application. What the developers did is not really different from what you do when you develop a skeleton or shell program. By learning to use the tools provided by the developers, AS/400 programmers can concentrate their efforts on the unique aspects of a particular application.


AS/400 Subfile Programming, Part I: Foundation

Figure 1 State Code subfile lookup

 Figure 1: State Code Subfile Lookup AL Alabama AK Alaska AZ Arizona AR Arkansas CA California CO Colorado CT Connecticut DE Delaware FL Florida GA Georgia HI Hawaii ID Idaho IL Illinois IN Indiana IA Iowa KS Kansas KY Kentucky LA Louisiana ME Maine MD Maryland MA Massachusetts MI Michigan MN Minnesota MS Mississippi MO Missouri MT Montana NE Nebraska NV Nevada NH New Hampshire NJ New Jersey NM New Mexico NY New York NC North Carolina ND North Dakota OH Ohio OK Oklahoma OR Oregon PA Pennsylvania RI Rhode Island SC South Carolina SD South Dakota TN Tennessee TX Texas UT Utah VT Vermont VA Virginia WA Washington WV West Virginia WI Wisconsin WY Wyoming 
AS/400 Subfile Programming, Part I: Foundation

Figure 2 Physical file XRD001PF

 A UNIQUE A R STREC A STSTAT 2A TEXT('State code') A STNAME 30A TEXT('State name') A K STSTAT 
AS/400 Subfile Programming, Part I: Foundation

Figure 3 Required screen appearance

 Figure 3: Required Screen Appearance List of Valid States 12/31/92 23:36:20 Abbreviation Code State Name Alabama AL Alaska AK Arizona AZ Arkansas AR California CA Colorado CO Connecticut CT Delaware DE Florida FL Georgia GA + F3=Exit F12=Cancel 
AS/400 Subfile Programming, Part I: Foundation

Figure 4 Display file XRD001DF

 A DSPSIZ(24 80 *DS3) A REF(XRD001PF) A CA03(03) A CA12(12) A INDARA * A R STATESFL SFL A STSTAT R O 10 10 A STNAME R O 10 28 * A R STATECTL SFLCTL(STATESFL) A OVERLAY A 31 SFLDSP A SFLDSPCTL A SFLSIZ(60) A SFLPAG(10) A 34 SFLEND A 1 29'List of Valid States' A DSPATR(HI) A 1 73DATE EDTCDE(Y) A 2 73TIME A 6 6'Abbreviation' A DSPATR(HI) A 7 9'Code' A DSPATR(HI) A 7 28'State Name' A DSPATR(HI) * A R STATETLR A 22 3'F3=Exit' A COLOR(BLU) A 22 15'F12=Cancel' A COLOR(BLU) 
AS/400 Subfile Programming, Part I: Foundation

Figure 5 RPG program XRD001RG

 * Indicators used: * 31 = Display subfile record (SFLDSP) * 34 = Display the '+' for more records (SFLEND) * FXRD001PFIF E K DISK FXRD001DFCF E WORKSTN F RRN KSFILE STATESFL * * Load the states records in to the subfile. C *IN34 DOWEQ*OFF C READ STREC 34 C *IN34 IFEQ *OFF C ADD 1 RRN 30 C WRITESTATESFL C ENDIF C ENDDO * * Determine if there are any records to display. C RRN IFGT *ZERO C MOVE *ON *IN31 C ENDIF * * Write the function keys legend. C WRITESTATETLR * * Display the list until the user presses F3 or F12. C *IN03 DOUEQ*ON C *IN12 OREQ *ON C EXFMTSTATECTL C ENDDO C MOVE *ON *INLR 
AS/400 Subfile Programming, Part I: Foundation

Figure 6 COBOL program XRD001CB

 * Indicators used: * 31 = Display subfile record (SFLDSP) * 34 = Display the '+' for more records (SFLEND) ****************************************************** IDENTIFICATION DIVISION. PROGRAM-ID. XRD001CB. ENVIRONMENT DIVISION. ****************************************************** * Identify the external files. ****************************************************** INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT DISPLAY-FILE ASSIGN TO WORKSTATION-XRD001DF-SI ORGANIZATION IS TRANSACTION ACCESS IS DYNAMIC RELATIVE KEY IS RRN. SELECT STATES-FILE ASSIGN TO DATABASE-XRD001PF ORGANIZATION IS INDEXED RECORD KEY IS EXTERNALLY-DESCRIBED-KEY. ****************************************************** * Define required formats. ****************************************************** DATA DIVISION. FILE SECTION. FD DISPLAY-FILE. 01 DISPLAY-FILE-RECORD. COPY DD-ALL-FORMATS-I OF XRD001DF. FD STATES-FILE. 01 STATES-RECORD. COPY DD-ALL-FORMATS OF XRD001PF. ****************************************************** * Define working variables. ****************************************************** WORKING-STORAGE SECTION. 01 SUBFILE-RECORD. COPY DD-ALL-FORMATS-O OF XRD001DF. 01 INDIC-AREA. 03 INDIC-TABLE OCCURS 99 PIC 1 INDICATOR 1. 88 IND-ON VALUE B"1". 88 IND-OFF VALUE B"0". 01 DISPLAY-FILE-VARIABLES. 05 RRN PIC 9(4) VALUE ZERO. 01 DATABASE-STATES. 05 SEQUENTIAL-STATUS PIC X. 88 END-OF-FILE VALUE "1". 88 NOT-END-OF-FILE VALUE "0". ****************************************************** * Program mainline. ****************************************************** PROCEDURE DIVISION. MAINLINE. PERFORM PROGRAM-INITIALIZATION. PERFORM LOAD-SUBFILE. ****************************************************** * Display the state list and wait for response. ****************************************************** PERFORM UNTIL IND-ON(3) OR IND-ON(12) IF IND-OFF(3) AND IND-OFF(12) PERFORM DISPLAY-READ-SUBFILE END-IF END-PERFORM. PERFORM PROGRAM-TERMINATION. DISPLAY-READ-SUBFILE. WRITE DISPLAY-FILE-RECORD FORMAT IS "STATETLR". WRITE SUBFILE DISPLAY-FILE-RECORD FORMAT IS "STATECTL" INDICATORS ARE INDIC-TABLE. READ DISPLAY-FILE FORMAT IS "STATECTL" INDICATORS ARE INDIC-TABLE. ****************************************************** * Load subfile with state records. ****************************************************** LOAD-SUBFILE. SET NOT-END-OF-FILE TO TRUE. PERFORM UNTIL END-OF-FILE READ STATES-FILE AT END SET END-OF-FILE TO TRUE END-READ IF NOT-END-OF-FILE MOVE CORRESPONDING STREC TO STATESFL-O ADD 1 TO RRN WRITE SUBFILE DISPLAY-FILE-RECORD FROM STATESFL-O FORMAT IS "STATESFL" END-IF SET IND-ON(34) TO TRUE END-PERFORM. IF RRN > 0 SET IND-ON(31) TO TRUE END-IF. ****************************************************** * Open files and set the indicators. ****************************************************** PROGRAM-INITIALIZATION. OPEN I-O DISPLAY-FILE. OPEN INPUT STATES-FILE. MOVE ZEROS TO INDIC-AREA. ****************************************************** * Close files and kill the beast. ****************************************************** PROGRAM-TERMINATION. CLOSE DISPLAY-FILE STATES-FILE. STOP RUN. 
BLOG COMMENTS POWERED BY DISQUS