Chapter 15: Report Writer Module -- Key Takeaways

Chapter Summary

The Report Writer module is a specialized feature of COBOL designed to automate the production of formatted printed reports. Instead of manually coding line counters, page-break logic, heading routines, footing routines, and accumulator fields, Report Writer allows the programmer to declare the entire report layout in the DATA DIVISION and then generate it with just three PROCEDURE DIVISION statements: INITIATE, GENERATE, and TERMINATE. The module handles page overflow detection, automatic heading and footing generation, control break processing, and subtotal/total accumulation behind the scenes, dramatically reducing the amount of procedural code required.

This chapter introduced the REPORT SECTION in the DATA DIVISION, where reports are defined through RD (Report Description) entries and their associated report group definitions. Each report group serves a specific role in the report structure: Report Heading (RH) appears once at the beginning of the report, Page Heading (PH) prints at the top of every page, Detail (DE) lines represent the individual data rows, Control Heading (CH) introduces each new control group, Control Footing (CF) summarizes a completed control group, Page Footing (PF) prints at the bottom of every page, and Report Footing (RF) appears once at the end of the entire report. The LINE, COLUMN, SOURCE, SUM, and GROUP INDICATE clauses control exactly where each field appears and what value it contains.

We also examined how Report Writer interacts with the control break mechanism through the CONTROL clause on the RD entry. When the value of a control field changes, Report Writer automatically generates the appropriate Control Footing for the completed group and the Control Heading for the new group, including the cascading behavior when multiple control levels change simultaneously. The SUM clause on Control Footing fields automatically accumulates values from Detail lines or lower-level Control Footings, making it straightforward to produce subtotals and grand totals without any manual accumulator logic. While Report Writer has fallen out of favor in some shops due to its complexity and the shift away from printed reports, it remains a valuable tool for batch reporting and appears in legacy codebases that must be maintained.

Key Concepts

  • The REPORT SECTION is declared within the DATA DIVISION after the FILE SECTION and WORKING-STORAGE SECTION, containing one or more RD entries and their associated report groups.
  • The RD (Report Description) entry names the report and specifies its control hierarchy through the CONTROL clause and its page layout through the PAGE clause.
  • The CONTROL clause lists the data items whose value changes trigger control breaks, ordered from major (leftmost) to minor (rightmost), with FINAL as the highest level.
  • The PAGE clause on the RD entry defines page geometry: PAGE LIMIT IS n LINES, HEADING at line h, FIRST DETAIL at line d, LAST DETAIL at line l, and FOOTING at line f.
  • Report Heading (TYPE RH) prints once at the very beginning of the report, before the first Page Heading.
  • Page Heading (TYPE PH) prints automatically at the top of every page, after the page is advanced, without any programmer intervention.
  • Detail (TYPE DE) lines are generated by the GENERATE statement and represent the individual data rows of the report.
  • Control Heading (TYPE CH) introduces a new control group and is generated automatically when a control break is detected, before the first Detail line of the new group.
  • Control Footing (TYPE CF) summarizes a completed control group and is generated automatically when a control break occurs, after the last Detail line of the finishing group.
  • Page Footing (TYPE PF) prints automatically at the bottom of every page when the page is full, before the page advance.
  • Report Footing (TYPE RF) prints once at the very end of the report, after all data has been processed and the final control footings have been generated.
  • The INITIATE statement activates the report, initializing all SUM counters and internal report state; it does not produce any output by itself.
  • The GENERATE statement triggers the production of a Detail line and handles all automatic control break processing, page overflow, headings, and footings.
  • GENERATE can also be used with a report group name (summary reporting) to produce control break output without individual detail lines.
  • The TERMINATE statement finalizes the report, forcing all pending control footings and the report footing to be generated.
  • The SOURCE clause specifies the data item whose value is moved into a report field when the line is generated.
  • The SUM clause on a Control Footing field automatically accumulates values from Detail line fields or lower-level Control Footing fields.
  • The LINE clause specifies the absolute or relative line position for a report group, and the COLUMN clause specifies the horizontal column position for a field.
  • GROUP INDICATE causes a field to print only on the first Detail line of a new control group, suppressing it on subsequent detail lines within the same group.

