SUMMARY INFORMATION IN COBOL REPORTS

There are two common problems among beginning Cobol programmers concerning summaries. The first problem is where do I get the totals? Secondly, where should I print the summaries and why do I seem to get the summaries on a page by themselves with column heading? We'll first look at accumulating totals and then printing the summary information

Accumulating Summary Totals

Before you can print the totals you MUST accumulate them. Remember that the real logic of your program is in the procedure division. Also, when we process a record we are performing an iteration. That simply means we go through a certain series of steps for ever record we process. If our detail line contains the prices of certain items and we want to ACCUMULATE the price of all of these items then we need an accumulator or "bucket".Under a group name in the working storage section which you may call NUMERIC-TOTALS you add an accumulator as follows: 01

NUMERIC-TOTALS.
      03 LINES-PRINTED-SO-FAR PIC X(02).
      03 RECORD-COUNT PIC X(03).
      03 PAGE-COUNT PIC X(02).
      03 SALES-TOTALS PIC 9(05)V99.
       03 TOTAL-ITEMS PIC 9(03).

Notice I simply added and accumulator called Sales-Totals with an appropriate PIC statement.I also want to accumulate the total items for each detail line. For instance I sold 4 hats on one detail line and on the next line I sold 10c oats. When I process a record (between my PERFORM-UNTIL and my END-PERFORM I need to add a line to do the accumulation.   The code in the procedure division (showing only important elements) might be as follows:

PERFORM  kkl UNTIL EOF-FLAG = "YES"

ADD 1 TO RECORD-COUNT
MOVE NAME-IN TO NAME-OUT
MOVE ITEM-COUNT-IN TO ITEM-COUNT-OUT
ADD ITEM-COUNT TO TOTAL-ITEMS

END-PERFORM

Notice a line was added that sent the number of items that appears on each detail line to an accumulator. Below is how our detail line might appear and what the accumulator would contain.

ITEM     QTY

HATS       4
COATS   10

After processing these two records our accumulator called TOTAL-ITEMS would hold 14. We added the ITEM-COUNT in each processed record to the TOTAL-ITEMS accumulator. In a similar manner you can accumulate item counts, sales amounts, department totals, etc.

An important note about RECORD-COUNT

Record count represents the total number of records processed. Every detail line you print might represent some sales item or perhaps a student or employee record. It follows logically that a RECORD-COUNT of 2 means I  processed two item, students, employees, etc. If on an advanced assignment you find you must check for good and bad records then the following formula applies: Total records processed = number of good records processed + number of bad records processed. You can see you would have to set up an accumulator to hold the number of bad records (that failed some test). You could then get the good records by saying Total records processed - bad records.

To sum up accumulation you simply need to add the name of your accumulator as an elementary item NUMERIC-TOTALS and then use and ADD statement WITHIN the iteration where you are processing your record.
 

Printing the Summary Information

You can be as simply or fancy as you like in printing summary information.Remember that your summary is handled AFTER you finish processing your records. At that point all the information you need to directly or by calculations produce your summary information resides in NUMERIC-TOTALS in one of the elementary items you created. The fancy way is to create another top of page just for the summary. If you have the time and desire feel free to do that but if it is not required then it is only extra work for you. Before you can print your summary lines you need to decide whether you want to print one long summary line with all the information or several. Printing several lines is easier to debug so I suggest this if you want to keep things simple. In the following code which appears in working storage one summary line is set up to print. To set up another line why not just cut and past these lines directly below and then make some modifications.

01 SUMMARY-LINE-1.

        03 PIC X(10) VALUE SPACES.
        03 PIC X(26)
                    VALUE 'TOTAL NUMBER OF ITEMS SOLD '.
        03 PIC X(10) VALUE SPACES.
        03 TOTAL-P PIC Z99.
 
 

01 SUMMARY-LINE-1.

        03 PIC X(10) VALUE SPACES.
        03 PIC X
(26)
                    VALUE 'TOTAL NUMBER OF ITEMS SOLD '.
        03 PIC X(10) VALUE SPACES.
        03 TOTAL-ITEMS-SL PIC
Z99.

Notice I have two blocks of code that are identical I have to change the 5 areas that are underlined and italicized. First you should change the group name to something descriptive such as SUMMARY-LINE-2 Second, you need a new name for the summary line and a new pic representing the length of this name. Third, I need a new total field and a new PIC statement that reflects the proper size, type (alpha or numeric), and editing of the output value. A possible change to output total number of records processed might be as follows:

01 SUMMARY-LINE-2.

        03 PIC X(10) VALUE SPACES.
        03 PIC X
(23)
                    VALUE 'TOTAL RECORDS PROCESSED '.
        03 PIC X(10) VALUE SPACES.
        03 TOTAL-RECS-SL PIC
999.

You add the number of summary lines you want. If you summary information for every detail column such as with a bank statement you will want to create one group name and lay out your summary line on a spacing chart.This way you can make sure all column headings, detail columns, and summary information lines up on the final report.

The Procedure division component of printing summary lines

We've discussed the actual accumulator and the summary line description both in working storage but how do you get the summary line to print with the accumulator totals? The following paragraph will move the accumulator called TOTAL-RECS to TOTAL-REC-SL and print the line. Because we will have a line after our iteration like PERFORM 300-PRINT-SUMMARIES we will perform the statements in this paragraph only once.

300-PRINT-SUMMARIES.

       MOVE TOTAL-ITEMS TO TOTAL-REC-SL
       MOVE SUMMARY-LINE-1 TO PRINT-OUT
       WRITE PRINT-OUT AFTER ADVANCING 3 LINES.

What if we want a second summary line to print with a different summary item? Then we cut and paste and make several changes. First, cut and paste a copy of the first 3 lines to just below the original lines as follows:

300-PRINT-SUMMARIES.

       MOVE TOTAL-ITEMS TO TOTAL-ITEMS-SL
       MOVE SUMMARY-LINE-1 TO PRINT-OUT
       WRITE PRINT-OUT AFTER ADVANCING3 LINES.

       MOVE TOTAL-ITEMS TO TOTAL-ITEMS-SL
       MOVE SUMMARY-LINE-1 TO PRINT-OUT
       WRITE PRINT-OUT AFTER ADVANCING3 LINES.

We only have to change the item we are moving from the numeric totals area and the destination of that item. The changed code would look as follows:

       MOVE TOTAL-ITEMS TO TOTAL-ITEMS-SL
       MOVE SUMMARY-LINE-1 TO PRINT-OUT
       WRITE PRINT-OUT AFTER ADVANCING3 LINES.

       MOVE RECORD-COUNT TO TOTAL-RECS-SL
       MOVE SUMMARY-LINE-1 TO PRINT-OUT
       WRITE PRINT-OUT AFTER ADVANCING3 LINES.

We would print two summary lines with the first being total items and the second being total records with 3 spaces in between the lines. 

Detail Column heading are above Summary information on a separate page

This is a common problem that has a short but tricky answer. Consider the following code:

PERFORM UNTIL EOF-FLAG = "YES"

     ADD 1 TO RECORD-COUNT
     MOVE NAME-IN TO NAME-OUT
     MOVE ITEM-COUNT-IN TO ITEM-COUNT-OUT
     ADD ITEM-COUNT TO TOTAL-ITEMS
     MOVE REPORT-LINE TO PRINT-OUT
     WRITE PRINT-OUT AFTER ADVANCING 2 LINES
     ADD 2 TO LINES-PRINTED-SO-FAR

          IF LINES-PRINTED-SO-FAR IS GREATER THAN 20
              MOVE LINE-OF-EQUALS TO PRINT-OUT
              WRITE PRINT-OUT AFTER ADVANCING 2 LINES
              PERFORM 100-TOP-OF-PAGE-ROUTINE
          END-IF

     READ SALES-FILE
          AT END MOVE 'YES' TO EOF-FLAG
     END-READ

END-PERFORM

Notice that within our iteration (between the PERFORM UNTIL EOF-FLAG= "YES" and the END-PERFORM we have read our next record. The first read (also called a prime read which could be avoided with a special statement in Cobol 85) occurs before the iteration begins and is not shown.Lets move several lines of code and look at the change in our logic. Consider the following code:

PERFORM UNTIL EOF-FLAG = "YES"

     ADD 1 TO RECORD-COUNT
     MOVE NAME-IN TO NAME-OUT
     MOVE ITEM-COUNT-IN TO ITEM-COUNT-OUT
     ADD ITEM-COUNT TO TOTAL-ITEMS
     MOVE REPORT-LINE TO PRINT-OUT
     WRITE PRINT-OUT AFTER ADVANCING 2 LINES
     ADD 2 TO LINES-PRINTED-SO-FAR

     READ SALES-FILE
          AT END MOVE 'YES' TO EOF-FLAG
     END-READ

          IF LINES-PRINTED-SO-FAR IS GREATER THAN 20
              MOVE LINE-OF-EQUALS TO PRINT-OUT
              WRITE PRINT-OUT AFTER ADVANCING 2 LINES
              PERFORM 100-TOP-OF-PAGE-ROUTINE
          END-IF

END-PERFORM.

Three lines have been moved but our the outcome of our processing is unaffected. Read the code and prove to yourself that we haven't changed our output. We read the next record before we tested to see if we needed a new top of page but after we made all the moves and accumulations for the previously read record. If you are satisfied no change has been made in the outcome of our processing then consider what is now available to us. If we read the record before we do the test for a new page we have the switch change available to help us decide when we need that new top of page.

We know that line IF LINES-PRINTED-SO-FAR IS GREATER THAN 20 will always give us a new top of page when we have printed 20 lines. The problem is we may not want a top of page if there are no more detail lines or we are printing the summary. Even without the summary you may find a top of page printing all by itself complete with column headings but no detail lines.  This is because we filled up one page but the logic was written in such a way that we found out we were out of records after we had already printed the top of page. We can use the end of file condition in a compound conditional to easily solve our problem.

PERFORM UNTIL EOF-FLAG = "YES"

     ADD 1 TO RECORD-COUNT
     MOVE NAME-IN TO NAME-OUT
     MOVE ITEM-COUNT-IN TO ITEM-COUNT-OUT
     ADD ITEM-COUNT TO TOTAL-ITEMS
     MOVE REPORT-LINE TO PRINT-OUT
     WRITE PRINT-OUT AFTER ADVANCING 2 LINES
     ADD 2 TO LINES-PRINTED-SO-FAR

     READ SALES-FILE
          AT END MOVE 'YES' TO EOF-FLAG
     END-READ

          IF LINES-PRINTED-SO-FAR> 20 AND EOF-FLAG NOT EQUAL TO "YES"
              MOVE LINE-OF-EQUALS TO PRINT-OUT
              WRITE PRINT-OUT AFTER ADVANCING 2 LINES
              PERFORM 100-TOP-OF-PAGE-ROUTINE
          END-IF

END-PERFORM. 

The above code solves our problem. We changed the location of the read to make the switch available. Also we added a compound conditional whose second component is only FALSE one time--when we have no more records to print. Thus the printing of a new top of page is suppressed after we are out of records and the summary will print without any heading at all.

HOME

All pictures and material Copyright © 1998 - 2004, A+ copyright Comptia, CCNA copyright Cisco Systems.  This page is optimized for Internet Explorer 6.0 at 800 x 600 resolution For problems or questions regarding this web contact [Webmaster]. Last updated: April 20, 2004.