Report generation in COBOL is the process of creating formatted, professional output documents from data. Reports are essential for business applications, providing readable summaries, transaction listings, financial statements, and analytical data. Effective report generation involves organizing data logically, applying proper formatting, calculating totals and subtotals, handling page breaks, and creating clear, professional layouts. Mastering report generation is crucial for creating business-ready output in mainframe COBOL applications.
Report generation transforms raw data into formatted, readable documents. A well-designed report includes:
Reports serve various purposes: financial statements, inventory listings, transaction summaries, customer statements, management reports, and analytical summaries. Effective report generation makes data accessible and actionable.
A typical COBOL report follows this structure:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980IDENTIFICATION DIVISION. PROGRAM-ID. SALES-REPORT. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT INPUT-FILE ASSIGN TO 'SALES.DAT' ORGANIZATION IS SEQUENTIAL ACCESS MODE IS SEQUENTIAL. SELECT REPORT-FILE ASSIGN TO 'SALES.RPT' ORGANIZATION IS SEQUENTIAL ACCESS MODE IS SEQUENTIAL. DATA DIVISION. FILE SECTION. FD INPUT-FILE LABEL RECORDS ARE STANDARD. 01 INPUT-RECORD. 05 SALES-DATE PIC 9(8). 05 SALES-REGION PIC X(10). 05 SALES-AMOUNT PIC 9(7)V99. 05 SALES-REP PIC X(20). FD REPORT-FILE LABEL RECORDS ARE STANDARD. 01 REPORT-LINE PIC X(132). WORKING-STORAGE SECTION. 01 WS-CONTROL-FIELDS. 05 WS-PAGE-NUMBER PIC 9(4) VALUE 0. 05 WS-LINE-COUNT PIC 9(2) VALUE 0. 05 WS-LINES-PER-PAGE PIC 9(2) VALUE 55. 05 WS-PREV-REGION PIC X(10) VALUE SPACES. 01 WS-TOTALS. 05 WS-REGION-TOTAL PIC 9(9)V99 VALUE 0. 05 WS-GRAND-TOTAL PIC 9(9)V99 VALUE 0. 01 WS-HEADER-LINE. 05 FILLER PIC X(20) VALUE SPACES. 05 FILLER PIC X(30) VALUE 'SALES REPORT BY REGION'. 05 FILLER PIC X(50) VALUE SPACES. 05 FILLER PIC X(6) VALUE 'PAGE: '. 05 WS-PAGE-NUM-OUT PIC ZZZ9. 01 WS-COLUMN-HEADER. 05 FILLER PIC X(5) VALUE SPACES. 05 FILLER PIC X(10) VALUE 'DATE'. 05 FILLER PIC X(15) VALUE SPACES. 05 FILLER PIC X(10) VALUE 'REGION'. 05 FILLER PIC X(15) VALUE SPACES. 05 FILLER PIC X(12) VALUE 'AMOUNT'. 05 FILLER PIC X(15) VALUE SPACES. 05 FILLER PIC X(20) VALUE 'SALES REP'. 01 WS-DETAIL-LINE. 05 FILLER PIC X(5) VALUE SPACES. 05 WS-DATE-OUT PIC 99/99/9999. 05 FILLER PIC X(10) VALUE SPACES. 05 WS-REGION-OUT PIC X(10). 05 FILLER PIC X(10) VALUE SPACES. 05 WS-AMOUNT-OUT PIC $,$$$,$$$.99. 05 FILLER PIC X(10) VALUE SPACES. 05 WS-REP-OUT PIC X(20). 01 WS-SUBTOTAL-LINE. 05 FILLER PIC X(5) VALUE SPACES. 05 FILLER PIC X(25) VALUE 'REGION SUBTOTAL: '. 05 WS-REGION-OUT-SUB PIC X(10). 05 FILLER PIC X(20) VALUE SPACES. 05 WS-SUBTOTAL-OUT PIC $,$$$,$$$,$$$.99. 01 WS-GRAND-TOTAL-LINE. 05 FILLER PIC X(5) VALUE SPACES. 05 FILLER PIC X(25) VALUE 'GRAND TOTAL: '. 05 FILLER PIC X(45) VALUE SPACES. 05 WS-GRAND-TOTAL-OUT PIC $,$$$,$$$,$$$.99.
This structure defines the input file, output report file, control fields for page management, totals for accumulation, and formatted output lines for headers, detail, subtotals, and grand totals.
Headers appear at the top of each page and provide context about the report. A good header includes:
12345678910111213141516171819202122232425262728293031323334PROCEDURE DIVISION. MAIN-PARA. OPEN INPUT INPUT-FILE OUTPUT REPORT-FILE PERFORM PRINT-REPORT-HEADER PERFORM PROCESS-INPUT-FILE PERFORM PRINT-GRAND-TOTAL CLOSE INPUT-FILE REPORT-FILE STOP RUN. PRINT-REPORT-HEADER. ADD 1 TO WS-PAGE-NUMBER MOVE WS-PAGE-NUMBER TO WS-PAGE-NUM-OUT MOVE WS-HEADER-LINE TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING PAGE MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE MOVE WS-COLUMN-HEADER TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE MOVE ALL '-' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE MOVE 4 TO WS-LINE-COUNT.
This header paragraph:
Detail lines display individual data records. Each input record typically produces one detail line, formatted for readability.
12345678910111213141516171819202122232425PROCESS-INPUT-FILE. PERFORM UNTIL END-OF-FILE READ INPUT-FILE AT END SET END-OF-FILE TO TRUE NOT AT END PERFORM CHECK-CONTROL-BREAK PERFORM PRINT-DETAIL-LINE PERFORM ACCUMULATE-TOTALS END-READ END-PERFORM. PRINT-DETAIL-LINE. PERFORM CHECK-PAGE-BREAK MOVE SALES-DATE TO WS-DATE-OUT MOVE SALES-REGION TO WS-REGION-OUT MOVE SALES-AMOUNT TO WS-AMOUNT-OUT MOVE SALES-REP TO WS-REP-OUT MOVE WS-DETAIL-LINE TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT.
The detail line printing process:
Control breaks occur when a control field (grouping field) changes value. They signal the start of a new group and trigger printing of subtotals for the previous group.
1234567891011121314151617181920212223242526272829303132CHECK-CONTROL-BREAK. IF WS-PREV-REGION NOT = SPACES IF SALES-REGION NOT = WS-PREV-REGION PERFORM PRINT-REGION-SUBTOTAL PERFORM INITIALIZE-REGION-TOTAL END-IF END-IF MOVE SALES-REGION TO WS-PREV-REGION. PRINT-REGION-SUBTOTAL. PERFORM CHECK-PAGE-BREAK MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT MOVE WS-PREV-REGION TO WS-REGION-OUT-SUB MOVE WS-REGION-TOTAL TO WS-SUBTOTAL-OUT MOVE WS-SUBTOTAL-LINE TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT MOVE ALL '-' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT. INITIALIZE-REGION-TOTAL. MOVE 0 TO WS-REGION-TOTAL.
Control break processing:
Reports can have multiple control break levels (major, intermediate, minor):
1234567891011121314151617181920212223242526272829303132333435363738WORKING-STORAGE SECTION. 01 WS-CONTROL-FIELDS. 05 WS-PREV-DEPARTMENT PIC X(10) VALUE SPACES. 05 WS-PREV-DIVISION PIC X(10) VALUE SPACES. 05 WS-PREV-REGION PIC X(10) VALUE SPACES. 01 WS-TOTALS. 05 WS-DEPARTMENT-TOTAL PIC 9(9)V99 VALUE 0. 05 WS-DIVISION-TOTAL PIC 9(9)V99 VALUE 0. 05 WS-REGION-TOTAL PIC 9(9)V99 VALUE 0. 05 WS-GRAND-TOTAL PIC 9(9)V99 VALUE 0. PROCEDURE DIVISION. CHECK-CONTROL-BREAKS. *> Check major break (Region) IF WS-PREV-REGION NOT = SPACES IF SALES-REGION NOT = WS-PREV-REGION PERFORM PRINT-DIVISION-SUBTOTAL PERFORM PRINT-REGION-SUBTOTAL PERFORM INITIALIZE-REGION-TOTALS ELSE *> Check intermediate break (Division) IF SALES-DIVISION NOT = WS-PREV-DIVISION PERFORM PRINT-DIVISION-SUBTOTAL PERFORM INITIALIZE-DIVISION-TOTALS ELSE *> Check minor break (Department) IF SALES-DEPARTMENT NOT = WS-PREV-DEPARTMENT PERFORM PRINT-DEPARTMENT-SUBTOTAL PERFORM INITIALIZE-DEPARTMENT-TOTALS END-IF END-IF END-IF END-IF MOVE SALES-REGION TO WS-PREV-REGION MOVE SALES-DIVISION TO WS-PREV-DIVISION MOVE SALES-DEPARTMENT TO WS-PREV-DEPARTMENT.
Multiple level breaks allow hierarchical grouping: regions contain divisions, divisions contain departments. Subtotals are printed at each level when that level's control field changes.
Page breaks ensure reports don't exceed page limits and maintain professional formatting. You track the line count and trigger a new page when the limit is reached.
12345678910111213141516171819CHECK-PAGE-BREAK. IF WS-LINE-COUNT >= WS-LINES-PER-PAGE PERFORM PRINT-PAGE-FOOTER PERFORM PRINT-REPORT-HEADER END-IF. PRINT-PAGE-FOOTER. *> Print footer information if needed MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE MOVE ALL '-' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE.
Page break handling:
Totals provide summary information at various levels. Subtotals appear at control breaks, grand totals at the end of the report.
12345678910111213141516171819202122232425262728293031323334353637ACCUMULATE-TOTALS. ADD SALES-AMOUNT TO WS-REGION-TOTAL ADD SALES-AMOUNT TO WS-GRAND-TOTAL. PRINT-REGION-SUBTOTAL. PERFORM CHECK-PAGE-BREAK MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT MOVE WS-PREV-REGION TO WS-REGION-OUT-SUB MOVE WS-REGION-TOTAL TO WS-SUBTOTAL-OUT MOVE WS-SUBTOTAL-LINE TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT. PRINT-GRAND-TOTAL. PERFORM CHECK-PAGE-BREAK MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT MOVE ALL '=' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT MOVE WS-GRAND-TOTAL TO WS-GRAND-TOTAL-OUT MOVE WS-GRAND-TOTAL-LINE TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 LINE ADD 1 TO WS-LINE-COUNT.
Total accumulation and printing:
Proper number formatting makes reports readable and professional. COBOL provides editing characters for formatting.
| Character | Purpose | Example |
|---|---|---|
| $ | Dollar sign (floating or fixed position) | PIC $,$$$,$$$.99 → $1,234.56 |
| , | Comma separator for thousands | PIC 9,999,999 → 1,234,567 |
| . | Decimal point | PIC 999.99 → 123.45 |
| Z | Zero suppression (leading zeros become spaces) | PIC ZZZ9 → " 123" (not "0123") |
| - | Negative sign (floating) | PIC ---,---.99 → -1,234.56 |
| + | Plus or minus sign | PIC +999.99 → +123.45 |
| CR | Credit indicator (appears if negative) | PIC 999.99CR → 123.45CR if negative |
| DB | Debit indicator (appears if negative) | PIC 999.99DB → 123.45DB if negative |
12345678910111213141516171819202122232425WORKING-STORAGE SECTION. 01 WS-RAW-AMOUNT PIC 9(7)V99 VALUE 1234567.89. 01 WS-FORMATTED-AMOUNTS. 05 WS-CURRENCY-FMT PIC $,$$$,$$$.99. 05 WS-NO-DECIMAL PIC Z,ZZZ,ZZ9. 05 WS-PERCENT-FMT PIC ZZ9.99. 05 WS-SIGNED-FMT PIC ---,---.99. PROCEDURE DIVISION. FORMAT-EXAMPLES. *> Currency format MOVE WS-RAW-AMOUNT TO WS-CURRENCY-FMT *> Result: $1,234,567.89 *> No decimal, zero suppression MOVE WS-RAW-AMOUNT TO WS-NO-DECIMAL *> Result: 1,234,568 (rounded, no leading zeros) *> Percentage format MOVE 123.45 TO WS-PERCENT-FMT *> Result: "123.45" (leading zeros suppressed) *> Signed format MOVE -1234.56 TO WS-SIGNED-FMT *> Result: "-1,234.56"
Editing characters transform raw numbers into readable, professional formats suitable for business reports.
Here's a complete report generation program combining all concepts:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180IDENTIFICATION DIVISION. PROGRAM-ID. COMPLETE-REPORT. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT SALES-FILE ASSIGN TO 'SALES.DAT'. SELECT REPORT-FILE ASSIGN TO 'REPORT.OUT'. DATA DIVISION. FILE SECTION. FD SALES-FILE. 01 SALES-RECORD. 05 SALE-DATE PIC 9(8). 05 SALE-REGION PIC X(10). 05 SALE-AMOUNT PIC 9(7)V99. 05 SALE-REP PIC X(20). FD REPORT-FILE. 01 REPORT-LINE PIC X(132). WORKING-STORAGE SECTION. 01 WS-CONTROL. 05 WS-PAGE-NUM PIC 9(4) VALUE 0. 05 WS-LINE-CTR PIC 9(2) VALUE 0. 05 WS-MAX-LINES PIC 9(2) VALUE 55. 05 WS-PREV-REGION PIC X(10) VALUE SPACES. 05 WS-EOF-FLAG PIC X VALUE 'N'. 88 END-OF-FILE VALUE 'Y'. 01 WS-TOTALS. 05 WS-REGION-TOT PIC 9(9)V99 VALUE 0. 05 WS-GRAND-TOT PIC 9(9)V99 VALUE 0. 01 WS-HEADER. 05 FILLER PIC X(40) VALUE SPACES. 05 FILLER PIC X(20) VALUE 'SALES REPORT'. 05 FILLER PIC X(40) VALUE SPACES. 05 FILLER PIC X(6) VALUE 'PAGE: '. 05 WS-PAGE-OUT PIC ZZZ9. 01 WS-COL-HEADER. 05 FILLER PIC X(5) VALUE SPACES. 05 FILLER PIC X(10) VALUE 'DATE'. 05 FILLER PIC X(10) VALUE SPACES. 05 FILLER PIC X(10) VALUE 'REGION'. 05 FILLER PIC X(10) VALUE SPACES. 05 FILLER PIC X(12) VALUE 'AMOUNT'. 05 FILLER PIC X(10) VALUE SPACES. 05 FILLER PIC X(20) VALUE 'SALES REP'. 01 WS-DETAIL. 05 FILLER PIC X(5) VALUE SPACES. 05 WS-DATE-OUT PIC 99/99/9999. 05 FILLER PIC X(10) VALUE SPACES. 05 WS-REG-OUT PIC X(10). 05 FILLER PIC X(10) VALUE SPACES. 05 WS-AMT-OUT PIC $,$$$,$$$.99. 05 FILLER PIC X(10) VALUE SPACES. 05 WS-REP-OUT PIC X(20). 01 WS-SUBTOTAL. 05 FILLER PIC X(5) VALUE SPACES. 05 FILLER PIC X(20) VALUE 'REGION TOTAL: '. 05 WS-REG-SUB PIC X(10). 05 FILLER PIC X(20) VALUE SPACES. 05 WS-SUB-AMT PIC $,$$$,$$$,$$$.99. 01 WS-GRAND-TOTAL-LINE. 05 FILLER PIC X(5) VALUE SPACES. 05 FILLER PIC X(20) VALUE 'GRAND TOTAL: '. 05 FILLER PIC X(45) VALUE SPACES. 05 WS-GRAND-AMT PIC $,$$$,$$$,$$$.99. PROCEDURE DIVISION. MAIN-PARA. OPEN INPUT SALES-FILE OUTPUT REPORT-FILE PERFORM PRINT-HEADER PERFORM PROCESS-RECORDS PERFORM PRINT-REGION-SUBTOTAL PERFORM PRINT-GRAND-TOTAL CLOSE SALES-FILE REPORT-FILE STOP RUN. PRINT-HEADER. ADD 1 TO WS-PAGE-NUM MOVE WS-PAGE-NUM TO WS-PAGE-OUT MOVE WS-HEADER TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING PAGE MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 MOVE WS-COL-HEADER TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 MOVE ALL '-' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 MOVE 4 TO WS-LINE-CTR. CHECK-PAGE-BREAK. IF WS-LINE-CTR >= WS-MAX-LINES PERFORM PRINT-HEADER END-IF. PROCESS-RECORDS. PERFORM UNTIL END-OF-FILE READ SALES-FILE AT END SET END-OF-FILE TO TRUE NOT AT END PERFORM CHECK-CONTROL-BREAK PERFORM PRINT-DETAIL PERFORM ACCUMULATE MOVE SALE-REGION TO WS-PREV-REGION END-READ END-PERFORM. CHECK-CONTROL-BREAK. IF WS-PREV-REGION NOT = SPACES IF SALE-REGION NOT = WS-PREV-REGION PERFORM PRINT-REGION-SUBTOTAL MOVE 0 TO WS-REGION-TOT END-IF END-IF. PRINT-DETAIL. PERFORM CHECK-PAGE-BREAK MOVE SALE-DATE TO WS-DATE-OUT MOVE SALE-REGION TO WS-REG-OUT MOVE SALE-AMOUNT TO WS-AMT-OUT MOVE SALE-REP TO WS-REP-OUT MOVE WS-DETAIL TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR. ACCUMULATE. ADD SALE-AMOUNT TO WS-REGION-TOT ADD SALE-AMOUNT TO WS-GRAND-TOT. PRINT-REGION-SUBTOTAL. PERFORM CHECK-PAGE-BREAK MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR MOVE WS-PREV-REGION TO WS-REG-SUB MOVE WS-REGION-TOT TO WS-SUB-AMT MOVE WS-SUBTOTAL TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR MOVE ALL '-' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR. PRINT-GRAND-TOTAL. PERFORM CHECK-PAGE-BREAK MOVE SPACES TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR MOVE ALL '=' TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR MOVE WS-GRAND-TOT TO WS-GRAND-AMT MOVE WS-GRAND-TOTAL-LINE TO REPORT-LINE WRITE REPORT-LINE AFTER ADVANCING 1 ADD 1 TO WS-LINE-CTR.
Follow these best practices for professional, maintainable reports:
Design your report layout on paper or in a document before coding. Define:
Maintain consistent formatting throughout the report:
Consider and handle edge cases:
1234567891011VALIDATE-AND-PRINT. IF SALE-AMOUNT < 0 DISPLAY 'WARNING: Negative amount for ' SALE-REGION MOVE 0 TO SALE-AMOUNT END-IF IF SALE-REGION = SPACES MOVE 'UNKNOWN' TO SALE-REGION END-IF PERFORM PRINT-DETAIL.
Document your report structure:
Think of report generation like creating a school report card:
Just like a report card organizes grades into a readable format, COBOL report generation organizes data into a professional, readable document!
Complete these exercises to reinforce your understanding:
Create a simple report that reads customer records (ID, name, balance) and prints a formatted report with headers, detail lines, and a grand total of all balances.
Create a sales report grouped by region. Include detail lines for each sale, subtotals for each region, and a grand total. Handle control breaks properly.
Enhance your report to handle page breaks. Print headers on each page, track page numbers, and ensure subtotals and grand totals don't get split across pages.
Create a financial report with properly formatted currency amounts, percentages, and signed numbers. Use various editing characters to format different types of numeric data.
Create a report with multiple control break levels: region, then department, then product. Print subtotals at each level and a grand total at the end.
1. What is a control break in COBOL report generation?
2. When should you print report headers?
3. How do you format a number as currency in COBOL?
4. What is the difference between detail lines and summary lines?
5. How do you handle page breaks in a COBOL report?
6. When should you print grand totals in a report?