JES: Just Educational Services

Jonathan E. Sisk's
Pick/BASIC: A Programmer's Guide

Chapter 15 - Formatting Reports and Passing PROC Arguments

Click to enlarge

The most important principles of Pick/BASIC have been discussed in the previous examples; the remaining program examples illustrate extensions to previous concepts and introduce a few new topics that you may run across in your applications.

Program Example 13, for instance, covers the concept of the PROCREAD statement, which is used to pass information from the PROC input buffer into a PICK/BASIC program. Then Example 14 shows you why you don't want to do this.

Enter Program Example 13 from the listing in Fig. 15-1.

After entering, compiling, and cataloging EX.013, you must enter the following PROCs before the program may be tested. It also is important that you have entered the data into the STAFF file before attempting to test this program.

The first PROC is called a trigger PROC. It goes into the MD, as follows:

>ED MD PROCREAD.TEST<cr>
NEW ITEM
TOP
.I<cr>
001 PQ<cr>
002 (PROCS PROCREAD.TEST)<cr>
003<cr>
TOP
.FI<cr>
'PROCREAD.TEST' FILED.

Fig. 15-1. Program Example 13.

EX.013
001 * EX.013
002 * Using PROCREAD
003 * mm/dd/yy: date last modified
004 * JES: author's initials
005 *
006 PROCREAD BUFFER ELSE
007 PRINT "THIS MUST BE RUN FROM THE PROC CALLED PROCREAD.TEST"
008 STOP
009 END
010 *
011 BEGIN.DATE = FIELD(BUFFER," ",1)
012 END.DATE = FIELD(BUFFER," ",2)
013 PRINTER.FLAG = FIELD(BUFFER," ",3)
014 *
015 IF PRINTER.FLAG = "" OR PRINTER.FLAG = "Y" THEN PRINTER ON
016 *
017 HEADING "'LC'BIRTHDAYS FROM" : BEGIN.DATE:" TO ":END.DATE: "'L"'
018 *
019 OPEN "STAFF" TO STAFF.FILE ELSE STOP 201,"STAFF"
020 DIM STAFF.ITEM(15)
021 *
022 1 READNEXT ITEM. ID ELSE
023 PRINTER OFF
024 PRINT "REPORT COMPLETE."
025 STOP
026 END
027 *
028 MATREAD STAFF. ITEM FROM STAFF.FILE,ITEM. ID ELSE
029 CRT "ITEM" : ITEM . ID: "IS MISSING FROM THE STAFF FILE"
030 CRT "PRESS RETURN TO CONTINUE OR 'QUIT' TO STOP" :
031 INPUT RESPONSE
032 IF RESPONSE = "QUIT" THEN STOP
033 GOTO 1
034 END
035 *
036 PRINT "STAFF ID : " : ITEM. ID
037 PRINT
038 PRINT "NAME" "L#20": STAFF.ITEM(l)
039 PRINT "ADDRESS" "L#20": STAFF.ITEM(2)
040 PRINT "CITY" "L#20": STAFF.ITEM(3)
041 PRINT "STATE" "L#20": STAFF.ITEM(4)
042 PRINT "ZIP" "L#20": STAFF.ITEM(5)
043 *
044 PRINT "PRESS ANY KEY FOR NEXT ITeM OR <CTL> X TO QUIT" ·
045 PAGE
046 *
047 GOTO 1
048 *
049 END

ED PROCS PROCREAD.TEST<cr>
NEW ITEM
TOP
.I<cr>
001 PQ
002 RI
003 10 OENTER BEGINNING DATE FOR SELECT +
004 S1
005 IP:
006 IF A1 = QUIT X
007 IF # A1 GO 10
008 20 OENTER ENDING DATE FOR SELECT +
009 S2
010 IP:
011 IF A2 = QUIT X
012 IF # A2 GO 20
013 30 ODO YOU WANT THE REPORT PRINTED ? (y/n=<CR>) +
014 S3
015 IHN
016 IP:
017 IF A3 = QUIT X
018 HSSELECT STAFF BY NAME WITH BIRTHDAY >=
019 A"1
020 H AND WITH BIRTHDAY <=
021 A"2
022 STON
023 HRUN BP EX.013
024 P
025 <cr>
.FI<cr>
'PROCREAD.TEST' FILED.

