COBOL Report Writer Feature

 

I was prompted to write this tutorial on the COBOL Report Writer feature, by the question "is Report Writer available in the MVT COBOL compiler and, if so, how do I use it?".  Of course the answer is "yes", and it is really quite easy to use.  

I started learning to use Report Writer before I was fully competent to write advanced COBOL programs, simply because one of the "gurus" at the university where I was a student was a devoted fan of Report Writer.  He was always eager to show me something new that could be done with Report Writer, quicker and more easily than manually coding.  I also learned that it was useful for more than just writing printed reports, since the first time I asked him, "what are you doing", he was using it to prepare a tape to submit to the state's college coordinating board. 

First of all, I want to clarify that the COBOL Report Writer feature is not an equivalent to a stand-alone data extracting and reporting program, such as Easytrieve or Mark IV.  Instead, it is probably more accurate to describe it as a printing control tool, since what it really does is simplify the coding of print output lines and automates the process of populating and writing the lines described in the Report Writer section of the program.

There have been some advancements made in Report Writer since the era of the MVT COBOL compiler, but I will only cover the features present in the MVT COBOL compiler.  They should all still work in any compiler that supports the Report Writer feature and if you understand the basics, the few new enhancements will be easy to pick up from the manual for your compiler. 

Report Writer allows you to code, in the Report Section, a logical representation of the report to be printed.  Therefore, the first step is to define the logical organization of the report you wish to produce.  A report may be divided into one or more report groups.  Each report group consists of a hierarchical sequence of items:  the report name, major group, minor group, elementary items.  Each report may contain several different types of grouped data, defined to the Report Writer as the TYPE of the group.

As I progress through this tutorial, I will include the COBOL programs to produce a series of reports, starting with a very simple report that I will subsequently enhance to utilize more advanced features of Report Writer.  The first report is a list of the contents of a transaction file.  The layout of the transaction record is:

Field Contents and Name

Picture

Customer Number (TR-CUSTOMER-NUMBER)
9(4)
Filler
X(1)
Customer Name (TR-CUSTOMER-NAME)
X(16)
Filler
X(1)
Item Number (first digit is department number)
            (TR-ITEM-DEPARTMENT)
            (TR-ITEM-NUMBER)
9(5)
Filler
X(1)
Item Cost (TR-ITEM-COST)
9(3)V99
Filler
X(47)

The layout for the report is:

                          C U S T O M E R  C H A R G E  R E P O R T

CUST. NO.     CUST. NAME     DEPT.    ITEM NO.    ITEM COST

  9999   XXXXXXXXXXXXXXXX      9       99999       $$$.$$

The first step is to utilize the layout of the report and decide how to group the lines that are to be produced by type.  For this simple report, there are only two groups needed:  the Page Heading, and a single Detail.  So now I will describe the syntax for the Report Description and the code necessary for this report.

 

Syntax for the Report Description Entry

The Report Section is coded following the Working Storage Section and preceding the Procedure Division.  If you need to code a Linkage Section in a program that also utilizes Report Writer, the Linkage Section should be coded before the Report Section.

The Report Description is similar in function to the File Description entry - it defines basic characteristics of the report.  The syntax for the Report Description entry is:

REPORT SECTION.
RD  report name
    [{CONTROL IS | CONTROLS ARE} [FINAL], identifier-1, identifier-2, ... ]
    [PAGE [LIMIT IS] integer-1 [LINES]
      [HEADING integer-2]
      [FIRST DETAIL integer-3]
      [LAST DETAIL integer-4]
      [FOOTING integer-5]
    ].    

The report name is a unique identifier which identifies the report to the COBOL program.  It is used in the File Description entry for the output file to which the report will be written and is used in Procedure Division statements that refer to the report.  The optional CONTROL specification is used to define what dataname(s) are used to determine control breaks in the report; for this report we will not need a CONTROL specification.  The PAGE LIMIT specification defines the size of the printed page as integer-1 lines, and determines when page overflow occurs.   The HEADING specification defines the line number on which the first line of the Page Heading report group will be produced.  Likewise, the FIRST DETAIL specification defines the line number on which the first line of the first Detail report group will be produced.  The LAST DETAIL specification defines the last line number on which any line of a Detail report group will be produced.  The FOOTING specification defines the last line number on which any line of a Control Footing report group will be produced.  The HEADING, FIRST DETAIL, LAST DETAIL, and FOOTING specifications are all optional.  If HEADING is omitted, the report will be produced as if the specification were coded with integer-2 as 1, that is, line number 1.  If FIRST DETAIL is omitted, the report will be produced as if the specification were coded with integer-3 equal to the value coded for integer-2.  If LAST DETAIL is omitted, the report will be produced as if the specification were coded with integer-4 equal to the value coded for integer-5.  If FOOTING is omitted, the report will be produced as if the specification were coded with integer-5 equal to the value coded for integer-4.  If both LAST DETAIL and FOOTING are omitted, the report will be produced as if the specification were coded with both integer-4 and integer-5 equal to the value coded for integer-1.  

The PAGE LIMIT clause is used to describe the physical format of a page of the report.  The clause specifies the specific line control to be maintained within the logical presentation of a page.  The PAGE LIMIT clause is required when the page format is to be controlled by the Report Writer.  If the PAGE LIMIT clause is coded for the report description, two numeric counters are generated for the report:  PAGE-COUNTER and LINE-COUNTER.  

PAGE-COUNTER is a numeric counter that may be used as a source data item in order to present the page number on a report.  The maximum size of a PAGE-COUNTER is based on the size specified in the PICTURE clause associated with the elementary item whose SOURCE is PAGE-COUNTER.  If more than one elementary item refers to the PAGE-COUNTER of a report, the PICTURE clauses of each must be identical.  The size must be adequate to prevent overflow.  If more than one Report Description entry exists in the Report Section, the user must qualify PAGE-COUNTER by the Report Name.  This counter may be referred to in any Procedure Division statement.  The counter is automatically set to 1 upon execution of the INITIATE statement for the Report Name and incremented by 1 for each page break recognized by the Report Writer (after the production of any Page Footing report group but before the production of any Page Heading report group).

LINE-COUNTER is a numeric counter that may be referenced in Procedure Division statements.  The counter is automatically set to 0 upon execution of the INITIATE statement for the Report Name, is incremented as lines from report groups are produced, and reset to 0 when the PAGE LIMIT Integer-1 LINES entry is exceeded during execution.  Changing the LINE-COUNTER by Procedure Division statements may cause the page format control to become unpredictable in the Report Writer.  The value of the counter during any Procedure Division test statement represents the number of the last line used by the previous report group or that of the last line skipped to by the previous NEXT GROUP specification.  If more than one Report Description entry exists in the Report Section, the user must qualify LINE-COUNTER by the Report Name.

 

Report Description Entry for Customer Charge Transaction List Report 

The coding for the report is:

RD  CUSTOMER-REPORT
    PAGE LIMIT IS 66 LINES
    HEADING 1
    FIRST DETAIL 5
    LAST DETAIL 58.

 

Syntax for the File Description for Report Writer Output

Now I want to take a step back and code the File Description entry for the file to which the report will be written.  Instead of coding one or more lines under the File Description defining a record to be written, and referring to that record description's 01 level data name in a DATA RECORD clause, you code a REPORT clause in the File Description entry.  The syntax is:

