前回の復習
「
第七回 データベース – ネイティブ・アクセス(更新、削除プログラム)」では、レコード・レベル・アクセスによるデータベース・レコードの更新、削除および追加について解説をしました。ネイティブ・アクセスと SQL のデータ操作との違いを理解していただけたのではないかと思います。
FFRPG の基本的な書き方、SQL によるデータ処理およびネイティブ・アクセスによるレコード・レベル・アクセスの基本はマスターしていただけたと思いますので、今回はデータベース以外への出力について解説していきます。IBM i のシステムを保守する上で必ず必要になる印刷および画面表示がこの記事のテーマです。ただし、そんなに難しくはありませんのでリラックスして取り組んでください。それでははじめましょう!
RPG の入出力について
第六回と七回で解説済ですが、RPG におけるネイティブ・アクセスはレコード・レベル・アクセスです。一度にアクセス可能なのはレコード単位であり、複数レコードを同時に処理する命令はありません。前二回の記事では、外部のファイル(テーブル)から1レコードを取得し、該当するプログラム変数(データ構造)に値をセットしました。これを入力といいます。通常プログラムは外部から情報を入力し、処理した結果をプログラムを出力します。

これまでのプログラムでは出力はすべて dsply という命令でジョブ・ログに出力していましたが、お世辞にも見やすいとは言えないものでしたね。dsply はプログラムを作成している過程において、内部処理の結果が正しいかどうかを簡単に確認する方法として利用されることが多く、業務で使用する完成したプログラムの出力方法として使用されることはほとんどありません。
ファイルからのデータの入力については解説済なので、今回はデータの出力の仕組みと RPG でのコーディング方法について説明します。出力する先は印刷データと画面表示です。dsply 命令も画面表示の一種ですが、今回はそれとは別の方法を学びましょう。
ファイルについて
ここで一旦ファイルについて整理しておきます。これまで使用してきたファイルはデータベース・ファイル(テーブル)ですが、これには2つの特徴があります。
- レコードの形が定義されている
- その形に名前が付いている
プログラムはこのレコード単位で入出力を行います。データベースからのレコードの入力には READ や CHAIN 命令を使い、レコードの出力(追加や更新)には WRITE や UPDATE 命令を使いましたね。レコードの出力時にはレコード様式名を指定しましたが、これはどの形のレコードを出力するのかを明示的に指定しているということです(ただし、物理ファイル(テーブル)にはレコード様式はひとつしか存在しません)。
では RPG 内での計算結果を印刷したり画面に表示するにはどうすれば良いのでしょうか。まず最初に、印刷について解説します。
IBM i には印刷する基本的な仕組みとしてスプール処理が使用されます。これは出力待ち行列というオブジェクト内に、一旦印刷データをスプール・ファイルとして保存しておき、必要に応じてライターと呼ばれるシステム・プログラムが実際のプリンターに印刷データを送って印刷するという仕組みです。

この仕組のおかげで、RPG プログラムはプリンターの制御を直接行うことなく、スプール・データの生成だけを行えば良いことになります。このスプール・データ作成に使用されるオブジェクトを印刷装置ファイルといいます。RPG プログラムは印刷装置ファイルに出力することにより、結果的にスプール・データが生成されます。
印刷装置ファイルも「ファイル」ですから、データベース・ファイル同様の特徴があります。
- レコードの形が定義されている
- その形に名前が付いている
ただし、目的はあくまでも印刷です。以下のような印刷イメージを想像してください。