FIG 15-2 THE PROC CALLED PROCREAD.TEST (Install in PROCS file).

Testing program example 13

This PROC, upon execution, transfers to the file called PROCS and executes a PROC called PROCREAD.TEST. Enter into the PROCS file the PROC shown in Fig. 15-2. Assuming all goes well, the program is entered and compiled, and both PROCS are present and working. Here's how you can test to see if it works.

At the TCL prompt, enter:

PROCREAD.TEST<cr>

The PROC then prompts you to enter the "beginning date," Enter:

1-1-51

The next prompt is the "ending date." Use any date that you want.

Finally, you are prompted to answer whether you want the report pprinted. I suggest that you initially answer the question with "N" (as in "Nope"). This happens to be the default, anyway, in case you just hit the Return key.

After executing the SSELECT statement from the PROC, a group of one or more items may be selected. If you get the message, "NO ITEMS PRESENT," return to the first step.

THE PROCREAD STATEMENT

Back in the old days, before the EXECUTE statement was introduced into the PICK/BASIC language, whenever a "select list" of items had to be passed into a program, it had to be done from PROC. PICK/BASIC has a statement called SELECT available, but the disadvantage of using it is that it selects the entire file, and no sorting or selection criteria may be applied.

The idea here is that a subset of a file needs to be gathered. In the PROC called PROCREAD.TEST, the operator is prompted to enter the beginning and ending dates. This is applied in an :"external" SELECT (in this case, SSELECT) statement, which :gathers: a list of item-ids in the requested sequence after using the selection criteria to determine which items are to be selected. Once the external select completes, the PICK/BASIC program is activated and the list is available for processing.

The PROCREAD statement is only required when one or more pieces of data have to be retrieved from the PROC Primary Input Buffer. It does two things: First it checks to make sure that the program was indeed activated from a PROC, and then it :reads: the contents of the Primary Input Buffer and assigns it to a variable.

The PROCREAD statement has the following general form:

PROCREAD variable [THEN statement(s)]  ELSE statement(s)

When the PROCREAD statement is executed, the THEN clause is optional and the ELSE clause is required. The ELSE clause is executed if the program was not run from a PROC. by the way, the statement is not smart enough to know if it was the "right PROC; it just checks to see that it was run from a PROC.

In example 13, if the program was not executed from the PROC, the program displays an error message and then stops the program;

006 PROCREAD BUFFER ELSE
007 PRINT "THIS MUST BE RUN FROM THE PROC CALLED PROCREAD.TEST"
008 STOP
009 END

Assuming that the program was run from the right PROC, the next executable statement occurs on line 11.

PROCREADING THE PRIMARY INPUT BUFFER

When the PROCREAD statement "worked," it grabbed the entire contents of the Primary Input Buffer and assigned it to the variable called BUFFER. Any variable name could have been used, but descriptive variables do make programs easier to read.

The way data is handled in the Primary Input Buffer varies among the several implementations of Pick. "Generic" Pick systems handle the Primary Input Buffer as one long string of characters, each of which is delimited by a space. Some systems handle the Primary Input Buffer as if it were a dynamic array.

The code in Example 13 illustrates the form that "generic" Pick systems require:

011 BEGIN.DATE = FIELD(BUFFER," ",1)
012 END.DATE = FIELD(BUFFER," ",2)
013 PRINTER.FLAG = FIELD(BUFFER," ",3)

Line 11 performs a FIELD function on the BUFFER variable, which extracts all the characters up to the first space and assigns this string to the variable BEGIN.DATE. This is the "beginning date" that you entered in the PROC.

Line 12 executes a FIELD statement, extracting all the characters between the first and second spaces in the BUFFER variable and assigning the resulting string to the variable END.DATE. Then line 13 executes one final FIELD statement to extract the "third" string from the BUFFER variable and assign it to the variable PRINTER.FLAG.

Shown below are the instructions that would be required on an Ultimate or McDonnell Douglas implementation accomplish the same end result.

