Procedural Statements


Contents:

Report Writer Verbs: Overview
Sequence of Operations
Keyword Table
GENERATE Statement
GENERATE Statement: Coding Rules
GENERATE Statement: Operation
GENERATE Processing Cycle
INITIATE Statement
INITIATE Statement: Coding Rules
INITIATE Statement: Operation
INITIATE Processing Cycle
Report Writer SET Statements
SET Statements: Coding Rules
SET Statements: Operation
SUPPRESS PRINTING Statement
SUPPRESS PRINTING Statement: Coding Rules
SUPPRESS PRINTING Statement: Operation
TERMINATE Statement
TERMINATE Statement: Coding Rules
TERMINATE Statement: Operation
TERMINATE Processing Cycle
USE BEFORE REPORTING Directive
USE BEFORE REPORTING Directive: Coding Rules
USE BEFORE REPORTING Directive: Operation

COBOL Report Writer will not act until your program executes a procedural statement.  Three main commands or "verbs", INITIATE, GENERATE, and TERMINATE, are sufficient to produce most of the output from your Report Descriptions.  INITIATE and TERMINATE are performed at the beginning and the end, respectively, of the processing for your report; while GENERATE is executed repeatedly, producing one DETAIL (except in summary reporting), preceded by any of the other TYPEs of group that may be needed as page breaks and/or control breaks are encountered.




Report Writer Verbs: Overview



The three main report writer verbs INITIATE, GENERATE, and TERMINATE may be used in the same way as any other COBOL verb and may be used anywhere in the program except in a USE BEFORE REPORTING Declarative SECTION.

Of the remaining procedural statements, the  USE BEFORE REPORTING directive (see 4.7) enables you to write a section of code in the DECLARATIVES portion that is to be performed automatically just before the specified report group is output, and the report writer  SET statements (see 4.4) make it possible to place report groups irregularly on the page.


Sequence of Operations

For a single report using a simple file as input, the normal sequence of operations is as follows:

  1. (once at start)
   OPEN INPUT input file
   OPEN OUTPUT or EXTEND report file
  2. (once at start)    INITIATE report
  3. (for each record
      in input file)
   GENERATE detail groups or report
  4. (once at end)   TERMINATE report
  5. (once at end)   CLOSE input file, report file

with the following basic plan for the PROCEDURE DIVISION:

 
           OPEN INPUT input-file OUTPUT report-file
           INITIATE report-name
           read first input record
           PERFORM UNTIL END-OF-FILE = 1
                GENERATE detail-group
      *      or GENERATE report-name if doing summary reporting
                read next input record
           END-PERFORM
           TERMINATE report-name
           CLOSE input-file report-file


Keyword Table

The following table lists the PROCEDURE DIVISION elements associated with COBOL Report Writer with a summary of their purposes.  The third and fourth columns tell you whether or not the item is part of the current standard (ANS 85) COBOL and, if so, whether COBOL Report Writer extends the facilities.


      Report Writer Verbs: Keyword Table

 
 Keyword

 Purpose

  ANS
  85  
 COBOL?
 Extensions to standard       
 COBOL
 INITIATE
 Prepares report
 for processing
  yes
 » INITIATE...UPON file-name
 » report may be GLOBAL
 GENERATE


 Handles main
 report processing

  yes


 » improved order of totalling,
   page-fit and DECLARATIVES
   if NOOSVS option used
 » report may be GLOBAL
 TERMINATE

 Concludes all
 processing for
 report
  yes

 » report may be GLOBAL

 USE BEFORE
 REPORTING

 Invokes SECTION in
 DECLARATIVES when
 named report group
 is printed
  yes


 » may specify DETAIL group
 » may be GLOBAL

 SUPPRESS
 PRINTING
 Prevents data
 being printed for
 a report group
  no



 MOVE 1 TO
 PRINT-
 SWITCH
 Alternative to
 SUPPRESS PRINTING
  yes



 SET PAGE/
 LINE/
 COLUMN
 Controls PAGE
 BUFFER operations
  no






GENERATE Statement



The GENERATE statement is COBOL Report Writer's main verb for the production of output.  It passes control to report writer to allow it to perform all the necessary mechanical tasks, including any control-break and page-break processing needed before producing all the lines and fields described in your DETAIL group, if specified.



   
Format

 >>--
GENERATE-+-detail-group-name-+-><
              +-report-name-------+


GENERATE Statement: Coding Rules

If GENERATE detail-group-name is coded, it must be the name of a DETAIL group coded in the current program, or in a GLOBAL report defined in a containing program.  (The group-name appears immediately after the 01 level-number.)  You may qualify the detail-group-name with the report-name, as in:  GENERATE MAIN-DETAIL IN SUMMARY-REPORT.  This is necessary if your detail-group-name is not unique in the REPORT SECTION.

The form GENERATE report-name has a special significance and is known as summary reporting.  It causes any DETAIL group to be suppressed, so do not use this form unless you require only CONTROL HEADING or CONTROL FOOTING groups in the body of the report at the point that you execute the GENERATE.  If you use this form, you must have at least one CONTROL HEADING or CONTROL FOOTING group in the report.

