Report Group Descriptions


Introducing Report Groups
What is a Report Group?
Report Groups: Keyword Table
Coding Report Group Descriptions
Report Groups: Coding Rules
BLANK WHEN ZERO Clause: Coding Rules
BLANK WHEN ZERO Clause: Operation
COLUMN Clause: Coding Rules
COLUMN Clause: Operation
Multiple COLUMNS Clause
COUNT Clause
COUNT Clause: Coding Rules
COUNT Clause: Operation
FUNCTION Clause: Coding Rules
FUNCTION Clause: Operation
Built-In Functions
GROUP LIMIT Clause: Coding Rules
GROUP LIMIT Clause: Operation
JUSTIFIED Clause: Coding Rules
JUSTIFIED Clause: Operation
LINE Clause
LINE Clause: Coding Rules
LINE Clause: Operation
Multiple LINES Clause
MULTIPLE PAGE Clause: Coding Rules
MULTIPLE PAGE Clause: Operation
NEXT GROUP Clause: Coding Rules
Effect of NEXT GROUP on Body Groups
Effect of NEXT GROUP on Non-Body Groups
OCCURS Clause and Related Phrases
OCCURS Clause: Coding Rules
OCCURS Clause: Operation
PICTURE Clause: Coding Rules
PICTURE Clause: Operation
Variable-Length Fields ("<" and ">" Symbols)
PRESENT/ABSENT WHEN Clause: Coding Rules
The Multiple-Choice Form
REPEATED Clause: Coding Rules
REPEATED Clause: Operation
SIGN Clause
SIGN Clause: Coding Rules
SIGN Clause: Operation
SOURCE Clause: Coding Rules
SOURCE Clause: Operation
Multiple SOURCES
STYLE Clause
STYLE Clause: Coding Rules
STYLE Clause: Operation
SUM Clause
SUM Clause: Coding Rules
SUM Clause: Operation
Use of Total Fields
Subtotalling and SOURCE SUM Correlation
Three Methods of Subtotalling
RESET Phrase
TYPE Clause
TYPE Clause: Coding Rules
TYPE Clause: Operation
USAGE Clause
USAGE Clause: Coding Rules
USAGE Clause: Operation
VALUE Clause
VALUE Clause: Coding Rules
VALUE Clause: Operation
Multiple VALUES
VARYING Clause: Coding Rules
VARYING Clause: Operation
WRAP Clause
WRAP Clause: Coding Rules
WRAP Clause: Operation

This part describes in detail every aspect of the Report Group Descriptions that follow your RD entry in the REPORT SECTION.  After the next section, the sections are in alphabetical order for easy reference.

Introducing Report Groups

What is a Report Group?

report group is an uninterrupted block of report lines, from zero up to any number.  With the exception of MULTIPLE PAGE groups (see MULTIPLE PAGE clause), the lines in a report group are always together on the same page and are generated in a single operation.  Of the seven TYPEs, all but the DETAIL groups are produced automatically.  Your program issues GENERATE statements for the DETAIL groups (or for the report as a whole), and any other groups that you have defined are automatically generated in the correct positions relative to the DETAILS, depending on their TYPE.

Your RD entry may be followed by any number of Report Group Descriptions, but there is a limit to the number each TYPE other than DETAIL.  Each Report Group Description begins with a 01 level-number entry in the A-margin.

More information about report groups follows or may be found later in this part (see TYPE Clause).

Report Groups: Keyword Table

The following table lists the major report writer keywords that may appear in a Report Group Description, 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.  The clauses may be found, listed in alphabetical order by keyword, following this section.

   Report Groups: Keyword Table



 Extensions to standard       
 only ...)

 Indicates whether
 group is produced
 explicitly (DE)

 » TYPE keyword optional
 » optional FOR/ON with CH/CF
 » CH FOR control OR PAGE form

 Provides extra
 vertical space
 between groups

 » PLUS can be written +
 » optional words BODY and
 » optional ON before NEXT PAGE
 Gives lowest per-
 missible position
 for body group

 Allows a group
 to span several


 Repeats body
 groups side-by-
 side across page

 at all

 Specifies vertical


 » PLUS can be written +
 » multiple form
 » LINE alone = LINE PLUS 1
 » LINE without subordinate
   COLUMNs gives blank line
 » absolute may follow relative
   if group starts with absolute
 » RH/RF or body groups may
   occupy several pages
 Indicates repeat-
 ing item


 Defines internal
 counter for use
 as subscript, etc.

 Gives condition
 for printing or
 skipping item

 Specifies intern-
 al condition for

 Simple form of
 » may be used at group level
 Causes zero value
 to be spaces
 » allowed at group level

 Changes alignment
 rules for alpha-
 numeric fields

 » allowed at group level


 Changes output
 convention for
 "S" PICTURE symbol

   literal format for user-
   specified "signs"

 Allows data to
 "wrap round" onto
 continuation lines

 Invokes a special
 printer property

 USAGE Documentary   yes » DISPLAY-1 for DBCS items
 ary level
 only ...)
 Specifies horiz-
 ontal position


 » may be shortened to COL
 » relative form (+ or PLUS)
 » CENTER and RIGHT options
 » multiple format
 » allowed alone as dummy entry

 Gives format in
 which field is to
 be presented

 » left-shift symbols <...> for
   variable left alignment
 » optional when VALUE "literal"
 » general insertion characters

 Specifies field
 whose contents
 are to appear
 in report item


 » SOURCE keyword optional
 » arithmetic-expression format
 » ROUNDED phrase
 » SUM or COUNT term may be
   used as operand
 » multiple format
 » multiple-choice format

 Specifies fixed
 value for report

 » VALUE keyword optional
 » multiple format
 » assumes default PICTURE

 Specifies run time
 routine to provide
 contents of item


 Indicates total-
 ling of specified


 » optional word OF after SUM
 » arithmetic-expression format
 » may be used as term in
   SOURCE expression
 » allowed in non-CF groups
 » may refer to SOURCE/VALUE
 » ROUNDED phrase
 » ANS-68 method (SOURCE SUM
   correlation) available
 » automatic check for overflow
 » > 1 SUM clause in entry ok
 Counts appearances
 of item(s)

 Special registers
 for page number &
 vertical position

 » adding to LINE-COUNTER
   creates gap on page
 Special register
 for horizontal

Coding Report Group Descriptions

Report Group Description is a REPORT SECTION data structure beginning with an 01-level entry and including any number of lower entries.  It may consist of the 01-level report group entry only.  You may code any number of Report Group Descriptions after your RD entry.

     v                |

where report-group-entry is defined as follows:


                  +-data-name-+ +-
TYPE clause-+

NEXT GROUP clause++GROUP LIMIT clause++REPEATED clause+

LINE clause-+ +-COLUMN clause-+ +-PICTURE clause-+

SOURCE clause---------------------++---------+-+ |
VALUE clause----------------------++- ROUNDED-+   |
    | +--------------+                  |              |
    | v              |                  |              |
SUM clause---+-+--------------+-+              |
    | +-
COUNT clause-+ +- RESET phrase-+                |
FUNCTION clause----------------------------------+

GROUP INDICATE clause-----------+
  +-multiple-choice (see below)-----+

WRAP clause++-+----+- MULTIPLE PAGE clause-+
NO-+               +-NO-+

OCCURS clause-+ +-VARYING clause-+ +-SIGN clause-+

BLANK WHEN ZERO clause++JUSTIFIED clause++ USAGE clause+

>-+------------------+-. -->
STYLE clause-----+

where multiple-choice is defined as follows:


   v                                         |
SOURCE clause--+-+-PRESENT AFTER clause-+-------><
VALUE clause---+ +-PRESENT WHEN clause--+
FUNCTION clause+

Report Groups: Coding Rules

Level-numbers are used, as in any DATA DIVISION record, to establish a hierarchy of group levels above the elementary level.  The level-number at the start of each report group must be 01.  (It may be written without the leading 0, but we shall still refer to it as the 01-level.)  Choose your lower level-numbers exactly as you would for any other COBOL logical record.

You need not place data-names on your report group entries except in the following cases, where they are required:

On the 01-level entry of a DETAIL group, or any other group that may be referred to in the USE BEFORE REPORTING header of a Declarative SECTION (see USE BEFORE REPORTING Directive ).  When a data-name is used at the 01-level, it gives a name to the entire report group and is called the report-group-name or group-name.  The group-name must be unique within an RD, but you may re-use the name in another RD.

On a numeric entry referred to in a SUM clause or term.  (See SUM Clause.)

On any entry at any level that is referred to in a COUNT clause or term.  (See COUNT Clause.)

   In all other cases it is preferable to omit data-names since an unnecessary data-name may mislead the program-reader into thinking that it is referred to in one of the ways above.  It may also impede the precompiler's optimization.

The following general-purpose DATA DIVISION clauses can be used in a report group.  The first four may be used at both group and elementary levels (not the 01 -level in the case of OCCURS).  PICTURE and VALUE are allowed only at the elementary level.


   but the following cannot be used in a report group:

   any USAGE other than DISPLAY, such as:

    88-level entries

   In addition to the general DATA DIVISION clauses, report groups may contain special-purpose clauses that describe the position and contents of fields.  The first four clauses, TYPE, NEXT GROUP, GROUP LIMIT, and REPEATED, can appear only at the 01-level.  The special-purpose clauses are:

 indicates the type of group
 creates extra space between groups
 gives a special lower limit for the group
 places groups side-by-side
 gives the vertical position
 enables a report group to span several pages
 gives the horizontal position
 used to capture a data field by name
 used to produce a total
 used to produce a count
 invokes a special formatting routine
 allows data to continue on a new line
 provides counters for a repeating entry
 produces special printer effects
 controls whether or not an item, line
    or group is output
 an older form of PRESENT AFTER

The clauses PICTURE, COLUMN, SOURCE, VALUE, SUM, COUNT, and FUNCTION can appear only at the elementary level.

For every entry with a COLUMN clause, there must be a LINE clause either at the same level as or at a higher level.  If a given report line contains only one elementary field (and provided the entry is not a multiple-choice entry, see PRESENT WHEN Clause), you may combine the LINE and the COLUMN clauses in the same entry, for instance:

          03  LINE 5  COL 60   VALUE "QUARTERLY REPORT".

   There is no limit to the number of elementary fields a report line may contain.  If the report line contains several elementary fields, you must code all the COLUMN entries within the line at a lower level than the LINE entry, for example:

        03  LINE 5.
          05  COL 60     VALUE "QUARTERLY REPORT".
          05  COL 90     VALUE "1997".

   Not all the COLUMN clauses within a LINE need be at the same level, since some or all elementary entries might be contained within non-LINE group entries; for example:

        03  LINE 5.
          05  COL 60     VALUE "QUARTERLY REPORT".
            07  COL 90   VALUE "YEAR:".
            07  COL +2   PIC X(4)   SOURCE YEAR.

LINE clause must not be subordinate to another LINE clause.  (If this rule is violated, the nested LINE entries will be treated as though they were defined at the same level as the first.)

If a given report group contains several lines, you must give all the LINE entries in that group a level-number other than 01.  If the group contains only a single report line, you may code the LINE clause in the 01-level entry; for instance:

      01  ORDER-LINE  TYPE DE  LINE + 1.
          05 ...

You may choose only one of five clauses: SOURCE, VALUE, SUM, COUNT, and FUNCTION to supply the contents of an elementary item automatically, bearing in mind that (a) SOURCE or VALUE can be repeated several times in a multiple-choice entry (see Multiple-Choice Form), and (b) SUM (see SUM Clause) or COUNT (see COUNT Clause) can be used as special operators in terms in an arithmetic expression (see SOURCE Clause).

If there is no SOURCE, VALUE, SUM/COUNT, or FUNCTION clause in an elementary item, the following conditions must be met:

The entry must have a data-name (following the level-number).

The entry must have a COLUMN clause.

If the COLUMN clause is relative, the item must have a fixed horizontal position (that is, it must follow an item with a fixed end-column, unless it is first in the line).

The item must have a PICTURE with none of the features that are unique to the REPORT SECTION (that is, "<" or ">" symbols or general insertion characters).  Report writer will then expect you to fill in the report field independently with some COBOL procedural statement.

   As an example, in the following case

          05  R-PRIOR-CUST-NO     COL 20     PIC 9(7).

   the only way this item can receive a value is through a COBOL MOVE, ADD, ACCEPT, or other procedural statement, which is outside the scope of report writer and is left to you.  Report writer will ensure that the report field is not overwritten by any other field, so any value stored in the item R-PRIOR-CUST-NO will remain there and will appear whenever the enclosing group is produced.

   Note that you should not attempt to change the value of a group field, such as a report line, in this way.

You may code the clauses of any report group entry in any order, except in the case of a  multiple-choice entry, where each SOURCE, VALUE, or FUNCTION operand is immediately followed by WHEN condition.  Details of this combination are given later (see 3.18).

However, you may code the SUM clause more than once in the same entry.  You may also code a SOURCE, VALUE, or FUNCTION clause and its associated PRESENT/ABSENT WHEN/AFTER clause more than once in a multiple-choice entry.  All other clauses may appear no more than once in an entry.


This causes a field with zero contents to be blanked out.


BLANK+------+-ZERO --><

BLANK WHEN ZERO Clause: Coding Rules

If you code BLANK WHEN ZERO in an elementary entry, the entry must have a numeric PICTURE.  If you code it in a group level entry, it applies to all the numeric elementary entries within the group.  (This clause is usually referred to as the BLANK WHEN ZERO clause, even though the word WHEN is optional.)

BLANK WHEN ZERO Clause: Operation

BLANK WHEN ZERO causes a numeric field to be replaced entirely by spaces if its value is zero.  For example:

 1,009.50     19.27     20.90              160.00

         05  COL 1     PIC Z,ZZZ.99    BLANK WHEN ZERO
                       OCCURS 4 STEP 10 VARYING RW-X   SOURCE WS-VAL (RW-X).

You may use BLANK WHEN ZERO even if your field is not in a fixed position.  It is also permitted with a variable-length field (PICTURE symbol "<"), in which case a zero value in a variable part has a length of zero.


The COLUMN clause specifies the horizontal positioning of a field in the report line.


    | +-
COL----+ +-NUMBER--+ | +- LEFT---+ +-IS--+
    |            +-NUMBERS-+ | +-
COLUMNS--------------+ +- CENTRE-+
COLS-----------------+ +- RIGHT--+
      v                    |
      | +- + --+           |

COLUMN Clause: Coding Rules

COLUMN with no operands is shorthand for COLUMN + 1.

For every entry with a COLUMN clause, there must be a LINE clause at the same or a higher level.  So you may write:

          05  LINE 5   COL 20     VALUE "TITLE PAGE".

   provided that there are no other entries within LINE 5.  If the line has two or more fields, you must then create a new level, as with:

          05  LINE 6.
            07   COL 5    VALUE "REPORT XYZ".
            07   COL 72   VALUE "ANNUAL RETURNS".

   If you code a COLUMN entry at the same level as the preceding LINE:

           05  LINE 6  COL 5    VALUE "REPORT XYZ".
           05          COL 72   VALUE "ANNUAL RETURNS".

   then report writer will diagnose this as invalid but will allow it as stated.

COLUMN may be the only clause in an entry.  The result is a blank field whose only purpose is to shift the current horizontal position (COLUMN-COUNTER ) to the right.  A blank field (absolute or relative) occupies one column's width in addition to the usual spacing for the COLUMN.  It is therefore equivalent to coding a VALUE consisting of a single space alongside the COLUMN clause (although doing so would be less efficient).  For example, COL + 4 coded alone in an entry shifts the current horizontal position four (not three) columns right.  (See the discussion in the next section).

The size of your item is calculated from the PICTURE clause or the size of the VALUE "literal", and is used in combination with your COLUMN clause to check that: (a) the line width is not exceeded (see LINE LIMIT Clause and, if you are using automatic line wrap, see WRAP Clause), and (b) no two items overlap (unless they both carry a PRESENT WHEN/AFTER clause).  If two or more items overlap in whole or in part, report writer will diagnose this as invalid but will allow the COLUMN positions and field sizes as coded.  The later-coded entry will then overwrite the earlier-coded entry at run time by the number of overlapping columns and data will be lost.  No run time error occurs.

Within each LINE, any absolute COLUMN numbers should be in ascending order, after the evaluation of all  PRESENT WHEN and PRESENT AFTER clauses (see 3.17 and 3.18).  If this rule is broken, report writer will diagnose this with a Warning (message 250) but will allow the COLUMN positions as coded.

The RIGHT and CENTER phrases cannot be coded with the + (relative) form of this clause.

You may write "+" with or without a space on either side.

COLUMN Clause: Operation

The COLUMN clause positions your elementary field horizontally.  Here is a list of the options:

COLUMN + integer-1.  This is the relative form.  It indicates that the horizontal position within the line is to be moved integer column positions from the last character of the preceding field to the first character of this field.  Note that the "gap" before the field will be one less than the value of the integer.  For example:

            COLUMN + 1 = "no gap"
            COLUMN + 2 = "one space before field", and so on.

   If you use COLUMN + integer in the first field of a line, it is treated as though you had written the absolute form, COLUMN integer-1, since the initial value of the horizontal position is zero.

COLUMN integer-2.  This is the absolute form.  It indicates that the left-hand column of the field must appear on that fixed position within the line.  Remember that the first column in the line is COLUMN 1LINE LIMIT is the highest possible value of integer.

COLUMNS integer-1 integer-2 ...  This is the multiple form of the clause.  It reduces your coding effort by including several operands in the same clause.  The relative multiple form, COLUMNS + integer, + integer ..., is also allowed and you may combine both forms in the same clause. Multiple COLUMNS are described in more detail below (see 3.4.4).

COLUMN RIGHT and COLUMN CENTER are used if you wish to specify the right-hand or center position of the field as alternative anchoring points, to save you the effort of "counting out" the length of the field to establish its left-hand column when you already know its center point or right-hand column.  COLUMN LEFT, the normal alignment, is provided for syntactic completeness.

   If you specify COLUMN CENTER and the field is an even number of column positions wide, the extra character position goes to the right of the central column.  The following example shows the allowable alternatives for a six-character field starting in column 1:

column 1
column center 3
column right 6

   You will get a ragged left-hand side in the case of COLUMN RIGHT and centralization with ragged left and right , in the case of COLUMN CENTER.  By successively generating the following entry on different lines with different values

               05  COL RIGHT 15  PIC 9<9(6)  SOURCE POPULATION-COUNT.

   you will obtain
               ^ column right 15

   The following, generated several times with a different CITY:

           05  COL CENTER 20
                               "LONDON"             WHEN CITY = "L"
                               "BATH"               WHEN CITY = "B"
                               "GLASGOW"            WHEN CITY = "G"
                               "KINGSTON UPON HULL" WHEN CITY = "H".

   gives you, for example,

                  LOND ON
                    ^ column 20

   Note that RIGHT and CENTER may also be used with the multiple format of the COLUMN clause discussed below (see 3.4.4).

   The CENTER or RIGHT option is required if you need to center or right-align a variable-length field - (see "<" and ">" symbols) for full details.  The output in the box above could also have been produced using a SOURCE item thus:

           05  COL CENTER 20   PIC <X(20)  SOURCE CITY-NAME.

If an elementary item has no COLUMN clause then, if the OSVS precompiler option is in effect or a data-name is present, the item will not appear in the report.  It is then termed an unprintable item.  Unprintable items are used chiefly for summing in the following cases:

For  SOURCE SUM correlation (see 3.23.5).  A SOURCE clause may be written as an unprintable item because a SUM of a certain data item is required but its individual values are not:

          05  PIC 9(6)   SOURCE IS WS-PAY.     *> unprintable
      01  TYPE CF ...
        03  LINE ...
          05  COL 22     PIC Z(6)9  SUM WS-PAY.

For rolling forward of certain values into totals.  This is report writer principal way of forming totals.  This time the unprintable item has a data-name and the data-name is summed:

          05  R-PAY      PIC 9(6)   SOURCE IS WS-PAY.
      01  TYPE CF ...
        03  LINE ...
          05  COL 22     PIC Z(6)9  SUM OF R-PAY.

For forming totals that are not printed directly but used indirectly:

      01  TYPE CF ...
          05  R-PAY      PIC 9(7)   SUM OF WS-PAY.
          05  R-TAX      PIC 9(7)   SUM OF WS-TAX.
          05  COL 22     PIC Z(6)9  SOURCE R-PAY - R-TAX.

   Further examples may be found in SUM Clause.

If the precompiler option is not in effect, and any elementary entry beneath the LINE level has no COLUMN clause, then COLUMN + 1 is assumed for the entry, provided that the level-number is not followed by a data-name.  Thus, you could omit both COLUMN clauses in the following fragment:

           05  LINE 1.
             07  COL 1    VALUE "REPORT ".
             07  COL 8    PIC XXX   SOURCE REPORT-IDENT.

Multiple COLUMNS Clause

You may use the multiple form of the COLUMN clause by placing several integer or + integer terms after the keyword.  This reduces the effort needed to code several adjacent entries that have a similar format.  Note the following points:

A multiple COLUMNS clause is functionally equivalent to an ordinary COLUMN clause used in conjunction with an  OCCURS clause (see 3.14); for example:

You may use VARYING to vary a counter that is used as a subscript in a SOURCE clause.

You may use a simple (single-operand) VALUE, SOURCE, SUM, or FUNCTION clause to place the same value repeatedly in each instance of the field.

You may use a multiple VALUE or SOURCE clause to place a different value in each instance of the field.

You may place a data-name at the start of the entry and SUM the data-name in another entry to produce a total of the instances or occurrences collectively or individually.  (To form individual totals, there must be another multiple or occurring COLUMN clause in the entry with the SUM clause.)

Unlike the method of repetition using the OCCURS clause, the intervals between the entries defined by a multiple COLUMNS clause need not be regular.

Your multiple COLUMNS clause will be syntactically correct if it would be correct when written as a series of separate COLUMN entries.

Here are some examples of the multiple COLUMNS clause:

    *This places the literal in all 3 column positions:
         05  COLS 9 21 36   VALUE "-------".

    *This gives you WVAL (1) WVAL (2) and WVAL (3) in the 3
    *right-hand positions:
         05  COLUMNS RIGHT 21 31 42   PIC ZZZZ9
             VARYING R-SUB      SOURCE WVAL (R-SUB).

    *This illustrates the combining of absolute and relative positions:
         05  COLUMN NUMBERS ARE 6 +3 +3 ...

The following diagram and corresponding code illustrates the usefulness of the multiple COLUMNS clause:


  NORTH    $1,420,000      $600,000      $150,500    $2,170,500
  EAST     $2,100,000      $850,000      $220,000    $3,170,000

       01  TYPE PH.
         03  LINE 2  COLS RIGHT 4 19 33 47 62   VALUES
                     "AREA" "BASIC PAY" "OVERTIME" "COMMISSION" "TOTAL    ".
         03  LINE 4  OCCURS 4         STEP 1      VARYING AREA-NO.
           05        COL 1            "NORTH" "EAST" "SOUTH" "WEST".
           05  R-PAY COLS RIGHT 19 33 47  PIC $$$,$$$,$$9    SOURCES
                     BASIC-PAY  OVERTIME  TAX.
           05        COL RIGHT 62         PIC $,$$$,$$$,$$9  SUM OF R-PAY.


COLUMN-COUNTER is a special register that, at any given instant, contains the value of the rightmost column number of the most recently processed report field.




COLUMN-COUNTER indicates the current horizontal position within a line.  At each stage during the processing of a line, it contains the most recent rightmost column number on which data was placed in the line.  It may also be incremented by an "empty" (unprintable) entry containing only a COLUMN clause.  Regardless of the number of reports and report lines it contains, each program has just one COLUMN-COUNTER.

Report writer uses COLUMN-COUNTER as a place-keeper and internal subscript while assembling variable-length or variable-position fields in a report line.  For the sake of efficiency, it does not initialize or update COLUMN-COUNTER in a report line consisting of fixed-length, fixed-position fields, unless you explicitly refer to it in an item in the line.

You may use COLUMN-COUNTER in the condition of a  PRESENT WHEN clause (see 3.18), or as the operand of a  SOURCE clause (see 3.21), or as a parameter to a FUNCTION (see 3.7).  It cannot be used in your PROCEDURE DIVISION, because the generating of each line is an indivisible operation.

COLUMN-COUNTER may be used to simplify the conditions that would otherwise be required to string together a series of conditional fields:

      05  COL 30.
      05  COL + 1  "A"    PRESENT WHEN A-FLAG = "Y".
      05  PRESENT WHEN B-FLAG = "Y".
        07  COL + 1  ","  PRESENT WHEN COLUMN-COUNTER > 30.
        07  COL + 1  "B".

If your current group is a  REPEATED group (see 3.19), or if you use the SET COLUMN statement of the Page Buffer feature (see SET Statements), you should bear in mind that COLUMN-COUNTER is relative to the left-hand boundary of the group.  So it does not include the extra left-hand margin used to offset your REPEATED groups or the extra margin you create with SET COLUMN.

COLUMN-COUNTER should not be used in a condition where the field is to be totalled using the SUM clause, because COLUMN-COUNTER is not updated when totalling is performed at the start of processing for the group.

COUNT Clause

The COUNT clause counts the number of appearances of any specified report field or group item.


     |          +----------------------+ |
     v          v                      | |
RESET-+--+-control-id-+ +- ROUNDED-+

COUNT Clause: Coding Rules

Each data-name must be the name of any REPORT SECTION entry other than an RD.  It may even be the data-name of a group entry that contains the COUNT clause.

