9.13 Using SKIP

Consider the problem of printing reports on special forms other than labels. Usually, these forms are line oriented, that is, they have information that must be printed on a certain line (usually in a box). The Report Writer has a statement that allows you to skip down to a particular line on a form. Let us illustrate this by printing invoices for the subscribers who are getting magazines. The invoice form has the following form requirements:

Line Column Description

2 1 Box that contains the word "Invoice".

5 1 Start invoice header, line contains word "From:".

6through9 3 Name and address of subscription house.

16 4 Start of customer information, line contains word "To:" followed by customer name.

16 54 The word "Date:" followed by the current date.

17 10 First address line.

17 54 Customer id #, starts with word "Cust#:", followed by subscriber code.

18through19 10 Remainder of subscriber address. Second address is omitted if empty.

25 1 Terms of invoice, line contains the phrase "Terms: Net 30 Days"

31 1 Start of column headings for subscriptions, contains word "Date", date started.

31 13 Magazine title subscribed to, contains word "Magazine".

31 64 Amount owed for magazine, contains word "Amount".

32 1 Remainder of headings, contains word "Ordered".

36through54 Contain the details of each transaction,

1 date subscription started,

13 title of magazine,

62 if first transaction, contains a dollar sign "S"

64 amount of subscription.

Form length is 56 lines.

In addition, a total line similar in format to the transaction line must be printed. In this case, a blank line is printed, and then a row of minus signs (-) is printed under the amount column. On the next line, the title, "Total Amount Due", followed by a dollar sign ($) is printed with the total amount for subscriptions printed under the amount column. The first amount contains a dollar sign and all those following do not until a total is given. The total also has a dollar sign showing. This business with dollar signs is the fancy way accountants like to see money amounts printed out in columns.

This is a rather wordy description of the form. A sample should help clarify what the output is to look like. The following is a sample run from the demo system:

Invoice

From:

Marvelous Magazines Subscription House

68000 Demo Rd

Suite z80

Portland, OR 97201

To:

Denise Neufeld Date: 08/19/82

2209 Monroe Cust#: NfldD2209

Los Angeles, CA 90016

Terms: Net 30 Days

Date Magazine Amount

Ordered

06/01/81 Byte Magazine $ 18.00

05/01/80 Computer Design 15.00

01/01/81 Computer World 21.00

01/01/81 Issac Asimov Science Fiction Mag. 19.00

____________

Total Amount Due $ 83.00

In addition to the above requirements, the invoices to be printed are sorted by subscriber. The individual subscriptions for one subscriber are sorted by magazine code. Keeping these requirements in mind we can go on to complete the report program. We begin with the files. For this example, we are printing information from all three of our demo files. The FILE and FIELD declarations are as follows:

FILE scripts IS "script"

FILE cust IS "sub"

FILE mags IS "mag"

FIELDS IN scripts ARE

subscriber, magazine, started;

FIELDS IN cust ARE

subscriber, name, address,

city, state, zip;

FIELDS IN mags ARE

magazine, title, year_rate;

You can verify that all of the information required by the form is present in the above field list.

We still need to determine what variables are required. Two obvious ones are the amount of a magazine subscription and the invoice total for one subscriber. Consider the problem of printing the dollar sign. We only want to print this on the first subscription, and on the total line. What we need is a flag to indicate if we are printing the first subscription or not. We set this flag to true after headings have been printed, and set it to false after each subscription has been printed. Then, when we print an amount, we simply need to check to see if we are printing the first amount (more on this later). With these things in mind, we have the following variable declaration:

VARIABLES ARE

amount_due,

invoice_total TOTAL OF amount_due,

first_script;

With our variables declared, we can move on to the MAIN procedure. The main process of this report is very simple:

Set report attributes for invoice forms.

Set breaks.

Sort the subscriptions.

Process the sorted subscriptions.