GENERATE must not appear in a USE BEFORE REPORTING Declarative SECTION.


GENERATE Statement: Operation

The GENERATE statement causes report writer to perform three main actions in an average report:

It tests for control breaks, producing CONTROL FOOTING and HEADING groups where necessary,

It performs a page-fit test, outputting PAGE FOOTING and PAGE HEADING groups where necessary; (these may also be produced as a result of a CONTROL HEADING or CONTROL FOOTING),

It generates each line in the DETAIL group, unless you are doing summary reporting (GENERATE report-name).

Once a report has been INITIATEd, your program may execute any number of GENERATE statements for each DETAIL group in the report.  If your Report Description contains several DETAIL groups, you may code a sequence of different GENERATE statements in any part of the program and, in this way, build up any required report layout.  You may also write a GENERATE for the same DETAIL group in more than one place in the program.

Summary reporting, where you code the report-name instead of a DETAIL group-name after the GENERATE, has the following effects:

No DETAIL group is output.

Any rolling forward of SUM operands takes place as usual, except for any rolling forward from a DETAIL group.

Any cross-footing of SUM operands takes place as usual, except for cross-footing within a DETAIL group.

Any subtotalling of (non-REPORT SECTION) SUM operands is executed as follows:

i.   If SOURCE SUM correlation is in effect, all the SUM operands that correspond to a SOURCE operand in a DETAIL group are added into their totals, as though you had GENERATEd each DETAIL group in turn.  Any non-REPORT SECTION SUM operands that do not correspond to a SOURCE operand are added into the totals once.

ii.   If SOURCE SUM correlation is not in effect, the SUM operands are added into the totals once.

Testing for control breaks takes place as usual.  If a control break is detected, any CONTROL FOOTING and/or CONTROL HEADING groups are output as usual, together with any PAGE FOOTING and/or PAGE HEADING groups that may be required as the result of a page advance.

   The GENERATE report-name statement can therefore only produce output (a) on the first GENERATE after an INITIATE, and (b) after a control break.

   Between an INITIATE and TERMINATE, your program may execute both the GENERATE report-name and the GENERATE group-name forms of the statement.

   The following example illustrates the different effects of the GENERATE report-name and GENERATE group-name clauses:

      SPORTS CLUB CASHBOOK
     DATE        AMOUNT

    
JAN 4          $20.00
    
JAN 16         $10.00
    
JAN 30        $195.00
    -------       -------
    
JAN TOTAL:    $225.00

    
FEB 12         $10.00
    
FEB 19         $55.00
    -------       -------
    
FEB TOTAL:     $65.00

       RD  CASHBOOK ...
       
01  CASH-LINE  DE.
         
...
           
05  COL 31 PIC $(4)9 SOURCE AMOUNT.

       01  CF FOR MONTH.
         
...
           
05  COL 31 PIC $(4)9 SUM OF AMOUNT.
         
...
           GENERATE CASH-LINE

      SPORTS CLUB CASHBOOK
     DATE        AMOUNT

    -------       -------
    
JAN TOTAL:    $225.00

    -------       -------
    
FEB TOTAL:     $65.00

       RD  CASHBOOK ...

      *(Same REPORT SECTION as above.)

           GENERATE CASHBOOK



GENERATE Processing Cycle

The following is a more thorough description of each stage in the execution of a GENERATE statement:

If the identifier form of the LAST DETAIL sub-clause is used, its value is checked and, if valid, is stored in the Report Control Area.

If your report is associated with a DUPLICATED file, the value of REPORT-NUMBER is examined to see whether it is the same as it was for the previous GENERATE for this report, thus checking that the correct duplicate of the report is in the main Report Control Area.  If not, this is swapped in.

If the report has not yet been INITIATEd, run time error diagnostic 14 is logged.

If this is the first GENERATE since the INITIATE:

If there is a REPORT HEADING group, this is produced.

If there are any CONTROL HEADING groups, each of them is produced, from highest down to lowest, and the initial value of each control is saved.

If this is not the first GENERATE since the INITIATE, each control identifier is compared with the corresponding saved previous value, beginning with the highest level.  If no control has changed, no special action takes place.  If a difference in value (a control break) is detected, comparison ceases and the following control break action takes place:

The value of each control-id is temporarily altered to the value it had immediately before the control break;

CONTROL FOOTING groups are produced, from the lowest up to the one at the level of the control break, if any;

The value of each control-id is restored to its value after the control break;

CONTROL HEADING groups are produced from the one at the level of the control break, if any, down to the lowest.

   Since CONTROL HEADING and CONTROL FOOTING groups are independent report groups in their own right, several of the same operations described below will be applied to them as for a DETAIL group, namely: the output of any pending REPEATED groups, page-fit test, storing of the latest value of the CODE (not done for CONTROL FOOTINGs), all types of totalling, performing of USE BEFORE REPORTING section, production of print lines and clearing of totals, plus the setting on of any PRESENT AFTER (or GROUP INDICATE) flags, when appropriate.