印刷の「形」が3通りありますね。①は各ページの「見出し」、②は印刷する項目(フィールド)の説明、③は得意先マスターのレコードに含まれるフィールドの値です。このように印刷装置ファイルには複数の「形」を定義することができ、その単位(レコード様式名で識別)でプログラムから出力します。出力する命令はデータベース・ファイルの出力と同じ WRITE 命令を使用します。同じ命令でも出力対象ファイルの種類により、レコードが追加されたりスプール・データが生成されたりするわけです。
印刷の形には、どういった項目(印刷する文字や変数など)を含むのかという情報の他に、何行目の何桁目に印刷するのか、印刷する行間をどれだけ空けるか(③)なども指定します。この情報はすべてファイル内に定義されており、プログラムで指定することはありません。
上記の印刷イメージの各レコードには、それぞれ以下のような情報が含まれています。
①(ヘッダー1)
- 各ページの2行目に印刷する
- タイトル「*** 得意先情報一覧 ***」という文字を xx 桁目から印刷する
- 印刷プログラムが実行された日付と時刻をタイトルの右側 xx 桁目にそれぞれ印刷する
②(ヘッダー2)
③(明細行)
- データベース・ファイル(テーブル)のレコード毎に一行印刷する
- 各明細毎に行を変えて印刷する
印刷装置ファイルはプログラムとは別のオブジェクトなので、プログラム作成前に別途作成しなければなりません。今回の記事では詳細は説明しませんが、ファイルの形を予め決められたフォーマット(DDS)で定義し、その定義を元に印刷装置ファイルを作成(CRTPRTF コマンド)します。RPG プログラムはそのファイルの名前と定義されているレコード様式名がわかれば、印刷プログラムを簡単に作成することが可能です。
画面に出力する場合も、表示する「形」を定義したファイルを同様に作成します。

この画面イメージには2つの「形」があり、それぞれ以下の情報を含んでいます。
①(画面タイトル)
- 画面の2行目に表示する
- タイトル「*** 得意先情報 ***」という文字を xx 桁目に表示する
- 画面が表示された日付と時刻をタイトルの右側 xx 桁目にそれぞれ表示する
②(明細)
- 各フィールドの説明後をそれぞれ xx 行目の xx 桁目に表示する
- データベース・ファイル(テーブル)のフィールドの値を各フィールドの説明の右側 xx 桁目に表示する
印刷装置ファイル同様、上記の「形」をDDS で定義し、表示装置ファイルを作成(CRTDSPF コマンド)します。RPG プログラムはそのファイルを定義し、WRITE 命令を実行することで必要な情報を画面に表示することができるようになります。
ここでファイルの種類とレコードに含まれる情報についてまとめておきましょう。
icafe021 プログラム(データの印刷)
それでは印刷プログラムを作成してみましょう。プログラム内で得意先コード ‘01010’ のレコードを TECSMP ファイルから取得し、その内容を予め決められた形で印刷します。
今回使用するのは以下のオブジェクトです。

印刷装置ファイル icafe021p は以下の「形」で作成済です。

レコード様式名:DETAIL
① CSCSCD:5A:4 桁目から印刷
② CSCSKN:20A:17 桁目から印刷
③ CSCSKJ:20O:42 桁目から印刷
④ CSADR1:20O:65 桁目から印刷
印刷装置ファイルをプログラムで使用するには DCL-F を使用して定義する必要があります。

印刷装置ファイルの定義には、ファイル名に続いて PRINTER を指定してください。印刷装置ファイルは出力しかないので、USAGE キーワードには *OUTPUT を指定します(PRINTER の場合の省略値)。
続いて、印刷装置ファイルに出力する際に使用するデータ構造を定義します。

レコード様式 DETAIL に含まれているフィールドをサブフィールドとした prtCustomer データ構造を定義しています。このデータ構造は出力用途で使用するので *OUTPUT で定義します。
TECSMP からデータを取得するのはすでに以前のプログラムで説明しました。以下のように記述します。

このデータ構造のサブフィールドと、icafe021P 印刷装置ファイルの DETAIL に含まれるサブフィールドは同じなので、CUSTOMER データ構造の値を prtCustomer データ構造にセットし、WRITE 命令で出力します。DETAIL レコードの出力は以下のように記述します。

WRITE 命令直後の DETAIL は印刷装置ファイルに定義されているレコード様式名、次の prtCustomer は印刷データをサブフィールドにセットしたデータ構造です。データ構造のサブフィールドと同名のフィールドに値がセットされ、レコード様式に定義されている印刷位置に値が印刷されます。
それでは icafe021.rpgle を作成してみましょう。

上記プログラムを作成後、実行するとすぐにメニュー画面が表示されます。印刷データはスプール・データとして生成されますので、メニューの6番「スプール・ファイル処理」で確認します。一番最後のファイル名 icafe021P を探し、オプション5で表示します。得意先コード 01010 の情報が以下のように表示されるはずです。

画面に表示しているのは印刷前のスプール・データです。必要に応じて、ライター・プログラムでプリンターに送信して印刷することになります。
出力待ち行列内に多くのスプール・ファイルが存在しており、もう必要ないものについてはオプション 4 で削除しておきましょう。
icafe022 プログラム(データの表示)
それでは次に、情報を表示するプログラムを作成しましょう。icafe021 と同様、得意先コード ‘01010’ のレコードを TECSMP ファイルから取得し、その内容を画面に表示します。
このプログラムでは以下のオブジェクトを使用します。