Common Pitfalls

  • Forgetting to INITIATE before GENERATE: The GENERATE statement will fail or produce unpredictable results if the report has not been initialized with INITIATE first. INITIATE must be issued after the report file is opened.
  • Forgetting to TERMINATE before CLOSE: If you close the report file without issuing TERMINATE, the final control footings and report footing will not be generated, and accumulated SUM values for the last group will be lost.
  • Incorrect PAGE clause geometry: If the FIRST DETAIL line number is less than or equal to the HEADING line, or if the FOOTING line is greater than the PAGE LIMIT, the compiler will reject the RD entry. The values must satisfy: HEADING <= FIRST DETAIL <= LAST DETAIL <= FOOTING <= PAGE LIMIT.
  • CONTROL fields not in the correct hierarchical order: The CONTROL clause must list fields from major to minor. If the input data is not sorted in the same hierarchical order as the CONTROL clause, control breaks will fire on every record, producing meaningless subtotals.
  • SUM clause referencing wrong fields: SUM can only reference SOURCE identifiers on DE lines or SUM identifiers on lower-level CF groups. Referencing a field that is not a SOURCE on a Detail line will cause a compilation error or incorrect accumulation.
  • Assuming Report Writer handles page headers on page one automatically with no GENERATE: The first Page Heading is produced when the first GENERATE executes, not when INITIATE runs. If no GENERATE is ever issued (empty input file), no headings appear.
  • Mixing Report Writer with manual WRITE statements for the same file: The report file used by Report Writer must not be written to with explicit WRITE statements. All output to the report file must be controlled by INITIATE, GENERATE, and TERMINATE.
  • Not providing sufficient LINE and COLUMN clauses: Omitting LINE or COLUMN on report group entries can cause fields to overlap or appear at position 1 by default. Every field that should appear at a specific position must have explicit COLUMN specification.

Quick Reference

      * Report file SELECT and FD
           SELECT REPORT-FILE ASSIGN TO "RPTOUT".
       FD  REPORT-FILE.
       01  REPORT-LINE            PIC X(132).

      * REPORT SECTION with RD and report groups
       REPORT SECTION.
       RD  DEPT-REPORT
           CONTROL IS FINAL WS-DEPT-CODE
           PAGE LIMIT IS 60 LINES
           HEADING 1
           FIRST DETAIL 6
           LAST DETAIL 55
           FOOTING 58.

      * Report Heading
       01  TYPE IS REPORT HEADING.
           05  LINE 1  COLUMN 45
               VALUE "DEPARTMENT SALARY REPORT".
           05  LINE 2  COLUMN 45
               VALUE "==========================".

      * Page Heading
       01  TYPE IS PAGE HEADING.
           05  LINE 4  COLUMN 01  VALUE "DEPT".
           05  LINE 4  COLUMN 10  VALUE "EMPLOYEE".
           05  LINE 4  COLUMN 45  VALUE "SALARY".
           05  LINE 5  COLUMN 01  VALUE "----".
           05  LINE 5  COLUMN 10  VALUE "--------".
           05  LINE 5  COLUMN 45  VALUE "------".

      * Control Heading for department
       01  TYPE IS CONTROL HEADING WS-DEPT-CODE.
           05  LINE PLUS 1 COLUMN 01
               PIC X(03) SOURCE WS-DEPT-CODE.

      * Detail line
       01  TYPE IS DETAIL.
           05  LINE PLUS 1 COLUMN 10
               PIC X(30) SOURCE WS-EMP-NAME.
           05  LINE PLUS 0 COLUMN 45
               PIC $$$,$$9.99 SOURCE WS-EMP-SALARY.

      * Control Footing for department subtotal
       01  TYPE IS CONTROL FOOTING WS-DEPT-CODE.
           05  LINE PLUS 1 COLUMN 35
               VALUE "DEPT TOTAL:".
           05  LINE PLUS 0 COLUMN 45
               PIC $$$,$$9.99 SUM WS-EMP-SALARY.

      * Control Footing for FINAL grand total
       01  TYPE IS CONTROL FOOTING FINAL.
           05  LINE PLUS 2 COLUMN 35
               VALUE "GRAND TOTAL:".
           05  LINE PLUS 0 COLUMN 45
               PIC $$$$,$$9.99 SUM WS-EMP-SALARY.

      * PROCEDURE DIVISION usage
           OPEN INPUT EMP-FILE
                OUTPUT REPORT-FILE
           INITIATE DEPT-REPORT
           PERFORM UNTIL WS-EOF = "Y"
               READ EMP-FILE INTO WS-EMP-RECORD
                   AT END
                       MOVE "Y" TO WS-EOF
                   NOT AT END
                       GENERATE DETAIL-LINE
               END-READ
           END-PERFORM
           TERMINATE DEPT-REPORT
           CLOSE EMP-FILE REPORT-FILE
           STOP RUN.

What's Next

Chapter 16 covers Declaratives and Exception Handling, which provide the mechanisms for intercepting and recovering from errors during file I/O and other operations. You will learn how the DECLARATIVES section and the USE AFTER STANDARD ERROR PROCEDURE statement allow you to centralize error-handling logic, how file status codes communicate the outcome of every I/O operation, and how condition phrases like INVALID KEY, AT END, and ON SIZE ERROR provide inline exception handling at the statement level. These techniques are essential for building robust, production-quality COBOL programs that handle errors gracefully rather than abending.