You may place the COUNT clause in a different report group from the item counted (rolling forward) or in the same group (cross-footing).  As with the SUM clause, if the COUNT clause appears in a multiple CONTROL FOOTING, all but the lowest level total is formed by rolling forward the next-lower total.

Unlike the situation with the SUM clause, the item counted need not be a numeric field.

Like the SUM clause, you may use the COUNT clause in two ways:

As a clause in its own right.  You write the clause in place of a SOURCE, VALUE, or FUNCTION clause.  For example:


As a term in an expression used as a SOURCE operand; for example:


You may combine SUM and COUNT terms in the same expression.  For example, the following will give you the average value of all the instances of a numeric field:

     05  COL 32  PIC ZZZZ9

COUNT Clause: Operation

This clause gives a count of the number of times the item referenced has appeared.  In other words, whenever the item appears in the Report, 1 is added to the count.  You cannot count items that are outside the REPORT SECTION, such as WORKING-STORAGE items.

The item referenced may be at any level; for example:

01-level entry: you will obtain the number of appearances of a particular group.

LINE entry: you will count the number of appearances of that particular LINE.

COLUMN entry: you will obtain a count of appearances of that particular elementary item.

Assuming that you do not use the RESET phrase, when your COUNT field has been output the count returns to zero.  Hence, you will always obtain the count of the number of appearances of the item since the last time the count was output.

You may use the RESET ON phrase to delay the resetting of the count to zero until a higher-level control break occurs, in exactly the same way as you can with the SUM clause.

If the item counted is one that repeats several times because of an OCCURS or REPEATED clause, the count will include each repetition.  An OCCURS ... DEPENDING will count just the number of items actually output.  A PRESENT clause (or the equivalent) is also taken into account, so that items "not present" do not contribute to the count.

You may count more than one item by writing more than one data-name as an operand in the clause.  The counts are then simply consolidated internally.

   (The COUNT clause is really a special variant of the SUM clause, so other points of interest can be found under SUM Clause.)


The FUNCTION clause invokes a special routine to reformat or convert the data before it appears in your report field.


FUNC-----++IS+               |   +-------+   |
                                   |   v       |   |
                                   +-( parameter )-+

FUNCTION Clause: Coding Rules

Function-name must be alphanumeric and must be either a standard supplied function name or a user-written one.  It may begin with a numeric character.  A full list of standard function names is given below, and you or any other person may add new ones to the list at any time.

The FUNCTION clause may be used only at the elementary level, in place of SOURCE, SUM, or VALUE.  It is permissible for the entry to have no COLUMN or PICTURE clause, i.e. the entry may be a dummy.  You may use it in a multiple-choice entry, if so desired.

The number of parameters you need, if any, and their formats are stated below (see 3.7.4) for each built-in function.  User-written functions should also have a description that tells you this information.  Some functions take no parameters while others allow either a fixed or a variable number.

Each parameter may be any identifier.  It may also be an integer, literal, or arithmetic expression, for example:


   in which case the parameter is given to the Function routine as a one-word signed binary field.  You cannot use SUM or COUNT terms in the expression.  Neither can you use LENGTH OF, ADDRESS OF, BY CONTENT, or BY REFERENCE, as part of a parameter.

The FUNCTION keyword may also be used in the format FUNCTION IS function-name (...) in a SOURCE clause or in a condition in a PRESENT WHEN clause.  In such cases function-name is a COBOL intrinsic function and is not part of the FUNCTION clause described here.

FUNCTION Clause: Operation

The function routine behaves like a subroutine whose parameters consist of the parameters specified in the FUNCTION clause, if any, together with information about the size of the report field, if any, and the report field's contents, both of which are automatically supplied by report writer.  Details on the linkage to function routines are given later (see Developing User-Written Functions).

If you code an edited PICTURE (numeric or alphanumeric) with the FUNCTION clause, report writer invokes the function routine using an internal intermediate field that has the unedited equivalent of your PICTURE.  This is obtained by removing all insertion characters, including any decimal point.  Also any "Z" or "*" symbol or floating sign or currency symbols are converted to an equivalent number of "9" symbols.  The "<" symbol is also removed.  For example, if your entry is as follows:

           05  COL 21   PIC $$,$$9.<99   FUNCTION MONEY (WS-VAL).

   Report writer will provide the function routine with an intermediate field with a PICTURE of 9999V99 as a parameter for receiving the output value.  Report writer then executes a MOVE from the intermediate field to your original report field.  This means that all functions, including user-written ones, can operate with edited report fields, without function routine developers needing to allow for the many possible edited formats.

One of the parameters report writer passes to the function routine is the size in bytes of the report field, if any, to be output.  If the PICTURE is edited, this size is the size of the intermediate field.  Using the case given in the previous paragraph, for instance, the function routine will be told that the size is 6.  The Function routine may decide to produce different formats for the output report field, depending on the number of bytes implied by this size.  It may also simply truncate the output value (on the left or the right) down to the number of characters required.  This can give you freedom to choose from many possible PICTUREs to use with a function.  For example, if DATE is used, and today's date is 5th January, 1997:

    PICTURE 9(6) will give you:


    PICTURE 99/99/99 will give you:


    PICTURE 99BXXXB9(4) will give you:

 05 JAN 1997

    PICTURE <99BX(9)B<9999 will give you:

 5 JANUARY 1997

   Functions cannot detect the kind of PICTURE symbols used.  For example PICTURE XXBXXBXX produces the same result as PICTURE 99B99B99.

Built-In Functions

The following is a list of the built-in functions.

CTIME   (Clock Time) is similar to TIME (see below) except that it uses the 12-hour clock and prints either AM or PM (or blanks at midnight (0.00) and noon (12.00)).  The (unedited) PICTURE should therefore allow for two additional non-numeric characters.  For example, PIC 99":"99BXX could result in 11:30 PM.

DATE   (European Date) returns a date in any one of a number of display formats in the order day/month/year.  The date does not change after the first invocation of the function.

      Number of parameters: 0 or 1.

      If no parameter is supplied, the date will be the current date at the start of the run.  If one parameter is supplied, it must be either a  7-digit date held in a PIC S9(7) COMP-3 (packed) format in the form ccyyddds (s = sign), or a 5-digit date held in a PIC S9(5) COMP-3 (packed) format in the form yyddds (in which case the current century is assumed).

      Report-field (PIC) lengths (excluding editing symbols):
        5  -  yyddd
        6  -  ddmmyy
        7  -  ddMMMyy       (MMM is first 3 characters of month name)
        8  -  ddmmccyy      (cc is century)
        9  -  ddMMMccyy
       13  -  ddM(9)yy      (M(9) is 9-character month name)
       15  -  ddM(9)ccyy

DAY      (Day-of-Week) returns the alphabetic day-of-the-week represented by the given date.

      Number of parameters: 0 or 1.

      If no parameter supplied, the current date is used.  If one parameter is supplied, it may be either a  7-digit date held in a PIC S9(7) COMP-3 (packed) format in the form ccyyddds (s = sign), or a 5-digit date held in a PIC S9(5) COMP-3 (packed) format in the form yyddds (when the current century is assumed), or a two- or four-byte (PIC S9(9) COMP or PIC S9(4) COMP) location containing a value from 1 (= Monday) to 7 (= Sunday), or a one-byte (PIC 9 DISPLAY) location containing a value from 1 to 7.

      Report-field lengths (excluding editing symbols):
      3 - first 3 letters of day (MON,TUE,WED,THU,FRI,SAT,SUN)
      9 - full name of day

DAYSIN   (Days Elapsed Since Base Date) converts a binary number of days since the base date (see below) to a date in the same format as for DATE.

      Number of parameters: 1.

      The parameter must be the number of days since the base date inclusive, held as one fullword binary (such as PIC S9(9) COMP).  The base date is January 1st 1601, i.e. 584,693 days since absolute year zero (ignoring calendar reforms).  A zero value means December 31 1600.  A negative value gives a date before December 31 1600.  You may change the base date by re-compiling the source of the FUNCTION supplied with this product, in which case your new function should have a different name to avoid incompatibility.

MDATE   (US Date) returns a date in any one of a number of display formats in the order month/day/year.  It is similar to the DATE function, except that the day and month fields are reversed.

      Report-field lengths (excluding editing symbols):
          5  -  yyddd
          6  -  mmddyy
          7  -  MMMddyy     (MMM is first 3 characters of the month name)
          8  -  mmddccyy    (cc is century)
          9  -  MMMddccyy
         13  -  M(9)ddyy    (M(9) is a 9-character month name)
         15  -  M(9)ddccyy

MDAYS   (Days Elapsed - US Format) converts a binary number of days since the base date, as defined under DAYSIN above, to a date in the same format as MDATE, that is, month/day/year.  This function is otherwise identical to DAYSIN.  See MDATE above for more information on report field lengths.

MONTH   (Month Name) returns an alphabetic month name.

      Number of parameters: 0 or 1

      If no parameter is supplied, the current month is returned.  If a parameter is supplied, it should be either a 7-digit date held in a PIC S9(7) COMP-3 (packed) format in the form ccyyddds (s = sign), or a 5-digit date held in a PIC S9(5) COMP-3 (packed) format in the form yyddds (when the current century is assumed), or a two-byte (PIC 99 DISPLAY) location containing a value from 01 to 12, or a four-byte binary (PIC S9(9) COMP) location containing a value from 1 to 12.

      Report-field lengths (excluding editing symbols):
        3  -  first three characters of month (JAN,FEB,MAR,etc.)
        9  -  full name of month

MOVE   (Save Register) copies any report writer special register to a specified working location.  This is a dummy function which requires no report field and may be coded without a COLUMN or PICTURE clause.  (If the entry is not a dummy, the field will be space-filled.)

      Number of parameters: 2.

      Parameter 1 is any numeric special register, typically LINE-COUNTER or COLUMN-COUNTER.  It may also be a user-defined data-name specified in a VARYING clause.

      Parameter 2 is any half-word binary location (PIC S9(4) COMP) to receive the contents of parameter 1.

      This FUNCTION is used to capture on the fly the contents of a register whose value is constantly changing.  The following sample code prints up to 12 monthly payments to print side-by-side showing only those which are not zero and, by storing each value of the VARYING subscript R-MONTH in LAST-MONTH for those occurrences selected, it is able to state which month was the last to be printed.

          03  LINE.
              07  COL + 3          PIC ZZZZ9 SOURCE PAY (R-MONTH).
              07                   FUNC MOVE (R-MONTH LAST-MONTH).
            05  COL 90             "Last month with a payment was".
            05  COL + 2  PIC X(9)  FUNC MONTH (LAST-MONTH).

RDATE   (Real DATE) is similar to DATE without the optional parameter, except that the current date is always fetched.  Compare RMDATE.

RMDATE   (Real MDATE) is similar to MDATE without the optional parameter, except that, if the date changes during the run, because the time passes through midnight (00:00:00), the date is changed.

        Report-field (PIC) lengths (excluding editing symbols):
          5  -  yyddd
          6  -  yymmdd
          7  -  yyMMMdd        (MMM is first 3 characters of month name)
          8  -  ccyymmdd       (cc is century)
          9  -  ccyyMMMdd
         13  -  yyM(9)dd       (M(9) is 9-character month name)
         15  -  ccyyM(9)dd

RYDATE   (Real YDATE) is similar to YDATE (see below) without the optional parameter, except that the current date is always fetched.  Compare RMDATE.

STATE   (US State) returns the name of one of the US states, plus "DC".

      Number of parameters: 1

      The parameter may be either a state number with PICTURE 99 (DISPLAY) ranging from 01 (ALABAMA) to 51 (WYOMING), in alphabetical order of their full names, or a two-character standard abbreviation e.g. "AL" or "WY".

      The report-field length must be at least 14.  If it is less than 20, then DISTRICT OF COLUMBIA is rendered as D.C.

STATEF   (US State or Territory) is similar to STATE (see above) except that the five overseas territories are included, merged into the set of 51 domestic states, in alphabetical order of their full names.

STIME   (Static Time) is similar to TIME (see below) except that the time is only fetched initially from the operating system and therefore does not change in value throughout the program.

TIME     (Run Time) returns the current time in format hhmmsstt, where tt is hundredths of a second, if available, otherwise zeros.  The value of the time may change on each invocation of the function.

      Number of parameters: none

      Report-field (PIC) lengths:
        4  -  hhmm
        6  -  hhmmss
        8  -  hhmmsstt

      As an example, the following example uses DAY, DATE, and TIME:

           05  COL 31  PIC <X(9)         FUNC DAY.
           05  COL +2  PIC <99/<99/9(4)  FUNC MDATE.
           05  COL 51  PIC 99,99,99      FUNC TIME.

      executed at 3 PM on March 7th, 1997 will result in:

 FRIDAY 3/7/1997     15,00,00

YDATE   (Date Reversed) returns a date in any one of a number of display formats in the order year/month/day.  Apart from this order, it is similar to DATE and MDATE.

ZIP      (Zip Code) prints a standard US or Canadian ZIP code.

      Number of parameters: 1.

      The single parameter must contain the ZIP code in the format S9(9) COMP-3.  This is then output in the form nnnnn-nnnn, but the final -nnnn is left blank if the last four digits are 9999.


This clause explicitly gives the lowest permissible vertical position for any line in a specific body group.


GROUP LIMIT IS integer--><

GROUP LIMIT Clause: Coding Rules

Your integer must not be greater than the lower limit (LAST DETAIL, LAST CONTROL FOOTING, or PAGE LIMIT) that would normally apply without the clause (see PAGE LIMIT Clauses ).

Code this clause only at the 01-level in a body group (DETAIL or CH/CF).

Your group's first LINE clause must be relative.

GROUP LIMIT Clause: Operation

When doing the page-fit test, report writer will use your integer as the bottom line number, beneath which no part of the group may appear, instead of the usual end-of-region values (see PAGE LIMIT Clauses).

This clause is especially useful in a CONTROL HEADING, which might appear misplaced if it appeared near the bottom of the page like the DETAIL and CONTROL FOOTING groups.


This clause causes a SOURCE, SUM, COUNT, VALUE, or FUNCTION clause whose operand is shorter or longer than the target report field to fill the report field with excess spaces, or perform truncation, on the left instead of the right.


JUST------+ +-RIGHT-+

JUSTIFIED Clause: Coding Rules

If you code JUSTIFIED RIGHT in an elementary entry, the entry must have an alphanumeric PICTURE.

This clause acts on elementary-level fields, but you may also code it in a group-level entry, including 01, where it applies to all the alphanumeric elementary entries in the group.

JUSTIFIED Clause: Operation

The JUSTIFIED clause is retained for compatibility with ANS COBOL and acts on an elementary field in the same way as in basic COBOL.  It cannot be used for right-flushing variable-length fields, for which COLUMN RIGHT should be used.  (See COLUMN Clause.)  This is because JUSTIFIED does not consider the contents of the sending field.

The JUSTIFIED clause takes effect when your alphanumeric SOURCE field is of a different size from the PICTURE.  The padding out with spaces or the truncation (if the PICTURE is smaller than the field) then takes place on the left instead of the right.  In the following example, we want to output either MONTH-NUMBER (2 characters) in columns 12 and 13 or YEAR-NUMBER (4 characters) in columns 10 through 13:

           05  COL 10  PIC X(4) JUSTIFIED RIGHT
                           SOURCE MONTH-NUMBER WHEN MONTH-IND = 1
                           YEAR-NUMBER WHEN OTHER.

LINE Clause

The LINE clause positions a line vertically on the page.


                             v                     |
LINE-+-------------+-+-+-+- PLUS-+-integer-1-+->
     |      +-NUMBER IS---+ | | +- + --+           |
     |      +-NUMBERS ARE-+ | |                    |
LINES ARE------------+ +--integer-2---------+


LINE Clause: Coding Rules

Here is a list of the alternative forms:

LINE + integer-1.  This is the relative form.  PLUS may be written in place of +.  It indicates that the line should advance integer lines from the previous position.  LINE + 0 or LINE + ZERO is allowed, indicating that no advance is to take place.  The result is that the line overprints the previous line.  You may write "+" with or without a space on either side.

LINE integer-2.  This is the absolute form.  It indicates that the line will appear on that fixed position on the page.  The first line on the logical page is LINE 1, corresponding to position reached on issuing a form feed.  The highest line number allowed is given by the PAGE LIMIT operand.  This absolute form is allowed only if you have a PAGE LIMIT clause in your RD.

LINE integer-2 ON NEXT PAGE.  This is similar to format b but the ON NEXT PAGE phrase forces a page advance to occur before the line is output, irrespective of whether the group containing it would fit on the current page.

LINE ON NEXT PAGE forces the line to be output in the FIRST DETAIL position on the next page (for a body group) or the HEADING position (for a REPORT HEADING or REPORT FOOTING group).

LINES ARE integer-1 integer-2 ... is the multiple form of the clause.  It enables you to save coding effort by describing several lines in the same clause.  You may also write LINES + integer, + integer etc (the relative form) and may combine both forms in the same clause.  You may also write ON NEXT PAGE after the last operand, in which case this phrase applies to the first line in the set.

LINE alone is shorthand for LINE + 1.

The first LINE clause in each group determines whether the group as a whole is to be relative or absolute.  If the first LINE clause is relative, the group is a relative group and all the other LINE clauses must be relative.  So the entire group can be positioned anywhere on the page, within the permitted upper and lower limits for the group:

      ^    ^
      ^    ^

   report group

      v    v
      v    v

  LINE + ...
  LINE + ...

   If the first LINE clause is absolute, the group is an absolute group and any of the remaining LINE clauses may be absolute or relative .  For example, the following two arrangements of LINE clauses within a group are equivalent:

          01  TYPE PH.                 01  TYPE PH.
            03  LINE 1. ...              03  LINE 1. ...
            03  LINE 2. ...              03  LINE + 1. ...
            03  LINE 4. ...              03  LINE + 2. ...

   Using relative lines has the advantage that you can adjust the position of the entire group by changing just the first LINE number.

If a group has absolute LINE clauses, except where NEXT PAGE is used, the integers must be in increasing order.  Except in the case of LINE + 0, no lines may overlap.  (If you place PRESENT WHEN condition clauses on the LINE entries, then mutually exclusive lines may have the same line numbers.  See PRESENT WHEN Clause.)

A LINE need not contain any COLUMN entries (whether actual or implied by default).  The result is a blank line containing no data.  For example:

       01  TYPE PH.
           05  LINE  2   VALUE "** HEADING **".
           05  LINE  4.                            *> (or LINE + 2.)

   This causes the PAGE HEADING to occupy lines 2 to 4, although data is written only on line 2.

One LINE clause must not be subordinate to another LINE clause.  If this rule is broken, a warning message will be issued and the previous line will be terminated; for example:

              03  COLUMN 1  ...
              03  LINE PLUS 1.
                05  COLUMN 1  ...

The ON NEXT PAGE phrase may be coded only in the first LINE clause of a report group, except when the report group entry has a MULTIPLE PAGE clause (or when this is assumed, as in the case of REPORT HEADING and REPORT FOOTING) where there is no restriction.  (See MULTIPLE PAGE Clause.)  This permits such groups to occupy several pages.

LINE Clause: Operation

If a group is absolute, its first LINE clause indicates the starting position of the group (see rule 3 above).  The next two paragraphs cover the relative case.

Positioning of relative body groups (CH, DE, and CF)

If the group is the first body group on the page, the first line of the group is positioned at the FIRST DETAIL position, irrespective of the integer of the LINE clause.  If you did not code a FIRST DETAIL sub-clause in your RD, the first line will appear one line after the PAGE HEADING group, if there is one, or at the HEADING position if not.  Subsequent lines in the group are positioned relative to each other.

If the group is not the first body group on the page, then the first line of the group is positioned relative to LINE-COUNTER, which normally contains the last line position of the preceding body group.  (But note that a NEXT GROUP clause or an alteration to the value of LINE-COUNTER in the PROCEDURE DIVISION can affect this positioning.)

Page-Fit Test for Body Groups

   When a report has a PAGE LIMIT clause, report writer performs a page-fit test before outputting any body group (CONTROL HEADING, DETAIL, or CONTROL FOOTING).  This is to ensure that none of the lines of the group will be output unless all the lines of the group will fit in the region of the page reserved for its type of body group.  (See PAGE LIMIT Clause.)  The type of page-fit test performed will depend on whether the group is absolute or relative.  In all cases, remember that LINE-COUNTER contains the current vertical position, normally the position of the line last written before this group was generated.

Absolute Page-Fit Test for Body Groups

   If the first LINE is absolute, report writer takes the first LINE number as the starting position of the group.  (If any of the absolute LINE clauses are conditional, then this "first line" need not be the first LINE number coded; if all absolute lines are ABSENT, the group will be treated as null or relative, as the case may be.)  If LINE-COUNTER is positioned at a line above the starting line position of the group, report writer will not skip to a new page.  In all other cases, a page advance takes place (see item 5 below) and the group is printed at the line specified on a fresh page.  The next diagram illustrates this process:

     *** page heading ***
     ***    if any    ***

 |                           |
 |       BODY-GROUP          |
 |                           |

     *** page footing ***
     ***    if any    ***

|  03  LINE 20 ...         |
|  03  LINE 21 ...         |
 << final LINE-COUNTER = 21
LINE-COUNTER = 21, which is
> line 20; so page advances.
     *** page heading ***
     ***    if any    ***

 |                           |
 |       BODY-GROUP          |
 |                           |

Space up to start of group
(line 20) is left blank.

Relative Page-Fit Test for Body Groups

   When all the LINE clauses in the group are relative, report writer computes the total of all the integers of the LINE + clauses.  This gives the total size of the group.  If the group contains LINE entries that have a condition attached, as from a PRESENT WHEN/AFTER clause, or from an OCCURS ... DEPENDING clause, all these clauses are evaluated first, so that the actual number of lines about to be produced is known.  The value LINE-COUNTER + total-size-of-group is the last line on which the group would appear if it were produced on the current page.  If this last line position is beyond the lower permitted limit of the group, the group cannot fit on the page and a page advance takes place.

   As shown by the diagram and rules under PAGE LIMIT Clause, and GROUP LIMIT Clause, the lower permitted limit of the group is given by:

 ¶   The report group's own GROUP LIMIT clause, if there is one, or

 ¶   The RD's LAST DETAIL, if the group is a DETAIL or CONTROL HEADING


   The LAST DETAIL and LAST CONTROL FOOTING sub-clauses need not be explicitly specified in your RD, as report writer will assume defaults for them, as outlined under  PAGE LIMIT Clause (see 2.9.3 (7)).

   The following diagram shows an example of a page-fit test.

     *** page heading ***
     ***    if any    ***

 |                           |
 |       BODY-GROUP          |
 |   total size 3 lines      |

 +- - - - - - - - - - - - - -+
 |      hypothetical         |
 |       BODY-GROUP          |
 |   total size 3 lines      |
 +- - - - - - - - - - - - - -+
     *** page footing ***
     ***    if any    ***

         LAST DETAIL 60
         PAGE LIMIT 64

      |  01  BODY-GROUP TYPE DE. |
      |    03  LINE + 2...       |
      |    03  LINE + 1...       |
 Initial LINE-COUNTER = 10;
 10 + 3 = 13 = last LINE position;
 13 not > 60, so enough room.

 Later, on the same page:

      |  01  BODY-GROUP TYPE DE. |
 - - -|    03  LINE + 2...       |
      |    03  LINE + 1...       |
 Initial LINE-COUNTER = 58;
 58 + 3 = 61 = last LINE position;
 61 > 60, so NOT enough room,
 so page advance takes place.
     *** page heading ***
     ***    if any    ***
 |                           |
 |       BODY-GROUP          |
 |                           |

 Second group produced at FIRST
 DETAIL position, line 3.

Positioning of relative non-body groups (RH, PH, PF, and RF)

TYPE RH and PH:  relative to HEADING minus 1.  (However, in the case of the first PH group when there is a RH group also on the first page, it is relative to the last line of the RH group.)


TYPE RF:  relative to HEADING minus 1.  (However, in the case where the RF group does not begin on a new page, it is relative to the last line of the PF group, if there is one, or to LAST CONTROL FOOTING, if there is no PF group.)

Page advance processing

   When report writer executes a page advance, it does the following:

 ¶   If you defined a PAGE FOOTING, this is output.

 ¶   PAGE-COUNTER is incremented by 1.

 ¶   An advance is made to the top of the next page.  In "batch" printing a form feed is output, but with an  Independent Report File Handler the action may vary (see 5.3).  LINE-COUNTER is then set to zero.

 ¶   If you defined a PAGE HEADING, this is output.

Multiple LINES Clause

By writing several integer or + integer terms in a LINE clause, you save time in defining a group of lines that all have a similar layout.  Note the following points:

A multiple LINES clause is functionally equivalent to a LINE with an OCCURS clause; for example:

You may use a VARYING clause to vary an internal counter that may be used as a subscript in a SOURCE clause within the scope of the LINE clause.

simple (single-operand) VALUE, SOURCE, SUM, or FUNCTION is repeated in every occurrence of the line.

You may use a multiple VALUE or SOURCE clause to place a different value in a report field in each occurrence of the multiple LINE.

You may place a data-name at the start of the entry and SUM it into another entry to produce a total of all the (multiple) entries.

However, in contrast to the OCCURS clause, the intervals between the lines defined by a multiple LINES clause need not be regular.

Your multiple LINES clause will be syntactically correct if it would be correct when written as a series of LINE clauses in separate entries.

Here are some examples of the multiple LINES clause:

a.   03  LINES 1, 3, 4.