If there are any REPEATED groups in this report other than the current DETAIL, a check is made whether any have been buffered.  If so, they are first output and the buffer is cleared.

If there are any cross-foot totals for this group, they are computed in the order implied by any inter-dependencies among them.

If OSVS is in effect any additional summing is now performed for the group with the following possible actions:

If there is any general "subtotalling" for the report (SUM clauses with non-REPORT SECTION operands, without UPON, and with no SOURCE SUM correlation), each SUM's operands are added into the total fields.  If you are generating a DETAIL group which is absent because of a PRESENT/ ABSENT WHEN/AFTER clause in the 01-level entry, this general subtotalling is also skipped.

If there is any special subtotalling triggered by this DETAIL group due either to an UPON phrase referring to this group or to SOURCE SUM correlation that implies this group, the SUM operands are added into the total fields.

If there is a SUM clause in another group referring to an entry in this group, then rolling forward of values into its total field takes place.

If there is a USE BEFORE REPORTING section for this group in the DECLARATIVES, it is performed.  If PRINT-SWITCH is non-zero as a result (meaning that printing is to be SUPPRESSed), then

If OSVS is in effect no further action takes place for this group;

If NOOSVS is in effect in effect then if no further totalling to be performed for this group, no further action takes place; otherwise the only further steps to be performed are 10 (PRESENT at 01-level), if applicable, and 8 (totalling).

If there is a PRESENT/ABSENT WHEN or PRESENT/ABSENT AFTER clause at the 01-level of this group, a test is made of the condition and, if the group is absent then

If OSVS is in effect no further action takes place for this group;

If NOOSVS is in effect then, if there is no general subtotalling to be performed, no further action takes place; otherwise the only further step to be performed is 8(a) (general subtotalling).

If there is an identifier form of a CODE clause in the RD, the contents of the identifier are moved to the CODE-VALUE location in the Report Control Area .

If this group has a REPEATED clause, the REPEATED buffer is prepared to receive the next instance of the group or, if this group is the last of the set, to produce the buffered groups alongside it.

If any lines are being produced and the report has a PAGE clause, a page-fit test is performed to test LINE-COUNTER, to establish whether or not a page advance is required before the group may be output.  If the group has a MULTIPLE PAGE clause, this test is performed for the first and each subsequent line (or group of lines with NO MULTIPLE PAGE).

If a page advance is required, the following action takes place:

The PAGE FOOTING group is produced, if one exists;

PAGE-COUNTER is incremented by 1;

form feed is output or, if an Independent Report File Handler is in use, a value of zero is placed in the current position location to cause this;

The PAGE HEADING group is produced, if one exists;

If there are any CONTROL HEADING groups specifying OR PAGE, they are produced, from highest down to lowest.

If NOOSVS is in effect and there is any further summing to be performed for this group, step 8 (subtotalling and rolling forward) is now executed.

Each report line field is stored in its report line, invoking FUNCTION routines where necessary and checking for column overlap, line overflow and any other possible error conditions, and then output.  If an Independent Report File Handler is in use, it is invoked; otherwise, report writer issues a WRITE for each report line.  In either case, LINE-COUNTER is first set to the target line position just before each line is produced.

If the group has a NEXT GROUP clause, LINE-COUNTER may be adjusted in accordance with the rules for that clause.  (See NEXT GROUP Clause.)  In the case of NEXT GROUP absolute, this may be deferred by setting the Saved Next Group Integer.

All total fields defined in this group are reset to zero, unless they are not PRESENT during this GENERATE or have a RESET phrase that defers resetting to a higher control break.

If there are any PRESENT AFTER (or GROUP INDICATE) clauses in the group, their indicators are set off.




INITIATE Statement



The INITIATE statement must be the first report writer statement to be executed for a report.


   Format
               +---------+
               v         |
 >>--
INITIATE--report-name--+----------------+---><
                            +-
UPON file-name-+


INITIATE Statement: Coding Rules

Each report-name must be the name of a report in the current program, or that of a GLOBAL report defined in a containing program.  (The report-name appears immediately after the RD level-indicator and also in the REPORT clause in the FD.)

If the UPON phrase is present, each report-name must be defined in a REPORT(S) clause in the FD of the specified file-name.  The UPON phrase must be used if any of the report-names is defined in more than one FD entry.

INITIATE must not appear in a USE BEFORE REPORTING Declarative.


INITIATE Statement: Operation

An INITIATE must be executed for a report before any GENERATE, INITIATE, or Page Buffer SET verb referring to the same report (or a DETAIL in the report) is executed.

An OPEN for the corresponding report file must have been executed before the INITIATE is executed.  The INITIATE does not OPEN the file.  You may however execute an INITIATE once again for a report that was TERMINATEd without closing and re-opening the file.  This fact may be used repeatedly to obtain REPORT FOOTING and REPORT HEADING groups in the interior of the report, or to obtain a fresh page with PAGE-COUNTER reset to 1.

CLOSE must not be issued for the file to which a report is directed once the report has been INITIATEd, unless a TERMINATE is first done.

If an UPON phrase is present, the report will be written only to the file specified.


INITIATE Processing Cycle