The only tricky part is how page headings and end of invoices are handled. The first thing you must do is to separate out each individual part of what happens for headings and footings. One obvious thing to note is that each subscriber must be started on a new form. Since the report starts at the top of form, this is the same as skipping to the top of the next form at the end of a subscriber. There is a subtle difference: if we try to skip to the top of form at the beginning of a subscriber, then the first subscriber produces a blank form.

The next thing to note is that we are reading the subscriptions file which does not have the information needed to print out the subscriber's address. This implies that we must look up the address for each subscriber. The only question is when that look up is done. If we do the look up at the time page headings are done, then the look up is done each time headings are printed, even if the subscriber is the same as the previous form. While we admit that this is not too likely, this is supposed to be a model report and as such this kind of inefficiency is unacceptable. All we need to do is look up the subscriber information when the subscriber code in the subscriptions file changes. Then, when we print out page headings, the information is there.

The next problem to solve is the sorting. It seems we have to sort not only by the subscriber code but by the magazine code as well! Fortunately, this is handled easily by the Report Writer. The fields to be sorted are listed one after the other. All of the records are sorted so that the first field appears in increasing order. Then, if two or more records have the same first field (i.e., one subscriber subscribes to two or more magazines) the next field (magazine) appears in increasing order. The SELECT statement for this is:

SELECT FROM scripts

SORTED BY subscriber, magazine;

The entire MAIN procedure looks like

MAIN

BEGIN

/* set up for invoice forms */

SET PAGELENGTH := 56,

FIRSTLINE := 2,

LASTLINE := 54;

AT TOP OF PAGE

DO headings;

CHECK scripts, AT START OF subscriber

DO new_sub;

CHECK scripts, AT END OF subscriber

DO close_invoice;

SELECT FROM scripts

SORTED BY subscriber, magazine;

FOR EACH scripts

DO details;

END

Let us now look at how the form headings are printed. You might have noticed in the MAIN procedure that we are setting the first print line to 2. According to the form requirements, this line contains a box into which we must print the word "Invoice". This means that if we just print the string "Invoice" on the first line of the headings, it will come out on line 2. After printing this, we must move down to line 5 and print the return address. If we wanted, we could just print 3 NLs. A more flexible method would be to use the SKIP statement. This statement looks like

SKIP TO LINE (number);

Number is an expression that is the line number you want to be on (most of the time this is a number, like 5). Armed with our new statement, we can now move directly to line 5 with the statement

SKIP TO LINE (5);

At this point we need to print out the name of the company sending out the invoice along with the address. After this is done, we move down to line 16 to start printing the subscriber's address. So far, our headings procedure looks like:

PROCEDURE headings /* print form headings */

BEGIN

PRINT "Invoice"

SKIP TO LINE (5);

PRINT "From:", NL,

TAB (3), "Marvelous Magazines Subscription House", NL,

TAB (3), "68000 Demo Rd", NL,

TAB (3), "Suite z80", NL,

TAB (3), "Portland, OR 97201"

SKIP TO LINE (16);

Now, notice how easy it would be to add or drop lines in the address of the company. All we do is make the changes, and the SKIP statement handles the proper spacing to get us down to line 16. The remainder of the headings procedure is basically more of the same.

We must also remember to set our flag for printing dollar signs. According to our discussion earlier, we need to set this flag to true. In the Report Writer this looks like:

first_script := $TRUE;

$TRUE is a parameter which always evaluates to true in a condition.

The procedure new_sub just does the look up for the new subscriber and is not presented at this time.

In the procedure details we have several things going on. First, we have to look up the title of the magazine. Second, we need to calculate the amount owed for the magazine. (Remember, when the result of this calculation is stored into amount_due, the result is also added into invoice_total.) The interesting part of this procedure comes when we print out the amount. In this case, we must first check to see if this is the first magazine on the form. We are assuming here that if it is, the variable first_script has a true value, otherwise it has a false value. This can be tested as

IF first_script THEN

