Case Study 1: Monthly Account Statement Report
Background
Columbia Trust Bank produces monthly account statements for each of its 185,000 active retail customers. Each statement includes a page header with the bank's branding and the customer's account information, a chronological listing of every transaction during the statement period, subtotals for debits and credits, and a closing balance summary. Statements for customers with multiple account types (checking, savings, money market) include separate sections for each account with grand totals across all accounts.
Historically, the statement generation program was a 4,500-line COBOL program with intricate procedural logic for page overflow detection, control break handling, subtotal accumulation, and header/footer formatting. Every time the marketing department wanted to change the statement layout -- adding a promotional message, adjusting column widths, or modifying the subtotal format -- the programmers had to modify dozens of interconnected paragraphs and retest the entire page flow logic.
The bank has decided to rewrite the statement generation program using COBOL's Report Writer module. Report Writer's declarative approach separates the "what" (the report layout) from the "how" (the page and control break mechanics), allowing layout changes to be made in the REPORT SECTION without touching the PROCEDURE DIVISION.
Data Design
The Input File
The input is a sorted file containing one record per transaction, ordered by customer number, then account number, then transaction date:
SELECT STATEMENT-INPUT-FILE
ASSIGN TO STMTINP
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-INPUT-STATUS.
FD STATEMENT-INPUT-FILE
RECORDING MODE IS F
RECORD CONTAINS 150 CHARACTERS.
01 STATEMENT-INPUT-RECORD.
05 SIR-CUSTOMER-NUMBER PIC X(8).
05 SIR-CUSTOMER-NAME PIC X(30).
05 SIR-CUSTOMER-ADDRESS.
10 SIR-STREET PIC X(30).
10 SIR-CITY PIC X(20).
10 SIR-STATE PIC X(2).
10 SIR-ZIP PIC X(10).
05 SIR-ACCOUNT-NUMBER PIC X(10).
05 SIR-ACCOUNT-TYPE PIC X(2).
88 SIR-CHECKING VALUE "CK".
88 SIR-SAVINGS VALUE "SV".
88 SIR-MONEY-MARKET VALUE "MM".
05 SIR-TXN-DATE PIC 9(8).
05 SIR-TXN-DESCRIPTION PIC X(25).
05 SIR-TXN-AMOUNT PIC S9(9)V99.
05 SIR-RUNNING-BALANCE PIC S9(9)V99.
05 SIR-FILLER PIC X(2).
The Report Output File
SELECT STATEMENT-REPORT-FILE
ASSIGN TO STMTRPT
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-REPORT-STATUS.
FD STATEMENT-REPORT-FILE
REPORT IS MONTHLY-STATEMENT.
Note that the FD for a Report Writer file contains no record description. Instead, it references the report name defined in the REPORT SECTION. The runtime generates the output records based on the report group definitions.
The Report Section: Declaring the Statement Layout
The REPORT SECTION is where Report Writer programs define the entire visual structure of the report. Each report group specifies its type, position, and content:
REPORT SECTION.
RD MONTHLY-STATEMENT
CONTROLS ARE FINAL
SIR-CUSTOMER-NUMBER
SIR-ACCOUNT-NUMBER
PAGE LIMIT IS 66 LINES
HEADING 1
FIRST DETAIL 12
LAST DETAIL 58
FOOTING 62.
The RD entry establishes several critical parameters:
-
CONTROLS ARE: Lists the control fields in major-to-minor order. FINAL is the highest level (triggered once at the very end of the report). SIR-CUSTOMER-NUMBER is the next level (triggered when the customer changes). SIR-ACCOUNT-NUMBER is the minor level (triggered when the account changes within a customer).
-
PAGE LIMIT IS 66: The physical page is 66 lines (standard for mainframe printing on 11-inch paper at 6 lines per inch).
-
HEADING 1: Page headings start on line 1.
-
FIRST DETAIL 12: Detail lines begin no earlier than line 12 (leaving room for headers).
-
LAST DETAIL 58: Detail lines print no later than line 58 (leaving room for footers).
-
FOOTING 62: Page footings print no later than line 62.
Report Heading (First Page Only)
01 TYPE IS REPORT HEADING.
02 LINE 1.
05 COLUMN 1 PIC X(60) VALUE
"========================================="
& "===================".
02 LINE 2.
05 COLUMN 5 PIC X(30) VALUE
"COLUMBIA TRUST BANK".
02 LINE 3.
05 COLUMN 5 PIC X(30) VALUE
"MONTHLY ACCOUNT STATEMENT".
02 LINE 4.
05 COLUMN 1 PIC X(60) VALUE
"========================================="
& "===================".
Page Heading (Top of Every Page)
01 TYPE IS PAGE HEADING.
02 LINE 6.
05 COLUMN 1 PIC X(20) VALUE
"Statement Date:".
05 COLUMN 22 PIC X(10)
SOURCE WS-STATEMENT-DATE-FORMATTED.
05 COLUMN 50 PIC X(5) VALUE "Page ".
05 COLUMN 55 PIC ZZ9
SOURCE PAGE-COUNTER.
02 LINE 8.
05 COLUMN 1 PIC X(10) VALUE "DATE".
05 COLUMN 14 PIC X(25) VALUE "DESCRIPTION".
05 COLUMN 42 PIC X(11) VALUE "DEBITS".
05 COLUMN 55 PIC X(11) VALUE "CREDITS".
05 COLUMN 68 PIC X(12) VALUE "BALANCE".
02 LINE 9.
05 COLUMN 1 PIC X(79) VALUE ALL "-".
Customer Control Heading
When a new customer begins, the statement prints the customer's name and mailing address:
01 TYPE IS CONTROL HEADING SIR-CUSTOMER-NUMBER.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(30)
SOURCE SIR-CUSTOMER-NAME.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(8) VALUE "Acct #: ".
05 COLUMN 10 PIC X(8)
SOURCE SIR-CUSTOMER-NUMBER.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(30)
SOURCE SIR-STREET.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(20)
SOURCE SIR-CITY.
05 COLUMN 22 PIC X(2)
SOURCE SIR-STATE.
05 COLUMN 26 PIC X(10)
SOURCE SIR-ZIP.
Account Control Heading
When a new account begins within a customer, the account type and number are printed:
01 TYPE IS CONTROL HEADING SIR-ACCOUNT-NUMBER.
02 LINE PLUS 2.
05 COLUMN 1 PIC X(12) VALUE
"Account: ".
05 COLUMN 14 PIC X(10)
SOURCE SIR-ACCOUNT-NUMBER.
05 COLUMN 28 PIC X(6) VALUE "Type: ".
05 COLUMN 35 PIC X(2)
SOURCE SIR-ACCOUNT-TYPE.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(60) VALUE ALL "-".
Detail Line (One Per Transaction)
01 STATEMENT-DETAIL TYPE IS DETAIL.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(10)
SOURCE WS-TXN-DATE-FORMATTED.
05 COLUMN 14 PIC X(25)
SOURCE SIR-TXN-DESCRIPTION.
05 COLUMN 40 PIC $(7),$$9.99-
SOURCE WS-DEBIT-AMOUNT.
05 COLUMN 54 PIC $(7),$$9.99-
SOURCE WS-CREDIT-AMOUNT.
05 COLUMN 67 PIC $(7),$$9.99-
SOURCE SIR-RUNNING-BALANCE.
```
### Account Control Footing (Subtotals Per Account)
```cobol
01 TYPE IS CONTROL FOOTING SIR-ACCOUNT-NUMBER.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(60) VALUE ALL "-".
02 LINE PLUS 1.
05 COLUMN 14 PIC X(16) VALUE
"Account Totals:".
05 COLUMN 40 PIC $(7),$$9.99-
SUM WS-DEBIT-AMOUNT.
05 COLUMN 54 PIC $(7),$$9.99-
SUM WS-CREDIT-AMOUNT.
05 COLUMN 67 PIC $(7),$$9.99-
SOURCE SIR-RUNNING-BALANCE.
The SUM clause is one of Report Writer's most powerful features. It automatically accumulates the values of the specified data items across all detail lines within the control group. When the account number changes, the accumulated sums are printed automatically, then reset to zero for the next group.
Customer Control Footing (Grand Total Per Customer)
01 TYPE IS CONTROL FOOTING SIR-CUSTOMER-NUMBER.
02 LINE PLUS 2.
05 COLUMN 1 PIC X(60) VALUE ALL "=".
02 LINE PLUS 1.
05 COLUMN 5 PIC X(25) VALUE
"CUSTOMER GRAND TOTAL:".
05 COLUMN 40 PIC $(7),$$9.99-
SUM WS-DEBIT-AMOUNT.
05 COLUMN 54 PIC $(7),$$9.99-
SUM WS-CREDIT-AMOUNT.
02 LINE PLUS 2.
05 COLUMN 5 PIC X(40) VALUE
"Thank you for banking with Columbia Trust".
At the customer control footing level, the SUM clause accumulates the account-level sums from the control footings below it. This automatic "rollup" of subtotals is a key advantage of Report Writer -- in manual code, you would need to explicitly add account subtotals into customer grand totals.
Report Footing (Last Page Only)
01 TYPE IS REPORT FOOTING.
02 LINE PLUS 3.
05 COLUMN 1 PIC X(60) VALUE ALL "=".
02 LINE PLUS 1.
05 COLUMN 5 PIC X(30) VALUE
"*** END OF STATEMENTS ***".
02 LINE PLUS 1.
05 COLUMN 5 PIC X(40) VALUE
"Total Customers Processed:".
05 COLUMN 46 PIC ZZ,ZZ9
SOURCE WS-CUSTOMER-COUNT.
02 LINE PLUS 1.
05 COLUMN 1 PIC X(60) VALUE ALL "=".
The Procedure Division: Minimal Code
With Report Writer, the PROCEDURE DIVISION is remarkably simple. The runtime handles all page breaks, control breaks, subtotal accumulation, and header/footer generation:
PROCEDURE DIVISION.
DECLARATIVES.
USE-BEFORE-DETAIL SECTION.
USE BEFORE REPORTING STATEMENT-DETAIL.
PREPARE-DETAIL-DATA.
* Format the transaction date for display
MOVE SIR-TXN-DATE(5:2) TO WS-TXN-MM
MOVE SIR-TXN-DATE(7:2) TO WS-TXN-DD
MOVE SIR-TXN-DATE(1:4) TO WS-TXN-YYYY
STRING WS-TXN-MM "/" WS-TXN-DD "/"
WS-TXN-YYYY DELIMITED SIZE
INTO WS-TXN-DATE-FORMATTED
* Split amount into debit/credit columns
IF SIR-TXN-AMOUNT < 0
COMPUTE WS-DEBIT-AMOUNT =
SIR-TXN-AMOUNT * -1
MOVE 0 TO WS-CREDIT-AMOUNT
ELSE
MOVE 0 TO WS-DEBIT-AMOUNT
MOVE SIR-TXN-AMOUNT TO WS-CREDIT-AMOUNT
END-IF
.
END DECLARATIVES.
MAIN-PROCESSING SECTION.
0000-MAIN.
OPEN INPUT STATEMENT-INPUT-FILE
OPEN OUTPUT STATEMENT-REPORT-FILE
INITIATE MONTHLY-STATEMENT
MOVE 0 TO WS-CUSTOMER-COUNT
MOVE SPACES TO WS-PREV-CUSTOMER
PERFORM 1000-READ-INPUT
PERFORM UNTIL WS-INPUT-EOF
IF SIR-CUSTOMER-NUMBER NOT = WS-PREV-CUSTOMER
ADD 1 TO WS-CUSTOMER-COUNT
MOVE SIR-CUSTOMER-NUMBER
TO WS-PREV-CUSTOMER
END-IF
GENERATE STATEMENT-DETAIL
PERFORM 1000-READ-INPUT
END-PERFORM
TERMINATE MONTHLY-STATEMENT
CLOSE STATEMENT-INPUT-FILE
CLOSE STATEMENT-REPORT-FILE
DISPLAY "STATEMENTS GENERATED FOR "
WS-CUSTOMER-COUNT " CUSTOMERS"
STOP RUN
.
1000-READ-INPUT.
READ STATEMENT-INPUT-FILE
AT END SET WS-INPUT-EOF TO TRUE
END-READ
.
The entire PROCEDURE DIVISION, excluding the declaratives section, is under 30 lines. Compare this to the 500+ lines that the equivalent manual report logic would require. Three statements do all the work:
- INITIATE: Activates the report, initializes all SUM counters, and triggers the Report Heading.
- GENERATE: Produces one detail line and handles all automatic processing: page overflow (triggers Page Heading/Footing), control breaks (triggers Control Headings and Footings), and SUM accumulation.
- TERMINATE: Triggers the final Control Footings at all levels and the Report Footing.
The USE BEFORE REPORTING Declarative
The USE BEFORE REPORTING declarative executes custom logic just before a specific report group is presented. In this case, it formats the transaction date and splits the transaction amount into separate debit and credit fields for display in two columns.
This is necessary because the input record stores the amount as a single signed field (negative for debits, positive for credits), but the statement displays debits and credits in separate columns. The declarative performs this transformation immediately before each detail line is generated.
JCL for Statement Generation
//STMTGEN JOB (ACCT),'MONTHLY STATEMENTS',
// CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//*
//GENSTMT EXEC PGM=STMTGEN
//STEPLIB DD DSN=PROD.LOADLIB,DISP=SHR
//*
//* SORTED TRANSACTION INPUT
//STMTINP DD DSN=BANK.MONTHLY.STMT.INPUT,DISP=SHR
//*
//* REPORT OUTPUT (PRINT FILE)
//STMTRPT DD SYSOUT=A,
// DCB=(RECFM=FBA,LRECL=133,BLKSIZE=0)
//*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
The output file uses RECFM=FBA (Fixed Block with ASA carriage control). The ASA carriage control character in column 1 controls printer page ejects and line spacing. Report Writer generates these control characters automatically.
Sample Output
===========================================================
COLUMBIA TRUST BANK
MONTHLY ACCOUNT STATEMENT
===========================================================
Statement Date: 01/31/2026 Page 1
DATE DESCRIPTION DEBITS CREDITS BALANCE
-------------------------------------------------------------------------------
Margaret A. Thompson
Acct #: 00045721
742 Elmwood Drive
Springfield IL 62704-1122
Account: 2847100445 Type: CK
------------------------------------------------------------
01/02/2026 OPENING BALANCE $ 5,247.83
01/03/2026 POS PURCHASE #4721 $ 47.95 $ 5,199.88
01/05/2026 ATM WITHDRAWAL $ 200.00 $ 4,999.88
01/07/2026 DIRECT DEPOSIT $ 3,285.00 $ 8,284.88
01/10/2026 CHECK #1047 $ 850.00 $ 7,434.88
01/15/2026 ONLINE PAYMENT $ 125.50 $ 7,309.38
01/22/2026 DIRECT DEPOSIT $ 3,285.00 $ 10,594.38
01/28/2026 UTILITY PAYMENT $ 187.43 $ 10,406.95
------------------------------------------------------------
Account Totals: $ 1,410.88 $ 6,570.00 $ 10,406.95
Account: 2847100446 Type: SV
------------------------------------------------------------
01/01/2026 OPENING BALANCE $ 12,500.00
01/15/2026 TRANSFER FROM CK $ 1,000.00 $ 13,500.00
01/31/2026 INTEREST EARNED $ 11.25 $ 13,511.25
------------------------------------------------------------
Account Totals: $ 0.00 $ 1,011.25 $ 13,511.25
===========================================================
CUSTOMER GRAND TOTAL: $ 1,410.88 $ 7,581.25
Thank you for banking with Columbia Trust
Lessons Learned
1. Report Writer Dramatically Reduces Code Volume
The original manual statement program was 4,500 lines. The Report Writer version is approximately 300 lines total (including the REPORT SECTION declarations). The reduction comes primarily from eliminating the procedural page-break, control-break, and accumulation logic that Report Writer handles automatically.
2. Layout Changes Are Isolated to the REPORT SECTION
When the marketing department requested a new promotional message line in the customer footing, the change required modifying only the CONTROL FOOTING SIR-CUSTOMER-NUMBER group in the REPORT SECTION. No changes to the PROCEDURE DIVISION were needed, and the change was tested in a single afternoon.
3. SUM Rollup Eliminates Manual Accumulator Management
In the manual version, the programmer maintained six separate accumulators (account-debit, account-credit, customer-debit, customer-credit, grand-debit, grand-credit) with explicit ADD, reset, and rollup logic. Report Writer's cascading SUM replaces all of this with two SUM clauses that automatically roll up from account to customer to final level.
4. USE BEFORE REPORTING Bridges the Gap
The declarative section provides a clean hook for data transformation logic that does not fit naturally into the REPORT SECTION's declarative model. Without it, the program would need to pre-process every record in the PROCEDURE DIVISION before calling GENERATE, which would add complexity to the main loop.
Discussion Questions
-
What happens when a customer has so many transactions that the account section spans multiple pages? How does Report Writer handle the Page Heading reprinting, and does the Account Control Heading reprint on the new page?
-
The FIRST DETAIL line is set to 12, leaving 11 lines for headers. If the customer address section requires more lines (for example, adding a second address line for suite numbers), what changes to the RD entry are needed?
-
Why is the customer count tracked manually in the PROCEDURE DIVISION rather than using a Report Writer SUM or counter? Could Report Writer's built-in mechanisms handle this?
-
Compare the Report Writer approach to generating statements as PDF files using a modern reporting tool. What are the advantages of each approach, and in what scenarios would Report Writer still be preferred?
-
If the bank wanted to produce statements in two formats (paper and electronic/CSV), how much of the Report Writer program could be reused for the electronic format?