The following is a more thorough description of each stage in the execution of an INITIATE statement:

The error flag is cleared.

If your report is associated with a DUPLICATED file and REPORT-NUMBER is zero, the remaining actions are performed for every duplicate report.

If your report is associated with an Independent Report File Handler, the file handler is invoked with an action code of 6.

If the identifier form of a LINE LIMIT clause was coded, the identifier is checked and, if valid, stored in the Report Control Area.

Other internal locations and special registers, such as the current position, "body group has appeared on page" indicator, REPEATED-COUNTER, and PAGE-COUNTER are cleared.

LINE-COUNTER is reset to zero.

PAGE-COUNTER is set to 1.

All total fields, sum overflow indicators, size error indicator and Saved Next Group integer, and PRESENT AFTER indicators, wherever appropriate, are cleared to zero.

The control break indicator is set to -1 to indicate "initial control break on INITIATE".

If a run time subroutine is used for control-break detection, the lengths of each control identifier (other than REPORT/FINAL) are determined and stored in a control area.




Report Writer SET Statements



These statements enable you to hold the current page, in whole or in part, and/or fill it in an irregular fashion.


   Format a

 >>-
SET PAGE STATUS-+------------------+-TO-+- HOLD----+-><
                    ++-
IN -+report-name-+    +-RELEASE-+
                     +-
OF -+
   Format b

>>-
SET LINE +----------------++-TO-+-integer-1-------+---+- ><
           ++
IN+report-name-+|    +-identifier-1----+   |
            +
OF+             |    +-FIRST-+-DETAIL -++   |
                             |            +-
DE-----+    |
                             ++-
UP--++--++-integer-2---++
                              +-
DOWN++BY++-identifier-2+
   Format c

>>-
SET+COLUMN ++---------------++TO---------++integer-3---+ ><
      +
COL---+++ IN+report-name+++LEFT -++--+++identifier-3+
               +
OF +             +RIGHT ++BY+


SET Statements: Coding Rules

Format a (SET PAGE) cannot be used unless there is (a) a WITH PAGE BUFFER clause in the SELECT ... ASSIGN clause for the associated file and (b) a PAGE LIMIT clause in the associated RD entry.  (The Page Buffer feature uses an  Independent Report File Handler to produce the report output and will assume MODE PRNT if there is no MODE specified in your SELECT ... ASSIGN clause.  File handlers are described later (see 5.3).)

The SET LINE and SET COLUMN statements cannot be used unless there is either a WITH PAGE BUFFER clause or a WITH RANDOM PAGE clause in the SELECT ... ASSIGN clause.

If your program contains more than one Report Description, you must qualify your SET PAGE STATUS, SET LINE and SET COLUMN statements by IN or OF report-name .  Without qualification, the statements are assumed to refer to your one and only Report Description.

Format b (SET LINE) is used for altering the value of LINE-COUNTERSET LINE TO ... sets LINE-COUNTER equal to the value given and forces the next line to appear there.  You can use the FIRST DETAIL form with the TO phrase.  SET LINE DOWN BY ... adds to LINE-COUNTER, while SET LINE UP BY ... subtracts from it.  In each case, the value that results must not be less than the FIRST DETAIL value and must not be greater than the LAST DETAIL value (or their defaults; see PAGE LIMIT Clause).  If you use SET LINE to decrease LINE-COUNTER, your report's PAGE STATUS must be HOLD.

Format c (SET COLUMN) is used for altering the value of the horizontal margin.   SET COLUMN TO ... sets it equal to the value given.  SET COLUMN RIGHT BY ... adds to it, while SET COLUMN LEFT BY ... subtracts from it.  In each case, the value that results must not be less than one and must not be greater than the LINE LIMIT, and any group produced must fit within the LINE LIMIT when the new left margin, resulting from SET COLUMN, is taken into account.

You cannot use any of these SET statements until a report is in an INITIATEd state.


SET Statements: Operation

The Page Buffer facility is designed to cope with the type of layout where you may not wish to store the groups starting at the top and working down to the bottom of the page.  Look at the following layout, for example:

          (A)                        ORDERS   1992
  +------------------+ +-------------------------------------+
  | NAME AND ADDRESS | | 20 APR  1 x GOLF 5 IRON       $180  |(B)
  | JOHNSON T.L.     | |         1 x SIZE 9 GOLF SHOES  $30  |
  | 216A EAST ST.    | +-------------------------------------+
  | NORTHWOOD        | +-------------------------------------+
  | SUSSEX           | | 18 MAY  2 x FEATHER SHUTTLES   $12  |(B)
  +------------------+ +-------------------------------------+

   Because groups A and B can be of any size, it is practically impossible to define the layout line-by-line.  The design has an attractiveness born of a revolt against slavish acceptance of the dictum that "printers cannot move backwards".  The best way to take advantage of the facility is to GENERATE report groups as their data becomes conveniently available, addressing the page in random-access fashion.  The Page Buffer facility enables you write code such as:

 
           SET PAGE STATUS TO HOLD
           GENERATE A
           SET LINE TO FIRST DETAIL
           SET COL RIGHT BY 20
           GENERATE B
           GENERATE B ...

   In fact, using this facility, you may return to any part of the page.  You may also shift a group laterally (left or right) using SET COLUMN.