PRINT TAB (62), "$"

This is followed by the statement

PRINT TAB (64), amount_due:8, NL;

Did you notice how printing the dollar sign had no effect on where the amount was printed? All credits go to the TAB function. The full detail procedure is

PROCEDURE details /* print one subscription */

BEGIN

FIND IN mag

WHERE magazine EQ scripts.magazine;

amount_due := year_rate;

PRINT started, TAB (13), title;

IF first_script THEN

PRINT TAB (62), "$"

PRINT TAB (64), amount_due:8, NL;

first_script := $FALSE;

END

Notice the last statement of this procedure. This insures that after we print a subscription the variable first_script is false. This agrees with what we had planned. When the first subscription for a subscriber is printed, first_script is set to true in the headings. Then when the detail is actually printed, first_script gets set back to false and stays that way until the next subscriber is processed (or a page overflow occurs).

The close_invoice procedure does two things: prints the total for the invoice, and moves up to the top of the next form. The entire report looks like:

/* print invoices */

FILE scripts IS "script" /* subscriptions file */

FILE cust IS "sub" /* subscriber file */

FILE mags IS "mag" /* magazine file */

FIELDS IN scripts ARE

subscriber, magazine, started;

FIELDS IN cust ARE

subscriber, name, address,

city, state, zip;

FIELDS IN mags ARE

magazine, title, year_rate;

VARIABLES ARE

amount_due

invoice_total TOTAL OF amount_due,

first_script;

MAIN

BEGIN

/* set up for invoice forms */

SET PAGELENGTH := 56,

FIRSTLINE := 2,

LASTLINE := 54;

AT TOP OF PAGE

DO headings;

CHECK scripts, AT TOP OF subscriber

DO new_sub;

CHECK scripts, AT BOTTOM OF subscriber

DO close_invoice;

SELECT FROM scripts

SORTED BY subscriber, magazine;

FOR EACH scripts

DO details;

END

PROCEDURE headings /* print form headings */

BEGIN

PRINT "Invoice"

SKIP TO LINE (5);

PRINT "From:", NL,

TAB (3), "Marvelous Magazines Subscription House", NL,

TAB (3), "2709 Demo Rd", NL,

TAB (3), "Suite 1309", NL,

TAB (3), "Bellingham WA, 98225"

SKIP TO LINE (16);

PRINT TAB (4), "To:", TAB (10), name,

TAB (54), "Date: ", $todays_date, NL,

TAB (10), address [1],

TAB (54), "Cust#: ", cust.subscriber, NL;

IF address [2] NE "" THEN

PRINT TAB (10), address [2], NL;

PRINT TAB (10), city, ", ", state, " ", zip;

SKIP TO LINE (25);

PRINT "Terms: Net 30 Days"

SKIP TO LINE (31);

PRINT "Date", TAB (13), "Magazine", TAB (64), "Amount", NL,

"Ordered"

SKIP TO LINE (36);

first_script := $TRUE;

END

PROCEDURE new_sub /* look up new subscriber */

BEGIN

FIND IN cust

WHERE subscriber EQ scripts.subscriber;

END

PROCEDURE details /* print one subscription */

BEGIN

FIND IN mags

WHERE (magazine EQ scripts.magazine);

amount_due := year_rate;

PRINT started, TAB (13), title;

IF first_script THEN

PRINT TAB (62), "$"

PRINT TAB (64), amount_due:8, NL;

first_script := $FALSE;

END

PROCEDURE close_invoice /* finish current invoice */

BEGIN

PRINT NL, TAB (63), "----------", NL,

TAB (13), "Total Amount Due", TAB (62), "$ ",

invoice_total:8, NL;

PRINT BP;

END

PROBLEM 7

Modify the previous report so that a floating dollar sign is printed instead of having the dollar sign printed in a fix position. You may need to consult Chapter 13, Formatting Data Values for help in creating a formatting string.