b.   03  LINE NUMBERS ARE +2, +1, +1  COL 6  VALUE "----".

   Here the ON NEXT PAGE phrase applies to the first of the three lines:

c.   03  LINES 1, +2, +2 ON NEXT PAGE.

The multiple LINES clause is useful in lines, such as headings, that have stacked text.  Consider the following example in conjunction with the description under Multiple SOURCES and Multiple VALUES:

  SALES               GROSS         PAGE   1
  THIS      LAST      PROFIT
  YEAR      YEAR

   It may be coded as follows:

01  TYPE PH.
  03  LINES 1 2 3.
    05  COL 1     VALUES    "SALES"
    05  COL 11    VALUES    " "
    05  COL 21    VALUES    "GROSS"
                            " ".
    05  COL 35    VALUES    "PAGE"  " "  " ".
*We use a blank "literal" or SOURCE NONE
*in any occurrence that is to be empty.

   You need not code the multiple VALUES in a "stacked" format like this, but it is suggested to aid readability.


LINE-COUNTER is an internal special register that contains the most recent report line number on which data was produced, or which has been advanced to by a blank LINE clause or a NEXT GROUP clause.  LINE-COUNTER may also be altered by an ordinary PROCEDURE DIVISION statement or implicitly by a Page Buffer SET statement.



IN -+-report-name-+
OF -+


LINE-COUNTER is a special register giving the current vertical position on the page.  After a GENERATE has been executed, LINE-COUNTER will be set to the line number of the last line occupied by the last group output.  A NEXT GROUP may change it further (see NEXT GROUP Clause).  You can test the value of LINE-COUNTER to determine the vertical position on the current page.

Whenever you issue a GENERATE, report writer examines LINE-COUNTER to decide where it should output the lines of the group.  It is set to zero by the INITIATE and by a page advance.  Then, if your line has a LINE + integer clause, report writer uses (LINE-COUNTER + integer) as its target line.  When the page-fit test is performed for a relative body group, report writer adds the size of your group to LINE-COUNTER to see whether the last line will be below the group's lower limit.

    You may alter the value of LINE-COUNTER in the PROCEDURE DIVISION, but take care!  Do not reduce the value of LINE-COUNTER, or you are liable to cause too many lines to be written to your page so that it overflows its lower limit.  You may increase its value safely.  Some legitimate reasons for altering its value are:

To create an additional gap between the previous group and the next group:

              ADD size-of-gap TO LINE-COUNTER

   If your page is nearly full (so that LINE-COUNTER is nearly equal to the LAST DETAIL value) this will simply cause a page advance upon the next GENERATE instead of a gap.  If your ADD statement sets LINE-COUNTER below LAST DETAIL, no harm is done.  You should note that the NEXT GROUP clause performs this function more elegantly.

To cause a page advance, that is, to force report writer to place no more body groups on this page, code:

              MOVE page-limit TO LINE-COUNTER

   Again, coding the NEXT GROUP NEXT PAGE clause on the previous group also performs this function better.  (See NEXT GROUP Clause.)

If your REPORT SECTION has several Report Descriptions, each will have its own distinct LINE-COUNTER.  In the main-line PROCEDURE DIVISION, you will therefore need to qualify LINE-COUNTER by the name of the report.  (See PAGE-COUNTER, and Multiple Reports.)


This clause allows a report group to span more than one page.

Format a


   Format b


MULTIPLE PAGE Clause: Coding Rules

This clause can be coded in any type of group other than PAGE HEADING and PAGE FOOTING.  The RD must have a PAGE LIMIT clause.

Either MULTIPLE PAGE or NO MULTIPLE PAGE may be coded at the 01 level.  Alternatively, NO MULTIPLE PAGE may be coded on a group of one or more LINE entries, provided that there is a MULTIPLE PAGE at the 01 level.  No other nesting is allowed.

By default, NO MULTIPLE PAGE is assumed for all body groups and MULTIPLE PAGE for REPORT HEADING and REPORT FOOTING groups.

The MULTIPLE PAGE clause is not allowed in a group that has a REPEATED clause.

MULTIPLE PAGE Clause: Operation

The MULTIPLE PAGE clause enables a single report group to occupy any number of consecutive pages.  It allows you to code NEXT PAGE on as many LINE clauses as you wish throughout the group (rather than just on the first).  It also allows you to define as many relative lines as you wish, irrespective of the size of the page.  Thus you can print very large tables using a single GENERATE.

When the group is a body group with MULTIPLE PAGE, no page fit-test is performed for the group as a whole.  Instead, each report line is subjected to an individual page-fit test.  A LINE clause with NEXT PAGE also causes a page advance to take place.  Loosely speaking then, a multiple page group may begin at any point and cause a page advance at any point.

When a page advance is required, a PAGE FOOTING and PAGE HEADING group are printed as usual if defined.  This is the only case where groups may interrupt another group.  If the line that caused the page advance is relative, it is placed in the FIRST DETAIL position, disregarding the integer of its LINE clause.  In the following layout, note how the "ROBINSON" group (in blue if you have color) spans three pages:










         03  LINE       COL 1    PIC X(20)   SOURCE W-SURNAME.
                        COL 3    PIC X(20)   SOURCE W-SPORT (R-SPORT).

NO MULTIPLE PAGE can be used to prevent the lines in its scope from being split over a page boundary.  If an OCCURS clause is also present, this rule applies separately to each occurrence.  In the following example we want each set of address lines to remain together on the page:

             VARYING R-ADDR-NO
             NO MULTIPLE PAGE.
             07  COL 1  PIC X(64)  SOURCE R-LINE (R-ADDR-NO R-LINE-NO).

   At the 01 level, NO MULTIPLE PAGE merely documents the usual situation that a group cannot span pages.


This clause is used to create additional vertical space after a group, without causing page overflow if there is no room on the page for the extra blank lines.


NEXT-+-----------------------------------+- GROUP IS-->
          +-+-DETAIL-+-OR-+-CONTROL HEADING-+-+
            +-DE-----+    +-CH--------------+

    | +- + --+           |
NEXT PAGE ------+

NEXT GROUP Clause: Coding Rules

This clause must be written only at the 01-level.

You can use the clause in any body group (DETAIL or CH/CF) and also in a REPORT HEADING (provided that a PAGE HEADING is present) as well as in a PAGE FOOTING (provided that a REPORT FOOTING is present).

If your report has no PAGE LIMIT clause, you can use only the + integer-1 form.

The optional words BODY and DE OR CH document the effect of the NEXT GROUP clause in the context of the type of group in which it is coded, but they do not have any actual effect on the clause.  You can write NEXT BODY GROUP only in a DETAIL or CONTROL HEADING group, and NEXT DE OR CH GROUP only in a CONTROL FOOTING group.


Effect of NEXT GROUP on Body Groups

Subject to certain constraints, the NEXT GROUP clause causes report writer to increase the value of LINE-COUNTER after all the lines in the body group have been produced, so that the next body group appears on a new page or after an additional vertical gap.

If you write NEXT GROUP + integer-1, report writer will add integer-1 to LINE-COUNTER, but using the LAST CONTROL FOOTING value as a maximum limit.  This creates an extra "gap" of that many lines between this group and the next, provided that there is room for both to appear on the same page.  The following diagram shows how to use the clause to create more space after a CONTROL FOOTING:

   HOUSTON      1200
   DALLAS        500
   AUSTIN       1400
 TOTAL TEXAS    3100

   MIAMI        1500
   ORLANDO      2300

 extra gap
 from NEXT

   TAMPA        2000

   ATLANTA      1100

 extra gap
 from NEXT


   Notice that there is no "gap" after the TOTAL GEORGIA group, because it already extends to the LAST CONTROL FOOTING position.

   You might suppose that you could also get extra blank lines by writing a blank LINE entry (containing no COLUMN entries or just a VALUE of SPACES) at the end of the group.  But this is not a satisfactory replacement for the NEXT GROUP clause, because the blank LINE is treated as a part of the group and will affect the page-fit test.  For example, if you had written

            03  LINE + 2.

        or  03  LINE + 2.
              05  COL 1     VALUE " ".

   at the end of the CF group instead of the NEXT GROUP clause in the above example, the TOTAL GEORGIA group would have appeared at the top of the next page, because its total depth would now be 5 lines instead of 3.  Likewise, a LINE + 2 at the front of the DETAIL group would produce unwanted blank lines ahead of every DETAIL group.

The NEXT GROUP integer-2 (absolute) form may force the next body group to be produced relative to the given line number.  Report writer first examines the LINE-COUNTER.  If this is less than integer-2 (in other words, if that position has not yet been reached), LINE-COUNTER is set equal to integer-2.  Otherwise, report writer sets LINE-COUNTER equal to LAST CONTROL FOOTING to ensure that no more body groups will appear on this page and saves the value of integer-2 in the Saved Next Group Integer location.  Before the next body group, if any, is produced, report writer sets LINE-COUNTER equal to the saved integer.  It is inadvisable to use this form of the clause unless your next body group will always be a relative group.

If you write NEXT GROUP NEXT PAGE, report writer will set LINE-COUNTER to the LAST CONTROL FOOTING value.  This forces report writer to leave the rest of the page blank and begin the next body group, if any, on the next page.  (LAST CONTROL FOOTING is the lowest position on which any body group can appear as described under PAGE LIMIT Clause).

   To begin on a fresh page after a control break, you may place NEXT GROUP NEXT PAGE in the CONTROL FOOTING for that control level, as the following example shows:

   HOUSTON      1200
   DALLAS        500
   AUSTIN       1400
 TOTAL TEXAS    3100

 Rest of
 page is
   MIAMI        1500
   TAMPA        2000

 Rest of
 page is

         03  LINE         VALUE "-----------------".
         03  LINE.
           05  COL 1      VALUE "TOTAL".
           05  COL + 2    PIC X(9)   SOURCE STATE.
           05  COL + 1    PIC ZZZ9   SUM OF SALES.
         03  LINE         VALUE "-----------------".

If you write a NEXT GROUP clause in a CONTROL FOOTING group, report writer checks the level of the control break being processed before putting the clause into effect.  If the level of the break is higher than the level of this group, the NEXT GROUP clause is ignored.  This means that a CONTROL FOOTING's NEXT GROUP clause can never affect the position of the next CONTROL FOOTING.  As the following example shows, the CONTROL FOOTING FOR REPORT (the grand total) will not be forced onto a new page.  To document this fact, the optional words DE OR CH are provided in the syntax.

   HOUSTON      1200
   DALLAS        500
   AUSTIN       1400
 TOTAL TEXAS    3100

 Rest of page
 is blank.

   MIAMI        1500
   TAMPA        2000

 GRAND TOTAL   73400

 has no effect
 on following
 TYPE CF group.

       01  CF FOR REPORT.
         03  LINE + 2.
           05  ..

   If you should want the CONTROL FOOTING FOR REPORT to appear on a new page in this case, you should instead code ON NEXT PAGE in its first LINE clause.

You can code a dummy report group containing only a NEXT GROUP clause, as in the example below.  When the group is processed, no output takes place, but LINE-COUNTER will be set equal to LAST CONTROL FOOTING solely because of the NEXT GROUP NEXT PAGE clause.  This may be useful when you want to begin a new page on change of, say, BRANCH, but there is no subtotal that would normally justify coding a CONTROL FOOTING group.  Just write:


   To obtain a gap of three lines at any time, as an alternative to altering LINE-COUNTER directly, code:

            01  THREE-LINE-GAP  DE  NEXT GROUP + 3.

   and in your Procedure Division, write: GENERATE THREE-LINE-GAP.

Effect of NEXT GROUP on Non-Body Groups

You can write a NEXT GROUP clause in a REPORT HEADING group, in which case the group affected will be your first PAGE HEADING group, which immediately follows the REPORT HEADING.  NEXT GROUP NEXT PAGE indicates that the REPORT HEADING is to be by itself on a separate page, rather than on the first page above the PAGE HEADING, but this will be assumed anyway if the REPORT HEADING will not fit above the first PAGE HEADING.

You can also write NEXT GROUP in a PAGE FOOTING group, in which case it affects the REPORT FOOTING.  This form is never necessary, as the first LINE clause used in the REPORT FOOTING is a better way to handle this case.

OCCURS Clause and Related Phrases

The OCCURS clause is used to show regular repetition of a field or a group of fields in a horizontal dimension, and a line or group of lines in a vertical dimension.


OCCURS-+--------------+-integer-2 TIMES-->


WIDTH-+           +-LINES---+
DEPTH-+           +-COLUMNS-+

OCCURS Clause: Coding Rules

The OCCURS clause must not be used at the 01-level.

You may use the OCCURS clause at any of these levels:

Below the LINE level in an elementary entry.  Your field will be repeated horizontally the number of times indicated by the operand:

         03  LINE.
           05  COL + 2   "NO"   OCCURS 5.


Below the LINE level in a group entry.  The whole group of fields will be repeated horizontally the number of times indicated by the operand.

         03  LINE.
          04  OCCURS 3.
           05  COL + 3   "DATE".
           05  COL + 2   "AMOUNT".


At the LINE level.  The line will be repeated vertically the number of times indicated by the operand.

         03  LINE  OCCURS 4.
           05  COL 1     "NAME".
           05  COL 21    "ADDRESS".


   NAME               ADDRESS
   NAME               ADDRESS
   NAME               ADDRESS
   NAME               ADDRESS

Below the 01-level but above the LINE level.  The whole group of lines will be repeated vertically the number of times indicated by the operand.

        02  OCCURS 3.
         03  LINE + 2      COL 1     "NAME".
         03  LINE + 1      COL 1     "ADDRESS".




 Each group of LINE + clauses
 takes effect number of times
 given in the OCCURS clause.

   These four levels are known as axes.  Any fields in your group can be repeated in this way on any of the four axes, and you may have repetition on up to four axes by nesting the OCCURS clauses.  Each of your report groups may have any number of OCCURS clauses, provided that the nesting limit of four is never exceeded at any one time.

You may use STEP, WIDTH, or DEPTH to specify the distance between the start of successive repetitions.  Its operand indicates the number of columns or lines between the start of one item and the start of its successor:

           05  COL 1  "PRICE"  OCCURS 4  WIDTH 8 COLUMNS.

 < - 8 ->< - 8 ->< - 8 ->

   Integer-3 of the STEP phrase must be at least as large as the field itself.  WIDTH and DEPTH are alternative keywords with the same meaning as STEP.  WIDTH may be used only in the horizontal direction and DEPTH may be used only in the vertical direction.  You can write the documentary words COLUMNS or LINES after integer-3 to make the direction explicit.  The STEP, WIDTH, or DEPTH phrase may be coded anywhere within the entry.

A STEP phrase is expected if your repeating entry is absolute.  (It is absolute if you write COLUMN integer or LINE integer or, in the case of a group field, if the first COLUMN or LINE in the group is absolute.)  However, if you omit STEP, a minimum value will be assumed, equal to the (maximum) size of the report field, with a cautionary message.

If your field is relative, the STEP phrase is optional.  If you omit it the distance between repetitions is the physical size of the field, which may vary at run time if there are "<" PICTURE symbols or if the field is a group field containing entries with a PRESENT WHEN clause.

As the examples above illustrate (see 2a - 2d), the VALUE clause is allowed within a entry subject to an OCCURS clause.

You must code the DEPENDING ON phrase if the number of occurrences is variable.  The expression can be any COBOL numeric identifier or arithmetic expression that has an integer value.  The data items used in your expression can come from anywhere in your program.  They need not appear elsewhere as report fields and need not reside in the same "record" as the SOURCE fields.

Integer-1 in the format above and the TO keyword are used only in conjunction with DEPENDING ON.  Integer-1 must be less than integer-2 and may be zero.  If you omit integer-1 TO and write OCCURS integer-2 TIMES DEPENDING ON, this is taken to mean OCCURS 0 TO integer-2 TIMES DEPENDING ON.

OCCURS Clause: Operation

You should use the OCCURS clause for source-code reduction when you need to obtain automatic repetition either horizontally or vertically within a report group.  The effect is as though you had coded every entry individually.

You may use a single-operand VALUE to place the same contents in each repetition.

If you use a SOURCE clause within an entry subject to OCCURS, the same SOURCE operand will be used to set up each occurrence.  However, you may allow the effective SOURCE operand to vary by use of the VARYING clause and making use of the VARYING data-name as its subscript or as a term in the SOURCE operand.  (See VARYING Clause for full details and examples.)

You may also use a  multiple SOURCES (see 3.21) or  multiple VALUES (see 3.26.4) to place different contents in each repetition.  The following sample layout shows both methods of combining both SOURCE and VALUE clauses with OCCURS:


  NORTH    $1,420,000      $600,000      $150,500
  EAST     $2,100,000      $850,000      $220,000
  SOUTH    $1,870,000    $1,000,000      $350,000
  WEST       $970,000      $250,000      $110,000

   which may be coded as follows:

       01  SUMMARY-PAGE.
         03  LINE 2     COLS 1 11 26 39
                        VALUES     "AREA" "BASIC PAY" "OVERTIME" "COMMISSION".
         03  LINE 4     OCCURS 4   STEP 1      VARYING AREA-NO.
           05  COL 1    VALUES     "NORTH" "EAST" "SOUTH" "WEST".
           05  COLS RIGHT 19 33 47       PIC $$$,$$$,$$9

   Notice how the series of row-heading items (NORTH, EAST, etc.) is handled: the enclosing OCCURS at the LINE level simply steps through each item in the series in turn.

If a  PRESENT WHEN clause is coded in the same entry as an OCCURS clause, the PRESENT WHEN applies to each occurrence (see 3.18.3).  If the STEP phrase is not used, an entry that is ABSENT will not take up any space, as in the case below where non-negative values are to be skipped:


  MARCH        $12000
  JUNE          $1000
  OCTOBER      $23000

       01  LOSS-MONTHS   TYPE DE.
             PRESENT WHEN PROFIT (R-MONTH) < 0.
           05  COL 1     PIC X(9)
               SOURCE MONTH-NAME (MONTH).
           05  COL 12    PIC $(6)9
               SOURCE PROFIT (MONTH).


   The effect is similar in the horizontal direction:

   120  230  100

       01  LOSS-LINE    TYPE DE.
         03  LINE.
           05  COL + 3  OCCURS 12   VARYING R-MONTH
                        PRESENT WHEN PROFIT (R-MONTH) < 0
                        PIC XXX     SOURCE MONTH-NAME (R-MONTH).
         03  LINE.
           05  COL + 2  OCCURS 12   VARYING R-MONTH
                        PRESENT WHEN PROFIT (R-MONTH) < 0
                        PIC ZZZ9    SOURCE PROFIT (R-MONTH).

   However, if a STEP phrase is used, the spacing - in whichever direction - is regular and even entries that are ABSENT take up their usual space:

            120            230                  90

   which may be coded as follows:

       01  LOSS-MONTHS  TYPE DE.
         03  LINE.
           05  COL + 3  OCCURS 12   VARYING R-MONTH
                        PIC XXX     SOURCE MONTH-NAME (R-MONTH).
         03  LINE.
           05  COL 2    OCCURS 12   VARYING R-MONTH   STEP 5
                        PRESENT WHEN PROFIT (R-MONTH) < 0
                        PIC ZZZ9  SOURCE PROFIT (R-MONTH).



If your report group has an OCCURS clause with a DEPENDING ON phrase, report writer will evaluate the associated identifier or expression at run time on each separate occasion when the report group is about to be generated.  If its value is outside the range of integer-1 TO integer-2 in your OCCURS clause, this is not an error condition, and report writer will assume the maximum number, integer-2.

Now that the actual number of repeats is known, report writer creates only that number of occurrences, treating your clause as though you had written a fixed OCCURS clause with that number as the integerThis is an important notion.  Here are some of its consequences:

If your OCCURS ... DEPENDING is in the horizontal direction and is followed by an absolute COLUMN clause, the space not filled by excess occurrences will be blank:

           05  COL 1   VALUE "ONE"  OCCURS 5 DEPENDING ON COUNT-1  STEP 5.
           05  COL 27  VALUE "END".

   If COUNT-1 contains 3, the effect is as though you had written:

           05  COL 1   VALUE "ONE"  OCCURS 3  STEP 5.
           05  COL 27  VALUE "END".

 ONE  ONE  ONE             END

If your OCCURS ... DEPENDING is in the horizontal direction and is followed by a relative COLUMN, it is positioned relative to the last actual occurrence:

           05  COL 1   VALUE "TWO"  OCCURS 5 DEPENDING ON (A + B) STEP 6.
           05  COL +2  VALUE "END".

If A + B equals 3, the result is as though you had written:

           05  COL 1   VALUE "TWO"  OCCURS 3  STEP 6.
           05  COL +2  VALUE "END".


If your OCCURS ... DEPENDING is in the vertical direction and is followed by an absolute LINE, excess occurrences will be blank:

         03  LINE 2    OCCURS 1 TO 4 DEPENDING ON COUNT-1  STEP 1.
           05  COL 1   VALUE "ADDRESS LINE".
         03  LINE 6.
           05  COL 1   VALUE "ZIPCODE".

   If COUNT-1 contains 2, the result is as though your OCCURS 1 TO 4 clause above were simply coded as OCCURS 2:

 ADDRESS LINE     < line 2
 ADDRESS LINE     < line 3

 ZIPCODE          < line 6

If your OCCURS ... DEPENDING is in the vertical direction and is followed by a relative LINE, no line positions will be occupied by the unused occurrences, and the line that follows will be relative to the last actual occurrence.

         03  LINE + 1  OCCURS 4 DEPENDING ON COUNT-1.
           05  COL 1   VALUE "ADDRESS LINE".
         03  LINE + 1.
           05  COL 1   VALUE "ZIPCODE".

 ADDRESS LINE     < line + 1
 ADDRESS LINE     < line + 1
 ZIPCODE          < line + 1

   The page-fit test allows only for the occurrences that are actually present.  So, if the group as a whole is relative, you will have a "best fit".  For instance, if you GENERATE the above group and only three lines are available to it, the group will fit on the page.

You may code several entries with OCCURS ... DEPENDING in the same report line and nest horizontal and vertical repetitions to produce many varied and useful effects.  The DEPENDING expression is re-evaluated each time the item is about to be output, so you may alter the size and shape of your report fields dynamically and automatically.  You may also use OCCURS ... DEPENDING in a horizontal or vertical group entry.


This special register contains the number of the current page.


IN -+-report-name-+
OF -+


PAGE-COUNTER contains the number of the current page.  It is set to 1 by the INITIATE statement and, if your report has a PAGE LIMIT clause, is incremented by 1 on each page advance after the initial one.  So its value is 1 on the first page, 2 on the second, and so on.  The incrementing takes place between the production of your PAGE FOOTING group, if you defined one, and your PAGE HEADING group, if you defined one.  So accessing PAGE-COUNTER in a USE BEFORE REPORTING Declarative section for a PAGE HEADING, for example, yields the value that applies to the new page.  The TERMINATE statement leaves PAGE-COUNTER unchanged.

You may treat PAGE-COUNTER as a numeric location (implicit PICTURE S9(9) COMP SYNC) in any SOURCE expression or condition.  For example, to print the page number anywhere in the page, write:

                   PIC ZZZ9 SOURCE IS PAGE-COUNTER.

   You can change the value of PAGE-COUNTER at any time.  Just treat it as any numeric data item (except that report writer defines it automatically).  As an example, if you want to restart your page numbering from 1, after each control break, code

                   MOVE ZERO TO PAGE-COUNTER

   in a Declarative SECTION for the CONTROL HEADING, so that when report writer next does a page advance it will increment it from zero to one.

Like all of the special registers except COLUMN-COUNTER, a PAGE-COUNTER is maintained separately for each report, because all your reports are completely independent of each other.  This also means that you must occasionally qualify PAGE-COUNTER if you have more than one report in the program.  You do this by using report-name as a qualifier, as shown in the format at the head of this section.

   You need a qualifier only if there is ambiguity, that is, in the main-line PROCEDURE DIVISION.  In the Report Group Descriptions and in a USE BEFORE REPORTING section report writer assumes that you mean "IN current-report".  However, you may still use a qualifier even in those cases, for instance when you want to access the PAGE-COUNTER of a different report.  More information on multiple reports will be found in 5.1.


A PICTURE clause is used, as in ordinary COBOL, to indicate the size and format for each report field.


PICTURE-+-IS character-string--><

PICTURE Clause: Coding Rules

All the available PICTURE symbols may be used, including a currency symbol defined by a CURRENCY SIGN phrase, provided they are consistent with a DISPLAY field, and the rules for combining them are exactly as for basic COBOL.  Here are some examples:

    reproduces the field with up to five integral places, of which four leading zeros can be changed to a space, followed by a decimal point and two fractional places.

 PIC -$(5)9
    outputs a "-" sign if the field is negative, followed by from 1 to 6 digits, with leading zeros changed to a space, and a currency symbol placed immediately before the first digit.

    outputs a six-character field, with spaces inserted between characters 2 and 3, and characters 4 and 5.

If the item is DBCS (Double-Byte Character Set), the PICTURE may contain only the symbols G and B (representing a DBCS space).  However, a PICTURE clause is not required with a DBCS literal.

Report writer allows the additional left-shift PICTURE symbols "<" and ">" to indicate that all or part of your field is variable-length .  These symbols may be used only in the REPORT SECTION.  You may place the "<" symbol anywhere within the PICTURE, in any number of places, provided that it is followed by one of the following symbols:  "X", "A", "9", "Z", or floating (that is, repeated) "-".  (In other words, it must appear before a symbol that represents "data", as opposed to an "editing" symbol.)  The ">" symbol may optionally be used to terminate its scope.  The effect of these symbols is described below (see 3.16.4).