011 BEGIN.DATE = BUFFER<l>
012 END.DATE = BUFFER<2>
013 PRINTER.FLAG = BUFFER<3>

The end result is the same: the variables BEGIN.DATE, END.DATE, and PRINTER.FLAG are extracted from the "dynamic" array BUFFER.

Line 15 checks PRINTER.FLAG to determine if it is null or the letter "Y." If either of these conditions apply, the PRINTER ON statement is executed. If not, execution falls through to line 17.

THE HEADING AND FOOTING STATEMENTS

If you have ever used the HEADING or FOOTING statements in an ACCESS sentence, this statement will be familiar. The HEADING statement is used to define the text that appears at the top of each page of output. While you could write the code to handle page headings, footings, line counters, page counters, and related logic, it is much easier to use the HEADING statement.

The HEADING and FOOTING statements have the general form:

HEADING string.expression

or

HEADING "text 'options'"

Generally, the HEADING statement is followed by a string of characters enclosed in double quotes. Between these double quotes may be any text to appear at the top of each page, and any of the special "options" that are available. Figure 15-3 illustrates the "standard" available options. To distinguish "options" from "text" in the HEADING or FOOTING, the options are enclosed in single quotes. This is important to remember. Additionally, multiple options may be (and sometimes must be) enclosed in the same set of single quotes.

The statement in example 13 appears as:

017 HEADING "'LC'BIRTHDAYS FROM ":BEGIN.DATE:" TO ":END.DATE: "'L"'

This constructs the "heading" line as follows: First, the "L" option instructs the program to put a blank Line at the top of each screen. Next, the heading line is to be Centered, Note that the "C" option was included in the same set of single quotes as the "L" option.

Next in the heading line comes the text, "BIRTHDAYS FROM." To this heading is concatenated the current value of the variable BEGIN.DATE. This is then followed by more literal text, this time the string, "TO "(note the spaces before and after the word).

Next, the current value of the variable END.DATE is concatenated to the end of the heading. Finally, an "L" option is concatenated to the end of the heading line. As mentioned earlier in this program, this "forces" a line feed between the heading line and the first line of output on each screen or page.

Line 19 opens the STAFF file for input and/or output. If the STAFF file is not found, then the program stops and executes error message 201, passing to it the string "STAFF." (See the discussion of the STOP statement for more information on this feature.)

Option    Function

'C'       Centers the text.
'D'       Retrieves the current date in the "standard"
          date format. For example, "12 DEC 1997".
'L'       Issues a line feed. Once you take control of the HEADING
          and/or FOOTING, you are responsible for everything that
          happens. For example, if you want a blank line between the
          heading text and the "top" line of data, then you must
          force the line feed to make it happen.
'P'       Retrieves the current report page number. Note: Consult
          your ACCESS reference manual on this one. Most versions of
          Pick have a few derivatives for handling the page number.
'T'       Retrieves the current system time and date. For example,
         "11:45:00 12 DEC 1997."

Fig. 15-3. The "standard" options for the HEADING and/or FOOTING statements.

Line 20 dimensions the array STAFF.ITEM in anticipation of a maximum of 15 subscripts,

THE READNEXT STATEMENT

Before executing this program, the PROC called PROCREAD.TEST externally selected a group of items, which must be dealt with one at a time. This is where the READNEXT statement comes into play:

022 1 READNEXT ITEM.ID ELSE
023      PRINTER OFF
024      PRINT "REPORT COMPLETE."
025    STOP
026    END

The READNEXT statement has the general form:

READNEXT id.variable {THEN statement(s)} ELSE statement(s)

When the READNEXT statement is executed, the program extracts the top item-id off the "stack" of item-ids created by the (external) SELECT or SSELECT statement. When this occurs successfully, the stack of item-ids "moves up" by one--exactly like removing a plate from one of those dispensers found in cafeterias. The item-id just "read" from the stack is assigned to the specified variable. In this program, that variable is called, creatively enough, ITEM.ID.

