COBOLの報告書作成機能(レポートライター機能)は、複雑な帳票出力も簡単に実現できる強力なツールです。しかし、「ただ明細を一覧表示して、最後に合計件数だけを表示したい」といったシンプルな帳票を作成する際、「集計キーなんていらないんだけどな…」と思ったことはありませんか?
今回は、そんな時に役立つ `CONTROLS ARE FINAL` という記述について、初心者の方にも分かりやすく解説していきます。これを使えば、集計キーを持たないレポートの「最初」と「最後」だけを効率的に制御できるようになりますよ!
1. 導入: なぜ重要か、どんな課題を解決するか
日常業務で作成する帳票の中には、商品の一覧リストや社員名簿など、個々のデータをただ羅列するだけで、特定の集計キーでのブレイク処理(例えば、部門ごとの小計や商品カテゴリごとの合計など)が不要なものがたくさんあります。
しかし、それでも「レポートのタイトルは一番最初に出したい」「全件数は一番最後に表示したい」といった要件は必ず出てきますよね。
通常、COBOLの報告書作成機能でこれらの制御を行うには、何らかの集計キーを設定する必要があると思われがちです。しかし、`CONTOLS ARE FINAL` を使うことで、「集計キーなし」でレポート全体の最初と最後に制御を集中させることができるようになります。これにより、シンプルながらも必要な情報をきちんと盛り込んだ帳票を、少ないコードで効率的に作成できるようになるのです。
2. 基礎知識: 初心者でも理解できるよう、そのテーマに関連する用語や仕組みの解説
まずは、`CONTROLS ARE FINAL` を理解するために、COBOLの報告書作成機能の基本的な概念を簡単におさらいしましょう。
- 報告書作成機能 (Report Writer機能):
COBOLに標準で備わっている、帳票出力のための強力な機能です。データの集計、改ページ、ヘッダー・フッターの制御などを自動で行ってくれます。`REPORT SECTION` という特別なセクションを使って、帳票のレイアウトや出力内容を定義します。
- RD (Report Description) エントリ:
`REPORT SECTION` の中で、一つのレポート(帳票)全体を定義する部分です。ここに、レポートの全体的な設定(ページサイズ、改ページ時の動作、そして今回解説する `CONTROLS ARE` 句など)を記述します。
- CONTROL 句:
`RD` エントリの中に記述し、「どの項目をキーにして集計やブレイク処理を行うか」を定義する句です。例えば `CONTROLS ARE ITEM-CODE` と書けば、商品コードが変わるたびに集計処理(コントロールブレイク)が行われます。
- FINAL とは?
通常、`CONTROL` 句の後には具体的なデータ項目名(例: `ITEM-CODE`)を指定します。しかし、`CONTROLS ARE FINAL.` と記述すると、これは「特定の集計キーは存在しない。レポート全体の最初と最後、つまり全てのデータ処理が終了した時点でのみ制御を行う」という意味になります。
つまり、データの読み込みが全て終わり、最終的な集計処理を行うタイミングで一度だけ、特別な制御(例えば、レポート全体のフッター出力)が渡される、と覚えておきましょう。
3. 実装/解決策: 具体的な手順や論理的な解説
`CONTROLS ARE FINAL.` を使ったレポート作成は非常にシンプルです。
1. `REPORT SECTION` の `RD` エントリに `CONTROLS ARE FINAL.` と記述します。
これにより、COBOLのReport Writerは、キーによるブレイク処理を行わず、レポート全体の開始時と終了時にのみ特別な処理を行うように設定されます。
2. レポートの開始部分 (`REPORT HEADING`):
`TYPE IS REPORT HEADING` を使って、レポート全体のタイトルやカラムヘッダーなどを定義します。これは `INITIATE` 文を実行したときに一度だけ出力されます。
3. 明細行 (`DETAIL`):
`TYPE IS DETAIL` を使って、各レコードの明細情報を定義します。メインの処理部分では、入力ファイルを読み込むたびに `GENERATE` 文でこの `DETAIL` 行を出力します。
4. レポートの終了部分 (`REPORT FOOTING`):
`TYPE IS REPORT FOOTING` を使って、レポート全体の合計件数や総合計などの集計結果を定義します。これは `TERMINATE` 文を実行したときに一度だけ出力されます。
この `REPORT FOOTING` に表示する件数や合計値は、`PROCEDURE DIVISION` で読み込んだレコードごとに自分でカウント・集計しておく必要があります。
このように、`CONTROLS ARE FINAL.` を指定することで、Report Writerは「レポート全体」という一番大きな単位でのみ制御ブレイクを認識し、データの羅列と最終的なまとめを効率的に行えるようになります。
4. サンプルプログラム: 実用的で、そのままコピー&ペーストして動作確認ができるコード例
以下に、商品販売データを読み込み、明細を一覧表示し、最後に総レコード件数を表示するプログラム例を示します。`INPUT.DAT` というファイルに、以下のようなデータを用意して実行してみてください。(文字コードはShift-JISを想定しています)
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE-FINAL-REPORT.
AUTHOR. COBOL-VETERAN.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
> 入力ファイル (例: 商品販売データ)
SELECT INPUT-FILE ASSIGN TO 'INPUT.DAT'
ORGANIZATION IS LINE SEQUENTIAL.
> 出力レポートファイル
SELECT REPORT-FILE ASSIGN TO 'REPORT.LST'.
DATA DIVISION.
FILE SECTION.
FD INPUT-FILE
RECORD IS VARYING IN SIZE FROM 1 TO 80 CHARACTERS
DEPENDING ON WS-INPUT-REC-LEN.
01 INPUT-RECORD.
05 IN-ITEM-CODE PIC X(5). > 商品コード
05 IN-ITEM-NAME PIC N(20). > 商品名 (日本語想定)
05 IN-QUANTITY PIC 9(3). > 数量
05 IN-UNIT-PRICE PIC 9(5). > 単価
05 IN-FILLER PIC X(47). > 残り
FD REPORT-FILE
RECORD CONTAINS 132 CHARACTERS.
01 REPORT-REC PIC X(132).
WORKING-STORAGE SECTION.
01 WS-SWITCHES.
05 WS-INPUT-EOF-SW PIC X(1) VALUE 'N'.
88 WS-INPUT-EOF VALUE 'Y'.
01 WS-COUNTERS.
05 WS-RECORD-COUNT PIC 9(9) VALUE 0. > 読み込んだレコード件数
05 WS-INPUT-REC-LEN PIC S9(4) COMP. > 入力レコードの実際の長さ
REPORT SECTION.
RD SALES-REPORT > レポートの名前
CONTROLS ARE FINAL > ここが今回のポイント!
PAGE LIMIT IS 60 LINES > 1ページの行数
HEADING 1 > ページヘッダーの開始行
FIRST DETAIL 5 > 明細の開始行
LAST DETAIL 55 > 明細の最終行
FOOTING 58. > ページフッターの開始行
> レポートヘッダー (レポートの最初に一度だけ出力される)
01 TYPE IS REPORT HEADING.
05 LINE NUMBER IS 2.
10 COLUMN 5 VALUE '---------------------------------------------------'.
05 LINE NUMBER IS 3.
10 COLUMN 15 VALUE '商品別販売明細リスト'.
05 LINE NUMBER IS 4.
10 COLUMN 5 VALUE '---------------------------------------------------'.
05 LINE NUMBER IS 6.
10 COLUMN 5 VALUE '商品コード'.
10 COLUMN 18 VALUE '商品名'.
10 COLUMN 40 VALUE '数量'.
10 COLUMN 50 VALUE '単価'.
10 COLUMN 60 VALUE '金額'.
05 LINE NUMBER IS 7.
10 COLUMN 5 VALUE '----------'.
10 COLUMN 18 VALUE '--------------------'.
10 COLUMN 40 VALUE '------'.
10 COLUMN 50 VALUE '------'.
10 COLUMN 60 VALUE '----------'.
> 明細行 (入力レコードごとに繰り返し出力される)
01 DETAIL-LINE TYPE IS DETAIL.
05 LINE NUMBER IS PLUS 1. > 前の行から1行開けて出力
10 COLUMN 5 PIC X(5) SOURCE IN-ITEM-CODE.
10 COLUMN 18 PIC N(20) SOURCE IN-ITEM-NAME.
10 COLUMN 40 PIC 9(3) SOURCE IN-QUANTITY.
10 COLUMN 50 PIC 9(5) SOURCE IN-UNIT-PRICE.
10 COLUMN 60 PIC 9(8) SUM IN-QUANTITY IN-UNIT-PRICE.
> 数量 単価 を計算して表示
> レポートフッター (レポートの最後に一度だけ出力される)
01 TYPE IS REPORT FOOTING.
05 LINE NUMBER IS PLUS 3.
10 COLUMN 5 VALUE '---------------------------------------------------'.
05 LINE NUMBER IS PLUS 1.
10 COLUMN 5 VALUE '総レコード件数:'.
10 COLUMN 25 PIC 9(9) SOURCE WS-RECORD-COUNT.
> プロシージャ部でカウントした件数を表示
05 LINE NUMBER IS PLUS 1.
10 COLUMN 5 VALUE '---------------------------------------------------'.
PROCEDURE DIVISION.
MAIN-ROUTINE.
> ファイルを開く
OPEN INPUT INPUT-FILE.
OPEN OUTPUT REPORT-FILE.
> レポートの初期化。これによりREPORT HEADINGが一度出力されます。
INITIATE SALES-REPORT.
> 入力ファイルを最後まで読み込むループ
PERFORM UNTIL WS-INPUT-EOF
READ INPUT-FILE INTO INPUT-RECORD
AT END

コメント