SET PAGE STATUS (Format a)

   The HOLD option places your report in HOLD status.  It will stay in HOLD status until you issue a SET PAGE STATUS TO RELEASE or until the report is TERMINATEd.  When your report is in HOLD status, all the lines produced are stored in a page buffer instead of being output, giving you the opportunity to return to a previous higher position at any time.

You can issue the SET PAGE STATUS TO HOLD at any time - not just at the start of the page.  You can then return to any vertical position on or below the position where you issue this command.

You may use the SET statements in a Declarative section.  In this way you may re-position a non-DETAIL report group such as a CONTROL FOOTING, HOLD the page at the start of a PAGE HEADING, and so on.

When the report is in HOLD status, LINE-COUNTER advances as usual.  Report writer performs the page-fit test on body (DETAIL and CH/CH) groups in the normal way by checking the value of LINE-COUNTER against the size of the group about to be printed.  If the group cannot be fitted on the page, report writer will execute a page advance despite the HOLD statusNEXT GROUP NEXT PAGE and LINE NEXT PAGE work as normal.  When a page advance takes place, all the lines in the page buffer are first printed.  No data will be lost.  The new page will still have HOLD status.

HOLD status does not change any of the logical processes of report writer.  It just makes it legal for you to return to a higher line using the SET LINE statement.  HOLD status only defers the actual time when output occurs, but the end result is always the same.  For efficiency, the best time to RELEASE a page is just after the last upward SET LINE on a page.

You cancel HOLD status by means of the SET PAGE STATUS TO RELEASE statement.  The page buffer will then gradually be emptied as you write more lines, until such a time as a page advance takes place or the report is TERMINATEd.


SET LINE (Format b)

   The DOWN and UP options increase or decrease LINE-COUNTER by the amount stated.  The TO option is used to place your next group in a fixed vertical position.  For example, if your next group begins at absolute line 6 and your report has passed line 6, you may issue SET LINE TO 6.  (If you do not do this, a page advance will take place.)  Similarly, if you GENERATE groups with relative lines and wish to return to the FIRST DETAIL position that has a value of 6, then again you would issue SET LINE TO 6.  The SET LINE TO FIRST DETAIL option is available as an alternative way of stating this.

   The effect of SET LINE is cancelled by a page advance (except before the first page - SET LINE can therefore be done immediately after INITIATE).


SET COLUMN (Format c)

   This statement changes the value of your report's left margin.  If you have not issued a SET COLUMN statement, the margin will be 1.  This is the normal value, indicating that the horizontal position is not to be shifted.  The RIGHT and LEFT options increase or decrease the setting of the left margin, while the TO option sets the margin to the value you specify.  Your report does not need to be in HOLD status for you to use this statement.

If the left margin has been set greater than 1, all the lines produced for the current page will be shifted to the right by the additional factor.  For example, if you issue SET COLUMN TO 5, then "COLUMN 1" in any print line is actually positioned on column 5.

When report writer executes a page advance it resets the left hand margin to 1.  Your SET COLUMN statements are therefore effective only within the current page.


All formats

   Using the SET LINE and SET COLUMN statements, you can now re-position your group to any position on the page.  You can fill the page in any manner.  Your groups may overlap, provided that you do not overwrite a character in the page buffer with a different character.  Spaces are excluded from this rule.  Spaces behave as "cellophane", not as "white-out", so you can overwrite with a space without losing what was there before.  You can also overwrite a character with the same character.  In all other cases, the file handler will signal a run time message.

