7.20.3 DEF_ARRAY の使用例

以下は、DEF_ARRAY コマンドの例です。

例1:データ・ディクショナリに、VAL01、VAL02、およびVAL03という、長さ7桁、小数点以下桁数2桁の3つのパック10進数フィールドが保持されています。

これらのフィールドを#VALという1つの配列にグループ化し、この配列をフィールド#IIで索引付けします。

DEF_ARRAY NAME(#VAL) INDEXES(#II) OF_FIELDS(#VAL01 #VAL02 #VAL03)
 

例2:配列#VALを使用して、3つの値をすべて入力するようユーザーに要求し、入力された値がすべて7~42の範囲にあるかどうかを検査します。

DEF_ARRAY NAME(#VAL) INDEXES(#II) OF_FIELDS(#VAL01 #VAL02 #VAL03)
 
REQUEST   FIELDS(#VAL01 #VAL02 #VAL03)
 
BEGINCHECK
    BEGIN_LOOP FROM(1) TO(3) USING(#II)
    RANGECHECK FIELD(#VAL#II) RANGE((7 42))
    END_LOOP
ENDCHECK
 

この例は、データ妥当性検査コマンドVALUECHECK、RANGECHECK、FILECHECK、DATECHECK、CONDCHECK、CALLCHECK、およびSET_ERRORによって、配列項目 (#VAL#II) だけでなく、基となるフィールド#VAL01、#VAL02、または#VAL03 (#IIの現行値によって異なる) に対してもエラーを設定する方法を示しています。

例3:#VALを使用して、ユーザーに3つの値をすべて入力するよう要求し、すべての値を10 %増加させ、その合計をユーザーに表示します。

DEF_ARRAY NAME(#VAL) INDEXES(#II) OF_FIELDS(#VAL01 #VAL02 #VAL03)
REQUEST   FIELDS(#VAL01 #VAL02 #VAL03)
CHANGE  FIELD(#RESULT) TO(0)
BEGIN_LOOP FROM(1) TO(3) USING(#II)
CHANGE  FIELD(#VAL#II) TO('#VAL#II * 1.10')
CHANGE  FIELD(#RESULT) TO('#RESULT + #VAL#II')
END_LOOP
DISPLAY FIELDS(#RESULT)
 

例4:データ・ディクショナリに、#LIBLSTという、長さ50桁の英数字フィールドが保持されています。このフィールドは、実際には、1つの長いフィールドに保管された最大5個のライブラリ名から成る「配列」です。

このフィールド内の個々のライブラリ名を簡単に参照できるよう配列を定義します。

DEF_ARRAY NAME(#LIB) TYPE(*CHAR) TOT_ENTRY(5) ENTRY_LEN(10) INDEXES(#JJ) OVERLAYING(#LIBLST 1)
 

例5:フィールド#LIBLSTをファイルUSERDETから取得し、画面上に5つの個別フィールドとして表示し、妥当性検査を実行して、データベースを更新できるようプログラムを作成します。

DEF_ARRAY NAME(#LIB) TYPE(*CHAR) TOT_ENTRY(5) ENTRY_LEN(10) INDEXES(#JJ) OVERLAYING(#LIBLST 1)
 
DEFINE FIELD(#LIB01) TYPE(*CHAR) LENGTH(10) TO_OVERLAY(#LIBLST 1)
DEFINE FIELD(#LIB02) REFFLD(#LIB01) TO_OVERLAY(#LIBLST 11)
DEFINE FIELD(#LIB03) REFFLD(#LIB01) TO_OVERLAY(#LIBLST 21)
DEFINE FIELD(#LIB04) REFFLD(#LIB01) TO_OVERLAY(#LIBLST 31)
DEFINE FIELD(#LIB05) REFFLD(#LIB01) TO_OVERLAY(#LIBLST 41)
DEFINE FIELD(#LIBWRK) REFFLD(#LIB01)
 
FETCH FIELDS(#LIBLST) FROM_FILE(USERDET) WITH_KEY(*USER)
REQUEST FIELDS(#LIB01 #LIB02 #LIB03 #LIB04 #LIB05)
BEGINCHECK
BEGIN_LOOP FROM(1) TO(5) USING(#JJ)
  IF     COND('#LIB#JJ *NE *BLANKS')
  CHANGE FIELD(#LIBWRK) TO(#LIB#JJ)
  EXEC_OS400 COMMAND('CHKOBJ QSYS/#LIBWRK *LIB') IF_ERROR(L10)
  GOTO L20
  L10:  SET_ERROR FOR_FIELD(#LIB#JJ)
  L20:  ENDIF
END_LOOP
ENDCHECK
UPDATE FIELDS(#LIBLST) IN_FILE(USERDET)
 

この例から分かるように、ファイルUSERDET内のフィールド#LIBLSTが#LIB01~#LIB05の5つのフィールドとしてそのファイル内に定義されていれば、プログラムのコードは少なくて済みます。

また、EXEC_OS400が、索引によるフィールド参照を行えない数少ないコマンドの1つであることから、作業フィールド#LIBWRKが必要になります。

例6:フィールド#LIBLSTをファイルUSERDETから取得し、レポート上に1つの列として印刷できるようプログラムを作成します。

DEF_ARRAY NAME(#LIB) TYPE(*CHAR) TOT_ENTRY(5) ENTRY_LEN(10) INDEXES(#JJ) OVERLAYING(#LIBLST 1)
 
OVERRIDE  FIELD(#LIB#JJ) COLHDG('Library' 'Names')
 
DEF_LINE  NAME(#LINE01) FIELDS(#LIB#JJ)
 
FETCH FIELDS(#LIBLST) FROM_FILE(USERDET) WITH_KEY(*USER)
 
BEGIN_LOOP FROM(1) TO(5) USING(#JJ)
      IF  COND('#LIB#JJ *NE *BLANKS')
      PRINT  LINE(#LINE01)
      ENDIF
END_LOOP
ENDPRINT
 

例7:SALESファイルにSALDATAというフィールドがあります。このフィールドは、MONTHS (12*CHAR(2)の配列)と、EXPECTED SALESおよびACTUAL SALES (それぞれ個別の12*DEC(7,2)の10進数配列)で構成されています。

この大きなフィールドに埋め込まれた3つの配列のコンポーネントを索引によって参照できる配列を定義します。

DEF_ARRAY NAME(#MTH) TYPE(*CHAR) TOT_ENTRY(12) ENTRY_LEN(2) INDEXES(#II) OVERLAYING(#SALDATA 1)
DEF_ARRAY NAME(#EXP) TYPE(*DEC) TOT_ENTRY(12) ENTRY_LEN(7) ENTRY_DEC(2) INDEXES(#II) OVERLAYING(#SALDATA 25)
DEF_ARRAY NAME(#ACT) TYPE(*DEC) TOT_ENTRY(12) ENTRY_LEN(7) ENTRY_DEC(2) INDEXES(#II) OVERLAYING(#SALDATA 73)
 

例8:例7のファイルを使用して、ファイルのすべてのレコードを列として印刷し、総計を算出します。

DEF_ARRAY NAME(#MTH) TYPE(*CHAR) TOT_ENTRY(12) ENTRY_LEN(2) INDEXES(#II) OVERLAYING(#SALDATA 1)
OVERRIDE  FIELD(#MTH#II) COLHDG('Month')
DEF_ARRAY NAME(#EXP) TYPE(*DEC) TOT_ENTRY(12) ENTRY_LEN(7) ENTRY_DEC(2) INDEXES(#II) OVERLAYING(#SALDATA 25)
OVERRIDE  FIELD(#EXP#II) COLHDG('Expected' 'Sales') EDIT_CODE(3)
DEF_ARRAY NAME(#ACT) TYPE(*DEC) TOT_ENTRY(12) ENTRY_LEN(7) ENTRY_DEC(2) INDEXES(#II) OVERLAYING(#SALDATA 73)
OVERRIDE  FIELD(#ACT#II) COLHDG('Actual' 'Sales') EDIT_CODE(3)
DEF_LINE  NAME(#SALES) FIELDS(#MTH#II #EXP#II #ACT#II)
DEFINE    FIELD(#EXP_TOT) REFFLD(#EXP#II) LABEL('Total Expected')
DEFINE    FIELD(#ACT_TOT) REFFLD(#ACT#II) LABEL('Total Actual')
DEF_BREAK NAME(#TOTAL) FIELDS(#EXP_TOT #ACT_TOT)
SELECT  FIELDS(#SALDATA) FROM_FILE(SALES)
    BEGIN_LOOP FROM(1) TO(12) USING(#II)
    KEEP_TOTAL OF_FIELD(#EXP#II) IN_FIELD(#EXP_TOT)
    KEEP_TOTAL OF_FIELD(#ACT#II) IN_FIELD(#ACT_TOT)
    PRINT LINE(#SALES)
    END_LOOP
ENDSELECT
ENDPRINT  
* 自動的に総計行を印刷