【実務・中級編】PICTURE編集文字 ‘CR’ と ‘DB’ の会計処理における挙動 – PL/Iの基本構文とデータ制御実践ガイド

おい、若いの。少し手を止めて、このレガシー画面を見てくれ。

基幹システムのオンライン画面や、夜間バッチで出力される総勘定元帳、あるいは外部金融機関へ渡す全銀協フォーマットの固定長ファイル……。金額の項目に `12345.67CR` とか `98765.43DB` なんて表示されているのを見たことがあるだろう?

あれだよ、あれ。今日のテーマは、PL/Iにおける PICTURE編集文字 ‘CR’ と ‘DB’ の会計処理における挙動 だ。

現代のオープン系やWEBアプリケーションのエンジニアから見ると、「わざわざサフィックスにクレジット(CR)やデビット(DB)を付けるなんて、レガシーで面倒くさい仕様だな」って思うかもしれない。だがな、メインフレームの世界では、この「符号の文字列表現」が監査や税務申告の整合性を保つ上で、死活問題になるんだ。

今日は、この `CR` と `DB` が内部的にどう符号を判定し、どうやってフォーマットを制御しているのか。長年、数々の修羅場をくぐってきた俺が、実務に直結するノウハウを叩き込んでやる。心して聞けよ。

—

1. 現場のエンジニアが陥る罠:PL/IのPICTURE ‘CR’ と ‘DB’ の基本

まず大前提として、PL/Iの強力な文字編集機能(PICTURE句)についておさらいしておこう。
COBOLなどでもおなじみだが、PL/IのPICTURE句では、数値データを印字用やファイル出力用の文字データに変換する際、負の数に対して特定の文字列を付加することができる。

ここで重要なのは、PL/Iには「予約語(Keyword)」という概念が極めて薄い(文脈依存の言語仕様である)という特性だ。変数名に `CR` や `DB` と名付けることすら理論上は可能だが、PICTURE句の中でこれらを記述すると、コンパイラは特別に「条件付きサフィックス」として解釈する。

仕様のキホン

  • `CR` (Credit): 値が負(< 0)の場合に `CR` が出力され、正またはゼロ(>= 0)の場合はスペース2文字 (` `) が出力される。
  • `DB` (Debit): 値が負(< 0)の場合に `DB` が出力され、正またはゼロ(>= 0)の場合はスペース2文字 (` `) が出力される。

勘の良いお前なら気付いたはずだ。
「あれ? 簿記の仕訳で、資産の増加や費用の発生を表すDB(借方)が、なぜPL/Iの内部判定では『負の値』のときに付くんだ?」ってな。

ここが実務で最も勘違いしやすいポイントだ。
コンピュータの内部数値計算において、残高や金額を保持する変数(例えば `DECIMAL FIXED(11,2)` など)は、「純粋な代数的な大小(正負)」で管理されている。会計システムにおいて「マイナス残高(赤字・過払い・戻入など)」を表現する場合、データ値自体が負数になっている。PL/Iの `CR`/`DB` PICTUREは、会計上の借方・貸方の意味論を直接解釈しているわけではない。単に「数値が負であるという事実」に対して、業界標準の慣習に合わせたラベル(CRまたはDB)を右側に添える機能に過ぎないのだ。

ここをき違えると、マイナス残高のデータを処理したときに「なんでDB(借方)なのにマイナスなんだ!?」と大パニックを起こし、夜間バッチのテスト工程で手を挙げる羽目になる。よく覚えておけよ。

—

2. レコード入出力とVSAMアクセスにおける実務上の注意点

メインフレームの現場では、この編集文字を含むデータをVSAMファイル(KSDSやESDS)や、セクタ単位の順編成ファイル(QSAM)へ入出力する場面が多々ある。

ここで問題になるのが、「編集済み項目(Edited Item)」と「計算用項目(Coded Arithmetic Item)」の暗黙の型変換(アサインメント)だ。

罠:入力時のアンエディティング(Unediting)

ファイルから `12345.67CR` という文字データが読み込まれ、それを計算用の変数(例: `DCL WK_AMT DECIMAL FIXED(11,2);`)に代入する場合、PL/Iコンパイラは自動的に文字列を解析し、末尾の `CR` を検知して、内部的に負の数値(`-12345.67`)へと変換(アンエディティング)してくれる。

しかし、もし入力ファイルのレイアウト定義が間違っていて、スペースのパディング位置がズレていたり、予期せぬ文字(例えば小文字の `cr` や、全角スペース、あるいはゴミデータ)が含まれていた場合、コンパイラやランタイムは CONVERSION エラー(IBM製メインフレームのABENDコードで言えば S0C7 や IBM0141 などの例外) を発生させてバッチを異常終了させる。

夜間バッチの真っ最中に `IBM0141S CONVERSION ERROR` でジョブが落ちたときの絶望感といったら、筆舌に尽くしがたいものがある。だからこそ、入出力時のデータ定義とONユニットによる例外処理の備えが不可欠なのだ。

—

3. 実践!PL/Iコード例:会計金額のフォーマットとONユニット制御

百聞は一見に如かずだ。実際に、VSAMマスターファイルから読み込んだ金額データを、編集付きの出力用レコードに整形し、万が一のデータ破損(コンバージョンエラー)に備えた堅牢なエラーハンドリングを組み込んだサンプルコードを見せてやろう。

このコードは、大文字ベースの標準的なコーディング規約に則り、現場でそのまま使える実用的な構造にしている。