The example on the following page shows how you may set up a page in "snaking columns" and then place a border around the whole page:


                         MEMBERSHIP LIST
 ****************************************************************
 * T.J. CODER            G. ANALYST            C.S. PAGE-BREAK  *
 * 26 TONBRIDGE ST.      33 EAST DRIVE         45 BOOKHAM DRIVE *
 * MARLBOROUGH           BENBECULA             ORPINGTON        *
 * WILTS                 TEL: 0955 1234        KENT             *
 * TEL: 0313 7775                              BR7 5RF          *
 *                       R. WRITER             TEL: 0975 3124   *
 * T.W. CODASYL          300 HOPE TERRACE                       *
 * 34AB SOUTH SIDE       HITCHAM               DR. S. COBOL     *
 * BRACKNELL             TEL: 0211-686 5432    99 STAINES ST.   *
 * BERKS                                       ABINGER          *
 * TEL: 0761 2376                v             SURREY           *
 *                               v             LH5 3ED          *
 *      v                       etc.           TEL: 0655 90101  *
 *      v                                                       *
 *     etc.                                           v         *
 *                                                    v         *
 *                                                              *
 ****************************************************************

   The following coding is suitable for this problem:


       RD  MEMBERSHIP-LIST
           FIRST DETAIL 2
           PAGE LIMIT 60
           LINE LIMIT 132.
      *
       01  TYPE PH   LINE 1     COL 40     VALUE "MEMBERSHIP LIST".
      *
       01  NAME-ADDR-BLOCK  TYPE DE.
         03  LINE + 2   COL 3   PIC X(32)  SOURCE NAME.
         03  LINE + 1   COL 3   PIC X(32)  SOURCE ADDR-LINE (ADDR-LINE-NO)
             OCCURS 1 TO 7 DEPENDING ON ADDR-LINE-CNT VARYING ADDR-LINE-NO.
         03  LINE + 1   COL 3   PIC X(32)  SOURCE TEL-NO.
      *
       01  BORDER  TYPE DE.
         03  LINE 2     PIC X(132)         VALUE ALL "*".
         03  LINE +1    OCCURS 57.
           05  COL 1    VALUE "*".
           05  COL 132  VALUE "*".
         03  LINE +1    PIC X(132)         VALUE ALL "*".
      *
       PROCEDURE DIVISION.
           ...
           open all files
           INITIATE MEMBERSHIP-LIST
           SET PAGE STATUS TO HOLD
           fetch first record
           MOVE 1 TO MAJOR-COL-COUNT
           PERFORM GENERATE-GROUP UNTIL EOF = 1
           TERMINATE MEMBERSHIP-LIST
           close all files
           STOP RUN.
      *
       GENERATE-GROUP.
      *TEST WHETHER THE GROUP WILL FIT ON THE PAGE
           IF   LINE-COUNTER + ADDR-LINE-CNT > 57
                PERFORM CHANGE-MAJOR-COLUMN.
           GENERATE NAME-ADDR-BLOCK.
           (read next record or set EOF = 1 if end of file).
       CHANGE-MAJOR-COLUMN.
      *IF WE ARE ALREADY IN THE 3RD COLUMN, PRINT THE "BORDER"
      *AND ALLOW PAGE TO ADVANCE, RETURNING US TO FIRST MAJOR COLUMN
      *OTHERWISE MOVE RIGHT TO TOP OF NEXT MAJOR COLUMN
           SET LINE TO FIRST DETAIL
           IF   MAJOR-COL-COUNT = 3               * > Finish the page
                SET COLUMN TO 1
                SET PAGE STATUS TO RELEASE        *> For efficiency
                GENERATE BORDER
                SET PAGE STATUS TO HOLD
                MOVE 1 TO MAJOR-COL-COUNT
           ELSE SET COLUMN RIGHT BY 40
                ADD 1 TO MAJOR-COL-COUNT.



SUPPRESS PRINTING Statement



The SUPPRESS PRINTING statement enables you to prevent a particular report group from being output on a particular occasion.


   Format

 >>-+-
SUPPRESS PRINTING------------+-><
    +-
MOVE integer TO PRINT-SWITCH -+

SUPPRESS PRINTING Statement: Coding Rules

The SUPPRESS statement may be coded only in a USE BEFORE REPORTING Declarative SECTION.

The form MOVE 1 TO PRINT-SWITCH is an alternative IBM extension that means the same as SUPPRESS PRINTING.  You may also write MOVE 0 TO PRINT-SWITCH to undo the effect of a MOVE 1 TO PRINT-SWITCH or SUPPRESS PRINTING, and generally treat PRINT-SWITCH as a numeric location, implicitly defined in your program.


SUPPRESS PRINTING Statement: Operation

The statement SUPPRESS PRINTING or MOVE 1 TO PRINT-SWITCH prevents the group specified in the USE BEFORE REPORTING from producing any output on this occasion.  In other words, no data is set up in any of the lines of the group and none of the lines is produced.  LINE-COUNTER is also left unaltered, so suppressing a body group will prevent a page advance.  This statement suppresses only the storing of report data and the output of the report lines.  It does not prevent other processing, such as the accumulation and clearing of totals and the setting and testing of CONTROL fields.  In this respect, it is different from a PRESENT WHEN clause at the 01-level which does prevent all other processing.

For example, you may use SUPPRESS PRINTING to "restart" your report after a breakdown.  Simply write a USE BEFORE REPORTING section for every group and SUPPRESS each group until your program clears a flag.  Your report will now be in the same internal state as when output really took place.

Each execution of a SUPPRESS PRINTING or MOVE 1 TO PRINT-SWITCH will prevent output only on that single occasion.  Report writer will reset PRINT-SWITCH to zero after each excursion into your USE BEFORE REPORTING section.

In USE BEFORE REPORTING there are further examples of SUPPRESS PRINTING.




TERMINATE Statement



The TERMINATE must be the last report writer statement to be executed for each report.


   Format
                +---------+
                v         |
 >>--
TERMINATE--report-name--><


TERMINATE Statement: Coding Rules

Each report-name must be the name of a report in the current program, or that of a GLOBAL report defined in a containing program.  (The report-name appears immediately after the RD level-indicator and also in the REPORT clause in the corresponding FD.)


TERMINATE Statement: Operation

TERMINATE must be executed for every report that has been INITIATEd before the final close-down of the program.