Report writer also allows general insertion characters, in the REPORT SECTION only.  These are indicated by writing the characters to be inserted in "quotes" (or 'apostrophes') anywhere in the PICTURE, for example: PIC 99"."99"."99.  These insertion characters do not take a repetition factor (so that PIC "."(5)X is invalid and must be written PIC "....."X).

You may omit the PICTURE clause in an entry that has a VALUE clause, whether nonnumeric (when a PICTURE X(n) is assumed) or (unsigned) numeric (when a PICTURE S9(n) DISPLAY is assumed.)  (A SYMBOLIC CHARACTER is treated as a one byte nonnumeric.)  A PICTURE is required if you use ALL "literal", or a figurative constant such as QUOTE.  In the case of a multiple VALUE or multiple-choice entry, there may be several "literals" but still no PICTURE is required.

If you use a SOURCE, SUM/COUNT, or FUNCTION clause, the PICTURE is necessary, even if you want to display the field in exactly the same format in which it is stored.

If the precompiler option is in effect, PICTURE symbol "A" may be used even with a literal that is not entirely alphabetic.

In common with the rest of the DATA DIVISION, PICTURE is allowed only in an elementary entry.

PICTURE Clause: Operation

In the REPORT SECTION, the PICTURE clause plays the same role as it does in other SECTIONs.  The rest of this section and the next describe the extensions which are unique to the REPORT SECTION.

General insertion characters may used to reduce the number of entries to be coded.  For example:

           05  COL 1          VALUE "(".
           05  COL +1         PIC 99          SOURCE W-TODAY-YY.
           05  COL +1         VALUE ".".
           05  COL +1         PIC 99          SOURCE W-TODAY-MM.
           05  COL +1         VALUE ".".
           05  COL +1         PIC 99          SOURCE W-TODAY-DD.
           05  COL +1         VALUE ")".

   may be reduced to:

           05  COL 1          PIC "("99"."99"."99")"   SOURCE W-TODAY.

           05  COL 20         PIC <9(5)>9     SOURCE LETZTE-ZAHLUNG.
           05  COL +1         VALUE "DM".

   may be reduced to:

           05  COL 20         PIC <9(5)>9"DM" SOURCE LETZTE-ZAHLUNG.

           05  COL 100        VALUE "Page:".
           05  COL +2         PIC ZZ9  SOURCE PAGE-COUNTER.

   may be reduced to:

           05  COL 100        PIC "Page: "ZZ9  SOURCE PAGE-COUNTER.

   Note that an insertion character specified in this way never has any semantic significance.  Thus "." is never treated as a decimal point for alignment purposes.

Variable-Length Fields ("<" and ">" Symbols)

If you code the "<" symbol somewhere in your PICTURE in the REPORT SECTION, report writer takes it as referring to the following symbol and repetitions of that symbol, until the end of the PICTURE or a change of symbol is found.  (The use of parenthesis as a shorthand for repetition does not count as a change of symbol.)  The "<" symbol itself does not contribute to the length of the field.  In the following case:

              PIC 9<99,999.<99

   Report writer will divide the field into the following parts:
               9     (1 character fixed)
               <99   (0 to 2 characters variable)
               ,999. (all fixed)
               <99   (0 to 2 characters variable)

   The variable parts of your field are represented by those parts of your PICTURE that follow a "<" symbol, up to a change of symbol.  To mark where each variable part ends, you may code a ">" symbol, resulting, in the above case, in:

              PIC 9<99>,999.<99>

   By convention, PIC <Z(n) is taken to mean the same as the more conventional PIC <9(n), and PIC <$(n) is understood to mean the same as PIC $<9(n-1).

When your field is output, report writer first stores the value to be output in a working area whose PICTURE is the same as the PICTURE you coded but without the "<" symbol(s) .  It then examines each part of your field that corresponds to a variable part of the PICTURE.  If the symbol after the "<" is "X" or "A", that part is non-numeric and report writer will delete trailing spaces (that is, it will not advance COLUMN-COUNTER over them).  If the symbol after the "<" is "9" or "Z" or "-", that part is numeric and report writer will delete leading zeros by left-shifting the contents of the rest of the field.  After a decimal point, either explicit (.) or implicit (V) followed by a "<" symbol, it is trailing zeros that are deleted.

When characters are deleted, any characters that follow them are pulled to the left over them.  This gives a free format effect to variable fields that have several parts.  When the field has been output, the horizontal pointer (COLUMN-COUNTER), will point to the last character stored.  If your next entry has an absolute COLUMN, you will have a variable number of spaces from the end of this field to the fixed starting point of the next.  If, however, your next entry has a relative COLUMN (COL +), the number of spaces between the fields will be fixed, but the starting position of the next field will vary.

You may use the "<" and ">" symbols to split any part of your field into two fragments, one variable and one fixed, resulting in a minimum size and a maximum size.  For example:  PIC XX<XXX> means from 2 to 5 non-numeric characters;  while PIC <999>9 means from 1 to 4 numeric characters (a form that is more useful than PIC <9(4) because a value of all zeros is reproduced as a zero).
Here are some examples of the "<" symbol:

a. If PICTURE -9999.99 gives you the result:


   Then PICTURE -9<999.<99 will give you the result:


b. If PICTURE 99/99/99 gives you the result:


   Then PICTURE <99/<99/<99 will give you the result:


c. If:
         05  COL 1    PICTURE X(6)  SOURCE TITLE.
         05  COL + 2  PICTURE X(20) SOURCE SURNAME.
         05  COL + 1  ":".

   gives you the result:

 MR.    SMITH               :

         05  COL 1    PICTURE <X(6)  SOURCE TITLE.
         05  COL + 2  PICTURE <X(20) SOURCE SURNAME.
         05  COL + 1  ":".

   gives you the result:


Special action is taken with the "," (comma) and "." (decimal point) symbols.  If you write a "<" and a series of "9" symbols before "," and the numeric value that corresponds to them is zero, then the "," will also be deleted.  Also, if you write "<" after a "." (decimal point) and all the numeric positions after the decimal point are zero, then the decimal point will also be deleted.  For example, if your field is described as:

                PICTURE <99,<999,<999.<99

   then values of 00002345.10 and 00000001.00 will be reproduced as:



Any "," or "." encountered in a numeric field after a "<" symbol turns off the effect of the "<".  If you want its effect to persist across such an insertion character, you must turn it on again by coding another "<" symbol; for example: PIC 9,<999>,<999>.99.



This clause is similar to the  PRESENT WHEN clause (see 3.18), except that it tests a condition arising internally within report writer's automatic control-break and page-advance processing, rather than evaluating a general COBOL condition.

Format a

PRESENT-+-AFTER NEW--+-control-id OR PAGE-+-><
ABSENT--+            +-PAGE OR control-id-+

   Format b


   Format c



If you specify the PAGE keyword, the RD for your report must have a PAGE LIMIT clause.  If you specify a control-id, then it must be one of the controls listed in your CONTROL clause in the RD, except that REPORT or FINAL is always assumed to be present in the CONTROL clause.

You may code this clause at the group or elementary level and may nest clauses.

You may use format a in any body group (DETAIL or CH/CF), but, if you use the control-id option in a CONTROL HEADING or CONTROL FOOTING group, the control level you refer to must be higher than the control level of the report group in which the PRESENT AFTER clause is coded.

You may also use format a in a PAGE HEADING or PAGE FOOTING group, but only with the control-id option.

Format b (with the JUST phrase) can be used only in a body group.

Format c, the GROUP INDICATE clause, is provided for compatibility with current standards.  Except for one minor but useful difference in its action with OCCURS (see below), it is equivalent to the clause:

            PRESENT AFTER NEW PAGE OR lowest-control-id

   where PAGE is present if the report has a PAGE LIMIT clause, and the control-id is present if the report has a CONTROLS clause.

   For example, if the RD entry has the format:

           RD  ...
               PAGE LIMIT 60 LINES

   the GROUP INDICATE clause is equivalent to:


It is not advisable to refer to an item subject to PRESENT/ABSENT AFTER or GROUP INDICATE in a SUM clause.  This is because, according to the ANS standard that applies if the option is in effect, summing takes place before the page-fit, so it not always easy to predict whether the item to be summed will actually be present.


The PRESENT AFTER clause operates in a way similar to a PRESENT WHEN clause except that our condition is set from within the report itself.  PRESENT AFTER NEW control-id behaves like a clause of the form:

           PRESENT WHEN this group has never yet been output
                     OR a control break has occurred at that level or above
                        since the last time it was output

   while PRESENT AFTER NEW PAGE behaves like a clause of the form:

           PRESENT WHEN this group has never yet been output
                     OR a page advance has taken place
                        since the last time it was output

   To understand this clause fully you should therefore refer to the  PRESENT WHEN clause (see 3.18).

If you code PRESENT AFTER NEW control-id, report writer will output the field (elementary or group field), provided that this is the first occasion this report group has been output since the start of the report or since the last control break at the level of control-id or above.  For example, if you write PRESENT AFTER NEW BRANCH-NO, your report field will be produced at the beginning of the report and at the first GENERATE after each change of BRANCH-NO (or any higher control).  Otherwise, the field is ignored, together with any subordinate entries, in exactly the same manner as with the PRESENT WHEN clause.

   In the following example, the field YEAR-NO is to be output the first time only and then whenever it has changed, while SEASON-NO is to be output the first time and then whenever it or YEAR-NO has changed.


               HACKER S.      RUGBY
               MANAGER D.P.   SWIMMING
               LOAD V.        CRICKET
               TESTER S.      GOLF
       SUMMER  DUMP J.        TENNIS
               ... etc ...


         01  NEW-MEMBER   TYPE DE    LINE + 1.
             05  COL 2    PIC 9(4)   SOURCE YEAR-NO PRESENT AFTER NEW YEAR-NO.
             05  COL 7    PIC X(6)   SOURCE WS-SEASON (SEASON-NO)
                                      PRESENT AFTER NEW SEASON-NO.

As is usual with controls, a higher control break implies a control break at all the lower levels.  Thus if you code PRESENT AFTER MONTH when YEAR and MONTH are the controls, the field will be PRESENT also after a change of YEAR, for JAN 1992 is certainly different from JAN 1991!

If you code PRESENT AFTER NEW PAGE, report writer will produce the entry if this is the first occasion this group has been produced since the start of the report or since the last page advance.  Otherwise, again, the field is not output.

   As the following example shows, it may cause the entry to be produced at any position within the page provided the group containing it has not yet appeared on the page.  If you want the entry to appear only if this group is also the first body group of the page, you should instead use the form: PRESENT JUST AFTER NEW PAGE.  In the example that follows, this would prevent the subheading UNFILLED ORDERS from being printed in the body of the page.

   In the following example, one group has a subheading for unfilled order details and we want this subheading to appear only the first time that the group is printed on the page:

 ITEM                  QTY IN STOCK
 GOLF 5 IRON                   3
 SQUASH RACKET                20
 TENNIS SOCKS                  4
SIMKINS     10  JUL 01
MABBOT       6  AUG 20
 SWIMMING TRUNKS              18
 RIDING HAT                    0
ADRIAN       1  JUN 20

03  LINE + 1.
05  COL 22      PIC X(10)   SOURCE NAME.
           ... etc ...

If you write PAGE OR control-id (this order can be reversed), the field will be produced if either or both conditions arise.  For instance, you might want the YEAR-NO and SEASON fields in the examples above (see item 2) to be printed again at the start of a new page even though there may have been no change.  In this case, you must write:

               05  ... PRESENT AFTER NEW YEAR-NO OR PAGE
               05  ... PRESENT AFTER NEW SEASON-NO OR PAGE

There may be a field, line, etc. that you would like produced the first time only.  To accomplish this, use PRESENT AFTER NEW REPORT.  (REPORT or FINAL is the highest control level and is always assumed even if not coded in the CONTROL clause.)  In the next example, it is in the PAGE HEADING:

            ** START OF REPORT **

       01  TYPE PH.
05  COL 15  VALUE "** START OF REPORT **".
         03  LINE + 1.
           ... etc ...

   To anchor the vertical starting line of this relative group, you may include a HEADING sub-clause in your RD.

If you write ABSENT instead of PRESENT, the clause will have exactly the opposite effect.  In other words, the field will be produced whenever it would have been ignored and vice versa.  In the next example, we use it to produce a "(CONTINUED)" message in our PAGE HEADING.  It will appear on every page except the first page after each new control value.  (This message is also useful in CONTROL HEADING groups.)

 PAGE 1               AREA 1
 PAGE 2               AREA 1  (CONTINUED)
 PAGE 3               AREA 2

         01  TYPE PH  LINE 60.
             05  COL 1     "PAGE:".
             05  COL + 2   PIC <999      SOURCE PAGE-COUNTER.
             05  COL 90    "AREA:".
             05  COL 96    PIC 9  SOURCE AREA-NO.

If there is an OCCURS clause, or a multiple LINES or COLUMNS clause, in the same entry, the PRESENT AFTER applies to the entire set of repetitions, so the occurrences are either all present or all absent.  (Compare GROUP INDICATE below (see rule 9).)

GROUP INDICATE behaves differently from the equivalent PRESENT AFTER clause if it is subject to OCCURS.  As soon as the first occurrence of the GROUP INDICATE item has been output, the GROUP INDICATE is switched off.  Hence the GROUP INDICATE clause only enables one entry to be output (the leftmost of topmost, depending on the axis), whereas PRESENT AFTER affects each occurrence equally and is switched off only when the whole table has been output.  This fact can be put to practical use if you want some text to appear with the first entry only:


                   ABSENT WHEN ADDR-LINE (R-LINE) = SPACES.
           05  COL 11      PIC X(32)  SOURCE ADDR-LINE (R-LINE).

   (Note that if you want "ADDRESS:" to be printed again each time ADDRESS-GROUP is GENERATEd you need to ensure that a control break occurs on each GENERATE of ADDRESS-GROUP.)  Using GROUP INDICATE in this example is better than coding PRESENT WHEN R-LINE = 1, since the latter will not work here if the first occurrence of ADDR-LINE might contain spaces.

If you use the PRESENT AFTER clause at the 01-level of a DETAIL group:


   and you require this group to appear as soon as there is a change to the control BRANCH-NO, your program should GENERATE this group before every other GENERATE for the report.  In spite of any appearance to the contrary, you may rest assured that the PRESENT AFTER clause will not make a group appear if your program does not GENERATE it.



This clause places a general COBOL condition on any report entry.  By evaluating the condition, report writer determines whether your entry is to be output as normal or skipped.

Format a

PRESENT-+ +- UNLESS-+ +-CONTROL +--+control-id-+
ABSENT--+                     +IS+

   Format b


PRESENT/ABSENT WHEN Clause: Coding Rules

The condition may be any valid COBOL conditional expression.  You are not restricted to simple conditions.  For example, the following compound condition is quite acceptable:


   Each of the data items you use in your condition may come from any COBOL SECTION (but see the note regarding PRESENT WHEN under 3.23.4 the SUM clause if you use SUM fields from the REPORT SECTION itself).  You may optionally place parentheses "(  )" around the whole conditional expression for clarity.  The symbols ">=" (greater than or equal to) and "<=" (less than or equal to) are allowed.  For more information, you should refer to your COBOL language reference (see Related Publications) under conditional expressions, for a list of the many varied ways of forming COBOL conditions.

The CONTROL IS control-id form if allowed only if the current group is a multiple CONTROL FOOTING, that is, one with a TYPE CONTROL FOOTING clause with more than one control-id operand, or TYPE CONTROL FOOTING FOR ALL.

The keyword PRESENT is implied if omitted.  Experience has shown that your code will be clearer if you include the PRESENT keyword in the single form of the clause but omit it in the multiple-choice form described below and in the following example:

           05  COL 11  PIC ZZ9    VALUE "OVER LIMIT"  PRESENT WHEN AMT > 100.
           05  COL 21  VALUE "BLACK"  WHEN IND = 1
                       VALUE "RED"    WHEN IND = 2
                       VALUE "WHITE"  WHEN OTHER.

The keyword ABSENT gives the clause the exact opposite meaning from the same clause with PRESENT; ABSENT WHEN condition is equivalent to PRESENT WHEN NOT (condition).  So you may find it more expressive to write:

                     ABSENT WHEN AGE < 21 AND LOCN = "NY"

   rather than:

                     PRESENT WHEN AGE NOT < 21 OR LOCN NOT = "NY".

   Whenever we refer to the PRESENT WHEN clause, you can assume that this term includes the ABSENT WHEN form.

PRESENT UNLESS is an older syntax, synonymous with ABSENT WHEN.

You may write these clauses in any report group entry other than the RD itself.  An entry that has a PRESENT WHEN clause is often referred to as a conditional entry.  The same field may be subject to any number of PRESENT WHEN clauses at any number of different levels.  The following sample group has one of the clauses in all the possible positions:

       01  TYPE PH   ABSENT WHEN PREPRINTED = "Y".      *>group level
         03  LINE 2.
           05  COL 20   "HACKNEY BEAUTY SUPPLIES".
           05  COL 60   "END OF YEAR"
               PRESENT WHEN THIS-MONTH = 12.            *>elementary level
         03  PRESENT WHEN FILE-END = "N".               *>group of lines
          04  LINE      "AMOUNT       DATE".
          04  LINE      PRESENT WHEN LAST-YEAR = "Y".   *>LINE level
           05  COL 1    "LAST YR      LAST YR".
           05  ABSENT WHEN YEAR-NO = ZERO.              *>group of columns
            06  COL 50  "YEAR:".
            06  COL +2  PIC 9999   SOURCE YEAR-NO.

If you nest more than one PRESENT WHEN clause by writing one clause in a higher entry and another in a lower entry beneath it, as in the preceding example, the outer condition takes precedence over the inner condition.  It is up to you to ensure that both conditions can be true at the same time.  Report writer will not check for contradictory combinations of conditions such as:

                   03  LINE 1        PRESENT WHEN A = 1.
                     05  COL 5  "X"  PRESENT WHEN A = 2.

   Here, if A is not 1, the whole LINE will not be output and that is an end to the matter: the test for A = 2 is short-circuited and the "X" will never be output.

   PRESENT/ABSENT WHEN Clause: Operation

Report writer tests the condition operand of your PRESENT WHEN clause each time it begins the processing of the report group.  If the condition is true, the field is output normally.  If the condition is false, the entry is ignored.  (For ABSENT WHEN , this rule applies vice versa.)  If the entry is a group entry, all the entries beneath it, including all its elementary entries, are also ignored.  When report writer "ignores" your entry, it treats the entry, for that instant only, as though you had not coded it.  Imagine the entry drawn in a rectangle of paper and imagine that you have a blank card that you can place over the rectangle to "mask" it out:

  03  LINE 3.
 | 05  COL 1 PIC X(6) SOURCE CITY |
 | 05 
 |   07  COL 13   "POLICY NO.:". |
 |   07  COL 25   PIC X(20)      |
 |       SOURCE POLICY-NO.       |
   05  COL 50 PIC X(20) SOURCE NAME.
       Mask for CITY-FLAG NOT = 1
           Mask for INS-FLAG = 0

   Remember, when the PRESENT WHEN is not on an elementary entry, your masking "card" must be large enough to cover all the lower-level entries, down to elementary level, as far as the next entry at the same level or higher. Now, to find out what will be produced when an entry is ABSENT, just cover the entry with the mask, so that it disappears from view.  The remaining entries are what report writer "sees" at that instant, and therefore what it will output.  For example, suppose that the field CITY-FLAG is 1 and INS-FLAG is zero in the example above.  What will report writer produce?  Just move the mask over the INS-FLAG group entry, as shown above, and this is what results:

                   03  LINE 3.
                     05  COL 1  PIC X(6)  SOURCE CITY.
                     05  COL 8  PIC XXX   SOURCE REGN.
                     05  COL 50 PIC X(20) SOURCE NAME.

   Keeping this simple principle in mind, consider the practical applications described in the following paragraphs:

To "blank out" a field with an absolute COLUMN, place your PRESENT WHEN on the absolute COLUMN entry and follow it with another absolute COLUMN entry:

         03  LINE 4.
           05  COL 10  PIC X(20) SOURCE STREET-NAME.

   If HOUSE-NO-FLAG is not 1, the entry in column 4 disappears.  Because the following column is in an absolute position, the first entry is blank:

     22  LONDON ROAD  << house number = 11
         DARK LANE << no house number

   This method also enables you to blank out an absolute LINE entry from a set of absolute LINE entries, leaving a gap in the printed output.

To insert a conditional field into the report line so that it displaces the fields that follow, simply make the entries that follow relative :

       01  AMOUNT-LINE   TYPE DETAIL     LINE + 1.
           05  COL +1    PIC 9<9(6)      SOURCE AMOUNT.

             DEBIT 12
             DEBIT 250
   When triggered by the PRESENT WHEN,
   the field in COLUMN 13 displaces the
   relative field that follows rightwards.

   The word DEBIT displaces the next field to the right because the next field has a relative COLUMN clause (COL +1).  Place your "mask card" over the DEBIT entry and you will see what occurs when its group is not produced:  the AMOUNT field is the first and only field to be produced, and its COLUMN number is +1.  It therefore appears in column 1.

   Similarly, the HOUSE-NUMBER field in the previous paragraph could be treated as a conditional insertion item by revising the code as follows.  (The "<" symbol eliminates the gap after short HOUSE-NUMBERs.)

         03  LINE 4.
           05  COL 2.
       *COL 4 can be coded here instead of COL +2:
           05  COL +2  PIC X(20) SOURCE STREET-NAME.

   This time, if HOUSE-NO-FLAG is not 1, there is no "gap" because the item that follows is relative.

     22  LONDON ROAD  << house number = 11
 << no house number
 << but this time no gap

To place one of a series of alternative entries into the same column positions, code several entries, each with a PRESENT WHEN clause.

    Take care that the conditions are mutually-exclusive so that none of the fields can overlap:

         05  COL 1     PIC X(16)  SOURCE SURNAME.
         05  COL 21    VALUE "MINOR"      PRESENT WHEN AGE < 16.
         05  COL 20    PIC ZZ9 SOURCE AGE PRESENT WHEN AGE > 15 AND < 65.
         05  COL 18    VALUE "OLD TIMER"  PRESENT WHEN AGE > 64.

 GOLIGHTLY            27

   Notice that the conditional fields need not all start in the same column and that the column numbers need not be strictly in sequence, provided that they are in sequence when we mask out the entries that are ABSENT.

   If all your entries start in the same column and are all literals or identifiers with the same PICTURE, you will find it more convenient to use a multiple-choice entry.  (See 3.18.5 Multiple-Choice Form, below.)

   You can also use the technique shown here to choose one LINE from a set of alternative absolute LINE entries.

To string out (concatenate) a number of conditional fields along the report line, where any combination could be present, use a series of relative conditional entries:

   NAME            ... SPORTS PLAYED ...
 LLOYD          GOLF

       01  TYPE PH      LINE 1  "  NAME            ... SPORTS PLAYED ...".
       01  SPORTS-LINE  TYPE DE          LINE + 1.
           05  COL 1    PIC X(12)        SOURCE NAME.
           05  COL 14.
           05  COL + 2  VALUE "RUGBY"    PRESENT WHEN RUGBY-FLAG = "Y".
           05  COL + 2  VALUE "TENNIS"   PRESENT WHEN TENNIS-FLAG = "Y".
           05  COL + 2  VALUE "GOLF"     PRESENT WHEN GOLF-FLAG = "Y".

   The dummy entry specifying COL 14 gives you an anchor point at which to begin.  It ensures that the first sport-field will appear in column 16.

   If you include many optional fields using relative COLUMNS, you may run the risk of causing line overflow if a large number happen to be present.  If you want report writer to "wrap the data round" on to a continuation line, you must code a WRAP clause (see WRAP Clause).  Otherwise, it will truncate the line and create a run time line overflow message.

   A similar problem might arise if you define an entry in an absolute column following your series of optional entries.  If there were too many entries present, report writer might signal a run time column overlap error.  If there is a risk of line overflow or column overlap, you must do some extra processing before you GENERATE the line, to make certain that no more than the maximum number of fields will be present.

To print one or more of a series of conditional lines in a report group, use relative LINE clauses and code your PRESENT WHEN clauses at the LINE level or above:

 MEMBER:    PHILLIPS       AGE:   34
                 AGE OF SPOUSE:   30
               NO. OF CHILDREN:   3
            BASIC SUBSCRIPTION:   $230
             GOLF SUBSCRIPTION:   $80

 MEMBER:    THOMPSON       AGE:   25
            BASIC SUBSCRIPTION:   $290

   In this example, the lines showing AGE OF SPOUSE and NO. OF CHILDREN are not to be produced unless there is a "family membership" condition, and the line showing GOLF SUBSCRIPTION is not to appear unless the member plays golf.  Here is some suitable report writer code:

       01  MEMBER-RECORD      TYPE DE.
         03  LINE + 2.
           05  COL 1          "MEMBER:"  ... etc ...
          04  LINE + 1.
           05  COL RIGHT 30   "AGE OF SPOUSE:".
           05  COL 34         PIC <99    SOURCE SPOUSE-AGE.
          04  LINE + 1        ABSENT WHEN NO-CHILDREN = ZERO.
           05  COL RIGHT 30   "NO. OF CHILDREN:".
           05  COL 34         PIC 9      SOURCE NO-CHILDREN.
         03  LINE + 1.
           05  COL RIGHT 30   "BASIC SUBSCRIPTION:".
           05  COL 34         PIC $9<99  SOURCE BASIC-SUB.
         03  LINE + 1         PRESENT WHEN GOLF-FLAG = "Y".
           05  COL RIGHT 30   "GOLF SUBSCRIPTION:".
           05  COL 34         PIC $9<99  SOURCE GOLF-SUB.

   Because report writer only "sees" the lines that have not been "masked out", it performs a sophisticated page-fit test.  Report writer will test the availability of only the number of lines that will actually be output.  If THOMPSON in the above example begins on line 59 of a 60-line page, his record will appear on that page because at that particular instant the DETAIL group is actually only 2 lines in depth.