The READNEXT statement executes its ELSE clause when it runs out of item-ids (no more plates). In this program, when the READNEXT statement discovers that there are no more item-ids to be dealt with, it takes the ELSE clause, which causes the statements from lines 23 through 25 to be executed. Line 23 thoughtfully remembers to tam off printer output with the PRINTER OFF statement, line 24 issues the "REPORT COMPLETE" message, and line 25 terminates the program with a STOP statement.

READING THE ITEM: THE MATREAD STATEMENT

This routine attempts to retrieve the item corresponding to the current item-id via the MATREAD statement:

028 MATRFAD STAFF.ITEM FROM STAFF.FILE,ITEM. ID ELSE
029    CRT "ITEM" :ITEM.ID :" IS MISSING FROM THE STAFF FILE"
030    CRT "PRESS RETURN TO CONTINUE OR 'QUIT' TO STOP" :
031    INPUT RESPONSE
032    IF RESPONSE = "QUIT" THEN STOP
033 GOTO 1
033 END

If the MATREAD statement on line 28 fails to find the item-id in the STAFF file (which is unlikely in this case), the statements from lines 29 through 33 are executed.

Line 29 executes a CRT statement to route the output unconditionally to the screen. The message displays the fact that the item-id is missing from the file, and further advises the operator to press the Return key to continue or enter QUIT to stop. After requesting the response on line 31, line 32 checks to see if the operator entered QUIT. If he did, then the program stops. If he did not enter QUIT, then the program executes the GOTO statement on line 33, which transfers execution to statement label 1, which attempts to retrieve the next item-id from the list.

PRINTING THE ARRAY

The following routine handles the print tasks:

036 PRINT "STAFF ID : " : ITEM. ID
037 PRINT
038 PRINT "NAME" "L#20": STAFF.ITEM(l)
039 PRINT "ADDRESS" "L#20" : STAFF.ITEM(2)
040 PRINT "CITY" "L#20": STAFF.ITEM(3)
041 PRINT "STATE" "L#20": STAFF.ITEM(4)
042 PRINT "ZIP" "L#20": STAFF.ITEM(5)

Line 36 prints the literal "STAFF ID: "and then displays the current item- id. Line 37 issues a blank line. Line 38 prints the literal "NAME," left- justified in a field of 20 blanks, immediately followed by the contents of array location one, STAFF.ITEM(I). This logic is the same for the next four fields.

THE PAGE STATEMENT

The PAGE statement clears the screen, or issues a page eject on the printer, when a HEADING or FOOTING is in effect:

045 PAGE

When a HEADING or FOOTING is "active" in a report program, the PAGE statement is used to handle pagination control. This means several important things to you as the programmer. First, you do not have to issue CHAR(12) or "@(-1)" to clear the screen (or eject a page). Second, the standard end-of-page options are in effect; this means that pressing any key (not the Any key) advances to the next page. Third, at any end of page, the operator may issue a "Control-X," which immediately terminates the program. Fourth, and last, the program "figures out" the device width, based upon the current terminal or printer characteristics as defined by the TERM command. Note that the items 2 and 3 of these features are irrelevant when the report is being directed to the printer (spooler).

DOING IT ALL AGAIN

Line 47 unconditionally transfers execution back to statement label 1 (one) to get the next item or wrap up the program.


REVIEW QUIZ 13

This quiz is is more of an essay question than fill-in-the-blanks as before. Here is your assignment:

1 ) Add the logic to display the other four fields from each item in the STAFF file. These are: PHONE (attribute 6), RENEW.DATE (attribute 7), BIRTHDAY (attribute 8), and HOURLY.RATE (attribute 9). Note that each of these requires special handling to output.

2) Add an "item counter" to the program to display the number of the item being displayed (not the item-id).

3) Add the logic to accumulate the total hourly rates for all the staff items. At the end of the report, on a page all by themselves, print out the following:

a) The total of all hourly rates.

b) The number of items that were processed.

c) The average hourly rate.

4) Assume that everyone will retire at the age of 65. Display the current age of each person and determine the number of years they have until retirement.

Previous chapter Next chapter Top

 

Creative Commons License
Jonathan E. Sisk's "Pick/BASIC: A Programmer's Guide" by Jonathan E. Sisk is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at jes.com.