The TERMINATE statement clears any pending REPEATED groups or Page Buffer contents.  It also outputs any final CONTROL FOOTING, PAGE FOOTING and REPORT FOOTING groups that may be required at the end of the report.  It then returns the report to an "uninitiated" state.  PAGE-COUNTER and LINE-COUNTER will contain the final values they attained at the end of the report, but total fields will be zero (except under erroneous circumstances - see the end of  (3c) SUM Clause).

A separate, subsequent CLOSE should be executed for the associated report file.  TERMINATE does not CLOSE the file.

If a TERMINATE is executed without any GENERATE statements being executed for the report since the INITIATE was executed, no output at all is produced.  If you wish to ensure that at least the REPORT HEADING and REPORT FOOTING groups appear, you should in this case GENERATE a blank DETAIL group before the TERMINATE.

A report may be TERMINATEd and then INITIATEd again any number of times without closing the report file.  The new INITIATE causes PAGE-COUNTER to return to 1 and, if the report has a PAGE LIMIT clause, will re-commence the report on a fresh page.


TERMINATE Processing Cycle

The following is a more thorough description of each stage in the execution of a TERMINATE statement:

If your report is DUPLICATED and REPORT-NUMBER is zero, the actions that follow are performed for each duplicate report.

If at least one GENERATE has been performed (indicated by the control break indicator being non-negative), the value of each control-id is temporarily altered to the value it had when the last GENERATE was executed, whilst each CONTROL FOOTING group is produced, from lowest to highest.

If any REPEATED groups are present, any buffered groups are output and the REPEATED buffer is flushed.  Also, if the Page Buffer contains any data, this is output.

If a PAGE FOOTING group is present, it is produced.

If a REPORT FOOTING group is present, it is produced.

If your report is associated with an Independent Report File Handler, the file handler is invoked with an action code of 8.  (If your report is DUPLICATED, this will only take place for reports that have been INITIATEd.)

The current vertical position location is set to -1 to indicate "report not initiated".

If any total fields are still non-zero, indicating that they have not all been output, an error diagnostic 15 is signalled.

If normal batch printing is in effect, a check is made of the error diagnostic flag and an appropriate run time error message is logged if necessary.




USE BEFORE REPORTING Directive



The USE BEFORE REPORTING directive causes a SECTION in the DECLARATIVES of your PROCEDURE DIVISION to be performed automatically just before a selected specified report group is produced.


   Format

 >>--
PROCEDURE DIVISION -+-----------------+-. -->
                        |       +-------+ |
                        |       v       | |
                        +-
USING data-name-+
                  +-----------------+
                  v                 |
 >-
DECLARATIVES. -declarative-section- END DECLARATIVES . --><

  where declarative-section is defined as:

 

 >>--section-name
SECTION-+----------------+-. -->
                          +-segment-number-+

 >--
USE-+--------+-BEFORE REPORTING report-group-name. -->
        +-
GLOBAL-+
    +---------------------------+
    v                           |
 >--paragraph-name. -+----------+-><
                     | +------+ |
                     | v      | |
                     +-sentence-+


USE BEFORE REPORTING Directive: Coding Rules

The format above shows the PROCEDURE DIVISION and DECLARATIVES headers for the sake of completeness.  They are used not just by report writer, and your program might already have Declarative sections for some other purpose.  It is the distinctive format of the USE BEFORE REPORTING directive that tells report writer that the section is part of its responsibility.  If you also have other Declarative sections, they may be intermixed with your USE BEFORE REPORTING sections in any order.

In order to code a USE BEFORE REPORTING section, you must ensure that the corresponding group has an 01-level data-name, so that you can refer to it as the report-group-name.

Your USE BEFORE REPORTING section may also PERFORM other sections.  These are normally additional sections within the DECLARATIVES portion (as required by all ANS Standards).  For this purpose, you may code additional sections within DECLARATIVES that have no USE statement.  Report writer also allows your USE BEFORE REPORTING section to PERFORM sections in your mainline PROCEDURE DIVISION.

   The example that follows shows how you may code one section to be performed when one of two report groups is about to be produced:

 
       01  BRANCH-HDDR   TYPE CH FOR BRANCH-CODE.
           ...
       01  DEPT-HDDR    TYPE CH FOR DEPT-CODE.
           ...
       PROCEDURE DIVISION.
       DECLARATIVES.

       CHANGE-BRANCH SECTION.
           USE BEFORE REPORTING BRANCH-HDDR.
       CHB-000.
           PERFORM CHANGE-BRANCH-DEPT.

       CHANGE-DEPT SECTION.
           USE BEFORE REPORTING DEPT-HDDR.
       CHD-000.
           PERFORM CHANGE-BRANCH-DEPT.

       CHANGE-BRANCH-DEPT SECTION.
       CBD-000.
           ... (common code) ...
       END DECLARATIVES.


Your USE BEFORE REPORTING section must not contain any INITIATE, GENERATE, or TERMINATE statements.  Neither may any of the sections it may perform.

If you specify GLOBAL, the named report group must exist either in the current program or in a contained program.


USE BEFORE REPORTING Directive: Operation