The form CONTROL IS control-id is a special condition that can be used only in a PRESENT WHEN clause within a multiple CONTROL FOOTING.  It is true if the level of the CONTROL FOOTING currently being generated is that of control-id.  For example, if the TYPE clause is:

                 01  TYPE CF FOR COUNTY, CITY, STREET.

   you may introduce any amount of variation for each level by coding, for instance:

                     05  PRESENT WHEN CONTROL IS CITY.
                       07  COL 1    "Name of city:".
                       07  COL +2   PIC X(20)  SOURCE CITY.

If PRESENT WHEN is used in the same entry as an OCCURS clause or a multiple SOURCES or VALUES, the PRESENT WHEN applies to each occurrence individually.


The general principles of the PRESENT (or ABSENT) WHEN clause apply when you use it with a SUM clause or with an item that is totalled.  Report writer acts according to certain vital principles, as follows:

Only those SUM operands that were PRESENT when they were processed will be added to a total field.  An item will not be added if it is subject to a PRESENT WHEN and the condition is false.  This means that you may total a series of "optional" fields and obtain a total that is true in the sense that only the fields that are processed appear in the total field.  (The word processed includes the case of unprintable fields - those having no COLUMN clause - which do not appear in the report.)

   The following example illustrates this principle:


    BASIC SUBSCRIPTION:         $25
    SQUASH SUPPLEMENT:          $40
           TOTAL DUE PLEASE:    $85

INITIATION FEE:             $40
    BASIC SUBSCRIPTION:         $25
    GOLF SUPPLEMENT:           $150
    SQUASH SUPPLEMENT:          $40

05  R-JOIN       COL 31       PIC $$$9     SOURCE  WS-JOIN-FEE.
         03  LINE.
           05  COL 4        VALUE "BASIC SUBSCRIPTION".
           05  R-BASIC      COL 31       PIC $$$9     SOURCE  WS-BASIC-SUB.
05  R-PLAYER     COL 31       PIC $$$9     SOURCE  WS-PLAYER-SUB.
         ... etc ...
03  LINE.
      *SUM clause shows total of only those fields that appear in report
05  COL 30       PIC $$$$9

If you write a SUM clause and a PRESENT WHEN together in the same entry, the total will not appear in the report if the entry is not present .  But neither will it be cleared to zero, because no total is cleared until it has been output.  Values will continue to be accumulated in the total field even though the SUM entry may not always be present.  In other words, the PRESENT WHEN in the SUM entry can delay the generating and clearing of your total field but it has no effect on the totalling itself.

   These facts may be utilized if you wish to generate a number of fields repeatedly but delay the appearance of their cross-foot total.  In the following example, we have a variable number (up to 31) of fields, but only up to five will fit on a line.  The total also occupies a field in the line.  The following solution takes advantage of the fact that if a DEPENDING ON operand is higher than the maximum, the maximum (in this case 5) is assumed.  (This problem can also be resolved now using the WRAP clause.)

2    $200    4    $150   11     $50   15     $90   21     $60
26    $100   28     $60 TOTAL:  $710

     1    $150    3    $240    7    $120    9    $210   11    $160
12    $210   14     $40   17     $20   19     $80   23    $180
24    $210   25     $60   28    $210 TOTAL: $1890

         03  LINE + 2          COL 1      PIC XXX    SOURCE MONTH.
         03  LINE.
           05  COL 3    OCCURS 5   STEP 13    VALUE "DAY  AMOUNT".
07  COL 4         PIC Z9     SOURCE W-DAY (R-SUB).
07  R-AMOUNT      COL 9      PIC $(4)9  SOURCE W-AMOUNT (R-SUB).
07  COL + 2       VALUE "TOTAL:".
07  COL + 1       PIC $(5)9  SUM OF R-AMOUNT.

To accumulate a series of totals split up by some category, that is into separate "pigeonholes" or "buckets", you may use a series of unprintable SUM fields partitioned by a series of mutually exclusive (and exhaustive) PRESENT WHEN condition clauses.  Suppose that you wish to print "Sales of Ice Cream" and you want to total separately the sales of Vanilla, Strawberry and Chocolate flavors.

   This is done by splitting up the sales entry invisibly into vanilla, strawberry and chocolate sales, as though we were actually splitting it thus at the place where it is printed.  We then SUM each unprintable entry to form three separate totals:

                       ICE CREAM SALES        YEAR 1992

    DATE          FLAVOR              SALES AMOUNT ($)

JAN 01         VANILLA                   1000
FEB 02         STRAWBERRY               11000
FEB 28         CHOCOLATE                 5500
MAR 12         CHOCOLATE                 4500
APR 03         VANILLA                   6000
    ...           ...                        ...


VANILLA                 32000
STRAWBERRY              12500
CHOCOLATE               15000

      01  ICE-SALES-LINE     TYPE DE.
03  LINE.
05  COL 3          PIC XXXB99      SOURCE SALES-DATE.
01  TYPE CF.
03  LINE + 2.
05  COL 18         VALUE "VANILLA".
05  COL RIGHT 47   PIC Z(7)9       SUM R-VANILLA.
03  LINE.
05  COL 18         VALUE "STRAWBERRY".
05  COL RIGHT 47   PIC Z(7)9       SUM R-STRAWBERRY.
03  LINE.
05  COL 18         VALUE "CHOCOLATE".
05  COL RIGHT 47   PIC Z(7)9       SUM R-CHOCOLATE.

   If you have a larger, or variable, number of categories, it will be easier to defined repeating values and totals using OCCURS.  Suppose that the flavors VANILLA, STRAWBERRY etc. are held in a table W-FLAVOR OCCURS 20.  The following code could now replace the corresponding entries used above:

           05  R-SALE   OCCURS 20 TIMES  VARYING R-FLAVOR-NO  PIC 9(7)
                        PRESENT WHEN R-FLAVOR = W-FLAVOR (R-FLAVOR-NO).
           05  COL 18         PIC X(16)   SOURCE W-FLAVOR (R-FLAVOR-NO).
           05  COL RIGHT 47   PIC Z(7)9   SUM R-SALE.

The Multiple-Choice Form

   v                                                    |
SOURCE clause--++-------+WHEN -+-condition-----------+>
VALUE clause---++ PRESENT+     +CONTROL +--+control-id+
FUNCTION clause+                      +IS+

SOURCE clause---++-------+ WHEN OTHER -+
VALUE clause----++ PRESENT+
FUNCTION clause-+

If you need to specify a series of alternative contents for a particular elementary field, you can do it with a single entry, instead of several separate entries containing PRESENT WHEN clauses.  You code the entry with several SOURCE, VALUE, or FUNCTION clauses, each followed immediately by a PRESENT WHEN clause.  One of the PRESENT WHEN clauses, and only one, may be of the form PRESENT WHEN OTHER.  It is normally placed last in the list (although this is not syntactically required).

Report writer scans your WHEN conditions, starting with the first in the order of coding, until it finds a condition that is true.  It then uses the SOURCE, VALUE, or FUNCTION clause preceding that PRESENT WHEN clause and ignores all the remaining PRESENT WHEN and SOURCE, VALUE or FUNCTION clauses.  So your conditions need not be mutually exclusive:  the testing is on a "first-come-first-served" basis.  Here is an example:

           05  COL 23  PIC ZZZ9   SOURCE INCOME WHEN TYP-IND = "A"
                                  SOURCE TAX    WHEN TYP-IND ALPHABETIC
                         SOURCE INCOME - TAX    WHEN TYP-IND = "1" OR "2".

   The contents of TAX will be produced when TYP-IND is between "B" and "Z" inclusive.

If your conditions do not cover all the possibilities, you have three choices:

Put WHEN OTHER instead of WHEN condition against the entry you would like to act as the catch-all, default, or wastebasket :

           05  COL 25  VALUE "TOO BIG"    WHEN AMOUNT > 99999
                       VALUE "TOO SMALL"  WHEN AMOUNT < 100
                       VALUE "JUST RIGHT" WHEN OTHER .

Code an extra "choice" using WHEN OTHER to indicate an error:

           05  COL 100 VALUE "LONDON"       WHEN CITY-CODE = "LN"
                       VALUE "BRISTOL"      WHEN CITY-CODE = "BR"
                       VALUE "UNKNOWN CITY" WHEN OTHER .

Leave it as it is.  If there is a case not covered by your multiple-choice entry, the whole field will then simply be ABSENT.  For example:

           05  COL 1   VALUE "DEAR".
           05  COL +2  VALUE "MR"      WHEN TITLE-CODE = 1
                       VALUE "MRS"     WHEN TITLE-CODE = 2
                       VALUE "MISS"    WHEN TITLE-CODE = 3.
           05  COL +2  PIC X(20)       SOURCE SURNAME.

   If SMITH has TITLE-CODE equal to 0, this will result in:

                       DEAR SMITH

If you specify only VALUE literal clauses without a PICTURE clause, they may be of different sizes, as in the preceding example.  The actual size of the field produced will be that of the chosen value.  Since SURNAME above has a relative COLUMN, you will obtain:

                       DEAR MR SMITH
                   or  DEAR MRS SMITH
                   or  DEAR MISS SMITH

You cannot repeat the PICTURE clause in an entry (nor any of the other clauses other than SOURCE, VALUE, and FUNCTION), so if your choices need different PICTUREs you must usually code a series of separate entries.  However, you may still be able to choose a PICTURE that suits each of the choices, such as PIC ZZZ9 to cover both PIC ZZZ9 and PIC ZZ9, and thus still be able to use a single entry with a multiple-choice PRESENT WHEN clause.

You can form a SUM of a multiple-choice entry.  Report writer will select the correct choice (if any) before adding it to the total:

           05  PAYMENT  COL 33     PIC ZZZZ9
               AMOUNT - TAX                   WHEN CAT = 1
               AMOUNT - TAX - CALIFORNIA-TAX  WHEN CAT = 2
               AMOUNT - EXPORT-TAX            WHEN CAT = 3.
           05  ... SUM OF PAYMENT ...

   This adds only the one correct choice each time.

You can use the CONTROL IS control-id form of condition anywhere in a multiple-choice entry.  For example:

         03  LINE + 2.
           05  COL 1    VALUE "Totals for".
           05  COL + 2  VALUE "state"  WHEN CONTROL IS STATE
                        VALUE "county" WHEN CONTROL IS COUNTY
                        VALUE "city"   WHEN OTHER.

You can use multiple SOURCE and VALUE clauses within your multiple-choice entry.  For example:

           05  COLS  23  43  64   PIC ZZZ,ZZ9.99
               SOURCES  VAL-1 VAL-2 VAL-3               WHEN TYP = "D"
               SOURCES (- VAL-1) (- VAL-2) (- VAL-3)    WHEN OTHER.

You cannot place a multiple-choice entry at the same level as a LINE clause.  The construct:

         03  LINE 1   COL 1   VALUE "WHITE" WHEN SHADE = 0
                                    "BLACK" WHEN SHADE = 1.

   is therefore illegal and must be replaced by:

         03  LINE 1.
           05  COL 1   VALUE "WHITE" WHEN SHADE = 0
                             "BLACK" WHEN SHADE = 1.


The REPEATED clause arranges body groups side-by-side across the page.


           |         +TIMES+++
EVERY +integer-2+---------+|
           |                 +
WIDTH+         +-COLUMNS-+|
           |                                 +--COLS---+|
EVERY +integer-2+---------++
WIDTH +         +-COLUMNS-+
                      +TIMES+                +--COLS---+

REPEATED Clause: Coding Rules

Write this clause at the 01-level of body groups (DETAIL or CH/CF) only.

You must code either the TIMES phrase or the EVERY/WIDTH phrase, or (preferably) both.  EVERY and WIDTH have the same meaning.

Code only the left-hand report group.  Report writer will automatically offset successive groups to the right of the left-hand group.

If you use the EVERY/WIDTH phrase, draw an imaginary "smallest box" around your group:

|  aaaaaaaaaaaa   aa    aaaaaaaaaaaa   |
|bbbbbbbbbbb                           |
|    ccccccccccc        cccc           |
|       ddddddd ddddddddddddddddddddddd|
 ^                                    ^
 leftmost column       rightmost column

   The width of your box must not be greater than the EVERY/WIDTH integer-2.  If any of your lines can have a variable rightmost column position, you must use the maximum expected size while drawing your box, but report writer cannot always predict the actual size at precompilation time.  If the actual width of the group then causes it to encroach into the area occupied by the group to its right, a run time error will be issued.

There are no other restrictions on the size of your group or the clauses that you can use within it.  For example, you may specify any number of LINES.

If you omit the TIMES phrase, report writer will examine your EVERY/WIDTH phrase and calculate how many repetitions of the group it can fit within the LINE LIMIT.  If you use the identifier form of the LINE LIMIT clause, report writer will do this dynamically when you GENERATE the groups.

If you omit the EVERY/WIDTH phrase, report writer will examine your TIMES phrase and will calculate how widely it can space the repeats of your group at regular intervals.  You cannot use the identifier form of the LINE LIMIT clause in this case.

The rightmost column of the rightmost REPEATED group must not go beyond the LINE LIMIT.  This possibility can arise only if you use both the TIMES phrase and the EVERY/WIDTH phrase.  In all other cases, report writer does the fit for you and makes sure that the repeats will fit side-by-side without violating the LINE LIMIT.

The REPEATED clause is not allowed in a report group that has no LINE clauses.

REPEATED Clause: Operation

If you code a REPEATED clause in a DETAIL group, report writer will place consecutive groups side-by-side:

   group #1


   group #2


   group #3

   Each instance of the group is produced by one GENERATE.  For example, to produce the above 3-up pattern, you would issue three successive GENERATEs.  Each instance may display different data and may differ from its companions in certain characteristics by virtue of any PRESENT or OCCURS... DEPENDING clauses that you have coded.

Report writer sets up a buffer to hold your repetitions.  If your group is REPEATED three times, as in the diagram above, this is what happens:

First GENERATE:   The group is not produced but is placed in the buffer; the special register REPEATED-COUNTER is set to 1.

Second GENERATE:   The second group is also not produced but is placed in the buffer; REPEATED-COUNTER is set to 2.

Third GENERATE:   All three groups are produced side-by-side, with the second and third groups offset by the number of columns given in the EVERY phrase.  The buffer is then cleared, ready for the next three groups.  REPEATED-COUNTER is reset to zero.

   The starting point for the repetitions is given by the COLUMN numbers in your group description.  These will become the COLUMN numbers of the left-hand group.  The following example shows the effect obtained:

         03  LINE + 2.
           05  COL 20      VALUE "xxxx".
           05  COL 26      VALUE "yyyyy".
         03  LINE + 1.
           05  COL 23      VALUE "zzzzzz".

xxxx  yyyyy
xxxx  yyyyy
xxxx  yyyyy
19-column offset
at start: decided
by your choice of
20 for first

^  ^  ^
20 23 26
offset between
from EVERY


^  ^  ^
40 43 46


^  ^  ^
60 63 66

If a different body group is produced, no more groups are placed side-by-side and any groups already in the buffer are output.  Any unused repetitions will result in blanks on the right-hand side.  The effect of writing:

  INITIATE report
  TERMINATE report

   is shown in the following:

     group A      group A     group A
    group A     group A    (blank entry)

group B

(blank entry)

   where A and B are DETAIL groups and A is REPEATED 3 TIMES.

   Group B may also be REPEATED, but even if it is also REPEATED 3 TIMES, it will not be printed alongside group A, but will start a new series of repetitions.  The same effect is seen if your program issues a TERMINATE when there are groups still in the buffer.  report writer will first produce them with blank unused entries on the right, so that no data will be lost.

If you need to have different groups placed side-by-side, you will have to define a single group and use the PRESENT WHEN clause above several LINE entries to create the impression of different groups at run time.

If a control break occurs that results in a CONTROL HEADING or CONTROL FOOTING group, it has the same effect as when you GENERATE a different DETAIL group.  That is to say, any groups in the buffer are first output.  This is true even if your CONTROL group is a dummy (with no LINE clauses to cause output).  Briefly, your groups always appear in chronological order.

If a clause in your group references LINE-COUNTER (in a condition or as a SOURCE), you will always obtain its correct effective value.  report writer updates LINE-COUNTER just as though the group were actually being output, although the group is being placed in a buffer in memory.  Then, when the next group is GENERATEd, LINE-COUNTER immediately reverts to the value it had at the start of the preceding group.

The page-fit test is applied to each repetition in turn.  So, if your REPEATED group has a depth that may vary (because of a PRESENT WHEN clause or an OCCURS...DEPENDING at LINE level), room must exist for the largest group that has been GENERATEd in the current "pass" across the line.

You may place a REPEATED clause in a CONTROL HEADING or CONTROL FOOTING group, but this is of no use except when you use summary reporting (GENERATE report-name), because there is no other way that the same CONTROL HEADING or CONTROL FOOTING group can appear twice in succession.

SIGN Clause

The SIGN clause enables a printable sign character to be produced automatically when the PICTURE has an "S" symbol.

   Format a

SIGN+--++ +- TRAILING-+ +-SEPARATE +---------++
          +IS+                         +CHARACTER+

   Format b

SIGN+--+++- LEADING literal-1++-TRAILING literal-2+

SIGN Clause: Coding Rules

If you write a SIGN clause in an elementary entry, the entry must have a numeric PICTURE with an "S" symbol.

This clause acts on elementary fields, but you may also code it in a group level entry, where it applies to all numeric elementary entries within the group whose PICTUREs begin with the "S" symbol.

Format b is unique to the REPORT SECTION.  Each literal must be a single character non-numeric literal.  At least one of the phrases must be present.

SIGN Clause: Operation

The use of the format a SIGN clause has been superseded by the "+" and "-" symbols of the PICTURE clause.  It is included for consistency with basic COBOL standards.  Refer to your COBOL language reference for further information.

The format b SIGN clause enables you to place symbols of your choice on the left or the right of any signed printed item to represent a negative amount.  The LEADING literal (if specified) is placed immediately before the first character of the report field.  If leading spaces are suppressed with the Z or floating currency symbol, the literal is placed immediately before the first non-space character.  The TRAILING literal (if specified) is placed in the last character position.  For example, to place parentheses around a negative payment (a common accounting requirement), you would code:


   which would output a value of -12 as:   (12)
   while a value of -1234 appears as:   (1234)

   This feature can be made to work for positive values by specifying the negative of the source (SOURCE (- PAY) in the case above).


This clause specifies the source field (or expression) that provides the contents of a field in your report.  The source field is usually outside the REPORT SECTION, but may also be implicitly defined within it.

                   v             |
SOURCE-+--+-+ +-expression-+ +- ROUNDED-+
    |        +IS+ |

SOURCE Clause: Coding Rules

Any valid COBOL identifiers or arithmetic expressions may be used as operands, including any COBOL term that may be the source item of a MOVE or COMPUTE; for example, report writer special registers such as PAGE-COUNTER, GLOBAL or EXTERNAL items, and special compiler registers such as LENGTH OF.

Each operand may be subscripted and/or qualified if necessary.  For example:


   The operand may have as many qualifiers, subscripts or indexes as are normally permitted for the subject of a MOVE statement.  Relative subscripting and reference modification may be used.

You must also code a PICTURE clause in the same entry (unlike VALUE, which need not have a PICTURE).  The PICTURE used must be compatible with the PICTURE of the operand(s).  If you are in any doubt, look at the description of the identifier where it is originally defined in the FILE, WORKING-STORAGE or LINKAGE SECTION of your program.  Ensure that its PICTURE is unedited and that you are not attempting to produce a COMPUTATIONAL field from a PICTURE X format.  The two PICTUREs may be of unequal length, in which case there will be truncation or space-filling on the right (for a non-numeric field) or truncation or zero-filling on the left (for a numeric field).  The rules for the SOURCE statement are exactly those of the MOVE or COMPUTE statements of procedural COBOL.

The SOURCE IS and SOURCES ARE keywords may be omitted, except when immediately following a VARYING clause.  We shall still refer to the clause as a SOURCE clause, however.

An expression may be any arithmetic expression containing any of the following symbols and keywords:

+   for addition
-   for subtraction
*   for multiplication
/   for division
**   for forming an exponent
( and ) to prioritize evaluation or to "structure" the code for documentation
SUM for a total (automatically reset to zero after output)
COUNT to show the number of times another REPORT SECTION item has appeared (also reset to zero after output)

   In addition, the expression may have any number of identifiers, and these may be subscripted or qualified.  Here are some examples of expressions:



   The rules for forming an expression are exactly as for the COBOL PROCEDURE DIVISION, as described in your COBOL language reference.  For more information see SUM Clause.  The effect of a potential zero divide or size error depends on the choice of action on overflow. (See OVERFLOW Clause.)

The ROUNDED phrase may be used in the same entry if you use a numeric PICTURE that has fewer digits to the right of the decimal point than the SOURCE identifier.  It will ensure that the value produced is the numerically closer of the two possible values, instead of always truncating the unwanted digits.  You can use ROUNDED with a single identifier as well as with an expression.  (So you need not code "+ 0" for ROUNDED to be legal.)  In the following example:

                     05  COL 20    PIC 999   SOURCE SALARY  ROUNDED.

   if SALARY contains 100.50 or 100.60 or 100.99, the value produced will be 101, not 100.

   For more details of the ROUNDED keyword, see in your COBOL language reference under the COMPUTE verb.  ROUNDED is a clause in its own right and thus may be written at any location in the entry.  If you have a multiple form of the SOURCE clause, or more than one such clause (see SOURCE Clause), ROUNDED will affect all of them wherever applicable.

You can indicate a multiple-choice entry by appending WHEN or UNLESS condition to the SOURCE clause, and then coding further consecutive pairs of SOURCE and WHEN/UNLESS clauses in the same entry (see Multiple-Choice Form).

SOURCE Clause: Operation

Rules for Generating Report Field

   The effect of the SOURCE clause is best described by reference to the COBOL MOVE or COMPUTE statements, because it obeys identical rules:

 Form of SOURCE clause

 (without ROUNDED)

 identifier ROUNDED

 (without ROUNDED)

 Equivalent procedural statement

 MOVE identifier TO report-field

 ADD ZERO, identifier
 GIVING report-field ROUNDED

 COMPUTE report-field = expression

 COMPUTE report-field ROUNDED
  = expression

   The special registers CURRENT-DATE and TIME-OF-DAY of OS/VS COBOL and DOS/VS COBOL make use of the conceptual data items DATE and TIME.

   If the report field has "<" PICTURE symbols, or begins in a variable position, report writer will not store the result directly in the report field, but will use an intermediate area.

Reference to controls

   If the SOURCE clause refers, directly or  indirectly, to a CONTROL operand, and the SOURCE is fetched at CONTROL FOOTING time, the contents of the control identifier before the control break will be used.  This means you will obtain before-the-break contents for your control fields in the following report groups:


In the PAGE FOOTING and PAGE HEADING, if the page advance was caused by a CONTROL FOOTING group.

   This rule applies whether the CONTROL operand is used as a SOURCE by itself, or as a subscript, or as part of an expression.  It also applies if you refer to the CONTROL operand via a redefinition, or via a group field that contains it, or a subordinate field.  This is because the pre-break values are temporarily stored directly back in the control fields outside the REPORT SECTION while CONTROL FOOTING processing is being done.

   One important consequence of this rule is that, if you use fields defined under an FD in the FILE SECTION as controls, your program must not execute any report writer statements - not even a TERMINATE - after the input file releases the buffers.  The correct order for "close down" is therefore:

             TERMINATE report
             CLOSE all report files and input files

   See CONTROL Clause, and GENERATE Statement for further details.

Multiple SOURCES

If you use the multiple form of the SOURCE clause by writing more than one identifier or expression after the keyword, you will avoid the effort of coding several separate entries.  Note the following:

You may include the keyword NONE to indicate that a particular field is to have no contents stored in it.  It is then treated as ABSENT.  An example of the use of NONE will be found under the LINE clause (see Multiple LINES Clause).

Your entry must be subject to at least one of the following:

fixed OCCURS clause (not OCCURS...DEPENDING), or

multiple LINES clause, or

multiple COLUMNS clause.

The number of terms in your multiple SOURCES must equal the total number of repetitions the entry is subject to in all dimensions, or the number of repetitions of one or more of the inner dimension(s).  For example, with the following layout:

                   03  LINE OCCURS 4.
                    04  OCCURS 3.
                     05  COLS +2, +1   PIC...   SOURCES ARE .....

   The number of SOURCES should be either 2 (just the inner dimension), 6 (the product of the inner two dimensions), or 24 (all the repetitions).

If the terms cover more than one dimension, they are distributed along the innermost dimension, periodically stepping to the next entry in the outer dimension(s).  For example:

         03  LINE 2    STEP 1  OCCURS 3.
           05  COL  2  STEP 5  OCCURS 4  PIC XXX   SOURCES ARE
               MONTH-NAME(1)  MONTH-NAME(2)  MONTH-NAME(3)  MONTH-NAME(4)
               MONTH-NAME(8)  MONTH-NAME(6)  MONTH-NAME(7)   MONTH-NAME(5)
               MONTH-NAME(9)  MONTH-NAME(10) MONTH-NAME(11) MONTH-NAME(12).

   will result in:


   This technique is useful when your SOURCE items are not already conveniently arranged in a table or when, as in the case above, the order is irregular.

