Page History
[ |../../index.htm#lansa/def_list_e.htm]
現在地:
...
7.26.4 DEF_LIST の使用例
例1:注文の明細をすべて表示するRDMLプログラムを作成します。 例1:注文の明細をすべて表示するRDMLプログラムを作成します。
必要な明細行リストを名前#ORDERLINEで定義し、注文頭書きファイルの必要なフィールドを名前#ORDERHEADでグループ化します。
| Code Block |
|---|
DEF_ |
...
LIST NAME(#ORDERLINE) |
...
FIELDS(#ORDLIN #PRODUCT #QUANTITY #PRICE) GROUP_BY NAME(#ORDERHEAD) |
...
FIELDS(#ORDNUM #CUSTNUM #DATEDUE) |
ユーザーに注文番号を入力するよう要求し、リスト内のすべての項目をクリアして表示モードに設定します。
| Code Block |
|---|
L1: |
...
REQUEST FIELDS(#ORDNUM) |
...
SET_MODE TO(*DISPLAY) |
...
CLR_LIST NAMED(#ORDERLINE) |
...
必要なフィールドをORDHDRファイルから取得します。見つからなかった場合は、自動エラー・メッセージと共にREQUESTコマンドに戻ります。 FETCH FIELDS
| Code Block |
|---|
FETCH FIELDS(#ORDERHEAD) |
...
FROM_FILE(ORDHDR) |
...
WITH_KEY(#ORDNUM) |
...
NOT_FOUND(L1) |
...
ISSUE_MSG(*YES) |
...
ORDLINファイルから必要なフィールドを選択します。選択したレコードごとに、新しい項目を#ORDERLINEという名前のリストに追加します。
| Code Block |
|---|
...
SELECT FIELDS(#ORDERLINE) |
...
FROM_FILE(ORDLIN) |
...
WITH_KEY(#ORDNUM) ADD_ |
...
ENTRY TO_LIST(#ORDERLINE) ENDSELECT |
...
最後に、注文のヘッダー・フィールドと明細行の詳細をユーザーに表示します。
| Code Block |
|---|
...
DISPLAY FIELDS(#ORDERHEAD) |
...
BROWSELIST(#ORDERLINE) |
...
LANSAがこのRDMLプログラム用に自動的に設計する画面形式は以下のようになります。
REQUEST FIELDS(#ORDNUM)コマンドの場合:
|
注文番号 : |
______________ |
DISPLAY FIELDS(#ORDERHEAD) BROWSELIST(#ORDERLINE)コマンドの場合:
|
例2:上記の例で使用したRDMプログラムを変更し、PROMST 例2:上記の例で使用したRDMプログラムを変更し、PROMST (製品マスター)ファイルのフィールド#PDESC (製品の説明)をリストに含めます。
リスト定義に#PDESCを含めます。
| No Format |
|---|
DEF_ |
...
LIST NAME(#ORDERLINE) |
...
FIELDS(#ORDLIN #PRODUCT #PDESC #QUANTITY #PRICE) GROUP_BY NAME(#ORDERHEAD) |
...
FIELDS(#ORDNUM #CUSTNUM #DATEDUE) L1: REQUEST FIELDS(#ORDNUM) |
...
SET_MODE TO(*DISPLAY) |
...
CLR_LIST NAMED(#ORDERLINE) |
...
FETCH FIELDS(#ORDERHEAD) |
...
FROM_FILE(ORDHDR) |
...
WITH_KEY(#ORDNUM) |
...
NOT_FOUND(L1) |
...
ISSUE_MSG(*YES) |
...
ORDLINファイルから必要なフィールドを選択します。選択したレコードごとに、関連付けられた製品の説明を取得し、新しい項目を#ORDERLINEというリストに追加します。
| Code Block |
|---|
...
SELECT FIELDS(#ORDERLINE) |
...
FROM_FILE(ORDLIN) |
...
WITH_KEY(#ORDNUM) |
...
FETCH FIELDS(#PDESC) |
...
FROM_FILE(PROMST) |
...
WITH_KEY(#PRODUCT) ADD_ |
...
ENTRY TO_LIST(#ORDERLINE) |
...
ENDSELECT DISPLAY FIELDS(#ORDERHEAD) |
...
BROWSELIST(#ORDERLINE) |
...
LANSAがこの変更後のRDMLプログラム用に自動的に設計する画面形式は以下のようになります。
REQUEST FIELDS(#ORDNUM)コマンドの場合:
|
DISPLAY FIELDS(#ORDERHEAD) BROWSELIST(#ORDERLINE)コマンドの場合:
|
例3:姓例3:姓(すべてまたは一部)を入力するようユーザーに要求し、指定された値で名前が始まるすべての社員のリストを表示する、以下の単純なRDMLプログラムについて考えます。
| Code Block | ||
|---|---|---|
| ||
******** |
...
Define work variables and browse the list to be used DEFINE FIELD(#L1COUNT) |
...
TYPE(*DEC) |
...
LENGTH(7) |
...
DECIMALS(0) DEF_ |
...
LIST NAME(#L1) |
...
FIELDS((#SURNAME) |
...
(#GIVENAME) |
...
(#EMPNO) |
...
(#ADDRESS1)) |
...
COUNTER(#L1COUNT) ******** |
...
Loop until terminated by EXIT or CANCEL BEGIN_LOOP ******** |
...
Get surname to search for REQUEST FIELDS(#SURNAME) ******** |
...
Build list of generically identical names CLR_LIST NAMED(#L1) |
...
SELECT FIELDS(#L1) |
...
FROM_FILE(PSLMST2) |
...
WITH_KEY(#SURNAME) |
...
GENERIC(*YES) ADD_ |
...
ENTRY TO_LIST(#L1) ENDSELECT ******** |
...
If names found, display list to user IF COND('#L1COUNT *GT 0') DISPLAY BROWSELIST(#L1) ******** |
...
else issue error indicating none found ELSE MESSAGE MSGTXT('No employees have a surname matching request') ENDIF ******** |
...
Loop back and request next name to search for END_LOOP |
...
機能的にはこれで充分ですが、例えば検索キーとして「D」を指定し、これに合致する従業員が800人いたとすればどうなるでしょうか。 この場合、800行ものリストが表示されることになってしまい、ユーザーにとって見にくい上に、相当の時間とコンピュータ資源を要します。
この場合、800行ものリストが表示されることになってしまい、ユーザーにとって見にくい上に、相当の時間とコンピュータ資源を要します。
これを解消するため、所定の行数ごとにページで区切って表示する方法がよく使われます。すなわち、条件に合致するレコードを「1ページ分」だけ検索し、これを表示するという方法です。次のページに進むためのキーが押されれば、改めてレコードを検索し、表示することになります。
このプログラムに「ページ単位」技法を実装するには、以下のように変更します。
挿入もしくは変更されたコマンドは赤で示されています。
| Panel |
|---|
| ******** Define work variables and browse list to be used DEFINE FIELD(#L1COUNT) TYPE(*DEC) LENGTH(7) DECIMALS(0) DEFINE FIELD(#L1PAGE) TYPE(*DEC) LENGTH(7) DECIMALS(0) DEFINE FIELD(#L1TOP) TYPE(*DEC) LENGTH(7) DECIMALS(0) DEFINE FIELD(#L1POS) TYPE(*CHAR) LENGTH(7) DEF_LIST NAME(#L1) FIELDS((#SURNAME) (#GIVENAME) (#EMPNO) (#ADDRESS1)) COUNTER(#L1COUNT) PAGE_SIZE(#L1PAGE) TOP_ENTRY(#L1TOP) SCROLL_TXT(#L1POS) ******** Loop until teminated by EXIT or CANCEL BEGIN_LOOP ******** Get surname to search for REQUEST FIELDS(#SURNAME) ******** Build list of generically identical names CLR_LIST NAMED(#L1) CHANGE FIELD(#IO$KEY) TO(UP) CHANGE FIELD(#L1TOP) TO(1) SELECT FIELDS(#L1) FROM_FILE(PSLMST2) WITH_KEY(#SURNAME) GENERIC(*YES) WHERE('#IO$KEY = UP') OPTIONS(*ENDWHERE) EXECUTE SUBROUTINE(DISPLAY) WITH_PARMS('''More...''') ADD_ENTRY TO_LIST(#L1) ENDSELECT ******** If names found, display list to user IF COND('#L1COUNT *GT 0') EXECUTE SUBROUTINE(DISPLAY) WITH_PARMS('''Bottom''') ******** else issue error indicating none found ELSE MESSAGE MSGTXT('No employees have a surname matching request') ENDIF ******** Loop back and request next name to search for END_LOOP ******** ******** Display names if the page is full or the list is complete ******** SUBROUTINE NAME(DISPLAY) PARMS(#L1POS) |
...
| DEFINE FIELD(#L1REMN) TYPE(*DEC) LENGTH(5) DECIMALS(5) CHANGE FIELD(#L1REMN) TO('#L1COUNT / #L1PAGE') |
...
| IF COND('(#L1COUNT *NE 0) *AND (#IO$KEY = UP) *AND ((#L1POS = ''Bottom'') *OR (#L1REMN *EQ 0.00000))') DOUNTIL COND('(#L1POS *NE ''Bottom'') *OR (#IO$KEY *NE UP)') |
...
| DISPLAY BROWSELIST(#L1) USER_KEYS((*ROLLUP)) |
...
| ENDUNTIL CHANGE FIELD(#L1TOP) TO('#L1TOP + #L1PAGE') ENDIF ENDROUTINE |
この手法は、表示するリストの行数が膨大になりうる状況で一般的に使えるもので、処理性能の向上にも効果があります。
「最初の例」に挙げたような、SELECTとDISPLAYを組み合わせて実装したプログラムは、この手法を取り入れて比較的簡単に最適化できます。プログラム構成や処理の流れにはあまり手を入れず、局所的な修正で対処できることがわかるでしょう。
この手法を実際に組み込むためには、サイトの要求に合致した「標準」アルゴリズムを設計し、充分にテストしておくとよいでしょう。これをテンプレートとして個々のアプリケーションに適用することができます。 例4:TRANSという取引ファイルを印刷します。このファイルには、10
例4:TRANSという取引ファイルを印刷します。このファイルには、10,000個のレコードが保持されています。印刷する取引ごとに、それに関連付けられた州の記述をファイルSTATESから抽出して印刷する必要があります。
この操作を実行する単純なRDMLプログラムは以下のようになります。
| Code Block | ||
|---|---|---|
| ||
GROUP_ |
...
BY NAME(#TRANS) |
...
FIELDS(#TRANNUM #TRANTIME #TRANDATE #TRANTYPE #TRANUSER #TRANSTATE #STATEDES) SELECT FIELDS(#TRANS) |
...
FROM_FILE(TRANS) |
...
FETCH FIELDS(#TRANS) |
...
FROM_FILE(STATES) |
...
WITH_KEY(#TRANSTATE) |
...
UPRINT FIELDS(#TRANS) ENDSELECT |
...
ただし、作業リストを使用すれば、このプログラムを大幅に高速化できます。
| Code Block | ||
|---|---|---|
| ||
GROUP_ |
...
BY NAME(#TRANS) |
...
FIELDS(#TRANNUM #TRANTIME #TRANDATE #TRANTYPE #TRANUSER #TRANSTATE #STATEDES) DEF_LIST NAME(#STATES) |
...
FIELDS(#STATE #STATEDES) TYPE(*WORKING) |
...
ENTRYS(10) |
...
SELECT FIELDS(#STATES) |
...
FROM_FILE(STATE) ADD_ |
...
ENTRY TO_LIST(#STATES) |
...
ENDSELECT SELECT FIELDS(#TRANS) |
...
FROM_FILE(TRANS) LOC_ |
...
ENTRY IN_LIST(#STATES) |
...
WHERE(' |
...
#STATE = |
...
#TRANSTATE') |
...
UPRINT FIELDS(#TRANS) ENDSELECT |
...
州が10個ある場合、この印刷プログラムでは、最初のバージョンよりもデータベース・アクセスが9,990回少なくなります。
以下のように、FETCHコマンドのKEEP_LASTパラメータを使用することにより、さらに簡単な方法でまったく同じようにパフォーマンスを高めることができます。
| Code Block | ||
|---|---|---|
| ||
GROUP_ |
...
BY NAME(#TRANS) |
...
FIELDS(#TRANNUM #TRANTIME #TRANDATE #TRANTYPE #TRANUSER #TRANSTATE #STATEDES) SELECT FIELDS(#TRANS) |
...
FROM_FILE(TRANS) |
...
FETCH FIELDS(#TRANS) |
...
FROM_FILE(STATES) |
...
WITH_KEY(#TRANSTATE) |
...
KEEP_LAST(10) |
...
UPRINT FIELDS(#TRANS) |
...
ENDSELECT |