If any of your report groups has a USE BEFORE REPORTING section, report writer will implicitly PERFORM the section during the processing of the group.  Assuming that your report has every possible feature, the section will be implicitly performed:

   After the testing of control breaks and the production of any CONTROL FOOTING and CONTROL HEADING groups (if your group is a DETAIL);

   After the computation of your group's cross-foot totals (if any), so your USE BEFORE REPORTING section can reference them;

   If OSVS is in effect, after the rolling forward into your totals and subtotalling associated with your group;

   If NOOSVS is in effect, before the rolling forward into your totals and subtotalling associated with your group, so your USE BEFORE REPORTING section can alter values that are due to be added into other groups' totals;

   Before the moving of any CODE identifier, so your USE BEFORE REPORTING section can change the originating identifier;

   Before the page-fit test and the production of any PAGE FOOTING and PAGE HEADING groups (if your group is a body group), so you may alter the originating fields due to be moved into them, or suppress them along with the body group itself.

   Before any of the SOURCE, SUM, or FUNCTION fields are set up in the lines of your group, so you may change any of the originating fields due to be displayed in your group.

You may include the statement  SUPPRESS PRINTING or MOVE 1 TO PRINT-SWITCH in a USE BEFORE REPORTING Declarative, in order to prevent output for the group at that instant (see 4.5).

USE BEFORE REPORTING sections were used a great deal in the ANS-68 and ANS-74 COBOL report writer.  So you may possess migrated programs that contain cases of their use.  With report writer much of their functions are now performed by the PRESENT WHEN and PRESENT AFTER clauses.  However, they can still be of considerable use.  For example:

You could use your Declarative section to WRITE additional records to another file, using the automatic control break processing to "drive" the rest of your program.

You might use the USE BEFORE REPORTING section for a CONTROL HEADING group to READ an additional record at the start of each new CONTROL value, or fetch it from your database.

You might need to suppress the printing of certain totals without preventing them from being reset to zero.  (The PRESENT clause will prevent the resetting of a total field if it was not output.)

You might want to force a CONTROL HEADING group to start on a new page under certain complex circumstances.  Your USE BEFORE REPORTING section would then force page advance processing thus:

           IF   complex-condition
                MOVE last-detail-value TO LINE-COUNTER.

You might want to search a table for a corresponding text field at the start of each CONTROL HEADING group, and move it to a WORKING-STORAGE field that is the operand of a SOURCE in a PAGE HEADING or the CONTROL HEADING itself.  (If your group is a DETAIL, it will be clearer to do this in the main-line program.)

There may be an item associated with a control which is not itself a control (such as a STATE-NAME logically associated with a STATE-NO control) which you will want to output during CONTROL FOOTING time.  Since the item is not a control you will not automatically obtain the before-the-break value.  You could code a Declarative section for the corresponding CONTROL HEADING group.  This would save the current value of the field in a WORKING-STORAGE location which is then used instead of the input item in all SOURCE clauses in PAGE HEADING, PAGE FOOTING and CONTROL FOOTING groups.

   If you have no CONTROL HEADING group, you may code one as a "dummy" (see 3.2) with no LINE clauses, in order to take advantage of report writer's automatic control break checking, as suggested in the following example:

 
RD  ...            CONTROL IS IN-STATE-NO.
01  NEW-STATE      CH FOR IN-STATE-NO.
01  CF FOR IN-STATE-NO.
    ...
    05  COL ...    SOURCE IS WS-STATE-NAME.
01  PH.
  ...
    05  COL ...    SOURCE IS WS-STATE-NAME.
DECLARATIVES.
SAVE-CURRENT-STATE SECTION.
    USE BEFORE REPORTING NEW-STATE.
SAVE-000.
    MOVE IN-STATE-NAME TO WS-STATE-NAME.
END DECLARATIVES.

You may find it desirable to suppress printing of a minor CONTROL FOOTING if only one DETAIL is printed above it, since a "total" of a single value will seem out of place.  Here is one way to do it:

 
01  DETAIL-ENTRY  DETAIL.
   03  LINE + 1.
     05  ... .
 ...
 01  MINOR-CF      CONTROL FOOTING FOR STATE-NO.
   03  LINE + 2.
     05  ... .
     05  R-DETAIL-COUNT  PIC 999  COUNT OF DETAIL-ENTRY.
 ...
 DECLARATIVES.
 ZAP-CF-SECTION SECTION.
     USE BEFORE REPORTING MINOR-CF.
 ZAP-CF-000.
     IF   R-DETAIL-COUNT = 1 SUPPRESS PRINTING.
 END DECLARATIVES.

    Do not instead code an ABSENT WHEN clause at the 01-level of the CONTROL FOOTING group, as this would have the undesirable side-effect of preventing the resetting and rolling forward of any SUM fields that you might have defined in the CONTROL FOOTING group.

If you specify GLOBAL, your Declarative section will apply both to the current program, if it contains a report group of that name, and also to any contained program that has a report group of that name but no USE BEFORE REPORTING section of its own for that name.  If a contained program also has a USE GLOBAL BEFORE REPORTING section for the same report-group-name, this overrides the effect of original section until the end of the contained program.