If there are two or more dimensions and the number of terms matches only the inner dimension(s), the terms are recycled from the first SOURCE operand for each repetition of some outer dimension.  For example, in the following case:

         03  LINE OCCURS 4.
           05  COLS 1, 6, 11   PIC...   SOURCES ARE JAN, FEB, MAR.

   the values of JAN, FEB and MAR will be repeatedly stored in each line.  However, you may vary the contents actually stored by allowing a VARYING operand to advance in step with each occurrence of the outer dimension and by using it as a subscript in the lower-level entry:

           05  COLS 1, 6, 11   PIC...   SOURCES ARE
               QTR-MO-1 (LINE-SUB), QTR-MO-2 (LINE-SUB), QTR-MO-3 (LINE-SUB ).

If a ROUNDED phrase is present in the entry, every SOURCE item will be rounded.

The multiple SOURCES may be used as one or more of the alternatives within a multiple-choice entry.  You need not use a multiple SOURCES in every alternative:

           05  COLS 1, 12, 25       PIC ZZ,ZZZ,ZZZ9
                  (- BASIC-AMOUNT) (- TAX) (- EXTRA)  WHEN OTHER.

You may omit the SOURCE keyword, except when immediately following a VARYING clause.

Other examples of the multiple SOURCES clause will be found under Multiple COLUMNS Clause and Multiple LINES Clause.

STYLE Clause

This clause enables the program to make use of any special effects provided by the printer or output device.

                 v        |
           +IS+|             +-
WHEN condition-+ |
NORMAL -----------------------+

STYLE Clause: Coding Rules

STYLE may be coded at any level, including in the FD (see Report Files) or RD (see REPORT SECTION and RD).  The WHEN condition phrase cannot be used in the FD or RD entry.  STYLE cannot be used if the device-name of the corresponding file is NONE.

NORMAL may be coded instead of a style-name, meaning that no special effect is to be produced.  It must be the only style-name in the clause and there must not be a WHEN condition phrase.

Apart from NORMAL, each style-name names a style or special effect that must be obtainable from the output device.  The type of output device in use is given in the TYPE clause of the SELECT statement.  The style-names available are either predefined or user-defined for the particular output device.  This check, and the processing of the styles themselves, may be delayed until run time by writing DEFERRED in the TYPE clause.  This enables the program to run, in theory, with a variety of different output devices, even when they are widely dissimilar.  For a mainframe, special device handling is usually the province of a user-written report file handler - see Installation and Operation.  For example, STYLE HIGHLIGHT might be implemented by any of the following means:

shadow printing,
switching to a different font,
printing in larger letters,
on a screen, by displaying intense,
"double-hammering" on an impact line-printer.

The following are standard device-independent style-names.  The first two are available with every TYPE of printer (other than TYPE NONE).  The last two are available with all printers except the most basic.

UNDERLINE    causes the report field to be underscored.  It is used for headings.

HIGHLIGHT    causes the report field to stand apart from the others, normally by appearing in bold or intense.  It is used to give emphasis to certain fields.

ALT-FONT    causes the report field to appear in a second contrasting font or typeface, such as italic.

GRAPHIC    causes the report field to appear in a third contrasting font.

   The remaining style-names used in the examples that follow are purely for the purpose of illustration, and are not necessarily available on any particular device.

Style-names are grouped into mutually-exclusive classes.  Styles HIGHLIGHT, ALT-FONT and GRAPHIC are mutually-exclusive but UNDERLINE belongs to a separate (one-member) class.  The classes are defined in the Printer Description File.  It is not valid to code two styles belonging to the same class in the same entry.  Thus the following clause is not valid:

                              STYLE IS ALT-FONT GRAPHIC

   However it is valid to place different members of the same class in nested entries, in which case the prevalent style is noted and restored at the end of the nested entry.  Thus, in the following entries, TOMATO is RED while all the other entries are GREEN:

                   03  LINE.
                     05  STYLE GREEN.
                       07  COL 1       PIC X(20)  SOURCE BEAN.
                       07  COL 21      PIC X(20)  SOURCE TOMATO  STYLE RED.
                       07  COL 41      PIC X(20)  SOURCE ARTICHOKE.
                       07  COL 61      PIC X(20)  SOURCE PEA.

The STYLE clause cannot be repeated in an entry.  Hence, if a multiple-choice entry is required, with a different STYLE on each choice, separate entries must be coded.

If STYLE is used in a report that uses the PAGE BUFFER feature it should not be coded in a Report Group Description at a level higher than the LINE level.

No style-name may be the same as one which is already in effect.  For example, the following is illegal:

                     05   LINE  STYLE IS ALT-FONT.
                       07  COL 1  STYLE IS ALT-FONT UNDERLINE.

The STYLE clause cannot be used on an unprintable elementary entry.

STYLE Clause: Operation

Report writer implements the STYLE feature in one of three ways:

By inserting non-printable control characters, or escape sequences, into the report data, before or after the data affected, or both.

By re-printing a line or part of a line without advancing the carriage.  This method is commonly used to highlight text and occasionally to produce an underline effect.

By some special technique chosen and implemented by the user (see Independent Report File Handlers).

   The method of implementation of each style is defined explicitly for each TYPE of device, and may be altered by the user.

The STYLE clause is transparent to the layout of the report.  That is, it does not affect any of the other clauses or entries in the report description.  For example, COLUMN numbers are unchanged, even though report writer may be inserting extra control sequences into the report lines.  You can therefore simply add STYLE clauses to enhance existing programs.

Several STYLE names can be combined in one clause, for example:


   Here the different characteristics are simply superimposed on each other (but see next item).

Two or more styles may be treated as related and perform a single action as a result of the combination.  For example

                    STYLE CG-TIMES 12CPI PORTRAIT

   One of these combinations might well be necessary to make use of a particular font and will result in a single escape sequence being sent to the device.

   The combination of style-names can be coded in any order.  It may also be represented by coding different parts of the combination at different levels .  In the following example, the STYLE 10CPI clause at the group level may not necessarily cause any control characters to be output.  Instead, it modifies the STYLE clauses below it, so that the effect is as though STYLE COURIER 10CPI and STYLE UNIVERS 10CPI had been coded at the lower levels:

                   03  LINE  STYLE 10CPI.
                    04  STYLE COURIER.
                     05  COL 1     VALUE "Customer Name:".
                     05  COL 21    PIC X(20)  SOURCE CUST-NAME.
                    04  STYLE UNIVERS.
                     05  COL 51    VALUE "Special Notes:".
                     05  COL 21    PIC X(40)  SOURCE SPEC-NOTES.

The scope of the STYLE clause is decided by the level of the entry in which it is coded, thus:

a.   In an elementary entry, the STYLE clause applies only to the elementary field, for example:

         03  LINE.
           05  COL 1     PIC X(20) SOURCE CUST-NAME.
           05  COL 25    PIC $(5)9.99  SOURCE ACCOUNT-BALANCE.
           05  COL 37    PRESENT WHEN ACCOUNT-BALANCE < 0
                         VALUE "IN ARREARS" STYLE HIGHLIGHT .

b.   In a LINE entry, the STYLE clause applies to the whole line, as in:

         03  LINE        STYLE EXTRA-WIDE.
           05  COL 1     "Annual Report".
           05  COL 31    PIC X(40)           SOURCE COMPANY-NAME.
           05  COL 75    PIC "Year: "X(4)    SOURCE ACCOUNT-YEAR.

c.   In a report group entry, the STYLE clause applies to the whole group, for example:


d.   In an RD entry, the STYLE clause applies to the entire report:


   If any control characters are output, this happens during the execution of each INITIATE or TERMINATE for the report, or both.

e.   In an FD entry, the STYLE clause applies to the entire report file:


   If any control characters are output, this happens during the execution of each OPEN or CLOSE for the file, or both.

The WHEN clause causes the STYLE to take effect only when the condition is true, for example:

        05  COL 21  PIC ZZZ9     SOURCE PERCENTAGE

Since you can only code STYLE once per entry, you cannot vary the STYLEs in a multiple-choice entry, and instead must code separate entries, as here:


If STYLE is defined on an elementary field that has suppressed zeros or trailing spaces, the STYLE will apply only to the characters printed.  For example, the coding:


   might result in:
             15 PAYMENT OVERDUE

           3156 PAYMENT OVERDUE

         152722 PAYMENT OVERDUE

   If you do not want this effect, code the STYLE clause at a group level, e.g.

        05  STYLE UNDERLINE.
          07  COL 11  PIC ZZZZZ9   SOURCE W-PAYMENT.


SUM Clause

This clause automatically forms totals from any other numeric field.  You may also use it as a term in an arithmetic-expression in a SOURCE clause.


     |        +--------------------------------------+ |
     v        v                                      | |
              +-expression---+ |      +--------+   |
                               |      v        |   |
UPON group-name---+

RESET+--+control-id-+ +- ROUNDED-+

SUM Clause: Coding Rules

There are two ways to code the SUM clause:

As a clause in its own right.  You write the clause in place of a SOURCE, VALUE, or FUNCTION clause.  For example:

           05  COL 21  PIC ZZZ9  SUM OF SALE.

As a term in an expression; for example

           05  COL 21  PIC ZZZ9
               SOURCE IS ((SUM OF REVENUE) + (SUM OF TAX)) / 100.

   This type of expression can only be used as a SOURCE operand (although, as usual, the SOURCE keyword is optional).  You cannot use a SUM term as part of a condition or, for instance, as a parameter to a FUNCTION.

The item summed can be either of two things:

The name of any numeric data item in your REPORT SECTION (other than a FUNCTION entry).  To use this, you must place a data-name on the item in the REPORT SECTION you want to total.  Suppose you need to form a total from the following report field:

           05  COL 41    PIC 99999           SOURCE WAGES.

   Just place a data-name of your own choosing on it, such as:

           05  R-WAGES   COL 41  PIC 99999   SOURCE WAGES.

   and you may now write SUM OF R-WAGES in another item in your report to form a total.  This is called a REPORT SECTION SUM clause.  A REPORT SECTION SUM operand never has any subscripts or arithmetic symbols - you can write only: SUM OF data-name.

   The data item referred to in the SUM clause may be qualified by the report-name, as in SUM R-PAYMENT IN SUMMARY-REPORT.  By default, the qualifier is the same report as the one in which the SUM is defined.  So if the same data-name appears in more than one report, it may be referred to by a SUM clause in its own report without qualification.  (It cannot be referred to by a SUM in a different report without a qualifier.)  This means that you can duplicate a complete report description with SUM clauses without changing any of the data-names on SUM entries.

A numeric identifier or expression from outside the REPORT SECTION.  In this form, it is similar in appearance to the operand of a SOURCE clause.  This is called a non-REPORT SECTION SUM clause.

   (Unless a naming convention is observed, there is no way of telling from the data-name whether the SUM clause references a REPORT SECTION SUM or not.  In the examples in this volume, we sometimes use a prefix such as "R-" to designate a REPORT SECTION item, so that "SUM OF R-..." will be recognized as a REPORT SECTION SUM.  Observing a standard like that will make your REPORT SECTION easier to follow.)

   A SUM clause may total several items, and you may combine REPORT SECTION and non-REPORT SECTION items; for example:

                          SUM OF W-BASIC, R-BONUS, R-OVERTIME

   where W-BASIC is a non-REPORT SECTION item, R-BONUS is a REPORT SECTION item in a different report group and R-OVERTIME is a REPORT SECTION item in the same report group.  In this case, the total field is always the sum of the individual totals that would be formed from each of its items.  You should then interpret the remarks in the remainder of this section for each of the single SUM operands individually.  Note that this is not similar to the multiple SOURCES clause (despite their syntactic similarity), since only one printable item is defined with the SUM clause.

Your report may contain as many entries with SUM clauses as you wish, in any TYPE of group (even RH).  Only elementary entries can have a SUM clause.

If you code the UPON phrase, each group-name must be the name of a DETAIL group and should not be the same group as the group you are currently defining.  The group-name may be qualified.  If not, the current report is assumed.

If your SUM clause is in a DETAIL group and the operand of your SUM clause is not in the REPORT SECTION (a rare situation), your report should contain more than one DETAIL group and you should logically code the UPON phrase, in order to specify on which GENERATE you want adding to take place.

If you code the RESET phrase, the control-id operand must be one of those defined in the CONTROL clause of your report (including REPORT, whose presence is assumed there).  If you are currently defining a CONTROL FOOTING group, the level of the control in your RESET ON should be higher than the level of this group.  (It may also be equal to the level of the current group, in which case resetting occurs at the normal time, and the phrase is therefore redundant.)

The RESET phrase cannot be defined anywhere in a multiple CONTROL FOOTING group.

You may code the SUM clause more than once in an entry.  The effect of this is to add together the totals formed from each of the clauses.  Hence:

             SUM A  SUM B     gives the same result as SUM A B

   (and, if A and B are non-REPORT SECTION items, SUM (A + B)).  This separation is essential only if you need to use a certain UPON phrase with one but not the other, for example:


ANS-85 note.  Since a reference-modified identifier is regarded as non-numeric, you cannot SUM it, either directly as the operand of your SUM clause, or indirectly by naming a REPORT SECTION item where it is used as a SOURCE.


SUM Clause: Operation

Report writer performs the totalling, presenting, and resetting (to zero) of your totals completely automatically.  These three stages are covered in the next three numbered paragraphs.


   The method used for totalling depends on whether the item referred to by SUM is a data-name on a REPORT SECTION entry (called henceforth a "REPORT SECTION SUM "), or not.


   Whenever the originating data item named in your SUM clause is output in the report, the item it references is also added into the (internal) total field.  If the REPORT SECTION data item totalled contains a SOURCE or VALUE clause, the amount added to the total is the SOURCE or VALUE operand outside the REPORT SECTION, not the intermediate REPORT SECTION field.  For example, if you write:

           05  R-FLD1    COL 1      PIC 999   VALUE 100.
           05  R-FLD2    COL 5      PIC 9999  SOURCE W-PAYMENT.
           05  ...       SUM OF R-FLD1, R-FLD2.

   the fields added into the total will be 100 and W-PAYMENT, not the report fields R-FLD1 and R-FLD2.  Thus, if W-PAYMENT has a PICTURE of 9(5)V99 rather than 9(4), the full originating value - not the truncated value that appears in the report line - will be added.

   There are two names used to distinguish two cases of REPORT SECTION SUMming:


   In the next illustration, the item to be totalled is in the same report group as your SUM clause:



    $2300    $3400    $1600    $3500   

                     PIC $(6)9   SOURCE  QTLY-SALE (SEASON).
05            COL +10     PIC $(7)9   SUM OF R-QUARTER.

   The SUM entry may appear earlier in the report group than the item it is totalling and this may be carried on to any number of stages.  Thus the physical order of totals and items being totalled within a single group is immaterial.  Report writer decides for itself the order in which totalling must be done.  Hence the correct result is obtained by coding for example:

          05  R-A    ...   SUM OF R-B ...
          05  R-B    ...   SUM OF R-C ...
          05  R-C    ...   SUM OF R-D ...   etc.

   However, you must avoid circular dependencies such as:

          05  R-A    ...   SUM OF R-A ...
          05  R-A    ...   SUM OF R-B ...
          05  R-B    ...   SUM OF R-A ...

Rolling Forward

   In the next illustration, the item to be totalled is in a different group from your SUM clause:

                          THIS YEAR  LAST YEAR

ARMCHAIRS                $3500      $2000
SETTEES                   $300       $200
WRITING DESKS            $2200      $1200
DINING TABLES            $1700      $2300

TOTALS                   $3500      $2000
-------    -------

05             COL 1   PIC X(20)  SOURCE DESCRIPTION.
05  R-SALES    COLS RIGHT 31 41   PIC $(6)9

03  LINE + 2.
05             COL 1   VALUE "TOTALS".
05             COLS RIGHT 31 41  PIC $(7)9  SUM OF R-SALES.
03  LINE + 1     COLS RIGHT 31 41  VALUE "-------".

   In this example, the "boxes" contain instances of the different report groups.  The values to be added appear in a DETAIL, and the total is in a CONTROL FOOTING.

   You may use also this method of summing between any reasonable combination of groups, namely any of the following:



 ¶   Any group to a REPORT FOOTING,

 ¶   Any body group to a PAGE FOOTING,


   Frequently there are several items that could be rolled forward to produce the same result.  For example, your YEAR totals are the total of the twelve MONTH totals; they are also the total of your fifty-two WEEK totals and your 365 DAY totals.  Rolling forward the immediately-lower-level total (such as MONTH totals into YEAR totals) is the most efficient technique.


   Here totals are gradually accumulated from values held outside the REPORT SECTION.  This method was much used in the earlier versions of report writer and you may possess some old programs that use it.  This is usually referred to as subtotalling.  Because the identifier or expression lies outside the REPORT SECTION, it is not as clear as it is with a REPORT SECTION SUM clause exactly when the values are added into the total, so the following rules are important:

If SOURCE SUM correlation is in effect (see Subtotalling and SOURCE SUM correlation), adding takes place when any DETAIL is being GENERATEd that contains the same identifier as a SOURCE item as the identifier appearing in the SUM clause.

If the UPON phrase is used, adding takes place when a DETAIL group specified in that phrase is GENERATEd.

If SOURCE SUM correlation is not in effect and there is no UPON phrase, adding takes place on each GENERATE that refers to the report.

   Almost all totalling can also be accomplished by means of REPORT SECTION SUM clauses.

Presenting the total

   When the entry containing you SUM is output, the (unedited) total to-date is used as an internal "source" for the contents of the field.  Thus, if you had coded:

           05  COL 5    PIC $$,$$$,$$9.99  SUM R-PAYMENT.

   the internal total field (which is fully described below under Use of Total Fields) is MOVEd to this report field, and edited according to the given PICTURE, according to the same rules as the SOURCE clause.

Resetting the total

   The total is reset (cleared to zero) at the end of the processing for the report group in which it is defined, unless you override this using the RESET phrase as described below (see RESET Phrase).  Thus the total field remains available for use anywhere in the same group (within a SOURCE for instance) before its contents are erased.

When adding a value into the total, the report writer code obeys the rules of the ADD statement.  Unless you coded SUM OVERFLOW PROCEDURE IS OMITTED in the RD, a SIZE ERROR test is always done and if there is size error, a run time error is signalled at once.

If the SUM clause appears in a multiple CONTROL FOOTING group, the SUM clause has its usual effect in the lowest level group and in the higher levels acts by rolling forward each previous level.  For example, in the following structure:

           05  COL 1   PIC ZZZ9 SUM OF W-PAY.

   the SUM clause acts like three different SUM clauses.  At the lowest level (CITY), it behaves as defined (by subtotalling W-PAY).  The CITY total is then rolled forward into the COUNTY total on change of CITY and the COUNTY total is rolled forward into the STATE total on change of COUNTY.

Summing a Repeated Item

   If you wish to sum a repeating item, you may form totals along any of four different axes.  These are, from minor to major:

Axis 1: COLUMN Axis

Axis 2: COLUMN-Group Axis (below LINE and above COLUMN)

Axis 3: LINE Axis

Axis 4: LINE-Group Axis (above LINE and below report group)

   Report writer will automatically total the repetitions of your field along any axes necessary to form the total.  The direction of the adding depends not on the syntax of the clause you use but on where you place it.  If your SUM clause has no repetitions at all (is not subject to an OCCURS clause or a multiple LINE or COLUMN clause), report writer will total all occurrences of the field.  You can thus total a REPORT SECTION table of any number of dimensions.  If your SUM clause is part of a repeating report field, then the item being summed must repeat the same number of times along the same axes as the SUM entry.  Your field will be output along any of the axes shared and totalled along any of the axes not shared by the SUM entry.  An example will make this clearer.  In the following case, the field R-QUARTER has an OCCURS clause in two axes: the LINE axis and the COLUMN axis.



 1988   $2300    $3400    $1600    $3500
 1989   $3200    $3600    $2700    $3000
 1990   $3500    $4000    $3400    $4300
 1991   $3600    $4300    $3800    $4500
 1992   $3800    $4200    $3900    $4750

   The following code produces this layout:

         03  LINE + 1    OCCURS 5  VARYING YEAR-NO.
           05            COL 1     PIC 9(4)   SOURCE 1987 + YEAR-NO.
           05  R-QUARTER COL 6     PIC $(6)9  OCCURS 4 STEP 10  VARYING SEASON
                                   SOURCE SALE (YEAR-NO SEASON).

   To obtain row totals, code the SUM clause as an entry at a level within the same LINE as the items referred to in SUM.  (The entry below is named ROW-TOTAL but you may choose any data-name).  To obtain column totals, place the SUM clause within a separate LINE and give it the same number of horizontal repetitions as its operand.  (The entry below is arbitrarily named COL-TOTAL.)  The final result is as follows:



 1988   $2300    $3400    $1600    $3500    
 1989   $3200    $3600    $2700    $3000    
 1990   $3500    $4000    $3400    $4300    
 1991   $3600    $4300    $4800    $4500    
 1992   $3800    $4200    $3900    $4750    

TOTALS $16400   $19500   $16400   $20050     $72350

         03  LINE + 1    OCCURS 5  VARYING YEAR-NO.
           05            COL 2     PIC 9(4)   SOURCE 1987 + YEAR-NO.
           05  R-QUARTER COL 8     PIC $(6)9  OCCURS 4 STEP 10
                         VARYING SEASON  SOURCE SALE (YEAR-NO SEASON).
         03  LINE + 3.
           05            COL 1     VALUE "TOTALS".
           05  COL-TOTAL COL 7     PIC $(7)9  OCCURS 4 STEP 10
                                    SUM OF R-QUARTER.

   Notice that the field ALL-TOTAL could also have been coded as SUM OF R-QUARTER (which is less efficient) or SUM OF ROW-TOTAL.  Also notice that the data-names ROW-TOTAL and ALL-TOTAL are not referenced and could have been omitted.

You may require just a single total of all the entries (the "corner" total in the above illustration), without any row or column totals.  Just write the ALL-TOTAL entry alone:

 . . . . . . . . . . . . . . . . . . . . . . . . . . .
 . . . . . . . . . . . . . . . . . . . . . . . . . . .


           05  ALL-TOTAL COL 47    PIC $(7)9  SUM OF R-QUARTER.

 Other Axes

   The examples shown earlier cover only two out of the four possible axes.  You may also SUM along the other two axes, that is: groups of COLUMNs and groups of LINEs.  As an example of groups of COLUMNs, take this layout, where we total the four weeks in each month horizontally:




  1   2   3   4

300 200  70 100
200  40 120  50
200  70  90  90

  1   2   3   4

450 600  50   0
250  30   0  60
300 160  40  90

  1   2   3   4

140  90 200 380
60  45  25 100
200 320 160  90

       01  INCOME-TABLE    TYPE DE.
         03    LINE +1     OCCURS 5        VARYING SPORT.
           05              PIC X(6)        SOURCE SPORT-NAME (SPORT).
05  R-QTR COL 7 PIC Z(4)9       SUM OF R-MONTH.
                                      (or: SUM OF R-WEEK.)
           05  OCCURS 3    STEP 22         VARYING MONTH FROM 4.
07  R-MONTH   COL 12          SUM OF R-WEEK  PIC Z(4)9.

   This example also illustrates the fact that cross-foot totals need not appear to the right, or below, the figures from which they are formed.

If your program contains more than one report, you are not restricted only to rolling forward within one report.  A SUM clause in one report may refer to a named numeric data item in a different report.  As with totalling in a single report, the value of the referenced field is added whenever the field is output.  (This does not apply to non-REPORT SECTION summing, however, when SOURCE SUM correlation is in effect: see ALLOW Clause.)  Note that all total fields in a Report are cleared by the INITIATE statement for the report.  Therefore, if you need to SUM from one report to another, be sure that both are INITIATEd at the start of the processing.

PRESENT WHEN clause may test the value of any total fields referenced in its condition-operand.  However, it should then not contain within its scope either an entry with a SUM clause or an entry that is summed by a SUM clause.  See Effect of PRESENT WHEN on SUM.

 Totalling Unprintable Items

   You may total unprintable items in your REPORT SECTION.  This is useful when you want to print the totals only, not the unprinted individual values.  In the next example, the report computes a yearly total from 12 unprinted monthly values:


1991   $2300.00
1992   $3766.50

         03  LINE.
           05  COL 2       PIC 9(4)  SOURCE
           05  R-EXPENSE   PIC 9(6)V99   OCCURS 12
05  COL 7       PIC $(6)9.99  SUM OF R-EXPENSE.

It is not possible to accumulate in an instant a single total all the entries in a table outside your REPORT SECTION without using an intermediate unprintable table as in the example above.  However, you may use a non-REPORT SECTION SUM clause to accumulate - over time - single entries in a table into a corresponding matching number of totals, typically in a CONTROL FOOTING.  Since your SUM operand is not in the REPORT SECTION, you may use subscripts with it, just as you would in the SOURCE clause:

   ..... ..... ..... ..... ..... ..... ..... ..... .....
   ..... ..... ..... ..... ..... ..... ..... ..... .....
   ..... ..... ..... ..... ..... ..... ..... ..... .....
$32400     $19500     $16400      $20050     $72350

       01  CF FOR REPORT.
         03  LINE  ...

