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.
Variations on a roll (isn't that a pita!)
As discussed in July's "Subfile Foundations," subfiles enable programmers to present a panel of columnar data with minimal programming. They take advantage of special capabilities built into display file definitions and extensions to the HLLs supported by OS/400. The net result is that subfiles make presenting columns of information easier with their own syntax and structure that you must understand to use subfiles effectively. This article focuses on the typical logic flow of a subfile program, along with the coding of both the display file and the RPG/400 program to control it.
The goal for this article is to write a typical application which displays a list of customers on the screen in alphabetical sequence as illustrated in 1. The user can enter the name, or partial name, of a customer he is searching for; the program loads one or more screens of customers and the user locates the customer he needs. The user can then branch to an inquiry program for customer details by selecting a customer from the list.
The goal for this article is to write a typical application which displays a list of customers on the screen in alphabetical sequence as illustrated in Figure 1. The user can enter the name, or partial name, of a customer he is searching for; the program loads one or more screens of customers and the user locates the customer he needs. The user can then branch to an inquiry program for customer details by selecting a customer from the list.
Last month, we covered three methods for processing subfiles: load-all, expanding, and page-at-a-time. The first program executed in this article uses the load-all method. Modifications to the program are also presented to demonstrate the other two methods.
In order to code this application, we must:
1. Create a display file that has the subfile DDS built into it.
2. Determine the logic flow of the program to control the screen.
3. Code the HLL program to implement the logic.
Screen Definition
For clear and easy definition, we break the screen into three record formats. The first format (named HEADER) includes the title, date and time, the selection fields and the headings for the subfile. This format also works as the subfile control format which contains the keywords that control the subfile. The second format is the subfile format itself (named DETAIL) which describes the information about each customer to list in the subfile. The third format, TRAILER, displays output constants that describe the available function keys. Since there are no overlay or windowing keywords on the TRAILER format, it will clear the screen whenever it is written.
The header format has an OVERLAY keyword associated with it (and the related subfile) so that it can coexist with the TRAILER, rather than clearing the screen whenever it is written. The display file (2) is defined either by directly coding the DDS with SEU or by using SDA to select the required keywords and visually lay out each format. The order in which the record formats are specified in the DDS source member is important. The display file compiler expects to process the subfile record format prior to the control record format that controls it. If we use SDA when defining a subfile, it prompts for the control format name and places the records in the right order in the DDS source.
The header format has an OVERLAY keyword associated with it (and the related subfile) so that it can coexist with the TRAILER, rather than clearing the screen whenever it is written. The display file (Figure 2) is defined either by directly coding the DDS with SEU or by using SDA to select the required keywords and visually lay out each format. The order in which the record formats are specified in the DDS source member is important. The display file compiler expects to process the subfile record format prior to the control record format that controls it. If we use SDA when defining a subfile, it prompts for the control format name and places the records in the right order in the DDS source.
The DETAIL record has the SFL keyword identifying it as a subfile, and the HEADER record has the SFLCTL keyword which identifies the DETAIL format as the subfile it controls. All user interaction (data entry, function keys, selections and so forth) is performed through the HEADER format. The HEADER format accepts the customer name the user keys to position the subfile, while the DETAIL format is used to load up the records and to read back records the user has selected. The point to remember is that the subfile control record and the subfile record both pass data back to the program when the control record is read.
The HEADER record contains what we will call the Basic Six subfile keywords:
SFLSIZ (subfile size): The initial size of the subfile when the display file is opened.
SFLPAG (subfile page): The number of records that should appear on the screen at a time.
SFLDSP (subfile display): Controls the display of the subfile information.
SFLDSPCTL (subfile display control): Controls the display of the control format.
SFLCLR (subfile clear): Controls clearing the records currently in the subfile.
SFLEND (subfile end): Controls the "+" (or More...) indicating more records exist.
In our sample, the first two keywords define the subfile with five pages of 10 records per page. The last four keywords have conditioning indicators associated with them. Through deft manipulation of these indicators in our HLL program, we control which of these DDS keywords is active. In so doing, we control whether a write to our control record (HEADER) will:
1. Display the header format only. We accomplish this by turning on the indicator that conditions the SFL-DSPCTL keyword, and turning off the indicator that conditions the SFLDSP keyword.
2. Display the header along with the contents of the subfile. To do this, we turn on the indicators that condition SFLDSP and SFLDSPCTL.
3. Purge the contents of the subfile. This is carried out by turning on the indicator that conditions the SFLCLR keyword.
4. Indicate that the display file should control the last page indicator based upon what is currently loaded into the subfile.
In our example, we have chosen four consecutive indicators for these switches. To quote the knight in Indiana Jones' The Last Crusade, we have chosen wisely-by making them consecutive, we can set all the indicators with a single MOVE operation.
The balance of the DDS source should not hold any mysteries. We have a series of output constants and referenced database fields, your standard collection of command keys, PRINT, BLINK, and other straightforward source code elements. The screen field names (with the exception of the @NAME field) are straight references to the database file, eliminating the need for move operations in our code.
Subfile Program Logic
In Lewis Carroll's Alice in Wonderland, upon first meeting the Cheshire Cat, Alice asks, "Cheshire Cat, can you tell me which way to go?" "Where are you going?" the cat replies. Alice says, "I really don't know." The cat answers, "Then it really doesn't matter which way you go." The same thing applies to programming. If you don't know where you are going in the first place, it doesn't matter where you begin (and your code reflects that when you are done).
Every subfile program has a certain number of standard sections. Before we start coding anything, let's make sure we understand the steps to be performed. Applying the structured concepts of sequence-condition-iteration, we can design the structure and flow before we code it. For our first program, we shall assume a load-all form of subfile, i.e., that we intend to load all the eligible records into the subfile at once and only reload if the search name changes. Load-all does not necessarily mean that we will load the entire file into the subfile. We will load a number of pages when we perform the load routine and let the user scroll through that fixed set of pages. If he wants to go beyond that range, he must provide a new starting name to reposition the search, and the program then reloads the subfile. For this program to function, the following things must happen (order of function execution is not a concern at this point):
Display a list of hits back to the user.
Display detail for any records the user selects.
Load the records from the database into the subfile.
Position our file based on the name the user is requesting.
Ask the user for a name to start.
Clear the current set of records from the subfile.
If we can assume that this is a reasonable statement of the processes that must occur, let's determine the logic of the program.
Sequence
First, we organize the steps into a reasonable order. The reasonable order varies significantly from one programmer to the next and is largely determined by the programmer's age, sex, socio-economic background, sexual preference, biorhythm schedule, horoscope and, of course, number of cups of coffee consumed. We will choose the following as our reasonable order:
1. Request the name to start with.
2. Clear the subfile.
3. Position the database file based upon the search name.
4. Load the records into the subfile.
5. Display the header/detail to the user.
6. Process any selections.
Iteration or Looping
Once we have determined the sequence of the steps, we need to decide which ones should happen repetitively. The way we want this hummer to work is to display the HEADER first time through, get the name to start with, and then keep displaying the header and detail to the user until he walks away from his terminal and the job times out, turns off the tube and goes home, or presses F3 or F12. This program is harmless enough that we don't need to worry about the first two, but we should code the function keys to exit. So let's introduce some iteration.
Request the name to start with
Until F3 or F12 is pressed
Clear the subfile
Position the file based upon the search name
Load the records into the subfile
Display the header/detail to the user
Process any selections
Conditional Processing
Next, we examine the structure we have and decide which things have to happen all the time and which should be done only under certain conditions. If F3 is pressed on the very first screen, we really don't want to do anything else. We only want to clear, position and load if the starting name changed. We want to process selections only if there were detail records shown in the first place (the search could have yielded no results). So we might wind up with program logic something like this:
Request the name to start with
While F3 and F12 are not pressed
If the search name changed
Clear the subfile.
Position the file based upon the search name
Load the records into the subfile
Display the header/detail to the user
If detail records were displayed
Process any selections
HLL Program Code
Now we can translate this program logic to HLL code and write the program (see 5, page 34). We are using RPG/400 to code the examples in this article, although we could just as easily choose COBOL or PL/I or C/400 (well, some of us might just as easily write in these languages). We must first identify to the RPG program the fact that there is a subfile in this display file. This is done in the file specifications with a file (K)ontinuation line. This line identifies a subfile record format and associates an internal RPG variable to act as its relative record number pointer. Once this is established, we can write to any record within the subfile by loading the record number into the pointer (RRN in our example) and writing to the subfile. Remember, subfiles work like direct files-we access a particular subfile record via its relative position in the subfile.
Now we can translate this program logic to HLL code and write the program (see Figure 5, page 34). We are using RPG/400 to code the examples in this article, although we could just as easily choose COBOL or PL/I or C/400 (well, some of us might just as easily write in these languages). We must first identify to the RPG program the fact that there is a subfile in this display file. This is done in the file specifications with a file (K)ontinuation line. This line identifies a subfile record format and associates an internal RPG variable to act as its relative record number pointer. Once this is established, we can write to any record within the subfile by loading the record number into the pointer (RRN in our example) and writing to the subfile. Remember, subfiles work like direct files-we access a particular subfile record via its relative position in the subfile.
We now get into the working portion of the code-the Calculation specifications. The mainline of the program is written to follow the logic we determined in the previous section. As you can see, the structure chart maps almost line-for-line to the mainline. We could write this program entirely in- line, but the subroutines allow us to focus on each section of code a bit more easily.
The first step, according to our logic model, is to get the initial name to start the search. This is accomplished in the *INZSR subroutine (*INZSR runs automatically at program initialization so we do not have to call it with EXSR) by setting our four switches (indicators 31-34) to show just the HEADER format to the user and inviting his response. Indicator 32 controls when to show the subfile control format which, in our case, is the HEADER. By setting it on and the other indicators off, only HEADER is shown when we EXFMT the HEADER.
The next process (subroutine CLEAR) clears the subfile contents. This is done by setting our four switches. We set the clear indicator on and set off the indicators for both the subfile and the subfile control format. Next, we write the HEADER format and initialize the RRN field. As a general practice, we should also reset the controlling switches to turn off the clear switch and set the control format display switch on after writing the format.
In subroutine POSIT, we take the customer name entered by the user and position the file to the first record in the file that matches or comes closest to the selection using SETLL.
The LOAD subroutine then reads records from the CUSTMST file and loads them into the subfile. The RRN variable is incremented before each write, which places the data from the database into successive records of the subfile. Loading ends when either the end of the database file is reached, or the subfile size is reached. Indicator 34 will turn on if the database file reaches EOF controlling the + (or More...) at the bottom of the screen. Specifying indicator 95 in columns 58-59 of the WRITE statement to the subfile is a special use of the WRITE operation code for subfile record formats. This technique allows us to put a scrollable window over even a very large file with minimal coding. The user will be able to scroll only through the number of pages that we load.
Once we have loaded the subfile, we want to display it to the user (subroutine DISPLY). This is done by setting the four conditioning indicators and running an EXFMT operation of the control record HEADER. If, after coming out of the load routine, our RRN field is still zero, we know that there were no records loaded into the subfile and therefore we should not try to display it. (If you do try to display an empty subfile, the world ends as we know it, and so does your program!) We have chosen to redisplay the HEADER to get a new name if no records were found, and not bother with a "No records found" message.
When the user presses the Enter key, the program runs the PROCES subroutine. This routine searches the subfile for records that the user has selected using the READC operation code. READC functions just like any other READ operation- the indicator in columns 58-59 comes on only when no record is read. For each subfile record in which the user entered an option of 5, we call a subprogram to handle the inquiry display. After processing the selections, the program blanks the SELECT field and posts it back to the subfile, since we only reload when a new name is entered.
From this example, you begin to get a feel for the basic routines needed in a typical subfile program. This load-all style can be quite appropriate for a production environment, depending on the application. It does have some drawbacks, however, in that we set aside space in the PAG for the entire size of the subfile and load the entire size, even if we don't normally use all the records.
Expanding Subfile
Let's take a look at the changes that would be involved if instead we wrote an expanding subfile. The expanding version of this subfile will lessen our PAG space at the expense of a possible performance overhead. If the user requests more records than we have allocated for the subfile size, the subfile will expand dynamically. Naturally, this creates a performance hit just like any noncontiguous file.
Our program performs the same basic routines; but because we're now operating in an expanding subfile context, we should add a ROLLUP (PAGEDOWN) key to the display file and change some of the conditions when certain things are done.
First, the differences in the screen. 3 (page 32) shows the changes necessary to make the DDS in 2 work as an expanding subfile-replace the entire highlighted section. The only statements that actually change are the two new statements highlighted in 3. We are adding a ROLLUP keyword to the display file on the HEADER record. The keyword is conditioned on indicator 34, the same indicator that controls the subfile end keyword. If indicator 34 is on, it means the last pass of the load routine has read to the end of the file, so it does not make sense to allow the user to attempt to roll again.
First, the differences in the screen. Figure 3 (page 32) shows the changes necessary to make the DDS in Figure 2 work as an expanding subfile-replace the entire highlighted section. The only statements that actually change are the two new statements highlighted in Figure 3. We are adding a ROLLUP keyword to the display file on the HEADER record. The keyword is conditioned on indicator 34, the same indicator that controls the subfile end keyword. If indicator 34 is on, it means the last pass of the load routine has read to the end of the file, so it does not make sense to allow the user to attempt to roll again.
The SFLRCDNBR keyword provides control over which page of the subfile is displayed when the subfile is presented. It uses a hidden field associated with this keyword to set the subfile record number. This contains the number of a record whose page you want presented-i.e., if the page size is 10, any value between 1 and 10 would show page one, 11-20 would show page two, and so on. We did not require this keyword on the first program since we always loaded the whole enchilada up front and always started from page one. I have chosen to use the RRN field to control the page displayed. This ensures that the page last loaded (or processed) is redisplayed.
The RPG program requires only a little modification as well. Add the lines of code in 6a to the mainline, replacing the highlighted EXSR DISPLY statement to execute the load routine if the ROLLUP indicator is on. There are a few ways this can be done, but this particular method is clear and easy to follow. The rest of the changes take place in the LOAD routine. Replace the entire LOAD subroutine with the code in 6b. The loop is modified to do just one page worth rather than continuing until the subfile is full.
The RPG program requires only a little modification as well. Add the lines of code in Figure 6a to the mainline, replacing the highlighted EXSR DISPLY statement to execute the load routine if the ROLLUP indicator is on. There are a few ways this can be done, but this particular method is clear and easy to follow. The rest of the changes take place in the LOAD routine. Replace the entire LOAD subroutine with the code in Figure 6b. The loop is modified to do just one page worth rather than continuing until the subfile is full.
Remember that the subfile automatically expands as long as you define the subfile size as larger than the subfile page. The subfile as it exists after the statements were added from 6a contains no code to limit the number of pages a user can load. Without some exception code to put a "reasonable" cap on this, the user could load 100 pages before the program bombs when it exceeds the maximum number of records allowed (subfiles can never have more than 9999 records).
Remember that the subfile automatically expands as long as you define the subfile size as larger than the subfile page. The subfile as it exists after the statements were added from Figure 6a contains no code to limit the number of pages a user can load. Without some exception code to put a "reasonable" cap on this, the user could load 100 pages before the program bombs when it exceeds the maximum number of records allowed (subfiles can never have more than 9999 records).
Page-at-a-Time
The last example is a page-at-a-time subfile. It stores only the records currently shown on the screen in the subfile. Both the ROLLUP and ROLLDOWN keywords are coded in the display file's DDS, and the subfile contents are cleared each time one of these keys is pressed.
We must modify the screen to make the subfile page equal to the subfile size by replacing the highlighted section of 2 with the code in 4 (page 32). This adds a ROLLDOWN key to the HEADER record. At this point, we want to code a conditioning indicator so that the ROLLDOWN is processed only when it is appropriate (i.e., there are records available to be shown). We also want to remove the SFLRCDNBR we added for the expanding subfile example, since a page-at-a-time subfile by definition loads only one page.
We must modify the screen to make the subfile page equal to the subfile size by replacing the highlighted section of Figure 2 with the code in Figure 4 (page 32). This adds a ROLLDOWN key to the HEADER record. At this point, we want to code a conditioning indicator so that the ROLLDOWN is processed only when it is appropriate (i.e., there are records available to be shown). We also want to remove the SFLRCDNBR we added for the expanding subfile example, since a page-at-a-time subfile by definition loads only one page.
The program logic needs to be modified so that we clear the subfile on each roll key and the logic to handle the ROLLDOWN key is added. To accomplish this, insert the code shown in 7a into the mainline routine shown in 5, replacing the highlighted EXSR DISPLY statement. The basic program logic remains the same.
The program logic needs to be modified so that we clear the subfile on each roll key and the logic to handle the ROLLDOWN key is added. To accomplish this, insert the code shown in Figure 7a into the mainline routine shown in Figure 5, replacing the highlighted EXSR DISPLY statement. The basic program logic remains the same.
The largest change is the introduction of a ROLLBACK routine, which can be achieved through a number of varying techniques and styles. We could read back two pages worth and then run the regular load routine; or read back to the top of the page and then load the last page in reverse; or keep track of the top of each page and use that to go to prior pages. There is no perfect ROLLBACK routine! Different techniques work better in different situations-are the search keys unique? Is the data dynamic? Is performance the most critical factor? For simplicity, we are holding the first key on each page in an array and using that for navigation. Insert the statement in 7b after the F- specs.
The largest change is the introduction of a ROLLBACK routine, which can be achieved through a number of varying techniques and styles. We could read back two pages worth and then run the regular load routine; or read back to the top of the page and then load the last page in reverse; or keep track of the top of each page and use that to go to prior pages. There is no perfect ROLLBACK routine! Different techniques work better in different situations-are the search keys unique? Is the data dynamic? Is performance the most critical factor? For simplicity, we are holding the first key on each page in an array and using that for navigation. Insert the statement in Figure 7b after the F- specs.
The load routine is modified to increment the TOPS array index "T" each pass. This index gets initialized each time we reposition the search. Within the load loop, we capture the key of the first record on the page, as shown in 7c. Replace the entire LOAD subroutine with the code in 7c.
The load routine is modified to increment the TOPS array index "T" each pass. This index gets initialized each time we reposition the search. Within the load loop, we capture the key of the first record on the page, as shown in Figure 7c. Replace the entire LOAD subroutine with the code in Figure 7c.
The ROLLBACK routine BACKUP (7d) uses the keys stored in the array TOPS to reposition to the top of the last page. The load routine is then called to refill the subfile. This technique limits the ROLLBACK so that it does not go beyond the first page of the search. This is handled by controlling when the ROLLDOWN key can be pressed. Add the BACKUP subroutine in 7d to the end of program.
The ROLLBACK routine BACKUP (Figure 7d) uses the keys stored in the array TOPS to reposition to the top of the last page. The load routine is then called to refill the subfile. This technique limits the ROLLBACK so that it does not go beyond the first page of the search. This is handled by controlling when the ROLLDOWN key can be pressed. Add the BACKUP subroutine in Figure 7d to the end of program.
Add Method to Your Madness
The HLL program logic really changes very little from one method of subfile processing to the next. The amount of time you want to put into the code should vary based upon the importance of a particular program to the application. Each of these subfile techniques has its merits, and each can be implemented from one basic shell. The key is not to get into a rut of coding all subfiles one way. Match the method to the application.
Our next article examines more of the subtleties of subfile processing, as well as some of the more exotic keywords and techniques. Until then, enjoy!
AS/400 Subfile Programming Part II: Basic Coding
Figure 1 Screen for sample application
Figure 1: Screen for Sample Application Work With Customers Date 6/16/92 Time 21:42:26 Position to name... A Type options, press Enter. 5=Display Opt Customer Customer Credit No. Name Limit _ 150 Alliance Gas Co. 60000.00 _ 950 Anaconda Supplies Inc. 300000.00 _ 550 Autocut Distributors Inc. 54000.00 _ 900 Boxcar Supplies Inc. 300000.00 _ 500 Distrends Inc. 54000.00 _ 100 Duplo Products Inc. 60000.00 _ 200 Dynopipe Inc. 50000.00 _ 250 Ever Ready Pipes Inc. 50000.00 _ 300 Fabricators Unlimited Inc. 75000.00 _ 1000 Integrated Dynamics Inc. 275000.00 + F3=Exit F12=Cancel
AS/400 Subfile Programming Part II: Basic Coding
Figure 2 Display file XRD002DF
A DSPSIZ(24 80 *DS3) A REF(CUSTMST) A PRINT A CA03(03) A CA12(12) A R DETAIL SFL A SELECT 1A I 12 6 A CSNUM R O 12 11 A CSNAME R O 12 23 A CSCRLT R O 12 56EDTCDE(1) A R HEADER SFLCTL(DETAIL) A OVERLAY A SFLSIZ(0050) A SFLPAG(0010) A 31 SFLDSP A 32 SFLDSPCTL A 33 SFLCLR A 34 SFLEND A 1 31'Work with Customers' A DSPATR(HI) A 1 68'Date' A 1 73DATE EDTCDE(Y) A 2 68'Time' A 2 73TIME A 4 2'Position to name:' A @CNAME R B 4 21REFFLD(CSNAME CUSTMST) A 6 2'Type options, press Enter' A COLOR(BLU) A 7 5'5=Display' COLOR(BLU) A 10 10'Customer' DSPATR(HI) A 10 23'Customer' DSPATR(HI) A 10 59'Credit' DSPATR(HI) A 11 5'Opt' DSPATR(HI) A 11 12'No.' DSPATR(HI) A 11 23'Name' DSPATR(HI) A 11 60'Limit' DSPATR(HI) A R TRAILER A 23 2'F3=Exit F12=Cancel' A COLOR(BLU)
AS/400 Subfile Programming Part II: Basic Coding
Figure 3 DDS modication for expanding subfile
A R HEADER SFLCTL(DETAIL) A OVERLAY A N34 ROLLUP(25) A SFLSIZ(0050) A SFLPAG(0010) A 31 SFLDSP A 32 SFLDSPCTL A 33 SFLCLR A 34 SFLEND A RRN 3 0H SFLRCDNBR
AS/400 Subfile Programming Part II: Basic Coding
Figure 4 DDS modificaiton for page-at-a-time subfile
A R HEADER SFLCTL(DETAIL) A OVERLAY A SFLSIZ(0010) A SFLPAG(0010) A N34 ROLLUP(25) A N35 ROLLDOWN(26) A 31 SFLDSP A 32 SFLDSPCTL A 33 SFLCLR A 34 SFLEND
AS/400 Subfile Programming Part II: Basic Coding
Figure 5 RPG program code
* Indicator usage: 03 - F3 response indicator * 12 - F12 response indicator * 31 - Display subfile contents * 32 - Display subfile control record * 33 - Clear the subfile * 34 - Control display of "+" * **************************************************************** FCUSTMST IF E K DISK FXRD002DFCF E WORKSTN F RRN KSFILE DETAIL * * This is a no-cycle program C MOVE *ON *INLR * * Mainline: Do until user presses F3 or F12 C *IN03 DOWEQ*OFF C *IN12 ANDEQ*OFF * * Only reload if the search name changes C HLDNAM IFNE @CNAME C EXSR CLEAR C EXSR POSIT C EXSR LOAD C MOVEL@CNAME HLDNAM C ENDIF * C EXSR DISPLY * * Process the selections if the user is still game C *IN03 IFEQ *OFF C *IN12 ANDEQ*OFF C RRN ANDNE*ZERO C EXSR PROCES C ENDIF C ENDDO **************************************************************** * Subroutine name: *INZSR ** Purpose: First pass logic **************************************************************** C *INZSR BEGSR * Set up a hold name and initialize it to all 9's C *LIKE DEFN CSNAME HLDNAM C MOVE *ALL'9' HLDNAM * * Get the starting name C MOVEA'0100' *IN,31 C WRITETRAILER C EXFMTHEADER C ENDSR **************************************************************** * Subroutine name: CLEAR * Purpose: Clear the subfile and RRN **************************************************************** C CLEAR BEGSR C MOVEA'001' *IN,31 C WRITEHEADER C Z-ADD*ZERO RRN 30 C WRITETRAILER * * Reset for the next process C MOVEA'010' *IN,31 C ENDSR **************************************************************** * Subroutine name: POSIT * Purpose: Position the file based upon the name **************************************************************** C POSIT BEGSR C @CNAME SETLLCUSTMST C ENDSR **************************************************************** * Subroutine name: LOAD * Purpose: Load the subfile **************************************************************** C LOAD BEGSR C *IN34 DOUEQ*ON C *IN95 OREQ *ON C READ CUSTREC 34 C *IN34 IFEQ *OFF C ADD 1 RRN C WRITEDETAIL C ENDIF C ENDDO C ENDSR **************************************************************** * Subroutine name: DISPLY * Purpose: Display the HEADER/DETAIL **************************************************************** C DISPLY BEGSR * * Set the subfile display indicator if records are loaded C RRN IFNE *ZERO C MOVE *ON *IN31 C ENDIF C EXFMTHEADER C ENDSR **************************************************************** * Subroutine name: PROCES * Purpose: Process the user's selections **************************************************************** C PROCES BEGSR * * Locate all the selected records C *IN95 DOUEQ*ON C READCDETAIL 95 C *IN95 IFEQ *OFF * C SELECT IFEQ '5' C CALL 'CUSTDSP' C PARM CSNUM C ENDIF * * Insure the SELECT field is reset C CLEARSELECT C UPDATDETAIL C ENDIF C ENDDO C ENDSR
AS/400 Subfile Programming Part II: Basic Coding
Figure 6A Mainline modificaiton for expanding subfile
C EXSR DISPLY C *IN25 IFEQ *ON C EXSR LOAD C ENDIF
AS/400 Subfile Programming Part II: Basic Coding
Figure 6B LOAD subroutine for expanding subfile
C LOAD BEGSR C 1 DO 10 X 30 C READ CUSTREC 34 * C *IN34 IFEQ *ON C LEAVE C ENDIF * C ADD 1 RRN C WRITEDETAIL C ENDDO C ENDSR
AS/400 Subfile Programming Part II: Basic Coding
Figure 7A Mainline modification for page-at-a-time subfile
C EXSR DISPLY * Reposition to the prior page - ROLLDOWN key C *IN26 IFEQ *ON C EXSR CLEAR C EXSR BACKUP C EXSR LOAD C ENDIF * Load another page on a ROLLUP key C *IN25 IFEQ *ON C EXSR CLEAR C EXSR LOAD C MOVE *OFF *IN35 C ENDIF
AS/400 Subfile Programming Part II: Basic Coding
Figure 7B E-spec for page-at-a-time subfile
E TOPS 100 30
AS/400 Subfile Programming Part II: Basic Coding
Figure 7C LOAD subroutine for page-at-a-time subfile
C LOAD BEGSR C ADD 1 T 30 * C 1 DO 10 X 30 C READ CUSTREC 34 * C *IN34 IFEQ *ON C LEAVE C ENDIF * C X IFEQ 1 C MOVELCSNAME TOPS,T C ENDIF * C ADD 1 RRN C WRITEDETAIL C ENDDO C ENDSR
AS/400 Subfile Programming Part II: Basic Coding
Figure 7D Rollback subroutine for page-at-a-time subfile
C BACKUP BEGSR * Backup to the first record on the prior page C T IFGE 2 C SUB 1 T C TOPS,T SETLLCUSTNAME C SUB 1 T C ENDIF * Set the ROLLBACK control indicator C T IFEQ *ZERO C MOVE *ON *IN35 C ELSE C MOVE *OFF *IN35 C ENDIF C ENDSR
LATEST COMMENTS
MC Press Online