1
/ /
/ プログラム名: ACCT010P /
/ 概要 : 会計金額のCR/DB編集と例外制御のサンプルバッチ /
/ /
ACCT010P: PROC OPTIONS(MAIN);

/ — 入力ファイル定義(VSAM KSDSを想定) — /
DCL 1 IN_REC,
5 IN_ACCT_ID CHAR(8), / 口座番号 /
5 IN_RAW_AMT CHAR(13); / 生の金額データ /

/ — 出力用レコード定義 — /
DCL 1 OUT_REC,
5 OUT_ACCT_ID CHAR(8),
5 OUT_DSP_AMT CHAR(16); / 編集済み金額(CR付き) /

/ — 計算用変数 — /
DCL WK_AMOUNT DECIMAL FIXED(11,2) INIT(0);

/ — フラグ・カウンタ — /
DCL EOF_FLAG CHAR(1) INIT(‘OFF’);

/ — ファイル宣言 — /
DCL ACCT_VSAM FILE RECORD SEQUENTIAL INPUT;
DCL RPT_FILE FILE STREAM OUTPUT;

/ — ファイルオープン — /
OPEN FILE(ACCT_VSAM) INPUT,
FILE(RPT_FILE) OUTPUT;

/ ========================================================= /
/ ONユニットによるコンバージョンエラー(データ異常)の捕捉 /
/ ========================================================= /
ON CONVERSION
BEGIN;
DISPLAY(‘【警告】数値変換エラーを検知しました。口座ID: ‘ || IN_ACCT_ID);
DISPLAY(‘ 該当不正データ: [‘ || IN_RAW_AMT || ‘]’);
/ 異常データを強制的にゼロとして処理を継続させる場合などのリカバリ記述 /
WK_AMOUNT = 0;
GOTO ERROR_RECOVERY;
END;

/ — メイン処理ループ — /
DO WHILE (EOF_FLAG = ‘OFF’);

READ FILE(ACCT_VSAM) INTO(IN_REC);
IF ENDFILE(ACCT_VSAM) THEN
EOF_FLAG = ‘ON’;
ELSE
DO;
/ 1. 入力文字データを演算用数値へ変換(ここで暗黙のアンエディティング評価) /
WK_AMOUNT = IN_RAW_AMT;

ERROR_RECOVERY:

/ 2. 出力用にPICTURE編集を適用(負数の場合は自動的にCRが付与される) /
/ SZZZ,ZZZ,ZZ9.99CR は、符号つき、先行ゼロをブランクに、CRサフィックスを持つ /
PUT STRING(OUT_DSP_AMT) EDIT (WK_AMOUNT) (SZZZ,ZZZ,ZZ9.99CR);

/ 3. 編集結果をレポートファイルに出力 /
PUT FILE(RPT_FILE) EDIT (OUT_ACCT_ID, ‘ ‘, OUT_DSP_AMT)
(A(8), A(1), A(16));
PUT FILE(RPT_FILE) SKIP;

END;

END;

/ — クローズ処理 — /
CLOSE FILE(ACCT_VSAM),
FILE(RPT_FILE);

DISPLAY(‘正常終了しました。ACCT010P’);
RETURN;

END ACCT010P;

—

4. ベテランからのデバッグのコツとアドバイス

このコードを見て、お前はただ「動くコードだな」と思うだけで終わっちゃいかん。現場のプロなら、以下のポイントに目を光らせるべきだ。

1. PICTUREの桁数あふれ(Overflow)に気をつけろ
`SZZZ,ZZZ,ZZ9.99CR` を指定しているが、データが想定以上に大きくなった場合、PICTUREの許容桁数を超えると、コンパイラや実行時環境によってはアスタリスク (“) が出力されるか、高位桁が切り捨てられる。数値の最大桁数(この場合は整数部9桁、小数部2桁)と、サフィックスの `CR`(2バイト分)の合計長が、出力先領域の長さにしっかりと収まっているか、データレイアウト(DCL文)を電卓叩いて必ず検証しろ。

2. ON CONVERSION のスコープを意識しろ
サンプルに入れた `ON CONVERSION` ユニットは、このブロック内、あるいはブロックを抜けるまでの有効範囲で発生した数値変換の不整合をキャッチする。実務の巨大なバッチプログラムでは、どのファイルのどの項目でエラーが起きたかを正確に特定するため、ファイルの読み込み直前や変換処理の直近に局所的なONユニットを配置するのが、デバッグを早く終わらせるための極意だ。

3. DBとCRの使い分けの基準
社内のコーディング標準や、接続する外向きのインターフェース仕様書(IF定義書)に必ず「CRを使用するのか、DBを使用するのか」が明記されているはずだ。開発環境のテストデータを作る際、正の値だけでなく、必ず「マイナス極大値」「マイナス極小値」「ゼロ」「正確に1円のマイナス」の境界値テストケースを網羅して、CR/DBの出力が仕様通りになるかをインスペクションしなさい。

—

おわりに

PL/IのPICTURE編集文字における `CR` と `DB` は、地味ながらも日本の金融・会計システムの歴史を支えてきたいぶし銀の機能だ。
「古い構文だから適当でいいや」なんて思っていると、監査法人のチェックが入るような重要な財務諸表出力で思わぬスペースズレや符号落ちを引き起こし、夜中に青い顔をしてホストのログを漁るハメになる。

仕様の本質を理解し、コンパイラの挙動を手の内に入れれば、PL/Iほど信頼性が高く、堅牢な記述ができる言語は他にない。
今日のこの話をしっかりと腹に落とし込んで、次の設計やコードレビューに活かしてくれ。期待しているぞ。

タイトルとURLをコピーしました