If the SUM operand is not in the REPORT SECTION, you may also total arithmetic expressions, such as:

           05  COL 54    PIC ZZZZ9     SUM OF (W-INCOME - W-TAX) * 100.

   An evaluation is performed for the expression on every GENERATE, before the result is added into the total field, so the use of this technique is less efficient - and more susceptible to rounding errors - than a method using unprintable intermediate totals.  (The accumulation is not affected by the status of SOURCE SUM correlation.)

Use of Total Fields

If you give a data-name to an entry that contains a SUM clause (not a SUM term that is part of an expression), report writer will relate the data-name to its own (internal) total field, not to the (edited) external field in the report line, as would be the case with a SOURCE, VALUE, or FUNCTION clause.  (The total field is called a sum-counter in older texts, but total field is clearer as it does not conflict with the COUNT clause.)  Compare these two cases:

a.  With SOURCE etc.:

                 + - - - - +
    |                  $$$$$$$9.99                    |<<< report line
                           + - Field R-PAYMENT is actual report-line field,
                               except when referenced in a SUM clause, in
                               which case WS-PAYMENT is what is added.
b.  With SUM:

                   | + - - - - - +
                   +>|           | < < Field TOT-PAYMENT is the REPORT
                     + - - + - - +    SECTION's internal total field.
    |                  $$$$$$$9.99                    |<<< report line
                           + - Report line field has no name.

The internal total field is a pure numeric, signed COMPUTATIONAL field with as many integral and fractional digits as the SUM entry.  Hence, no precision will be lost when the total field is stored in the report field.  If the SUM clause refers to a REPORT SECTION item, the precision of the total field is increased if necessary so that it has at least as many integral and fractional digits as the entry being totalled.  Hence the total will have at least the precision of the field being totalled, rounding or truncation taking place, if indicated, when the field is output, not while it is being accumulated.  Here are some examples:

    PICTURE in SUM Entry    PICTURE of SUM Operand    PICTURE of Internal Total
                            if in REPORT SECTION

        99999                 (not in REPORT SECTION)     S9(5) COMP
        ZZZ9.99                   ZZ9.99                  S9(4)V99 COMP
        $(6)9-                    $(5)9.99-               S9(6)V99 COMP

   Note that the total field is always signed, even if the report line field is not signed, so the adding into the total field is always algebraic.

Accessing the Total Fields

   You may access the internal total field directly in the following four ways.

In a SOURCE Clause

   You may capture an internal total field with a SOURCE clause reference, either as its single operand or as a term in an operand that is an expression.  The value you obtain depends on the category of the total field you access, as follows:

SOURCE Refers to Total Field Defined in the Same Report Group

   You will always obtain a true value of the total as specified.  The position of the SOURCE clause within the group is immaterial, as report writer always computes the totals before producing any of the group's report lines (which is when SOURCE operands are filled in).

   This feature is useful when you wish to form an unprintable total from a non-REPORT SECTION field without loss of precision and then output it ROUNDED .  You might wish to form totals to cents precision and output them to the nearest dollar.  You should then write two entries in the same report group, one of which has no COLUMN clause and is therefore unprintable, as in this example:

        *the first item is unprintable:
        *the second item prints its contents:
            05  COL 21        PIC -(6)9      SOURCE

   If you had written instead:

    05  COL 21        PIC -(6)9      SUM OF WS-FIELD.

   the internal total field would have the implied PICTURE S9(6) COMP, so you would lose precision each time the (truncated) value of WS-FIELD is added in.  Truncation would not arise if the SUM operand were a REPORT SECTION data-name, since the precision of the summed field is then also taken into account in establishing the required precision of the sum field.

   Alternatively, you may make use of report writer's less efficient but highly accurate default PICTURE S9(12)V9(6) for SUM terms in SOURCE clauses, by coding:

    05  COL 21        PIC -(6)9      SOURCE (SUM OF WS-FIELD).

   The next example uses an arithmetic expression involving total fields:

    05  COL 10        VALUE "TOTAL INCOME:".
    05  R-TOT-INCOME  COL + 2       PIC Z(6)9      SUM OF INCOME.
    05  COL 35        VALUE "TOTAL TAX:".
    05  R-TOT-TAX     COL + 2       PIC Z(6)9      SUM OF TAX .
    05  COL 55        VALUE "NET PAY:".
    05  COL + 2       PIC Z(6)9     SOURCE (R-TOT-INCOME - R-TOT-TAX).

   It would also have been correct to code the last entry as:

    05  COL + 2       PIC Z(6)9     (SUM OF INCOME) - (SUM OF TAX).

   However, the first code shown is more economical since we are printing the individual totals R-TOT-INCOME and R-TOT-TAX already elsewhere and can therefore re-use them in the expression instead of summing them again.

SOURCE Refers to Total Field Not Defined in Same Group (Snapshots)

   If the SUM total field referred to in turn refers to a non-REPORT SECTION item (subtotalling) or to an entry in a different report group (rolling forward), you will obtain at that instant the up-to-date accumulated value, a technique which is useful for obtaining brought forward and carried forward totals, as in the layout on the following page:


 01/01/83   BAR             $200.00
 01/01/83   LOAN            $150.00
   ...                        ...
 07/04/83   PETTY CASH       $50.00
  << First Page

  Grand total field TOT-CASH
  is being accumulated while
  these fields are output.

 . . . . . . . . . . . . . . . . . . 
 08/05/83   ADVERTISING     $200.00
 09/06/83   RESTAURANT      $300.00
   ...                        ...
 GRAND TOTAL:             
 ===========               ========
  << Last Page

       01  WS-TOT-CASH        PIC S9(4)V99 COMP.
       01  TYPE PH.
         03  LINE 1     COL 1  VALUE "      SPORTS CLUB DONATIONS".
         03  LINE + 2   ABSENT AFTER NEW REPORT.
           05  COL 1    VALUE "BROUGHT FORWARD:".
05  COL 25   PIC $(5)9.99      SOURCE WS-TOT-CASH.
       01  CASH-ENTRY   TYPE DE      LINE.
           05 ...
           05  P-CASH   COL 26  PIC $(4)9.99  SOURCE CASH.
       01  TYPE CF FINAL.
         03  LINE.
           05  COL 1    VALUE "GRAND TOTAL:".
05  TOT-CASH COL 26  PIC $(4)9.99  SUM OF P-CASH.
       01  TYPE PF      LINE 60.
           05  COL 1    VALUE "CARRIED FORWARD".
05  COL 25   PIC $(5)9.99      SOURCE WS-TOT-CASH.

   We reference a SUM total field in a SOURCE to capture a snapshot of the running total.  The SUM entry is gradually accumulated over a certain part of the report, so we obtain any number of versions of it at any state up to the eventual total.  This, incidentally, gives us an alternative to the RESET phrase for forming cumulative (running) totals.

   In the sample code we save the SUM total field procedurally in a working location (WS-TOT-CASH) after each GENERATE and use that in the SOURCE for the next cycle.  This is done for two reasons:

   It is independent of whether or not the option is in effect.  The  (standard but "less logical") option does rolling forward and subtotalling before the page-fit test (see GENERATE Processing Cycle), so our total fields will already have been updated by the new value of CASH and we would otherwise have to subtract it again in the SOURCE to get the true total.  The option corrects this anomaly, but there is a second problem:

   Whichever option is in effect, the total field is reset to zero immediately after its CONTROL FOOTING group has been output, so it cannot appear in the PAGE FOOTING beneath it (the last page in our example, since the group is a CF FINAL).  Hence the use of WS-TOT-CASH which is the current total "suspended from the last GENERATE".

   If we did not wish to print a grand total field from which to "snapshot" the values, we could define the total as an unprintable item (with no COLUMN clause).

In a PRESENT WHEN clause

   You may test the value of a total field in a PRESENT WHEN's condition to control what is produced in the report group.  The effective value will be the same as for the case with SOURCE above.  However, if you do this, do not code any SUM clauses or any summed entries within the scope of your PRESENT WHEN clause.  This avoids a deadlock situation where summing depends on conditions and conditions depend on summing.  A useful example is the common requirement to suppress zero totals.  The code should be as follows:

          04  TOTAL-CASH     PIC 9(4)   SUM OF CASH.
          04  LINE + 2       PRESENT WHEN TOTAL-CASH NOT = ZERO.
           05  COL 1         "TOTAL = ".
           05  COL 11        PIC ZZZ9   SOURCE TOTAL-CASH.

   TOTAL-CASH is an unprintable SUM entry that is - as necessary - outside the scope of the PRESENT WHEN.  (If your entire LINE is subject to the PRESENT WHEN, place your unprintable field in another LINE of the same group.  Since it is unprintable, its placement is immaterial.)

   You may use the total field even if it is defined later in the same group because totalling is completed for each group before production of any of the report lines begins.


   You may capture the contents of a subtotalled or rolled forward total field in a main-line COBOL procedural statement.  As an example of the use of this property, you may move a total field into a record in a different output file.  This will save you the effort and inefficiency of totalling the same field independently.  However, the contents of an unconditional cross-foot total will always be zero, because it will always have been output as soon as it was totalled.  (A total field is reset to zero at the end of the report group in which it is defined, unless the RESET phrase defers this action - see RESET Phrase.)

   You may also procedurally alter (that is, ADD TO, SUBTRACT FROM etc.) the value of any named total field at any time.  Of course, if you do so the results that appear in the total fields will be different from those you would expect if report writer alone were accumulating the totals.  You may also need to handle any possible size errors in the total field.  The values you added or subtracted will be reset with the rest of the value at the usual time.

   Total fields are cleared to zero by the INITIATE statement.  They will also normally be zero after execution of the TERMINATE statement.  This is because they are always cleared after being output, and the TERMINATE statement outputs all CONTROL FOOTING groups and any PAGE FOOTING and REPORT FOOTING.  However, if a SUM clause was coded in another type of group, such as a DETAIL, that is not automatically output when your program issues the TERMINATE, there could be a non-zero total waiting in vain to be output.  Also, if the SUM clause was conditional, the field with the SUM might have been absent on the last occasion, in which case a non-zero total might still be waiting to be output.  In all these cases, report writer will issue a run time error and the total will be cleared if and when your program issues another INITIATE for the corresponding report.

In a Declarative SECTION

   You may also access total fields in a USE BEFORE REPORTING Declarative SECTION for any report group.  As is the case with reference to sum totals in a SOURCE, described above (see a(ii)), the state of any total fields you may access depends on whether the OSVS option is in effect or not.

   Any cross-foot totals for the group will already have been calculated in all cases.

   If OSVS is in effect, any rolling forward (from this group into a different group) and subtotalling (if this is a DETAIL group, or a PH or PF triggered by a DETAIL group) are done before entry to the Declarative SECTION.  Hence you will obtain all totals fully updated.  (See GENERATE Processing Cycle.)

   If OSVS is not in effect, by contrast, any rolling forward and subtotalling are done after entry to the Declarative SECTION.  So, especially if your group is a PAGE FOOTING (or HEADING), you will obtain an accurate value of the total at that "physical point" in the report.

Precision of SUM terms

   If you use SUM or COUNT as a term in a SOURCE's expression, report writer will assign the internal total field with PICTURE S9(12)V9(6) COMP , irrespective of the PICTURE of the report field.

Subtotalling and SOURCE SUM Correlation

Subtotalling is the term used when your SUM clause or SOURCE clause SUM term specifies a non-REPORT SECTION operand, that is, an item in your FILE, WORKING-STORAGE, or LINKAGE SECTION.  OS/VS and DOS/VS COBOL report writer, which is based on ANS-68, depends on subtotalling for forming most totals.  With report writer, you should rely instead on rolling forward, by giving a data-name to a DETAIL group's SOURCE entry, so that there is no need to worry about when the items are added into the total fields.  However, there are still times when subtotalling might be preferred, such as when you are creating total lines in a summary report and have not coded SOURCE items in a DETAIL group to refer to.  The rules of operation are as follows:

Report writer adds the SUM operands ("addends") directly into the total field, following the normal rules of the ADD statement.  If there is a size error, the same action takes place as for REPORT SECTION SUM totals, as described above.

SOURCE SUM Correlation.

   The decision as to when to add the items depends on whether SOURCE SUM correlation is in effect.  This is the chief difference between the ANS-68 standard used in OS/VS and DOS/VS COBOL, which automatically applies SOURCE SUM correlation, and the ANS-74 and ANS-85 standards, which do not.  You will observe a difference only when the following circumstances occur simulataneously:

When your report has more than one DETAIL group; and

When your program SUMs an operand that is also a non-REPORT SECTION SOURCE operand in one or more of the DETAIL groups.

   Otherwise, report writer will not apply SOURCE SUM correlation.  SOURCE SUM correlation is in effect if:

The precompiler was installed with the OSVS option set on, or

You code an ALLOW SOURCE SUM CORR clause in your RD.

SOURCE SUM correlation is not in effect if:

Your system was installed with the OSVS option set off (ANS74 or ANS85), or,

You code an ALLOW NO SOURCE SUM CORR clause in your RD.

If SOURCE SUM correlation is in effect, report writer takes each non-REPORT SECTION operand specified in your SUM clause and scans the DETAIL groups of your report to establish whether the same item is coded in more than one of them as a SOURCE operand.  (The SOURCE keyword may, as usual, have been omitted.)  Arithmetic expressions are not examined.  Redefinitions of the same item and differences in subscripts or qualifiers (apart from interchanging the words IN and OF) mean that there is no match.  All your DETAIL groups are scanned in this way.  The appearance of the same operand more than once as a SOURCE in the same DETAIL counts as only a single match.  If a match is found, report writer will add the item into the total field only when the DETAIL or DETAILs that contain your item are GENERATEd. If no match is found, report writer will add the item into the total field on every GENERATE for that report.

Using a dummy DETAIL group for Summary Reporting.

   With the ANS-68 standard of OS/VS and DOS/VS COBOL, a corresponding SOURCE was required for every SUM.  This meant that in a totals only report, a dummy DETAIL group needed to be defined, as in the following sample:

           CONTROL IS STATE.
           05                       SOURCE IS WS-PAY-THIS-YEAR.
           05                       SOURCE IS WS-PAY-LAST-YEAR.
       01  TYPE CF FOR STATE.
         03  LINE PLUS 2.
           05  COLUMN 1   PIC ZZZ9  SUM WS-PAY-THIS-YEAR.
           05  COLUMN 11  PIC ZZZ9  SUM WS-PAY-LAST-YEAR.

   Although report writer accepts this code unaltered, the dummy group is now unnecessary - even if SOURCE SUM correlation is in effect.  The dummy group in the example above may be deleted and the GENERATE replaced by GENERATE report-name:

           CONTROL IS STATE.
       01  TYPE CF FOR STATE.
         03  LINE PLUS 2.
           05  COLUMN 1    PIC ZZZ9     SUM WS-PAY-THIS-YEAR.
           05  COLUMN 11   PIC ZZZ9     SUM WS-PAY-LAST-YEAR.

   More details will be found under "Summary Reporting" (see GENERATE Statement).

If SOURCE SUM correlation is not in effect, report writer will add every operand of the SUM clause into the total field on every GENERATE for the report.

Three Methods of Subtotalling

In the items just preceding, you observe that, if SOURCE SUM correlation is not in effect, adding into your total field will take place on each GENERATE for the report.  This may not be suitable, especially when you have several DETAIL groups.  If you have two record types, say SALARY and NAME-ADDRESS, with DETAIL groups that correspond to these, and you want the total of SALARY, you will clearly want the field SALARY to be added only when your program generates the SALARY DETAIL group.  There are three ways of avoiding this problem, which are illustrated below.

The recommended method of report writer is to place a data-name on the entry to be totalled (omitting the COLUMN clause if it is not be printed), and SUM the item using that data-name.

If SOURCE SUM correlation is in effect and both the SOURCE operand and the SUM operand names are identical, the item will be added, as expected, only when the SALARY group is GENERATEd.

Using the UPON phrase.  You may use this whether or not SOURCE SUM correlation is in effect, because UPON overrides its effect.  By writing UPON SALARY-GRP (where SALARY-GRP is the 01-level name of your DETAIL group), you ensure that the item will be added into the total only when the SALARY-GRP DETAIL group is GENERATEd.

   The next example compares these methods:


NAME: J.C. CODER        SALARY:  $10000


NAME: T.A. ANALYST      SALARY:  $12000

BANK: ...

                  TOTAL SALARIES:  $89000

< - SALARY group

< - NAME-ADDRESS group

a.   Method Using REPORT SECTION SUM (recommended)

       01  SALARY-GRP  TYPE DE  LINE + 1.
05  R-SALARY      COL 50      PIC $(6)9   SOURCE SALARY.

       01  NAME-ADDRESS  DE ...
       01  CF  ...
           05  COL 49        PIC $(7)9  


b.   Using SOURCE SUM Correlation:

       RD  ...
      *Following may be omitted if set on customization.

       01  SALARY-GRP  DE  LINE + 1.
05  COL 50        PIC $(6)9   SOURCE SALARY.
       01  NAME-ADDRESS  DE  ...
       01  CF  ...
      *Correlation between SOURCE and SUM.
           05  COL 49        PIC $(6)9  


c.   Using the UPON Phrase:

       01  SALARY-GRP TYPE DE  LINE + 1.
05  COL 50        PIC $(6)9   SOURCE SALARY.
       01  NAME-ADDRESS  TYPE DE  ...
       01  TYPE CF  ...
      *UPON phrase indicates "ADD only when SALARY-GRP generated".
           05  COL 49        PIC $(6)9   SUM OF SALARY   UPON SALARY-GRP.


RESET Phrase

In all our examples presented earlier in this section, the total field is reset to zero at the end of the processing for the group in which it has appeared.  Sometimes you will not want this to happen.  Such a case is called a cumulative (or running) total.  Here the total is not necessarily cleared or reset after it has been output.  Values then continue to be added into the total.  You will have seen above that you can capture cumulative totals by "taking a snapshot" of a higher-level total field.  Another method is to use the RESET phrase.  Its operand states at which (normally higher) level of control break, if any, the total field is to be cleared.  If you specify RESET ON REPORT (or RESET ON FINAL), the total field will not be reset after the final control footing has been presented, during the execution of the TERMINATE.

For example, by writing:

            03  COL 20 PIC ZZZ9.99   SUM OF ACC-BAL  RESET ON BRANCH-CODE.

you ensure that the total field is not cleared until a new BRANCH-CODE is reached.

Here is an example of a cumulative total:


     DATE             AMOUNT   CUMULATIVE

    010270            100.00
    010370            150.00

 TOTALS JAN          
350.00      350.00

    020770             50.00

 TOTALS FEB           
50.00       400.00

    030370            100.00
    160370             40.00
    270370             60.00

 TOTALS MAR          
200.00      600.00

 ...etc...            ......      ......

    050171            100.00
    270171            200.00

 TOTALS JAN          
300.00      300.00

< cumulative and
< normal totals same
< first time

< cumulative total
< is not cleared
< before adding 50.00

< total reset after
< change of YEAR.

       RD  ...
       01  CF FOR MONTH.
05  COL 21 PIC ZZZ9.99
05  COL 33 PIC ZZZ9.99
             RESET ON YEAR.

TYPE Clause

This clause is used at the 01-level to indicate which of the seven possible types of report group is being defined.


REPORT HEADING -+---------------------------+-><
TYPE+--++|+RH -------------+                           |
       +IS+ ++
PAGE HEADING-+-----------------------------+
PH-----------+                             |
CONTROL HEADING-++------------------------++
            |                   +ON-+          +
            |                   +FOR+                    |
DE-----+                                   |
CONTROL FOOTING-+-+---------------------+--+
CF--------------+ |         +--------+  |  |
            |                   |         v        |  |  |
            |                   ++----+-+-control-id-++  |
            |                    +-ON-+ +-
ALL--------+   |
            |                    +-FOR+                  |
PAGE FOOTING-+-----------------------------+
PF-----------+                             |
REPORT FOOTING-+---------------------------+

where control-id is an identifier in the CONTROL(S) clause, or the word REPORT or FINAL.

TYPE Clause: Coding Rules

Write the TYPE clause at the 01-level entry only.  You may omit the keywords TYPE IS.  If you do not code a TYPE clause for a group, it will be assumed to be TYPE DETAIL.

All TYPEs of report group are optional, whatever the circumstances, but every report must have at least one body group (CONTROL HEADING, DETAIL, or CONTROL FOOTING).

PAGE HEADING, PAGE FOOTING and the OR PAGE phrase of CONTROL HEADING groups are allowed only if you have a PAGE LIMIT clause in the RD.

In the CONTROL HEADING and CONTROL FOOTING forms each control-id operand must be chosen from the list of controls in your CONTROL clause, including REPORT (or FINAL) which is always assumed present.

If CONTROL HEADING is coded with no control-id operand, there must not be more than one control-id in the CONTROL(S) clause.  The clause is then taken to mean CONTROL HEADING FOR control-id, if there is just one control-id in the CONTROL(S) clause, or CONTROL HEADING FOR REPORT if there is no CONTROL(S) clause at all.

If more than one (different) control-id is coded in the CONTROL FOOTING form, the result is a set of multiple CONTROL FOOTING report groups.  The control-ids need not be coded in any particular order and need not form a consecutive hierarchic sequence.  For example, if the CONTROLS clause is:


   it is permissible to code:


   which means the same as


   If a CONTROL FOOTING is required for all levels of control, ALL may be coded instead of the exhaustive list of control-ids.

   If a DETAIL group also has the same format as some CONTROL FOOTINGs, it is usually worth the effort to define it as the lowest-level CONTROL FOOTING group, and force a lowest-level control break on each GENERATE, in order to make full use of this feature.  In this case summary reporting is used (see GENERATE Statement) and each totalled value, generated by a SUM clause, will be the "total" of just a single value in the case of the lowest CONTROL FOOTING.

If CONTROL FOOTING is coded with no control-id operand, it is taken to mean CONTROL FOOTING FOR ALL or, CONTROL FOOTING FOR control-id , if there is just one control-id in the CONTROL(S) clause, or CONTROL FOOTING FOR REPORT if there is no CONTROL(S) clause at all.

In any report you may have any number of DETAIL report groups, but only one PAGE HEADING, PAGE FOOTING, REPORT HEADING, REPORT FOOTING, and each control-id may appear in only one CONTROL HEADING and only one CONTROL FOOTING group.  If CONTROL FOOTING FOR ALL is coded, it must be the only CONTROL FOOTING in the report.

The physical order of report group descriptions is irrelevant.  For example, the PAGE HEADING group need not necessarily appear before the DETAIL and PAGE FOOTING.  Report writer produces them in the correct sequence according to the rules for page-fit and control break testing.  However, for ease of maintenance, the order implied in the format above is recommended.  Also, it is helpful if CONTROL HEADING groups are coded in major-to-minor order and CONTROL FOOTING groups in minor-to-major order, paralleling the sequence in which these groups will be presented in the report.

In a report with a PAGE LIMIT clause, if your group contains any absolute LINE clauses, report writer will check that each line of the group will lie within the region of the page appropriate to the TYPE of the group.  Refer to the diagram of the regions of the page (see PAGE LIMIT Clause: Operation).  REPORT HEADING and REPORT FOOTING groups may appear anywhere on the page from the HEADING position onwards.  If your group contains only relative LINE clauses, and the report has a PAGE LIMIT clause, report writer will check at compilation time that your group is not larger than the appropriate region of the page, allowing for any other groups that may share that region (that is, a REPORT HEADING appearing above the first PAGE HEADING, or a REPORT FOOTING appearing below the last PAGE FOOTING).

All the CONTROL HEADING groups with an OR PAGE phrase must be able to fit on the page above any other DETAIL or CONTROL HEADING group.  Stated precisely: (a) each DETAIL or other CONTROL HEADING must either have only relative LINE clauses or must begin with an absolute LINE which is higher than the highest possible line number produced by the CONTROL HEADING groups with an OR PAGE phrase, and (b) the LAST DETAIL value must be sufficient to accommodate the largest such combination.

TYPE Clause: Operation

You use the TYPE clause to indicate, implicitly, where and how your group is to be produced in the report.  Here is a summary of how each TYPE is handled:

This group will appear once, at the very start of the report.  (See GENERATE Statement: Operation.)

This group will be produced as the first group in each page.  (See LINE Clause: Operation.)

This group will appear automatically at the start of each different actual value of the corresponding control.  (See CONTROL Clause.)  If you code the OR PAGE phrase, the report group will also be triggered by a page advance.  See 3.24.4 below for full details.

All the remaining report groups that are not of one of the other six types are of TYPE DETAIL.  DETAIL groups are the only report groups that can be GENERATEd explicitly by the program.  The remaining six TYPEs of report group are produced automatically whenever necessary before the DETAIL group is processed.  (Note that with summary reporting , the other six TYPES are the only ones that can be produced.  See GENERATE Statement: Coding Rules.)

This group will appear automatically at the end of each different actual value of the corresponding control or controls.  (See CONTROL Clause .)

This group will be produced as the last group in each page (except on a page occupied only by a REPORT HEADING and immediately after a REPORT FOOTING ).  (See LINE Clause: Operation.)

This group will appear once, at the very end of the report.  (See TERMINATE Statement.)