icafe022d は以下の「形」で作成済です。

レコード様式名:DETAIL
① CSCSCD:5A:5 行目 33 桁目に表示
② CSCSKN:20A:7 行目 33 桁目に表示
③ CSCSKJ:20O:9 行目 33 桁目に表示
④ CSADR1:20O:11 行目 33 桁目に表示
⑤ 上記フィールドの説明文を同行の 10 桁目にそれぞれ表示
表示装置ファイルも DCL-F を使用して定義します。

表示装置ファイルは、ファイル名に続いて WORKSTN と指定します。表示装置は画面に出力すると同時に、ユーザーからの入力およびアクションを受け取らなければならないので、USAGE キーワードには *INPUT と *OUTPUT の指定が必要です(WORKSTN の場合の省略値)。
表示装置ファイルで定義したレコード様式 DETAIL の全フィールドを含むデータ構造を定義します。

icafe021 と同様に TECSMP を読み取った結果の値が含まれている CUSTOMER データ構造の値を dspCustomer データ構造にセットして WRITE することでその内容が画面に表示されます。

ただし、表示装置ファイルに対しては WRITE を実行しただけでは不十分です。WRITE 命令だけではその後の命令もそのまま実行されてしまいます。通常は、ユーザーが画面に表示された内容を確認し、アクション(例えば ENTER キーを押すなど)を実施するまで待機させなければなりません。これは WRITE 直後に同じレコード様式を READ することで実現します。

WRITE の直後に同じレコード様式を READ するのと同様のアクションを同時に行う EXFMT 命令もあります。以下のように記述できます。

画面表示におけるユーザーのアクションは、ENTER キーとその他の機能キー(F1 から F24 キーなど)が主ですが、ENTER キー以外は表示装置ファイル内で明示的に使用するよう定義しなければなりません。今回使用する icafe022d ファイルには機能キーは一切定義していないので、ENTER キーのみが許されている点に注意してください。F3 キーなどを押すとエラーとなり、キーボードがロックします。ロックの解除には左下の Ctrl キー(Windows の場合)を押してください。
それでは icafe022 を作成してみましょう。

上記プログラムを実行すると以下のような画面が表示されます。この情報が表示されている間は EXFMT 命令でプログラムはユーザーのアクションを待機中です。ENTER キーを押すとプログラムが終了してメニューが表示されます。
icafe021 と icafe022 の比較
icafe022 を作成しながら、「ほとんど icafe021 と同じだな」と思われたのではないでしょうか。2つのプログラムは結果の出力が印刷と画面表示というまったく異なる内容であるにもかかわらず、プログラム自体はほとんど同じです。出力先の違いはすべて装置ファイルが吸収し、プログラムは装置ファイルに定義されているレコード様式に対する入出力命令を実行するだけですね。出力形態とその形をプログラムと分離することで、RPG プログラムは入力したデータの処理に集中できるわけです。
表示装置ファイルを使用したプログラムを特に対話型プログラムといいます。このプログラムは 5250 エミュレータで使用するプログラムですが、昔から使用されているデータ入力プログラムだけではなく、色をつけたり Windows と同様のメニューの作成やマウス操作との融合も可能なので、興味のある方は表示装置ファイルの作成などにも挑戦してみましょう。
終わりに
今回は、RPG プログラムからの出力に焦点をあてて解説しました。2 つのプログラムは、プリンターに印刷するか画面に表示するかというまったく異なる処理であるにもかかわらず、プログラム自体はほとんど変わらないことに驚かれたことと思います。出力する「形」はプログラムとは別の装置ファイルに定義しておくことによりプログラム・コードはデータの処理にのみ集中することができるのですね。
印刷装置ファイルおよび表示装置ファイルともに、IBM i の基本機能です。今回は FFRPG でそのファイル・オブジェクトを操作しましたが、RPG Ⅲ 言語などからももちろん扱うことができます。実際に稼働しているプログラムは RPG Ⅲ で作成されているものも多いと思いますので、今回の概念を思い出しながら RPG Ⅲ のプログラムにもぜひ挑戦してみてください。
著者プロフィール