FD  file-name
    [BLOCK CONTAINS clause]
    [RECORD CONTAINS clause]
    [LABEL RECORDS clause]
    {REPORT IS report name | REPORTS ARE report name-1, report name-2, ...

You may code the File Description entries such that more than one report is written to a single file.  If you code the statements in the Procedure Division in such a way that the groups of the reports are produced sequentially, that is all of the groups of report 1 are produced before any groups of report 2, all of the groups of report 2 are produced before any groups of report 3, etc., the reports will appear properly in sequence in the output file.  If the Procedure Division logic is such that the groups will be produced for each report interspersed, you will need to include a WITH CODE clause in the Report Description and process the resulting output file with a utility to separate the lines of the reports for printing.  That is a bit beyond this brief tutorial, but implementing it is quite easy and should be explained in your COBOL compiler reference manual. 

You may also include an individual report name in more than one File Description entry.  This will cause each group generated for the report to be written to all output files where the report name is specified.  This can be useful if you wish to both print a copy of the report and produce an archive copy on tape or disk in the same execution.

 

File Description Entry for Customer Charge Transaction List Report

The File Description entry for the report is:

FD  REPORT-FILE
    LABEL RECORDS ARE OMITTED
    REPORT IS CUSTOMER-REPORT.

 

Syntax and Rules for Report Group Entries

The entries defining the individual groups of a report are coded following the Report Description entry in the Report Section.  The syntax for the group definitions is very similar to that used to code group items in storage.  In the next few paragraphs I will present the syntax and rules for coding report group entries.  Although I present all the clauses, including some quite advanced ones, they are not all required for all reports; in fact, many reports can be coded with only a few very simple entries.  You may want to glance over the syntax/rules and proceed to the coding for the first report; then come back to the syntax/rules as a reference when you need to.

Syntax for the Report Groups Entries

Format 1
01  [data-name-1]
    [LINE clause]
    [NEXT GROUP clause]
    TYPE clause.		
Format 2
level-number [data-name-1]
    [BLANK WHEN ZERO clause]
    [COLUMN clause]
    [GROUP clause]
    [JUSTIFIED clause]
    [LINE clause]
    [NEXT GROUP clause]
    PICTURE clause
    [RESET clause]
    {SOURCE | SUM | VALUE} clause
    TYPE clause.

A report group is a set of data made up of one or more print lines with one or more data items.  Report groups may exist within report groups -- all or each capable of a reference by a GENERATE or USE statement in the Procedure Division.  From the syntax above, the data-name for any report group is optional; inclusion of a data-name for a report group permits the group to be referred to by a GENERATE statement in the Procedure Division or by a USE statement in the Declaratives Section of the Procedure Division.  At execution time, report groups are written to the output file as a result of the GENERATE statement.

This entry defines the characteristics of a report group. whether a series of lines, one line, or an elementary item.  The placement of an item in relation to the entire report group, the hierarchy of a particular group within a report group, the format description of all items, and any control factors associated with the group -- all are defined in the entry.  The system of level numbers is employed here to indicate elementary items and group items within the range of 01-49.

Pictorially to the programmer, a report group is a line, or a series of lines, initially consisting of all spaces; its length is determined by the compiler based on the associated File Description specifications.  Within the framework of a report, the order of report groups specified is not significant.   Within the framework of a report group. the programmer describes the presented elements consecutively from left to right, and then from top to bottom.  The description of a report group is analogous to the data record and consists of a set of entries defining the characteristics of the included elements.  However, unlike a data record, any positions in a report line for which no elementary item is defined will be filled with spaces.

The report group description entry specifies the characteristics of a particular report group and of the individual data-names within a report group.  A report group may be comprised of one or more report groups.  Each report group is described by a hierarchy of entries similar to the description of the data record.  There are three types of report groups:  heading, detail, and footing.  A report group is considered to be one unit of the report consisting of a line or a series of lines that are printed (or not printed) under certain conditions.

Report Group Description Entry Rules

  1. Except for the data-name clause (which, when present, must immediately follow the level number) the clauses may be written in any order.
  2. In order for a report group to be referred to by a Procedure Division statement, it must have a data-name.
  3. If a COLUMN clause is present in the data description of an item, the data description must also contain a PICTURE clause in addition to one of the clauses:  SOURCE, SUM, or VALUE.
  4. In Format 2, the level numbers may be any number from 1 through 49.
  5. If Format 1 is used to indicate a report group, a report group must contain a report group entry (level 01), and it must be the first entry.  A report group extends from this entry either to the next group level 01 or to the end of the next group description.
  6. Format 2 is used to indicate an elementary item or a group item within a report group.  If a report group is an elementary item, Format 2 may include the TYPE or NEXT GROUP clause to specify the report group and elementary item in the same entry.
  7. When the LINE clause is specified in Format 1, the entries for the first report line within the report group are presented on the specified line.  When the LINE clause is specified in Format 2, sequential entries with the same level number in the report group are implicitly presented on the same line.  A LINE NUMBER at a subordinate level must not contradict a LINE NUMBER at a group level.
  8. The NEXT GROUP clause, when specified, refers to the spacing at execution time between the last line of this report group and the first line of the next report group.

Report group names (data-name-1 in the syntax) are required in the following instances:

  1. When the data-name represents a DETAIL report group referred to by a GENERATE statement in the Procedure Division.
  2. When the data-name represents a HEADING or FOOTING report group referred to by a USE statement in the Declaratives Section of the Procedure Division.
  3. When a reference is made in the Report Section to a DETAIL report group by a SUM UPON clause.


Syntax for the LINE Clause

The LINE clause indicates the absolute or relative line number of a particular entry in reference to the page or a previous entry.  The syntax of the LINE clause is:

LINE [IS] { integer-1 | PLUS integer-2 | NEXT PAGE }

Integer-1 indicates an absolute line number which sets the LINE-COUNTER to this value for printing the item in this and following entries within the report group until a different value for the LINE-COUNTER is specified.  It indicates the fixed line of the page in which the line is to be printed.

Integer-2 indicates a relative line number that specifies the number of lines to be skipped before printing the line.  The line is relative to the previous line printed or skipped.  The LINE-COUNTER is incremented by the value of Integer-2 and is used for printing the items in this and following entries until a different value for LINE-COUNTER is specified.

The phrase NEXT PAGE may be used to indicate an automatic skip to the next page before presenting the first line of the next report group.  Appropriate Page Footing and Page Heading groups will be produced as specified as a result of the action of producing a report group in which the LINE IS NEXT PAGE phrase is coded.  This LINE clause may appear only in a report group entry or may be the LINE clause of the first line of a report group.

Line Clause Rules

  1. Integer-1 and Integer-2 must be positive integers.  Integer-1 must be within the range specified in the PAGE LIMIT(S) clause in the report description entry.
  2. The LINE clause must be given for each report line of a report group.  For the first line of a report group, the LINE clause must be given either at the report group level or prior to or for the first elementary item in the line.  For report lines other than the first in a report group. it must be given prior to the first elementary item in the line.
  3. When a LINE clause is encountered, subsequent entries following the entry with the LINE clause are implicitly presented on the same line until either another LINE clause or the end of the report group is encountered.
  4. Absolute LINE NUMBER entries must be indicated in ascending order, and an absolute LINE NUMBER cannot be preceded by a relative LINE NUMBER.

The NEXT GROUP clause is used to define the line control following the printing of the current report group being processed.  The syntax of the NEXT GROUP clause is:

NEXT GROUP [IS] { integer-1 | PLUS integer-2 | NEXT PAGE }

Integer-1 indicates an absolute line number which sets the LINE-COUNTER to the value after printing the last line of the report group.

Integer-2 indicates a relative number which increments the LINE-COUNTER by the Integer-2 value after printing the last line of the report group.

Syntax for the NEXT GROUP Clause

The NEXT GROUP phrase may be used to indicate an automatic skip to the next page before printing the first line of the next group.

Next Group Clause Rules

  1. The same rules apply for Integer-1, Integer-2, and NEXT PAGE options as enumerated for the LINE clause above.
  2. The NEXT GROUP clause must appear only at the 01 level which defines the report group.  When specified for a Control Footing/Heading report group, the NEXT GROUP clause results in automatic line spacing only when a control break occurs on the level for which that control is specified.


Syntax for the TYPE Clause

The TYPE clause specifies the particular type of report group that is described in any particular entry and indicates the time at which the report group is to be generated.  The syntax for the TYPE clause is:

TYPE [IS] { REPORT HEADING | RH |
            PAGE HEADING | PH |
            CONTROL HEADING | CH {identifier-n | FINAL } |
            DETAIL | DE |
            CONTROL FOOTING | CF { identifier-n | FINAL } |
            PAGE FOOTING | PF |
            REPORT FOOTING | RF }

The REPORT HEADING entry indicates a report group that is produced only once, at the beginning of the report, during the execution of the first GENERATE statement.  Only 1 REPORT HEADING is permitted in a report.  SOURCE clauses used in REPORT HEADING report group items refer to the value of data items at the time of the first GENERATE statement is executed.

The PAGE HEADING entry indicates a report group that is automatically produced at the beginning of each page of the report.  Only one PAGE HEADING is permitted for each report.  The PAGE HEADING is printed on the first page after the REPORT HEADING is specified.

The CONTROL HEADING entry indicates a report group that is printed at the beginning of a control group for a designated identifier, or, in the case of FINAL, is produced once before the first control at the initiation of a report during the execution of the first GENERATE statement.  There can be only one report group of this type for each identifier and for the FINAL specified in a report.  In order to produce any CONTROL HEADING report groups, a control break must occur.  SOURCE clauses used in a TYPE CONTROL HEADING FINAL report group refer to the value of the items at the time the first GENERATE statement is executed.

The DETAIL entry indicates a report group that is produced for each GENERATE statement in the Procedure Division.  There is no limit to the number of DETAIL report groups that may be included in a report.

The CONTROL FOOTING entry indicates a report group that is produced at the end of a control group for a designated identifier, or, in the case of FINAL, is produced once at the termination of a report ending in a FINAL control group.  There can be only one report group of this type for each identifier and for the FINAL specified in a report.  In order to produce any CONTROL FOOTING report groups, a control break must occur.  SOURCE clauses used in a TYPE CONTROL FOOTING FINAL report group refer to the value of the items at the time the TERMINATE statement is executed.

The PAGE FOOTING entry indicates a report group that is automatically produced at the bottom of each page of the report.  There can be only one report group of this type in a report.

The REPORT FOOTING entry indicates a report group that is produced only once at the termination of a report.  There can be only one report group of this type in a report.  SOURCE clauses used in TYPE REPORT FOOTING report groups refer to the value of the items at the time the TERMINATE statement is executed.

Type Clause Rules

  1. The level number 01 identifies a particular report group to be generated as output as the TYPE clause indicates the time for the generation of this report group.
  2. If the report group is described as other than TYPE DETAIL, its generation is an automatic Report Writer function.
  3. If the report group is described with the TYPE DETAIL clause, the Procedure Division statement -- GENERATE data-name -- directs the Report Writer to produce the named report group.
  4. Nothing precedes a REPORT HEADING entry, and nothing follows a REPORT FOOTING entry within a report.
  5. A FINAL type control break may be designated only once for CONTROL HEADING or CONTROL FOOTING entries within a particular report group.
  6. CONTROL HEADING report groups appear with the current values of any indicated SOURCE data items before the DETAIL report groups of the CONTROL group are produced.
  7. CONTROL FOOTING report groups appear with the previous value of any indicated CONTROL SOURCE data items just after the DETAIL report groups of the CONTROL groups have been produced.
  8. The USE procedure (in the Declaratives Section of the Procedure Division) specified for a CONTROL FOOTING report group refers to:
    1. Source data items specified in the CONTROL clause affect the previous value of the data item.
    2. Source data items not specified in the CONTROL clause affect the current value of the item
  9. LINE NUMBER determines the absolute or relative position of the CONTROL report group exclusive of the other HEADING and FOOTING report group.

 

Syntax for the COLUMN Clause

The COLUMN clause indicates the absolute column number in the printed page of the leftmost character of an elementary item.  The syntax for the COLUMN clause is:

COLUMN [NUMBER IS] integer-1

Integer-1 must be a positive integer.  The clause can only be given at the elementary level within a report group.

Syntax for the GROUP INDICATE Clause

The GROUP INDICATE clause specifies that the elementary item is to be produced only on the first occurrence of the item after any control or page break.  The syntax of the GROUP INDICATE clause is:

GROUP [INDICATE]

The clause must be specified only at the elementary level within a Detail report group.  The elementary item is not only group-indicated on the first Detail report group containing the item after a control break, but is also indicated on the first Detail report group containing the item on a new page, even though a control break did not occur.


Syntax for the RESET Clause

The RESET clause indicates the CONTROL identifier that causes the SUM counter in the elementary item entry to be reset to zero on a control break.  The syntax of the RESET clause is:

RESET [ON] { identifer-1 | FINAL }

After printing a TYPE CONTROL FOOTING report group, the counters associated with the report are reset automatically to zero unless an explicit RESET clause is given specifying resetting based on a higher-level control than the associated control for the report group.  The RESET clause may be used for programming totaling of identifiers where subtotals of identifiers may be desired without automatic resetting upon printing the report group.  The RESET clause may only be used in conjunction with a SUM clause at the elementary level.

Identifier-1 must be one of the identifiers described in the CONTROL clause in the  report description entry.  Identifier-1 must be a higher-level CONTROL identifier than the CONTROL identifier associated with the CONTROL FOOTING report group in which the SUM and RESET clause appear.

Syntax for the SOURCE Clause

The SOURCE clause indicates a data item to be used as the source for this report item.  The syntax of the SOURCE clause is:

SOURCE [IS] identifier-1

The SOURCE clause has two functions:  to specify a data item that is to be printed, and to specify a data item that is to be summed in a CONTROL FOOTING report group.

Syntax for the SUM Clause

The SUM clause is used to cause automatic summation of data and may appear only in an elementary item entry of a CONTROL FOOTING report group.  The syntax of the SUM clause is:

SUM identifier-2, identifier-3, ... [UPON data-name]

Sum Clause Rules

  1. A SUM clause may appear only in a TYPE CONTROL FOOTING report group.
  2. If a SUM counter is referred to by a Procedure Division statement or a Report Section entry, a data-name must be specified with the SUM clause entry.  The data-name then represents the summation counter automatically generated by the Report Writer to total the operands immediately following the SUM.  If a summation counter is never referred to, the counter need not be named explicitly by a data-name entry.  A SUM counter is only algebraically incremented just before the presentation of the TYPE DETAIL report group in which the item being summed appears as a source item.
  3. Whether the SUM clause names the summation counter or not, the PICTURE clause must be specified for each SUM counter.  Editing characters or editing clauses may be included in the description of a SUM counter.  Editing of a SUM counter only occurs upon presentation of that SUM counter.  At all other times, the SUM counter is treated as a numeric data item.  The SUM counter must be large enough to accommodate the summed quantity without truncating of integral digits.
  4. An operand of a SUM clause must be an elementary numeric data item that appears in the File, Working-Storage Sections, or data-name that is the name of a SUM counter.
  5. Each item being summed must appear as a SOURCE item in a TYPE DETAIL report group, or be the name of a SUM counter in a TYPE CONTROL FOOTING report group at an equal or lower position in the control hierarchy.  Although the items must be explicitly written in a TYPE DETAIL report group, they may actually be suppressed at presentation time.  
  6. If higher-level report groups are indicated in the control hierarchy, counter updating procedures take place prior to the reset operation.
  7. The summation of data items defined as SUM counter in the TYPE CONTROL FOOTING report groups is accomplished explicitly or implicitly with the Report Writer automatically handling the updating function.  If a sum control of a data item is not desired for presentation at a higher level, the lower-level SUM specification may be omitted.  In this case the same results are obtained as if the lower-level SUM were specified.
  8. The UPON data-name is required to obtain selective summation for a particular data item which is named as a SOURCE item in two or more TYPE DETAIL report groups.  Identifier-2 and Identifier-3 must be source data items in data-names.  Data-name must be the name of a TYPE DETAIL report group.  If the UPON data-name option is not used, Identifier-2 and Identifier-3, etc. respectively, are added to the SUM counter at each execution of a GENERATE statement.  This statement generates a TYPE DETAIL report group that contains the SUM operands at the elementary level.


Syntax for the VALUE Clause

The VALUE clause causes the report data item to assign the specified value each time its report group is presented only if the elementary item entry does not contain a GROUP INDICATE clause.  The format of the VALUE clause is:

VALUE [IS] literal-1


BLANK WHEN ZERO, JUSTIFIED, PICTURE Clauses

The same rules apply to the use of the BLANK WHEN ZERO clause, the JUSTIFIED clause, and the PICTURE clause when used in a report group description as when used in the Data Division.

 

Report Group Entries for Customer Charge Transaction List Report

For this simple report, it is necessary to code entries for two report groups -- a PAGE HEADING and a DETAIL.  To code the entries, I refer back to the transaction record layout, for field names, and the layout for the report, for line and column positions, as well as literal values.  The entries required to produce the report are:

01  PAGE-HEAD-GROUP TYPE PAGE HEADING.                      
    02  LINE 1.                                             
        03  COLUMN 27   PIC X(41) VALUE                     
            'C U S T O M E R  C H A R G E  R E P O R T'.    
    02  LINE PLUS 2.                                        
        03  COLUMN 01   PIC X(09) VALUE 'CUST. NO.'.        
        03  COLUMN 15   PIC X(10) VALUE 'CUST. NAME'.       
        03  COLUMN 30   PIC X(05) VALUE 'DEPT.'.            
        03  COLUMN 39   PIC X(08) VALUE 'ITEM NO.'.         
        03  COLUMN 51   PIC X(09) VALUE 'ITEM COST'.        
01  CHARGE-DETAIL TYPE DETAIL.                               
    02  LINE PLUS 1.                                         
        03  COLUMN 03   PIC Z(04) SOURCE TR-CUSTOMER-NUMBER. 
        03  COLUMN 10   PIC X(16) SOURCE TR-CUSTOMER-NAME.   
        03  COLUMN 32   PIC 9(01) SOURCE TR-ITEM-DEPARTMENT. 
        03  COLUMN 40   PIC 9(05) SOURCE TR-ITEM-NUMBER.     
        03  COLUMN 51   PIC $$$$.99 SOURCE TR-ITEM-COST. 

The PAGE-HEAD-GROUP report group describes the information printed at the top of each page of the report.  In this extremely simple report, all the information is provided with the VALUE clause and literal values.  The report name is printed on the first line of each page, followed by column headings on the third line.

The CHARGE-DETAIL report group describes the information printed for each record in the transaction file and will result in a single line being printed on the report for each execution of the GENERATE statement naming the DETAIL report group.

As you see, even though the syntax and rules for the report group information is extensive and may initially seem confusing, you do not need to use all of the clauses for every report.  It is quite easy to generate a simple report with very little coding.  And when Report Writer is used, 99% of the coding is in the Report Section; the Procedure Division statements required for most reports consist of three verbs, described below.

 

Report Writer Procedure Division Statements

A report is produced by the execution of the INITIATE, GENERATE, and TERMINATE statements in the Procedure Division.  The INITIATE statement initializes all counters associated with the Report Writer, the GENERATE statement is used each time a detailed portion of the report is to be produced, and the TERMINATE statement is used to end the report.  The Report Writer feature allows additional manipulation of data by means of a USE BEFORE REPORTING declarative in the Declaratives Section of the Procedure Division.

 

Syntax for the INITIATE Statement

The INITIATE statement begins the processing of a Report Writer report.  The syntax of the INITIATE statement is:

INITIATE report-name-1, report-name-2, ...


Syntax for the GENERATE Statement

The GENERATE statement actually produces the report.  The syntax of the GENERATE statement is:

GENERATE identifier

Identifier represents either a TYPE DETAIL report group or a report name (the name following an Report Description - RD - entry).  If the identifier is the name of a TYPE DETAIL report group, the GENERATE statement performs all the automatic operations of the Report Writer and produces an actual output detail report group in the output file.  This is called detail reporting.  If the identifier is the name of a RD entry, the GENERATE statement does all the automatic operations of the Report Writer and updates the footing report group(s) within a particular report group without producing an actual detail report group associated with the report.  In this case, all SUM counters associated with the report descriptions are algebraically incremented each time a GENERATE statement is execute.  This is called summary reporting.  


Syntax for the TERMINATE Statement

The TERMINATE statement is used to terminate the processing of a report.  The syntax of the TERMINATE statement is:

TERMINATE report-name-1, report-name-2, ...

 

USE BEFORE REPORTING Declaratives

A USE BEFORE REPORTING declarative statement may be written in the Declaratives Section of the Procedure Division if the programmer wishes to alter or manipulate the data before it is presented in the report.  The syntax of the USE BEFORE REPORTING statement is:

USE BEFORE REPORTING data-name.

As with other Declaratives Section statements, the USE statement must immediately follow a section header in the Declaratives Section of the Procedure Division, and must be followed by a period and a space.  The remainder of the section must consist of one or more procedural paragraphs that define the procedures to be processed. 

Data-name represents a report group named in the Report Section.  The data-name must not be used in more than one USE statement.  The data-name must be qualified by the report name if not unique.  No Report Writer statement (INITIATE, GENERATE, or TERMINATE) may be written in the Declaratives Section.

When the programmer wishes to suppress the printing of the report group whose name is specified in the USE statement, the statement:

MOVE 1 to PRINT-SWITCH.

is used in the USE BEFORE REPORTING Declarative Section.  When this statement is encountered, only the specified report group is not printed.

The USE BEFORE REPORTING procedures must not change the contents of control data items or alter subscripts or indexes used in referencing the controls.

 

Procedure Division for Customer Charge Transaction List Report

The procedure statements required for our simple report are the minimum necessary to open the files, INITIATE the report, read the records from the transaction file, GENERATE the detail group, TERMINATE the report, and close the files.  The complete code is:

008300 000-INITIATE.
008400
008500     OPEN INPUT TRANSACTION-DATA,
008600          OUTPUT REPORT-FILE.
008700
008800     INITIATE CUSTOMER-REPORT.
008900
009000     READ TRANSACTION-DATA
009100         AT END
009200             MOVE 'Y' TO END-OF-FILE-SWITCH.
009300*    END-READ.
009400
009500     PERFORM 100-PROCESS-TRANSACTION-DATA THRU 199-EXIT
009600         UNTIL END-OF-FILE.
009700
009800 000-TERMINATE.
009900     TERMINATE CUSTOMER-REPORT.
010000
010100     CLOSE TRANSACTION-DATA,
010200           REPORT-FILE.
010300
010400     STOP RUN.
010500
010600 100-PROCESS-TRANSACTION-DATA.
010700     GENERATE CHARGE-DETAIL.
010800     READ TRANSACTION-DATA
010900         AT END
011000             MOVE 'Y' TO END-OF-FILE-SWITCH.
011100*    END-READ.
011200
011300 199-EXIT.
011400     EXIT.

The three Report Writer statements are highlighted.  You will notice that the usual COBOL coding is used to open and read the records from the transaction file.  When each record has been read in and its fields are available for access by Procedure Division statements, the GENERATE statement for the DETAIL report group -- CHARGE-DETAIL -- is executed.  In the report group definition, the elementary items for the report all refer to fields in the transaction record with SOURCE statements.  This is the basic technique for all Report Writer generated reports; COBOL statements are used to make ready all the fields required for Report Writer to extract the contents and move them to the report output area, as defined in the report group statements, and the execution of one or more GENERATE statements complete the production of the report.  Line counters are automatically updated, page overflow detected, page headings/footings are produced, page counters are updated -- all that is necessary for the programmer to do is make the data fields ready and execute the GENERATE statement.  In more advanced reports, control fields are automatically tested and CONTROL HEADINGS/FOOTINGS are produced.

The output from the COBOL compiler for the complete program may be viewed at:   RWEX01 Compile and the output from the execution of the program may be viewed at:   RWEX01 Report.

 

Extending the Customer Charge Transaction List Report

Now that I have the code complete to produce a report that simply lists the contents of the transaction file, it is easy to extend the coding to produce a more useful report.  The new report will include some calculations, as well as a simple control break.  The layout for the report:

                          C U S T O M E R  C H A R G E  R E P O R T                      PAGE 99999

CUST. NO.     CUST. NAME     DEPT.    ITEM NO.    ITEM COST    DISCT. %    DISCT. AMT.    CHARGE

  9999   XXXXXXXXXXXXXXXX      9       99999       $$$.$$         99%         $$$.$$         $$$.$$
                                                                                            $$$$.$$ *

In addition to the information presented on the first report, which all came directly from the fields of the transaction file records, for each transaction the detail line will include a discount percentage (based upon the department of the item), a computed discount amount, and a computed net amount.  The charges for each customer are to be added and a total line will be produced following the charge detail lines for the customer.  The page heading has been changed as well, by the addition of a page number.

As before, the first step is to look at the desired report layout and decide what report groups will need to be coded.  From the layout you will notice that the Page Heading and single Detail group are still required, simply with more elementary data items added.  But there is also now a need for a Control Footing group for the customer total line.

There are no changes required for the Report Description entries, but the existing report groups will need to be modified and a new one coded.  The discount percent will be derived from a table in Working-Storage, and the discount amount and net amount will be held in Working-Storage fields.  It will be necessary to add statements to the Procedure Division to prepare these fields prior to executing the GENERATE statement for the Detail report group, but for the coding of the report groups, it is only necessary to refer to the fields in SOURCE clauses.  So the modified report group code is:

008200 01  PAGE-HEAD-GROUP TYPE PAGE HEADING.
008300     02  LINE 1.
008400         03  COLUMN 27   PIC X(41) VALUE
008500             'C U S T O M E R  C H A R G E  R E P O R T'.
008600         03  COLUMN 90   PIC X(04) VALUE 'PAGE'.
008700         03  COLUMN 95   PIC ZZZZ9 SOURCE PAGE-COUNTER.
008800     02  LINE PLUS 2.
008900         03  COLUMN 01   PIC X(09) VALUE 'CUST. NO.'.
009000         03  COLUMN 15   PIC X(10) VALUE 'CUST. NAME'.
009100         03  COLUMN 30   PIC X(05) VALUE 'DEPT.'.
009200         03  COLUMN 39   PIC X(08) VALUE 'ITEM NO.'.
009300         03  COLUMN 51   PIC X(09) VALUE 'ITEM COST'.
009400         03  COLUMN 64   PIC X(08) VALUE 'DISCT. %'.
009500         03  COLUMN 76   PIC X(11) VALUE 'DISCT. AMT.'.
009600         03  COLUMN 91   PIC X(06) VALUE 'CHARGE'.
009700
009800 01  CHARGE-DETAIL TYPE DETAIL.
009900     02  LINE PLUS 1.
010000         03  COLUMN 03   PIC Z(04) SOURCE TR-CUSTOMER-NUMBER.
010100         03  COLUMN 10   PIC X(16) SOURCE TR-CUSTOMER-NAME.
010200         03  COLUMN 32   PIC 9(01) SOURCE TR-ITEM-DEPARTMENT.
010300         03  COLUMN 40   PIC 9(05) SOURCE TR-ITEM-NUMBER.
010400         03  COLUMN 51   PIC $$$$.99 SOURCE TR-ITEM-COST.
010500         03  COLUMN 67   PIC V99 SOURCE DISCOUNT (DISCOUNT-IX).
010600         03  COLUMN 69   PIC X(01) VALUE '%'.
010700         03  COLUMN 78   PIC $$$$.99 SOURCE WS-DISCOUNT-AMT.
010800         03  COLUMN 93   PIC $$$$.99 SOURCE WS-CHARGE-AMT.
010900
011000 01  CUSTOMER-TOTAL TYPE CONTROL FOOTING TR-CUSTOMER-NUMBER
011100     NEXT GROUP IS PLUS 2.
011200     02  LINE PLUS 1.
011300         03  COLUMN 92   PIC $$$$$.99 SUM WS-CHARGE-AMT.
011400         03  COLUMN 101  PIC X VALUE '*'.

Notice that the source for the discount percent is a table entry; it is necessary for statements in the Procedure Division to set the correct index field -- DISCOUNT-IX -- prior to the execution of the GENERATE statement for the CHARGE-DETAIL report group.  The two computed fields will be store in WS-DISCOUNT-AMT and WS-CHARGE-AMT.

In the CUSTOMER-TOTAL CONTROL FOOTING, the field which is examined to trigger the control break is TR-CUSTOMER-NUMBER.  We know from the prior report that the transaction file is correctly sorted on this field.  The total for each customer is automatically added and printed on the print line by the use of the SUM clause on line 011200.  Each time the GENERATE statement is executed for the CHARGE-DETAIL Detail report group, the value of WS-CHARGE-AMT is added to a counter field that is generated by Report Writer for this elementary item in this report group.  When the value of the control field -- TR-CUSTOMER-NUMBER -- changes, the contents of the counter field are moved to the print line in the report and the value is set to zero.  In line 011100, the NEXT GROPU IS PLUS 2 clause is coded to cause a blank line to be left following each customer total.

The output from the COBOL compiler for the complete program may be viewed at:   RWEX02 Compile and the output from the execution of the program may be viewed at:   RWEX02 Report.

 

Using Group Indicate and Two Control Breaks

When I look at the report produced, I notice that the customer number and customer name repeating down the left hand side of the report for the second and subsequent transactions for the same customer is not very appealing.  That can easily be corrected by the addition of the GROUP INDICATE clause on those elementary data items:

010000         03  COLUMN 03   PIC Z(04) SOURCE TR-CUSTOMER-NUMBER
010100                                          GROUP INDICATE.
010200         03  COLUMN 10   PIC X(16) SOURCE TR-CUSTOMER-NAME
010300                                          GROUP INDICATE.

I also think it would be good to provide totals for the other two monetary amount columns in the report:  item cost and discount amount.  And a report similar to this in the real world would probably need grand totals for the entire transaction file.  These changes are easily accomplished by a few changes.  First, the CONTROL clause is modified to add FINAL, which causes a control break to occur when the TERMINATE statement is executed:

007600     CONTROLS ARE FINAL, TR-CUSTOMER-NUMBER

The additional column totals are added to the existing CONTROL FOOTING report group:

011200 01  CUSTOMER-TOTAL TYPE CONTROL FOOTING TR-CUSTOMER-NUMBER   
011300     NEXT GROUP IS PLUS 2.                                    
011400     02  LINE PLUS 1.                                         
011500         03  COLUMN 50   PIC $$$$$.99 SUM TR-ITEM-COST.       
011600         03  COLUMN 59   PIC X VALUE '*'.                     
011700         03  COLUMN 77   PIC $$$$$.99 SUM WS-DISCOUNT-AMT.    
011800         03  COLUMN 86   PIC X VALUE '*'.                     
011900         03  COLUMN 92   PIC $$$$$.99 SUM WS-CHARGE-AMT.      
012000         03  COLUMN 101  PIC X VALUE '*'.                     

Finally, a new CONTROL FOOTING report group is added for the FINAL control break:

012200 01  FINAL-TOTAL TYPE CONTROL FOOTING FINAL.                 
012300     02  LINE PLUS 1.                                        
012400         03  COLUMN 10   PIC X(12) VALUE 'GRAND TOTALS'.     
012500         03  COLUMN 48   PIC $$$,$$$.99 SUM TR-ITEM-COST.    
012600         03  COLUMN 59   PIC XX VALUE '**'.                  
012700         03  COLUMN 75   PIC $$$,$$$.99 SUM WS-DISCOUNT-AMT. 
012800         03  COLUMN 86   PIC XX VALUE '**'.                  
012900         03  COLUMN 90   PIC $$$,$$$.99 SUM WS-CHARGE-AMT.   
013000         03  COLUMN 101  PIC XX VALUE '**'.                  

The output from the COBOL compiler for the complete program may be viewed at:   RWEX03 Compile and the output from the execution of the program may be viewed at:   RWEX03 Report.

 

Creating a Customer Charge Summary Report

So far all of the reports produced utilize detailed reporting, because the GENERATE statement in the Procedure Division refers to the data name associated with a Detail report group.  By simply changing the GENERATE statement to refer to the report name -- the name of the report given in the Report Description entry following RD -- the report can be changed to produce only the Control report groups.  This is known as summary reporting.  The only change necessary to accomplish this is on the GENERATE statement:

015100     GENERATE CUSTOMER-REPORT.

When the GENERATE statement names the report rather than a Detail report group, the entries for the elementary items in the Detail report groups are processed only to the extent required to determine changes in fields named as CONTROL fields and to provide data required for SUM fields in the CONTROL FOOTING report groups.  The Detail report groups are not printed.  

Even though the change to the generate statement is the only change required to produce the summary report, I made a few additional changes to improve the appearance of the report.  I moved the lines for the elementary items for printing the customer number and name from the detail group to the CONTROL FOOTING for TR-CUSTOMER-NUMBER and removed the GROUP INDICATE clause, which was not needed in this location.  In order for the generated code to properly handle the customer number and name during summary reporting, it is necessary to modify the input record description to add a group item to contain both the customer name and customer number:

00041   003410     03  TR-CUSTOMER.                                             20110227
00042   003500         05  TR-CUSTOMER-NUMBER  PIC 9(04).                       20110227
00043   003600         05  FILLER              PIC X(01).                       20110227
00044   003700         05  TR-CUSTOMER-NAME    PIC X(16).                       20110227

Then the code for the CONTROL FOOTING is changed to refer to the group level item TR-CUSTOMER.

I also removed the columns, and column headings, for department, item, and discount percent, which would make little sense for a summary report.   Finally, I removed the elementary items for the single asterisks on the TR-CUSTOMER-NUMBER CONTROL FOOTING and changed the double asterisks on the FINAL CONTROL FOOTING to single, and increased the line spacing to 2 before producing the FINAL CONTROL FOOTING report gropu.

The output from the COBOL compiler for the complete program may be viewed at:   RWEX04 Compile and the output from the execution of the program may be viewed at:   RWEX04 Report.

 

Using Declaratives to Modify/Create Report Data

Although rare, there are circumstances when it is necessary to manipulate the data that Report Writer has processed before the report groups are written to the output file.  In those cases you can code USE sections in the Declaratives Section of the Procedure Division.

An example of when that might be used can be illustrated by processing a list of sales transactions sorted by salesman number and district code.  A summary report is to be produced showing the total sales for each salesman plus the computed commission on the total sales for the salesman.  The commission is based upon a rate table using the district code as a key to retrieve the specific rate for each salesman.  The layout of the sales transaction record is:

Field Contents and Name

Picture

Salesman Number (SR-SALESMAN-NUMBER)
9(2)
Filler
X(1)
District Code (SR-DISTRICT-CODE)
X(1)
Filler
X(1)
Sale Amount (SR-SALE-AMOUNT)
9(4)V99
Filler
X(69)

Here is the code for the key report groups:

009600 01  SALE-DETAIL TYPE DETAIL.                                  
009700     02  LINE PLUS 1.                                          
009800         03  COLUMN 01   PIC 99      SOURCE SR-SALESMAN-NUMBER.
009900         03  COLUMN 04   PIC X       SOURCE SR-DISTRICT-CODE.  
010000         03  COLUMN 06   PIC 9999.99 SOURCE SR-SALE-AMOUNT.    
010100                                                               
010200 01  SALESMAN-TOTAL TYPE CONTROL FOOTING SR-SALESMAN-NUMBER.   
010300     02  LINE PLUS 1.                                          
010400         03  COLUMN 20   PIC 99    SOURCE SR-SALESMAN-NUMBER.  
010500         03  ST-SALES-AMT COLUMN 24 PIC $$$,$$9.99 SUM         
010600                 SR-SALE-AMOUNT.                               
010700         03  COLUMN 37 PIC $$$,$$9.99 SOURCE WS-COMMISSION.    

Since this is a summary report, the GENERATE statement will refer to the report name and the fields named in the DETAIL report group will never be printed; they are only included to allow access by the CONTROL FOOTING report groups.

In the SALESMAN-TOTAL CONTROL FOOTING report group, the column that will contain the SUMmed SR-SALE-AMOUNT has been given a data name in order to be able to access the generated counter in the USE procedure.  The commission column for this group is obtained from SOURCE WS-COMMISSION, a field that will be populated during the execution of the USE procedure.

The USE procedure coded for this report is:

012400 DECLARATIVES.                                                    
012500 USE-SALESMAN-TOTAL SECTION. USE BEFORE REPORTING SALESMAN-TOTAL. 
012600 USE-SALESMAN-TOTAL-PROC.                                         
012700     SET COMMISSION-IX TO +1.                                     
012800     SEARCH COMMISSION-ENTRY                                      
012900         AT END                                                   
013000             MOVE +0.00 TO WS-COMMISSION                          
013100         WHEN CE-DISTRICT (COMMISSION-IX) = SR-DISTRICT-CODE      
013200             COMPUTE WS-COMMISSION ROUNDED =                      
013300                 CE-RATE (COMMISSION-IX) * ST-SALES-AMT.          
013400                                                                  
013500 USE-SALESMAN-TOTAL-EXIT.                                         
013600     EXIT.                                                        
013700                                                                  
013800 END DECLARATIVES.                                                

The output from the COBOL compiler for the complete program may be viewed at:   RWEX05 Compile and the output from the execution of the program may be viewed at:   RWEX05 Report.

 

An example with many USE procedures

As I was cleaning up my folder of sample data, I came across this set of payroll data and realized that it would make a great example of using a number of USE procedures to modify Report Writer's automatic control.  The coding for this program utilizes several techniques that I don't think will be found in any textbook discussion of Report Writer, including one technique that I really have to consider a trick, and it is one that I have used many times in production reports.

The data file contains records used to produce pay checks for employees.  The time period spanned by the data is three months, so there are several records for each employee.  The records contain fields for department number, employee number and name, gross pay, deductions, and net pay.  The goal is to produce a report with the following layout:

                                      C E N T U R Y   M E D I C A L   C E N T E R
                                  Q U A R T E R L Y   P A Y R O L L   R E G I S T E R                PAGE ZZZZ9
     --------- EMPLOYEE ---------      GROSS         FICA        FED W/H       MISC.          NET
      NO             NAME               PAY           TAX          TAX        DEDUCT.         PAY
DEPARTMENT NUMBER:  99 XXXXXXXXXXXXXX

     9999    XXXXXXXXXXXXXXXXXXXX    $$,$$9.99      $$$9.99      $$$9.99      $$$9.99      $$,$$9.99

             DEPARTMENT TOTALS       $$,$$9.99 *    $$$9.99 *    $$$9.99 *    $$$9.99 *    $$,$$9.99 *

             COMPANY TOTALS         $$$,$$9.99 ** $$,$$9.99 ** $$,$$9.99 ** $$,$$9.99 **  $$$,$$9.99 **

A second report is to be produced that re-states the department and company totals for each column, and calculates the percentage that each department's total contributes to the company's total for each column.  The layout for this report is:

                                   C E N T U R Y   M E D I C A L   C E N T E R
                               Q U A R T E R L Y   P A Y R O L L   R E G I S T E R                PAGE ZZZZ9
                                   GROSS             FICA            FED W/H           MISC.              NET
                                    PAY               TAX              TAX            DEDUCT.             PAY
* * * DEPARTMENT TOTALS * * *
99 XXXXXXXXXXXXXXX               $$,$$9.99 999%     $$$9.99 999%     $$$9.99 999%     $$$9.99 999%     $$,$$9.99 999%
                                $$$,$$9.99 100%   $$,$$9.99 100%   $$,$$9.99 100%   $$,$$9.99 100%    $$$,$$9.99 100%

Because the data file contains several records for each employee and I am not interested in the details of the individual payroll periods that the records represent, this report will use the technique of summary reporting.  The name used in the GENERATE statement will be the name of the report, which will cause the elementary data items named in the Detail report group to be used to calculate Control Footing fields, but the detail fields will not be printed.

Looking at the first report layout, you will see that it may be produced by defining six report groups:  Page Heading, Control Heading (department number), Detail (to collect the fields from the input record, but will not be printed), Control Footing (employee number), Control Footing (department number), Control Footing (final, to produce the company total line).

In a real world situation, I probably would have omitted the Page Heading report group, and instead have produced only a Control Heading for each department number break that would have started on a new page and included the page/column heading information.  That would have made the layout a bit cleaner as I would have then placed the department heading above the column headings.  However, since my test data file includes a limited number of employees per department the design I have used is an adequate solution, and I have designed reports using exactly this structure in a real world environment, too.

Here is the coding for the report definition and report groups that will produce this report:

010600 RD  QUARTERLY-PAY-REGISTER
010700     CONTROLS ARE FINAL, PRR-DEPARTMENT-NUMBER,
010800         PRR-EMPLOYEE-KEY
010900     PAGE LIMIT IS 66 LINES
011000     HEADING 1
011100     FIRST DETAIL 7
011200     LAST DETAIL 60.
011300
011400 01  TYPE PAGE HEADING.
011500     02  LINE 1.
011600         03  COLUMN 39   PIC X(13) VALUE 'C E N T U R Y'.
011700         03  COLUMN 55   PIC X(13) VALUE 'M E D I C A L'.
011800         03  COLUMN 71   PIC X(11) VALUE 'C E N T E R'.
011900     02  LINE 2.
012000         03  COLUMN 35   PIC X(17) VALUE 'Q U A R T E R L Y'.
012100         03  COLUMN 55   PIC X(13) VALUE 'P A Y R O L L'.
012200         03  COLUMN 71   PIC X(15) VALUE 'R E G I S T E R'.
012300         03  COLUMN 111  PIC X(04) VALUE 'PAGE'.
012400         03  COLUMN 116  PIC ZZZZ9 SOURCE PAGE-COUNTER.
012500     02  LINE 4.
012600         03  COLUMN 06   PIC X(28) VALUE
012700             '--------- EMPLOYEE ---------'.
012800         03  COLUMN 40   PIC X(05) VALUE 'GROSS'.
012900         03  COLUMN 54   PIC X(04) VALUE 'FICA'.
013000         03  COLUMN 66   PIC X(07) VALUE 'FED W/H'.
013100         03  COLUMN 80   PIC X(05) VALUE 'MISC.'.
013200         03  COLUMN 95   PIC X(03) VALUE 'NET'.
013300     02  LINE 5.
013400         03  COLUMN 07   PIC X(02) VALUE 'NO'.
013500         03  COLUMN 22   PIC X(04) VALUE 'NAME'.
013600         03  COLUMN 41   PIC X(03) VALUE 'PAY'.
013700         03  COLUMN 55   PIC X(03) VALUE 'TAX'.
013800         03  COLUMN 68   PIC X(03) VALUE 'TAX'.
013900         03  COLUMN 79   PIC X(07) VALUE 'DEDUCT.'.
014000         03  COLUMN 95   PIC X(03) VALUE 'PAY'.
014100
014200 01  DEPT-HEAD TYPE CONTROL HEADING PRR-DEPARTMENT-NUMBER
014300     NEXT GROUP PLUS 1.
014400     02  LINE PLUS 1.
014500         03 COLUMN 01    PIC X(18) VALUE
014600            'DEPARTMENT NUMBER:'.
014700         03  COLUMN 21   PIC 9(02) SOURCE PRR-DEPARTMENT-NUMBER.
014800         03  COLUMN 24   PIC X(15) SOURCE DE-NAME (DE-IX).
014900
015000 01  EMPLOYEE-DETAIL TYPE DETAIL.
015100     02  LINE PLUS 1.
015200         03  COLUMN 01   PIC X(27) SOURCE PRR-EMPLOYEE-KEY.
015300         03  COLUMN 50   PIC 9(04).99 SOURCE PRR-GROSS-PAY.
015400         03  COLUMN 60   PIC 9(03).99 SOURCE PRR-FICA-WH.
015500         03  COLUMN 70   PIC 9(03).99 SOURCE PRR-FED-WH.
015600         03  COLUMN 80   PIC 9(03).99 SOURCE PRR-MISC-DED.
015700         03  COLUMN 90   PIC 9(04).99 SOURCE PRR-NET-PAY.
015800
015900 01  EMPL-FOOT TYPE CONTROL FOOTING PRR-EMPLOYEE-KEY.
016000     02  LINE PLUS 1.
016100         03  COLUMN 06   PIC ZZZ9  SOURCE WS-EMPLOYEE-NUMBER.
016200         03  COLUMN 14   PIC X(20) SOURCE WS-EMPLOYEE-NAME.
016300         03  COLUMN 38   PIC $$,$$9.99 SUM PRR-GROSS-PAY.
016400         03  COLUMN 53   PIC $$$9.99 SUM PRR-FICA-WH.
016500         03  COLUMN 66   PIC $$$9.99 SUM PRR-FED-WH.
016600         03  COLUMN 79   PIC $$$9.99 SUM PRR-MISC-DED.
016700         03  COLUMN 92   PIC $$,$$9.99 SUM PRR-NET-PAY.
016800
016900 01  DEPT-FOOT TYPE CONTROL FOOTING PRR-DEPARTMENT-NUMBER
017000     NEXT GROUP PLUS 2.
017100     02  LINE PLUS 2.
017200         03  COLUMN 14   PIC X(20) VALUE
017300             'DEPARTMENT TOTALS'.
017400         03  DEPT-FOOT-GROSS       COLUMN 38   PIC $$,$$9.99
017500                                   SUM PRR-GROSS-PAY.
017600         03  COLUMN 48   PIC X         VALUE '*'.
017700         03  DEPT-FOOT-FICA        COLUMN 53   PIC $$$9.99
017800                                   SUM PRR-FICA-WH.
017900         03  COLUMN 61   PIC X         VALUE '*'.
018000         03  DEPT-FOOT-FWT         COLUMN 66   PIC $$$9.99
018100                                   SUM PRR-FED-WH.
018200         03  COLUMN 74   PIC X         VALUE '*'.
018300         03  DEPT-FOOT-MISC        COLUMN 79   PIC $$$9.99
018400                                   SUM PRR-MISC-DED.
018500         03  COLUMN 87   PIC X         VALUE '*'.
018600         03  DEPT-FOOT-NET         COLUMN 92   PIC $$,$$9.99
018700                                   SUM PRR-NET-PAY.
018800         03  COLUMN 102  PIC X         VALUE '*'.
018900
019000 01  COMP-FOOT TYPE CONTROL FOOTING FINAL.
019100     02  LINE PLUS 2.
019200         03  COLUMN 14   PIC X(20) VALUE
019300             'COMPANY TOTALS'.
019400         03  CO-GROSS    COLUMN 37   PIC $$$,$$9.99
019500                         SUM PRR-GROSS-PAY.
019600         03  COLUMN 48   PIC XX        VALUE '**'.
019700         03  CO-FICA     COLUMN 51   PIC $$,$$9.99
019800                         SUM PRR-FICA-WH.
019900         03  COLUMN 61   PIC XX        VALUE '**'.
020000         03  CO-FWT      COLUMN 64   PIC $$,$$9.99
020100                         SUM PRR-FED-WH.
020200         03  COLUMN 74   PIC XX        VALUE '**'.
020300         03  CO-MISC     COLUMN 77   PIC $$,$$9.99
020400                         SUM PRR-MISC-DED.
020500         03  COLUMN 87   PIC XX        VALUE '**'.
020600         03  CO-NET      COLUMN 91   PIC $$$,$$9.99
020700                         SUM PRR-NET-PAY.
020800         03  COLUMN 102  PIC XX        VALUE '**'.

There are three control fields named for this report:  FINAL, PRR-DEPARTMENT-NUMBER, PRR-EMPLOYEE-KEY (from high to low).  Only the lowest -- PRR-EMPLOYEE-KEY -- needs further explanation, since it is involved in the aforementioned trick.  Here are the lines from the record description for the input record for the first part of the record:

003400 01  PAYROLL-REGISTER-RECORD.
003500     03  PRR-DEPARTMENT-NUMBER   PIC 9(02).
003600     03  FILLER                  PIC X(01).
003700     03  PRR-EMPLOYEE-KEY.
003800         05  PRR-EMPLOYEE-NO     PIC 9(04).
003900         05  FILLER              PIC X(01).
004000         05  PRR-GENDER          PIC X(01).
004100         05  FILLER              PIC X(01).
004200         05  PRR-EMPLOYEE-NAME   PIC X(20).
004300     03  FILLER                  PIC X(01).
004400     03  PRR-PAY-DATE            PIC 9(08).

Since this is a summary report, the fields in the Detail report group will not be printed, they are named only so that Report Writer will be able to use the fields in SOURCE and SUM clauses in the Footing report groups.  The field defined as PRR-EMPLOYEE-KEY is named as the control field for the Control Footing report group produced for each employee.  It would seem correct to name PRR-EMPLOYEE-NO as the control field; however, I want to print both the employee number and employee name in the Control Footing, and, in order to have Report Writer correctly store the contents of both of these fields to be made available for me to print when the control break occurs, they must be defined together as a single field, which is named as the controlling field for the break.  I must define a USE group to be activated before printing the Control Footing for the employee that will move this group level field to a Working-Storage group, the sub-fields of which are those referenced in the definition of the elementary items to print for employee number and employee name (WS-EMPLOYEE-NUMBER, WS-EMPLOYEE-NAME).  Here is the code for that USE procedure:

037300 EMPL-FOOT-USE SECTION. USE BEFORE REPORTING EMPL-FOOT.
037400 EMPL-FOOT-PROC.
037500     MOVE PRR-EMPLOYEE-KEY TO WS-EMPLOYEE-KEY.
037600
037700 EMPL-FOOT-EXIT.
037800     EXIT.

Report Writer will correctly store and make available the contents of any field named as a control break field at the time the Control Footing is to be produced, but if the employee name field is omitted from that control information, even though only the employee number is required to produce the break correctly, the contents of the employee name from the data record will be that of the next value of the control field.

You will notice that I have omitted the data name from the Page Heading report group.  It is only necessary to provide a data name for report groups that must be referenced from USE procedures.  Another USE procedure is required for the Control Heading produced when the department number changes.  The purpose of this procedure is to set the index value for a table in Working-Storage which defines both the values of the department names as well as provides an area in which department totals are stored.  Those stored totals will be discussed later, but for now here is the code from the USE procedure for the Control Heading for the department number:

036100 DEPT-HEAD-USE SECTION. USE BEFORE REPORTING DEPT-HEAD.
036200 DEPT-HEAD-PROC.
036300     SET DE-IX TO +1.
036400     SEARCH DEPARTMENT-ENTRY
036500         WHEN DE-NUMBER (DE-IX) = PRR-DEPARTMENT-NUMBER
036600             MOVE ZEROS TO DE-GROSS (DE-IX), DE-FICA (DE-IX),
036700                           DE-FWT (DE-IX), DE-MISC (DE-IX),
036800                           DE-NET (DE-IX).
036900
037000 DEPT-HEAD-EXIT.
037100     EXIT.

 All that really occurs here is that a SEARCH statement is used to set the index value to the proper value to access the entry of the PRR-DEPARTMENT-NUMBER that cause the control break.  In a real world application, there would be an error procedure coded if there was no matching table entry, but I have omitted it in this simple program.  The action taken on the WHEN is redundant, since the table is defined with the individual total fields set to zeros.  In fact, a NEXT SENTENCE would have done just as well.

In the Control Footing report group for the department number, each elementary data item has been coded with a data name.  Remember, data names are required in the report groups for fields generated/maintained by Report Writer only when the fields are to be referred to in the Procedure Division.  Here is the coding for the USE procedure that is executed prior to the printing of this report group:

038000 DEPT-FOOT-USE SECTION. USE BEFORE REPORTING DEPT-FOOT.
038100 DEPT-FOOT-PROC.
038200     MOVE DEPT-FOOT-GROSS TO DE-GROSS (DE-IX).
038300     MOVE DEPT-FOOT-FICA TO DE-FICA (DE-IX).
038400     MOVE DEPT-FOOT-FWT TO DE-FWT (DE-IX).
038500     MOVE DEPT-FOOT-MISC TO DE-MISC (DE-IX).
038600     MOVE DEPT-FOOT-NET TO DE-NET (DE-IX).
038700
038800 DEPT-FOOT-EXIT.
038900     EXIT.

The contents of each of the fields that has been summed by Report Writer are moved to the corresponding field in the department table in Working-Storage.  This is the first area in which there is overlap between the two reports that are to be produced by this program.  When looking at the layouts of the two reports to be produced, you can see that the information in the second report is already available in the first report, so it is in fact simply a restatement of the same data in a bit different format and with some additional fields.  So, by capturing these totals in this table, which is already available and has the index properly set as a result of the preceding/corresponding Control Heading USE procedure, it is not necessary to recalculated the column totals for the second report.  When we get to the details of the second report, you will see how these values are used.

Likewise, in the Control Footing report group FINAL, each item includes a data name.  This allows the value summed by Report Writer for the columns for the entire company to be used in calculations in the Procedure Division.

Now let us look at the coding for the second report.  Since you see that all the data required to produce the second report is already available from the first report, you can understand that the second report can be produced totally by the definition of a Report Footing report group.  Here is the code for that report group:

021000 01  REPORT-FOOT TYPE REPORT FOOTING.
021100     02  LINE 1.
021200         03  COLUMN 39   PIC X(13) VALUE 'C E N T U R Y'.
021300         03  COLUMN 55   PIC X(13) VALUE 'M E D I C A L'.
021400         03  COLUMN 71   PIC X(11) VALUE 'C E N T E R'.
021500     02  LINE 2.
021600         03  COLUMN 35   PIC X(17) VALUE 'Q U A R T E R L Y'.
021700         03  COLUMN 55   PIC X(13) VALUE 'P A Y R O L L'.
021800         03  COLUMN 71   PIC X(15) VALUE 'R E G I S T E R'.
021900         03  COLUMN 111  PIC X(04) VALUE 'PAGE'.
022000         03  COLUMN 116  PIC ZZZZ9 SOURCE PAGE-COUNTER.
022100     02  LINE 4.
022200         03  COLUMN 40   PIC X(05) VALUE 'GROSS'.
022300         03  COLUMN 58   PIC X(04) VALUE 'FICA'.
022400         03  COLUMN 74   PIC X(07) VALUE 'FED W/H'.
022500         03  COLUMN 92   PIC X(05) VALUE 'MISC.'.
022600         03  COLUMN 111  PIC X(03) VALUE 'NET'.
022700     02  LINE 5.
022800         03  COLUMN 41   PIC X(03) VALUE 'PAY'.
022900         03  COLUMN 59   PIC X(03) VALUE 'TAX'.
023000         03  COLUMN 76   PIC X(03) VALUE 'TAX'.
023100         03  COLUMN 91   PIC X(07) VALUE 'DEDUCT.'.
023200         03  COLUMN 111  PIC X(03) VALUE 'PAY'.
023300
023400     02  LINE PLUS 2.
023500         03  COLUMN 05   PIC X(29) VALUE
023600             '* * * DEPARTMENT TOTALS * * *'.
023700     02  LINE PLUS 2.
023800         03  COLUMN 05   PIC 9(02) SOURCE DE-NUMBER (1).
023900         03  COLUMN 08   PIC X(15) SOURCE DE-NAME (1).
024000         03  COLUMN 38   PIC $$,$$9.99 SOURCE DE-GROSS (1).
024100         03  COLUMN 48   PIC ZZ9 SOURCE WPC-PERCENT (1 1).
024200         03  COLUMN 51   PIC X VALUE '%'.
024300         03  COLUMN 57   PIC $$$9.99   SOURCE DE-FICA (1).
024400         03  COLUMN 65   PIC ZZ9 SOURCE WPC-PERCENT (1 2).
024500         03  COLUMN 68   PIC X VALUE '%'.
024600         03  COLUMN 74   PIC $$$9.99   SOURCE DE-FWT (1).
024700         03  COLUMN 82   PIC ZZ9 SOURCE WPC-PERCENT (1 3).
024800         03  COLUMN 85   PIC X VALUE '%'.
024900         03  COLUMN 91   PIC $$$9.99   SOURCE DE-MISC (1).
025000         03  COLUMN 99   PIC ZZ9 SOURCE WPC-PERCENT (1 4).
025100         03  COLUMN 102  PIC X VALUE '%'.
025200         03  COLUMN 108  PIC $$,$$9.99 SOURCE DE-NET (1).
025300         03  COLUMN 118  PIC ZZ9 SOURCE WPC-PERCENT (1 5).
025400         03  COLUMN 121  PIC X VALUE '%'.
025500     02  LINE PLUS 2.
025600         03  COLUMN 05   PIC 9(02) SOURCE DE-NUMBER (2).
025700         03  COLUMN 08   PIC X(15) SOURCE DE-NAME (2).
025800         03  COLUMN 38   PIC $$,$$9.99 SOURCE DE-GROSS (2).
025900         03  COLUMN 48   PIC ZZ9 SOURCE WPC-PERCENT (2 1).
026000         03  COLUMN 51   PIC X VALUE '%'.
026100         03  COLUMN 57   PIC $$$9.99   SOURCE DE-FICA (2).
026200         03  COLUMN 65   PIC ZZ9 SOURCE WPC-PERCENT (2 2).
026300         03  COLUMN 68   PIC X VALUE '%'.
026400         03  COLUMN 74   PIC $$$9.99   SOURCE DE-FWT (2).
026500         03  COLUMN 82   PIC ZZ9 SOURCE WPC-PERCENT (2 3).
026600         03  COLUMN 85   PIC X VALUE '%'.
026700         03  COLUMN 91   PIC $$$9.99   SOURCE DE-MISC (2).
026800         03  COLUMN 99   PIC ZZ9 SOURCE WPC-PERCENT (2 4).
026900         03  COLUMN 102  PIC X VALUE '%'.
027000         03  COLUMN 108  PIC $$,$$9.99 SOURCE DE-NET (2).
027100         03  COLUMN 118  PIC ZZ9 SOURCE WPC-PERCENT (2 5).
027200         03  COLUMN 121  PIC X VALUE '%'.
027300     02  LINE PLUS 2.
027400         03  COLUMN 05   PIC 9(02) SOURCE DE-NUMBER (3).
027500         03  COLUMN 08   PIC X(15) SOURCE DE-NAME (3).
027600         03  COLUMN 38   PIC $$,$$9.99 SOURCE DE-GROSS (3).
027700         03  COLUMN 48   PIC ZZ9 SOURCE WPC-PERCENT (3 1).
027800         03  COLUMN 51   PIC X VALUE '%'.
027900         03  COLUMN 57   PIC $$$9.99   SOURCE DE-FICA (3).
028000         03  COLUMN 65   PIC ZZ9 SOURCE WPC-PERCENT (3 2).
028100         03  COLUMN 68   PIC X VALUE '%'.
028200         03  COLUMN 74   PIC $$$9.99   SOURCE DE-FWT (3).
028300         03  COLUMN 82   PIC ZZ9 SOURCE WPC-PERCENT (3 3).
028400         03  COLUMN 85   PIC X VALUE '%'.
028500         03  COLUMN 91   PIC $$$9.99   SOURCE DE-MISC (3).
028600         03  COLUMN 99   PIC ZZ9 SOURCE WPC-PERCENT (3 4).
028700         03  COLUMN 102  PIC X VALUE '%'.
028800         03  COLUMN 108  PIC $$,$$9.99 SOURCE DE-NET (3).
028900         03  COLUMN 118  PIC ZZ9 SOURCE WPC-PERCENT (3 5).
029000         03  COLUMN 121  PIC X VALUE '%'.
029100     02  LINE PLUS 2.
029200         03  COLUMN 05   PIC 9(02) SOURCE DE-NUMBER (4).
029300         03  COLUMN 08   PIC X(15) SOURCE DE-NAME (4).
029400         03  COLUMN 38   PIC $$,$$9.99 SOURCE DE-GROSS (4).
029500         03  COLUMN 48   PIC ZZ9 SOURCE WPC-PERCENT (4 1).
029600         03  COLUMN 51   PIC X VALUE '%'.
029700         03  COLUMN 57   PIC $$$9.99   SOURCE DE-FICA (4).
029800         03  COLUMN 65   PIC ZZ9 SOURCE WPC-PERCENT (4 2).
029900         03  COLUMN 68   PIC X VALUE '%'.
030000         03  COLUMN 74   PIC $$$9.99   SOURCE DE-FWT (4).
030100         03  COLUMN 82   PIC ZZ9 SOURCE WPC-PERCENT (4 3).
030200         03  COLUMN 85   PIC X VALUE '%'.
030300         03  COLUMN 91   PIC $$$9.99   SOURCE DE-MISC (4).
030400         03  COLUMN 99   PIC ZZ9 SOURCE WPC-PERCENT (4 4).
030500         03  COLUMN 102  PIC X VALUE '%'.
030600         03  COLUMN 108  PIC $$,$$9.99 SOURCE DE-NET (4).
030700         03  COLUMN 118  PIC ZZ9 SOURCE WPC-PERCENT (4 5).
030800         03  COLUMN 121  PIC X VALUE '%'.
030900     02  LINE PLUS 2.
031000         03  COLUMN 05   PIC 9(02) SOURCE DE-NUMBER (5).
031100         03  COLUMN 08   PIC X(15) SOURCE DE-NAME (5).
031200         03  COLUMN 38   PIC $$,$$9.99 SOURCE DE-GROSS (5).
031300         03  COLUMN 48   PIC ZZ9 SOURCE WPC-PERCENT (5 1).
031400         03  COLUMN 51   PIC X VALUE '%'.
031500         03  COLUMN 57   PIC $$$9.99   SOURCE DE-FICA (5).
031600         03  COLUMN 65   PIC ZZ9 SOURCE WPC-PERCENT (5 2).
031700         03  COLUMN 68   PIC X VALUE '%'.
031800         03  COLUMN 74   PIC $$$9.99   SOURCE DE-FWT (5).
031900         03  COLUMN 82   PIC ZZ9 SOURCE WPC-PERCENT (5 3).
032000         03  COLUMN 85   PIC X VALUE '%'.
032100         03  COLUMN 91   PIC $$$9.99   SOURCE DE-MISC (5).
032200         03  COLUMN 99   PIC ZZ9 SOURCE WPC-PERCENT (5 4).
032300         03  COLUMN 102  PIC X VALUE '%'.
032400         03  COLUMN 108  PIC $$,$$9.99 SOURCE DE-NET (5).
032500         03  COLUMN 118  PIC ZZ9 SOURCE WPC-PERCENT (5 5).
032600         03  COLUMN 121  PIC X VALUE '%'.
032700     02  LINE PLUS 2.
032800         03  COLUMN 05   PIC 9(02) SOURCE DE-NUMBER (6).
032900         03  COLUMN 08   PIC X(15) SOURCE DE-NAME (6).
033000         03  COLUMN 38   PIC $$,$$9.99 SOURCE DE-GROSS (6).
033100         03  COLUMN 48   PIC ZZ9 SOURCE WPC-PERCENT (6 1).
033200         03  COLUMN 51   PIC X VALUE '%'.
033300         03  COLUMN 57   PIC $$$9.99   SOURCE DE-FICA (6).
033400         03  COLUMN 65   PIC ZZ9 SOURCE WPC-PERCENT (6 2).
033500         03  COLUMN 68   PIC X VALUE '%'.
033600         03  COLUMN 74   PIC $$$9.99   SOURCE DE-FWT (6).
033700         03  COLUMN 82   PIC ZZ9 SOURCE WPC-PERCENT (6 3).
033800         03  COLUMN 85   PIC X VALUE '%'.
033900         03  COLUMN 91   PIC $$$9.99   SOURCE DE-MISC (6).
034000         03  COLUMN 99   PIC ZZ9 SOURCE WPC-PERCENT (6 4).
034100         03  COLUMN 102  PIC X VALUE '%'.
034200         03  COLUMN 108  PIC $$,$$9.99 SOURCE DE-NET (6).
034300         03  COLUMN 118  PIC ZZ9 SOURCE WPC-PERCENT (6 5).
034400         03  COLUMN 121  PIC X VALUE '%'.
034500     02  LINE PLUS 2.
034600         03  COLUMN 37   PIC $$$,$$9.99 SOURCE CO-GROSS.
034700         03  COLUMN 48   PIC X(5) VALUE '100%'.
034800         03  COLUMN 55   PIC $$,$$9.99  SOURCE CO-FICA.
034900         03  COLUMN 65   PIC X(5) VALUE '100%'.
035000         03  COLUMN 72   PIC $$,$$9.99  SOURCE CO-FWT.
035100         03  COLUMN 82   PIC X(5) VALUE '100%'.
035200         03  COLUMN 89   PIC $$,$$9.99  SOURCE CO-MISC.
035300         03  COLUMN 99   PIC X(5) VALUE '100%'.
035400         03  COLUMN 107  PIC $$$,$$9.99 SOURCE CO-NET.
035500         03  COLUMN 118  PIC X(5) VALUE '100%'.

The Page Heading information is not automatically produced for a Report Footing report group, so the first items repeat the information presented in the Page Heading report group.  In a way this is good, because there are a couple of columns that do not appear in this report and their headings have been omitted when the heading items are repeated in the Report Footing report group.

Everything else in the report group is produced from the department table (in Working-Storage), a table of computed percentages (also in Working-Storage), or the fields generated/maintained by Report Writer for the FINAL Control Footing.  In order to compute the percentage values, a USE procedure is coded for this Report Footing report group:

039100 COMP-FOOT-USE SECTION. USE BEFORE REPORTING COMP-FOOT.
039200 COMP-FOOT-PROC.
039300     PERFORM COMP-FOOT-CALC
039400         VARYING WPCD-IX FROM +1 BY +1
039500         UNTIL WPCD-IX > +6.
039600     GO TO COMP-FOOT-EXIT.
039700
039800 COMP-FOOT-CALC.
039900     SET DE-IX TO WPCD-IX.
040000     SET WPCC-IX TO +1.
040100     COMPUTE WPC-PERCENT (WPCD-IX WPCC-IX) ROUNDED =
040200         ((DE-GROSS (DE-IX) / CO-GROSS) * 100) + .5.
040300     SET WPCC-IX TO +2.
040400     COMPUTE WPC-PERCENT (WPCD-IX WPCC-IX) ROUNDED =
040500         ((DE-FICA (DE-IX) / CO-FICA) * 100) + .5.
040600     SET WPCC-IX TO +3.
040700     COMPUTE WPC-PERCENT (WPCD-IX WPCC-IX) ROUNDED =
040800         ((DE-FWT (DE-IX) / CO-FWT) * 100) + .5.
040900     SET WPCC-IX TO +4.
041000     COMPUTE WPC-PERCENT (WPCD-IX WPCC-IX) ROUNDED =
041100         ((DE-MISC (DE-IX) / CO-MISC) * 100) + .5.
041200     SET WPCC-IX TO +5.
041300     COMPUTE WPC-PERCENT (WPCD-IX WPCC-IX) ROUNDED =
041400         ((DE-NET (DE-IX) / CO-NET) * 100) + .5.
041500
041600 COMP-FOOT-EXIT.
041700     EXIT.

The SET statements for the column index are necessary to satisfy the requirements of the MVT COBOL compiler.  

If you examine the complete program for this example, you will see that the entire contents of both reports are produced entirely using REPORT SECTION definitions and USE procedures.  The only other Procedure Division coding is to open and process the payroll information file.

I think it probably needs to be mentioned that using the Report Footing to produce the second report would only work for a company with a small number of departments.  But, for this small example company, it was very simple to just copy the lines defining each report line in the report group and alter the subscripts from which the data is drawn.  For a larger company, many of the techniques illustrated here are sound, you would only need to define a second Report Definition and GENERATE the Detail report group to produce the department lines by using a PERFORM VARYING to step through the tables.  It would still be a useful technique to extract the calculated values from the first report rather than having to process the data file two times.

The output from the COBOL compiler for the complete program may be viewed at:   RWEX06 Compile and the output from the execution of the program may be viewed at:   RWEX06 Report.

 

Jobstreams to Execute All Programs 

All six of the Report Writer example programs and the data to execute them may be downloaded in a single archive from rwcobol.tgz [MD5: 8029734214123bb60b71869a495687cc  Size: 11 kB].  Note that the source programs in this archive were created on a Windows host system, so each line is terminated with x'0d0a', which should be translated with fromdos, or a similar utility, for use under Linux.

Corrections to Source Programs

I had not revisited this tutorial, or the sample programs, since I first created this page in 2008; therefore I am very grateful for the errors in two of the sample programs that were discovered and reported to me by David Jackson in February, 2011.  

The first error, occurring in sample program #4, caused the report to incorrectly list, for each customer number printed, the name of the customer from the next control group.  This error has been corrected by including a definition in the input record for a group level item to include both the customer number and name, and then to use the group level item as the control field.

The second errors, occurring in sample program #6, were introduced when I copied the code to replicate the functionality of one control level at another level in the Declaratives Section of the program.  Amazingly, these coding errors were not flagged by the compiler and produced no discernable error in the report.


If you are interested in writing COBOL programs that utilize the Report Writer feature, I hope this documentation has provided you with the information you need to install my routine and get started writing programs on your own.  If I can answer any questions about installing and/or using the routine, or if you find errors in these instructions, please don't hesitate to send them to me:



Return to Site Home Page 


This page was last updated on January 17, 2015.