RH and PH together

   If your report contains both a REPORT HEADING and a PAGE HEADING group, report writer will attempt to place them both in the Page Heading region of the page.  If it can do this without overlap, without overflowing the region, and without violating any of the above rules, then your REPORT HEADING group will be produced on the first page of the report, above the PAGE HEADING.  If the PAGE HEADING has relative LINE clauses, it begins relative to the last line of the REPORT HEADING.  If, despite this, you require the REPORT HEADING to appear on a page by itself, you should code NEXT GROUP NEXT PAGE in the 01-level entry of the REPORT HEADING, to suppress this check.

   If you want the REPORT HEADING to appear on the first page above the PAGE HEADING and "push it down" so that your DETAIL groups start lower on the first page than they do on the remaining pages, you should omit the FIRST DETAIL sub-clause.  Your DETAIL groups will then begin on the line following the PAGE HEADING .  To get extra space before your first DETAIL group, you may define a blank LINE entry at the end of your PAGE HEADING:

       RD  ...
           PAGE LIMIT 60.                  *> no FIRST DETAIL clause

       01  TYPE RH.
         03  LINE 1.
           05  COL 1          VALUE "END OF YEAR REPORT".
         03  LINE + 1.
           05  COL 1          VALUE "******************".
         03  LINE + 2.                     *> blank lines for first sheet layout

       01  TYPE PH.
         03  LINE + 1.
           05  COL 1          VALUE "WOLFITDOWN PETFOODS".
         03  LINE + 2.                     *> blank lines before DETAILs begin

   You may also achieve the same result without using a REPORT HEADING, by including all the lines in a single PAGE HEADING and using a PRESENT AFTER REPORT clause (see PRESENT AFTER Clause).

PF and RF together

   If your report contains both a PAGE FOOTING and a REPORT FOOTING group, report writer will attempt to place them both in the Page Footing region of the page.  If it can do this without overlap, without overflowing the region, and without violating any of the above rules, then your REPORT FOOTING group will be produced on the last page of the report, below the PAGE FOOTING.  If the REPORT FOOTING has relative LINE clauses, it begins relative to the last line of the PAGE FOOTING.  If, despite this, you require the REPORT FOOTING to appear on a page by itself, you should code an ON NEXT PAGE phrase in the first LINE clause of the REPORT FOOTING, to suppress this check.


You may add the OR PAGE phrase after the control-id operand for TYPE CONTROL HEADING.  This causes your CONTROL HEADING to be produced at the top of each page.  This enables you to repeat essential "key" information after your regular PAGE HEADINGs.  The precise rules of operation are as follows:

If your report contains any such TYPE CH groups with the OR PAGE phrase, the CONTROL HEADING group will be presented after a control break at the relevant level, exactly as when the PAGE option is not present, but in addition, the actions on page advance processing are modified as follows:

If a DETAIL group causes a page advance then, after the usual page advance has taken place, the CONTROL HEADING group is printed.  If more than one TYPE CH group has the OR PAGE option, these CONTROL HEADING groups are printed in hierarchic order, from highest to lowest.  Each CONTROL HEADING is, of course, printed on the new page, irrespective of whether or not it would fit on the previous page.

If a CONTROL HEADING group causes a page advance, the same action occurs as in (a) above, except that the CONTROL HEADING group that caused the page advance is output only once on the new page, whether it has the OR PAGE phrase or not.

If a CONTROL FOOTING group causes a page advance, the same action occurs as for a DETAIL except that no CONTROL HEADINGS below the level of the CONTROL FOOTING are printed.

If a group has CH FOR PAGE without a control-id, it will be treated as equivalent to CH FOR PAGE OR REPORT.

The following shows the layout you might require:

 ** HEADING **     PAGE 1
 YEAR: 1991
 MONTH: 01
 ........   20
 ........   30
 MONTH: 02
 ........   10
 ........   20
 MONTH: 03
 ........   20
 ........   30
 ........   40


 ** HEADING **     PAGE 2
 YEAR: 1991
 MONTH: 03
 ........   50
 MONTH: 09
 ........   20
 ........   30
 MONTH: 11
 ........   20
 ........   40
 ........   10


 ** HEADING **     PAGE 3
 YEAR: 1991
 MONTH: 12
 ........   10
 ........   20
 ........   30
 ........   10
 ........   20
 ........   30
 ........   10
 ........   20
 ........   30
 ........   10


 ** HEADING **     PAGE 4
 YEAR: 1991
 YEAR: 1992
 MONTH: 01
 ........   20
 ........   10
 ... etc.

Note the following labelled points in the diagram:

(A)   Because of the OR PAGE phrases, both CH groups re-appear at the top of the page even though neither control has changed .

(B)   When a control break occurs and the corresponding CH group will not fit on the current page, it appears once only at the top of the new page, even though it has an OR PAGE phrase.

(C)   If a CF group causes a page advance, the CH groups are produced at the top of the next page, but only those at the same level or above that of the CF group.

The following is the report writer code required to produce this layout:

       RD  REP-ONE
           PAGE LIMIT 40

       01  PH                     LINE 1.
           05  COL 1      "** HEADING **".
           05  COL 19     "PAGE".
           05  COL 21     PIC Z9  SOURCE PAGE-COUNTER.

       01  CH FOR YEAR OR PAGE    LINE + 1.
           05  COL 1      "YEAR:".
           05  COL + 2    PIC 9(4)     SOURCE YEAR.

       01  CH FOR MONTH OR PAGE   LINE + 1.
           05  COL 1      "MONTH:".
           05  COL + 2    PIC 99       SOURCE MONTH.

       01  REP-DET  TYPE DE            LINE + 1.
           05  COL 1      "........".
           05  PVAL  COL + 2    PIC ZZZ9     SOURCE WVAL.

       01  TYPE CF FOR MONTH           LINE + 1.
           05  COL 1      "TOTAL FOR MONTH:".
           05  M-TOT      COL + 2    PIC ZZZ9     SUM OF PVAL.

       01  TYPE CF FOR YEAR            LINE + 1.
           05  COL 1      "TOTAL FOR YEAR:".
           05  COL + 2    PIC ZZZ9     SUM OF M-TOT.

USAGE Clause

This clause is allowed for documentary purposes in the REPORT SECTION, for consistency with basic COBOL, or to emphasize that an entry is DBCS.


USAGE+--++ +- DISP-------+
            +IS+  +-

USAGE Clause: Coding Rules

The USAGE clause may be coded at any level, but no item may be subject to both USAGE DISPLAY and USAGE DISPLAY-1.

DISP is synonymous with DISPLAY.

Only non-DBCS items may be subject to USAGE DISPLAY and only DBCS items may be subject to USAGE DISPLAY-1.

No other forms of the USAGE clause are permitted in the REPORT SECTION.

USAGE Clause: Operation

DISPLAY is retained for consistency with basic COBOL but it is never required.

USAGE DISPLAY-1 indicates that the item (or items if on a group level) is DBCS (Double-Byte Character Set), such as Japanese Kanji.  However, it is not required in the REPORT SECTION, since it is implied by the presence of a DBCS PICTURE string (containing the symbols "G" and "B" only) or a DBCS literal, of the form G"" or G'' where so and si are the shift-out and shift-in characters.  DBCS items are stored with a shift-out character on the left and a shift-in on the right.  Each double-byte character occupies one print column position even though it takes up two bytes of memory.  COLUMN numbers (absolute or relative) take this into account.  Spaces inserted between DBCS items are the regular (non-DBCS) space.

VALUE Clause

This clause may be used whenever the report field to be output consists of a fixed literal value.

                   v       |
    |      +IS+  |

VALUE Clause: Coding Rules

You may specify a numeric or non-numeric literal, including a figurative constant, or a DBCS literal.  An ANS-85 SYMBOLIC CHARACTER is also permitted.

Unless you specify ALL or a figurative constant, you do not need a PICTURE clause.  For example:

           05  COL 21   VALUE "*** ALL-IN SPORTS CLUB ***".

You may use 'apostrophes' instead of "quotes" if your current compiler options expect them.  The Precompiler accepts either delimiter at the start of a literal, scanning for the same delimiter to close the literal.  Continued literals are also permitted.  As usual, two quotes juxtaposed within a "literal" signify a single quote as part of the value, and similarly for apostrophe.

You may use the ALL "literal" form or a numeric literal or figurative constant, but in all these cases you must specify a PICTURE.  Here is an easy method of coding a repeated value:

           05  COL 1    PIC X(24)   VALUE ALL "XOX".

   which gives you the repeated pattern: XOXXOXXOXXOXXOXXOXXOX

If the item is defined as DBCS by virtue of its PICTURE clause or USAGE DISPLAY-1 clause, the literal must also be DBCS.  However a PICTURE clause is not required, a PICTURE of G(n) where n is the number of double bytes being assumed in default.

Any literal may also be hexadecimal.  However, it is inadvisable to use this facility to insert printer control characters into your print data, since these will (a) make your program non-portable and unreadable (b) put your COLUMN positions out of alignment.  The STYLE clause is designed specifically for this purpose and has none of these drawbacks.  (See STYLE Clause.)

VALUE Clause: Operation

The VALUE clause results in the specified fixed literal appearing in your report field.  Assuming that your program does not alter the value by overwriting the report field procedurally (which it can do if the field is named), the value will be unchanged throughout the report.

Report writer will either "pre-set" (fill in) your report field with the specified literal at compile time; or it may move the literal into the report field at run time, in cases where the report field is in a variable position, or where the report line cannot hold pre-set values because it is subject to an OCCURS clause.

If the item is DBCS, it is stored in the report line with each double-byte character occupying one column position.  (See USAGE Clause.)

Multiple VALUES

If you use the multiple form of the VALUE clause, by writing more than one literal after the keyword, it will save you the effort of coding several separate entries.  Note the following:

If you wish to place no value in a particular occurrence, you may simply code a space character: " ".

Your entry must be subject to at least one of the following:

fixed OCCURS clause (not OCCURS...DEPENDING), or

multiple LINES clause, or

multiple COLUMNS clause.

All the literals must be either DBCS or non-DBCS.

The rule for the number of literals allowed in your multiple VALUE is similar to that of the multiple SOURCES clause (see Multiple SOURCES); that is, it must exactly equal either the total number of repetitions in all the dimensions of the entry, or the product of the numbers of repetitions of one or more of the inner dimension(s).  For example, with the following layout:

         03  LINE OCCURS 2.
          04  OCCURS 3.
           05  COLS +3, +3, +3, +1    VALUES ARE .....

   the number of literals should be either 4 (just the inner dimension), 12 (the product of the inner two dimensions), or 24 (all the dimensions).

If the literals cover more than one dimension, they are distributed along the innermost dimension, periodically stepping to the next entry in one or more outer dimensions.  For example:

     03  LINES 2   STEP 1  OCCURS 3.
       05  COL  2  STEP 5  OCCURS 4
       VALUES  "JAN" "FEB" "MAR" "APR"
               "MAY" "JUN" "JUL" "AUG"
               "SEP" "OCT" "NOV" "DEC".

   will result in:


If there are two or more dimensions and the number of terms matches only the inner dimension(s), the series of literals is re-cycled from the first operand for each of the outer repetitions.  For example, the following case:

         03  LINE OCCURS 4.
           05  COLS 1 13      VALUES
           "THIS YEAR" "SOME TIME".

   will result in:


The multiple VALUE operand may be used as one or more of the alternatives in a multiple-choice entry.  You need not use a multiple VALUE in every alternative:

           05  COLS 1 12 25    VALUES
               "BLEU"      "ROUGE"     "JAUNE"        WHEN LANGUAGE = "F"
               "BLAU"      "ROT"       "GELB"         WHEN LANGUAGE = "G"
               "BLUE"      "RED"       "YELLOW"       WHEN LANGUAGE = "E"
               "????"                                 WHEN OTHER.

If, as is usual, you omit a PICTURE clause, the size of each field is the size of its corresponding literal, as seen in the following example:

           05  COLS 1 +2 +2    VALUES "CAESAR" "QUELLED" "VERCINGETORIX".

   which yields:


   This is also true of multiple-choice entries.

In all cases, you may omit the VALUE keyword.

Other examples of the multiple VALUE clause will be found under Multiple COLUMNS Clause and Multiple LINES CLause).


This clause enables you to vary the value of a numeric counter (typically for use elsewhere as a subscript) during the production of a repeating field.


            v                                            |
FROM expression-1++BY expression-2+

VARYING Clause: Coding Rules

You may write any number of different data-name operands in this clause, each with an optional associated FROM and BY phrase.

Your entry must also have either an OCCURS clause or a multiple COLUMN clause or a multiple LINES clause.

Your data-names must not be defined already anywhere else in the program and you should not attempt to define them separately.  Report writer creates a description for them itself, internally.  (This is similar to the way COBOL handles index-names.)

You can re-use the same data-names in different VARYING clauses, provided that you do not do this when the clauses are nested (enclosed one within the other).  For example, you could write VARYING R-LINE on each repeating LINE, and VARYING R-COL on each repeating COLUMN, throughout your program.

If you intend FROM 1, you may omit the FROM phrase and report writer will infer it.  Likewise, if you intend BY 1, you may omit the BY phrase and report writer will infer it.  (FROM 1 and BY 1 are the most usual requirements, so these assumptions are convenient.)

Each expression may be any integer, or an identifier, or an arithmetic expression, provided that the result has an integer value.  The expression may contain data-names of an enclosing VARYING clause.  It can also use a data-name of the same VARYING clause, but only in its BY expression.  It must not contain data-names of an enclosed VARYING clause, or of any other VARYING clause.  Thus the following are legal:

   a.     05  OCCURS 3  VARYING R-MONTH.

   b.     05  OCCURS 3  VARYING R-MONTH FROM 1 BY (R-MONTH + 1).

   but the following are illegal:

            07  OCCURS 4  VARYING R-MONTH.

   d.     05  OCCURS 3  VARYING R-MONTH FROM (R-MONTH + 1).

   e.     05  OCCURS 3  VARYING R-MONTH.

VARYING Clause: Operation

When report writer is about to produce the first occurrence, it places the FROM value in an internal named data item set up implicitly by the VARYING clause.  This is repeated, in the order given in the clause, for any additional data-names that may have been specified in the VARYING clause.

When report writer is about to produce each of the remaining occurrences, it adds the BY value to the data item.  This is also repeated, in the order given in the clause, for any additional data-names that may have been specified in the VARYING clause.

The VARYING clause enables you to produce different source-items or values in successive appearances of a repeated field.  Here are some examples:

a.   To generate the numbers 1 through 10 in a line:

    1    2    3    4    5    6    7    8    9   10

         03  LINE.

b.   To output a two-dimensional array in Working-Storage into a two-dimensional array in your report (for example daily costs for four seven-day weeks):

 WEEK 1   $19  $230   $34   $56  $378  $270    $9
 WEEK 2  $340  $236   $43   $23  $248    $0  $354
 WEEK 3  $120  $134   $58  $442   $98  $739  $121
 WEEK 4   $39    $0  $800  $344  $801   $89  $387

           05  COL 1   "WEEK".
           05  COL 6   PIC 9     SOURCE WEEK-NO.
           05  COL 9   PIC $$$9  OCCURS 7 STEP 6  VARYING DAY-NO
                       SOURCE WS-VALUE (WEEK-NO DAY-NO).

c.   You could display each week's entries from right to left by writing:

             VARYING DAY-NO FROM 7 BY -1.

d.   Now let's display the same entries, except that they are all held in a one-dimensional array of twenty-eight entries.  (This example is important .)

                                      WEEK-NO FROM 1 BY 1.
           05  COL 1   "WEEK".
           05  COL 6   PIC 9     SOURCE WEEK-NO.
           05  COL 9   PIC $$$9  OCCURS 7 STEP 6
                       VARYING DAY-NO FROM START-DAY-NO BY 1
                       SOURCE WS-VALUE (DAY-NO).

   As each week is processed, START-DAY-NO takes values 1, 8, 15 and 22.  DAY-NO takes the seven values 1 to 7, then 8 to 14, then 15 to 21, then 22 to 28 in turn, each time starting with the new value of START-DAY-NO.  In the clause VARYING START-DAY-NO FROM 1 BY 7, the phrase FROM 1 could have been omitted and in the clause VARYING DAY-NO FROM START-DAY-NO BY 1, the phrase BY 1 could have been omitted.

To "fold round" a large array in boustrophedon ("as the ox turns") sequence (if NO-ACROSS is the horizontal repeat factor):

         03  LINE OCCURS ... TIMES
                     INCR FROM 1 BY (- INCR - INCR).
           05  ...   OCCURS 0 TO 100 TIMES DEPENDING ON NO-ACROSS ...
                     SOURCE TABLE-ENTRY (SUBSCRIPT).

  1 -> 2 -> 3 -> 4 -> 5 - > 6 -> 7 -> 8 -> 9 ->10
 20 <-19 <-18 <-17 <-16 <-15 <-14 <-13 <-12 <-11
 21 ->22 ->23 ->24 ->25 ->26 ->27 ->28 ->29 ->30
 40 <-39 <-38 <-37 <-36 <-35 <-34 <-33 <-32 <-31

To produce a pyramid-shaped design:


         03  LINE OCCURS 6  VARYING SUB-1 FROM 5 BY -1
                            SUB-2 FROM 1 BY 2.
           05  COL + 1   OCCURS 0 TO 5 DEPENDING ON SUB-1.
           05  COL + 1   VALUE "*"     OCCURS 1 TO 11 DEPENDING ON SUB-2.

Note that VARYING can also be used with a multiple COLUMN or LINE, as the following example shows:

         03  LINES 2 3 4   VARYING LINE-INDEX.
           05  COLS  10 20 31 52   VARYING COL-INDEX  PIC ZZZ9
                           SOURCE SALES (LINE-INDEX COL-INDEX).

To set up a "running index" which continues each time from its latest value, do not code something like VARYING R-WEEK FROM R-WEEK + 1 , but calculate the starting value explicitly.

To give your counter a series of values, say W-CNT (1), W-CNT (2), which are not formed by simple incrementing, write:

               VARYING R-MOD FROM 0 BY 1
                       R-COUNTER FROM W-CNT (1) BY W-CNT (R-MOD) - R-COUNTER

By experimenting with the VARYING clause, you will discover many novel and surprising uses.

WRAP Clause

The WRAP clause is used to produce an automatic wrap round to a new continuation line when the next field will not fit on the current line.

   Format a

                  +-COL----+ +-identifier-1-+
                 +-COL----+ +-identifier-2-+
STEP integer-3+-----++

   Format b


WRAP Clause: Coding Rules

The AFTER phrase gives the rightmost column number that any field may occupy before wrap round becomes necessary. If integer-1 is specified, it must lie in the range 1 to maximum line width.  Its value acts as a maximum line width for any lines in its scope.  The rightmost column position of every entry with an absolute COLUMN must therefore not exceed integer-1.  If identifier-1 is specified, a similar check is made at run time.  If the phrase is omitted, a value of the LINE LIMIT is assumed for integer-1 and, if the identifier form of LINE LIMIT is in use, its value will be computed, as usual, at INITIATE time.  Thus, by default, lines are allowed to reach the usual page width before wrap round.

The TO phrase gives the column number at which printing continues after wrap round.  If integer-2 is specified, it must lie in the range 1 to maximum line width.  If identifier-2 is specified, a similar check is made at run time.  If the phrase is omitted, a value of 1 is assumed for integer-2.  Thus, by default, a line wraps round to column 1.

The STEP phrase gives the relative vertical offset for any continuation lines.  If the phrase is omitted, a value of 1 is assumed for integer-3 .  Thus, by default, a line is continued onto the immediately following line.  If a PAGE LIMIT clause is present in the RD, the value of integer-3 is used by the precompiler in calculating the (maximum) vertical size of the group to check that it will fit correctly into its assigned region of the page.

WRAP may be coded either (a) in an entry containing a LINE clause or (b) at a higher level having one or more LINE entries beneath it.  This second possibility allows you to avoid repeating the same clause in several LINE entries.

Only relative COLUMN entries are allowed to cause wrap round.  If a LINE entry has a WRAP clause, the COLUMN entries forming the description of the line must end in one or more relative COLUMN entries.  Entries with absolute COLUMN numbers still cannot exceed the maximum line width.

A superfluous WRAP clause is not permitted.  So the COLUMN entries (in particular the trailing relative COLUMN entries) must be such that the LINE LIMIT could be exceeded.  (If this is not foreseeable at precompilation time, it will be assumed that this could happen at run time.)

If the WRAP clause is coded at a higher level with more than one LINE entry beneath it, it is sufficient if at least one of the LINE clauses obeys these rules.  For example, it is permissible to code the WRAP clause at the 01-level, even if only one of LINE entries in the group can cause wrap round.  However, in general any number - even all - the LINE entries in a report may be capable of causing wrap round.

The format b NO WRAP clause is allowed only at a level subordinate to a format a WRAP clause.  The entry containing NO WRAP must represent more than one physical elementary printable field.  No other nesting of the clause is permitted.

WRAP Clause: Operation

The WRAP clause causes data to wrap round automatically to a new continuation line when the next field or group of fields will not fit on the line.  It may be used in any TYPE of report group.  The point where wrap round begins is always after a complete elementary field.  Hence a horizontal "fit test" is performed before each field is output, unless it has an absolute COLUMN or is known to fit.  (Compare the "page-fit test" performed in the vertical direction.)  If the field's right-hand column would extend beyond the column position given in the AFTER phrase, the line is output without the field and then space-filled.  The field in question is now placed in the new line, starting in the column position given in the TO phrase.  The initial spacing implied by the "PLUS integer" of the COLUMN clause is ignored.  The vertical line spacing is given by the STEP phrase.

   If the identifier form of the AFTER or TO phrase is used, the identifier's current value is used.

   The following complete example shows how a variable number of error messages may be output:


  NAME           AMOUNT     DATE    MESSAGE(S)

 JONES            A0.00   09/11/89  AMOUNT NON-NUM.
 TIMSON           80.00   44/32/89  INVALID DATE
 RO%ERS           X0.0Y   44/32/89  NOT ALPHA  AMOUNT NON-NUM.
                                    INVALID DATE
 SMITH           100.00   12/01/89
                             col 36 ^                    col 64 ^

           PAGE LIMIT 60.
         03  LINE + 1       WRAP AFTER COL 64 TO COL 36.
           05  COL 1        PIC X(20)          SOURCE name.
           05  COL 15       PIC X(8)           SOURCE amount.
           05  COL 26       PIC X(8)           SOURCE date.
           05  COL + 3      "NOT ALPHA"        PRESENT WHEN name invalid .
           05  COL + 3      "AMOUNT NON-NUM."  PRESENT WHEN amount invalid.
           05  COL + 3      "INVALID DATE"     PRESENT WHEN date invalid.

   The phrase AFTER COL 64 gives the last column that can be occupied by any field in the line.  The phrase TO COL 36 gives the starting column for the wrap round.  STEP 1 is assumed in default, so continuation is onto the next line.  Note that the initial spacing implied by the "+ 3" of the first COLUMN clause on the new line is ignored.

As well the conditional case just described, where the continuation line appears in exceptional circumstances, it is possible (though less useful) for the wrap round to occur every time, as in this example:

         03  LINE + 2    WRAP AFTER COL 30 TO COL 11.
           05  COL 1     PIC X(30)   SOURCE W-SURNAME.
           05  COL + 3   PIC X(20)   SOURCE W-GIVEN-NAME (1).
           05  COL + 3   PIC X(20)   SOURCE W-GIVEN-NAME (2).

   which is exactly equivalent to:

         03  LINE + 2.
           05  COL 1     PIC X(30)   SOURCE W-SURNAME.
         03  LINE + 1.
           05  COL 11    PIC X(20)   SOURCE W-GIVEN-NAME (1).
           05  COL + 3   PIC X(20)   SOURCE W-GIVEN-NAME (2).

Horizontal Fit Test

   The "fit test" takes into account a field's variable length.  By changing the PICTUREs in the previous example to make them variable length, we have the following, more common, situation:

       01  FULL-NAME     TYPE DE.
         03  LINE + 2    WRAP AFTER COL 30 TO COL 11.
           05  COL 1     PIC X<X(29)>   SOURCE W-SURNAME.
           05  COL + 3   PIC X<X(19)>   SOURCE W-GIVEN-NAME (1).
           05  COL + 3   PIC X<X(19)>   SOURCE W-GIVEN-NAME (2).

   The following sample output shows one of each possible outcome:





   The longer names in this layout are a good example of the rare conditions that have to be allowed for, but which, without this special feature, often take up a disproportionate amount of programming effort.

If the containing group is a body group beginning with a relative LINE clause, the continuation lines are taken into account during the group's page-fit test.  For example, if only two lines are available for the printing of the last group in the preceding example, a new page would be started:


   whereas in all the other instances the group would fit on the current page.

With repetition

   When an OCCURS clause or a multiple LINE clause is coded at the same level as WRAP, the WRAP clause applies separately to each occurrence .

NO WRAP indicates that the entries subject to NO WRAP must appear together in the same line.  The horizontal "fit test" is therefore performed before the entire set of fields is output to ensure that they are not to split over a line boundary.  (Compare NO MULTIPLE PAGE which does the same for the page boundary.)  When an OCCURS clause is coded at the same level as NO WRAP, the NO WRAP clause applies separately to each occurrence.  The following example lists names across several lines, keeping initials and surnames together:

           PAGE LIMIT 60
           LINE LIMIT 40.
       01  NAMES-GROUP  TYPE DE.
        02  LINE + 2    WRAP.
             NO WRAP.
          04  COL + 1   OCCURS 4 TIMES VARYING R-INTL-NO
                        PIC X"."   SOURCE W-INTL (R-NAME-NO R-INTL-NO)
                        ABSENT WHEN W-INTL (R-NAME-NO R-INTL-NO) = SPACE.
          04  COL + 2   PIC <X(20) SOURCE W-SURNAME (R-NAME-NO).
          04  COL + 2.