Every operations team eventually owns the same problem: fifty batch reports that all need the company name on line one, the run date on line three, page numbers bottom-right, and a standard footer when records exceed a page. Copy-pasting TITLE and HEADING blocks across programs works until someone changes the corporate logo text—then forty programs need edits. The reusable report framework design pattern solves that by separating report chrome from report content. You build a Library skeleton once: macros or PROCs that initialize page counters, print standard headings from parameter fields, format dates with shared MASK routines, and invoke SKIP or NEWPAGE consistently. Each business REPORT subactivity then declares only its input file, CONTROL breaks, quantitative LINE fields, and detail masks. Beginners often confuse this with a single giant report program; the framework is the shared foundation, not the finished listing. This page teaches framework layers, parameter conventions, multi-report JOB layout, integration with BEFORE-LINE and AFTER-BREAK hooks, testing strategy, and how the pattern compares to COBOL copybooks and JCL cataloged procedures on z/OS.
A template is a starting file you duplicate. A framework is live shared code every report calls. Templates drift: developer A widens a column in one copy but not another. Frameworks enforce one definition of heading layout, one PAGE-NUMBER field width, one rule for when FINAL totals print. Easytrieve Library macros expand at compile time—include STD-HEADING once and every REPORT gets identical heading lines. PROC-based frameworks use PERFORM so you can add logic such as reading a control file for holiday banners without recompiling every consumer if you version carefully. Choose macros when layout is static; choose PROCs when headings branch on run options passed through working storage flags.
| Layer | Contents | Maintained by |
|---|---|---|
| Presentation | TITLE, HEADING, FOOTING, PAGE, SKIP, standard MASKs | Framework team |
| Driver | INIT-REPORT, TERM-REPORT, RESET-PAGE-COUNT PROCs | Framework team |
| Parameters | RPT-TITLE, RPT-DATE, RPT-ID, RUN-OPTION fields | Each report JOB |
| Business detail | LINE masks, CONTROL fields, SORT keys | Application developer |
| Data access | FILE, JOB INPUT, GET, EOF guards | Application developer |
Presentation layer never references department-specific field names. Business layer never redefines page width. Violating layer boundaries is the most common framework failure: a payroll developer adds a custom TITLE line inside the shared macro copy, fork the framework, and the next merge overwrites their change.
123456789* STD-REPORT-HEADING macro — expand in REPORT TITLE section MACRO STD-REPORT-HEADING TITLE RPT-TITLE SKIP 1 LINE COMPANY-NAME COL 1 LINE 'Run Date:' RPT-DATE MASK DATE-MASK COL 50 LINE 'Report ID:' RPT-ID COL 1 SKIP 2 END-MACRO
RPT-TITLE, RPT-DATE, and RPT-ID are working storage fields the JOB activity sets before the REPORT runs. MOVE statements in JOB logic populate them from SYSDATE, a parameter file, or JCL symbolic substitution translated through a small driver PROC. MASK DATE-MASK keeps date formatting identical on every report. Consumers include the macro in TITLE and focus HEADING on column titles only.
12345678910INIT-REPORT. PROC MOVE ZERO TO PAGE-COUNT LINE-COUNT MOVE SYSDATE TO RPT-DATE MOVE 'PAYROLL REGISTER' TO RPT-TITLE MOVE 'PAYR01' TO RPT-ID END-PROC TERM-REPORT. PROC DISPLAY 'PAGES PRINTED' PAGE-COUNT END-PROC
JOB activity calls PERFORM INIT-REPORT before the first REPORT and PERFORM TERM-REPORT after the last. PAGE-COUNT and LINE-COUNT are framework fields updated in FOOTING or PAGE procedures. DISPLAY at termination gives operations a quick sanity check in batch logs. Replace DISPLAY with writes to a statistics file if your error-handling pattern requires centralized run metrics.
12345678910111213141516JOB INPUT PAYROLL-FILE PERFORM INIT-REPORT REPORT PAYROLL-REGISTER TITLE %STD-REPORT-HEADING HEADING LINE 'EMP ID' COL 1 'NAME' COL 12 'GROSS' COL 40 CONTROL DEPT LINE EMP-ID NAME GROSS-PAY MASK MONEY-MASK FOOTING PERFORM STD-FOOTING END-REPORT PERFORM TERM-REPORT
PAYROLL-REGISTER supplies CONTROL DEPT and the detail LINE. STD-REPORT-HEADING and PERFORM STD-FOOTING come from the framework. A second REPORT EXCEPTION-LIST in the same JOB reuses INIT-REPORT with different RPT-TITLE moved in a tiny SETUP-EXCEPTION PROC between reports—two listings, one heading standard.
Human-readable report name on the printed listing. Keep under heading width; truncate in INIT-REPORT if longer than MASK allows. Differentiate batch versus on-demand reruns by suffixing RPT-TITLE when a RERUN-FLAG is set.
SYSDATE and SYSTIME system fields copied at INIT-REPORT capture compile-time versus run-time correctly when you MOVE at execution. Document whether date is processing date or business date read from a control file—auditors care.
Short code matching job catalog and operations run books. Tie to JCL job name or internal application ID. Error-handling patterns often write RPT-ID into error files when a report aborts.
Single-character or numeric flags select detail versus summary, suppress FOOTING, or request NEWPAGE per CONTROL break. Framework PROCs test IF RUN-OPTION = 'S' before printing detail LINE—summary-only mode without duplicating the REPORT block.
BEFORE-LINE can PERFORM a framework routine that increments detail counters or applies redaction MASKs for sensitive fields. AFTER-BREAK can PERFORM STD-SUBTOTAL-HEADER to print a standard break banner line before quantitative totals. Keep hooks thin: one PERFORM into framework code, not twenty lines of duplicated MASK logic. BEFORE-BREAK at major CONTROL level is the right place to reset LINE-COUNT when your framework limits lines per page and needs custom paging beyond default PAGE statement behavior.
| Situation | Recommendation |
|---|---|
| Three or more reports share headings | Adopt framework macros |
| Regulatory audit requires identical run metadata | Centralize RPT-DATE and RPT-ID in INIT-REPORT |
| Single annual census listing | Inline TITLE is acceptable |
| Headings change quarterly | Framework—one macro edit updates all consumers |
| Report widths differ radically | Split into two framework profiles (wide vs narrow) |
Imagine every school worksheet must have the same name line and date at the top. Instead of each teacher drawing that by hand on every page, the school prints one master strip of paper everyone tapes on top. The reusable report framework is that master strip. Each teacher only writes the math problems in the middle—the detail lines. When the school changes its logo, they update the master strip once and every worksheet looks right the next day.
1. A reusable report framework centralizes:
2. Report-specific detail logic belongs in:
3. Parameter fields for report titles typically live in:
4. Multiple reports in one JOB use:
5. Framework macros differ from copy-paste because: