フリー・フォーマット RPG で対話型アプリケーション (顧客マスターメインテナンス)

メインメニューから F5 キーを押したことで呼び出される処理は、顧客データのメインテナンス処理 (表示/変更/追加/削除) です。

画面イメージはこちらにあります。


画面の定義

まず、画面ファイルの定義です。

     A*****************************************************************
     A* ファイル名: MNTMENU                                           *
     A* 関連プログラム: CUSMNT                                        *
     A* 関連ファイル: CUSMSTL1 (論理ファイル)                         *
     A* 説明: これは表示装置ファイルMNTMENU です。                    *
     A*       3 つのレコード様式があります                            *
     A*****************************************************************
     A                                      REF(CUSMSTL1)
     A                                      CHGINPDFT(CS)
     A                                      PRINT(QSYSPRT)
     A                                      INDARA
     A          R HDRSCN
     A                                      TEXT('PROMPT FOR CUST NUMBER')
     A                                      CA03(03 'END MAINTENANCE')
     A                                      CF05(05 'ADD MODE')
     A                                      CF06(06 'UPDATE MODE')
     A                                      CF07(07 'DELETE MODE')
     A                                      CF08(08 'DISPLAY MODE')
     A            MODE           8A  O  1  4DSPATR(HI)
     A                                  1 13'MODE'
     A                                      DSPATR(HI)
     A                                  2  4TIME
     A                                      DSPATR(HI)
     A                                  2 28'CUSTOMER FILE MAINTENANCE'
     A                                      DSPATR(HI RI)
     A                                  2 70DATE
     A                                      EDTCDE(Y)
     A                                      DSPATR(HI)
     A            CUST      R     Y  I 10 25DSPATR(CS)
     A                                      CHECK(RZ)
     A  51                                  ERRMSG('CUSTOMER ALREADY ON +
     A                                      FILE' 51)
     A  52                                  ERRMSG('CUSTOMER NOT ON FILE' +
     A                                      52)
     A                                 10 33'<--Enter Customer Number'
     A                                      DSPATR(HI)
     A                                 23  4'F3 End Job'
     A                                 23 21'F5 Add'
     A                                 23 34'F6 Update'
     A                                 23 50'F7 Delete'
     A                                 23 66'F8 Display'
     A          R CSTINQ
     A                                      TEXT('DISPLAY CUST INFO')
     A                                      CA12(12 'PREVIOUS SCREEN')
     A            MODE           8A  O  1  4DSPATR(HI)
     A                                  1 13'MODE'
     A                                      DSPATR(HI)
     A                                  2  4TIME
     A                                      DSPATR(HI)
     A                                  2 28'CUSTOMER FILE MAINTENANCE'
     A                                      DSPATR(HI)
     A                                      DSPATR(RI)
     A                                  2 70DATE
     A                                      EDTCDE(Y)
     A                                      DSPATR(HI)
     A                                  4 14'Customer:'
     A                                      DSPATR(HI)
     A                                      DSPATR(UL)
     A            CUST      R        O  4 25DSPATR(HI)
     A            NAME      R        B  6 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ADDR1     R        B  7 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ADDR2     R        B  8 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            CITY      R        B  9 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            STATE     R        B 10 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ZIP       R        B 10 40DSPATR(CS)
     A                                      EDTCDE(Z)
     A  04                                  DSPATR(PR)
     A                                 23  2'F12 Cancel'
     A            MODE1          8   O 23 13
     A          R CSTBLD                    TEXT('ADD CUST RECORD')
     A                                      CA12(12 'PREVIOUS SCREEN')
     A            MODE           8   O  1  4DSPATR(HI)
     A                                  1 13'MODE' DSPATR(HI)
     A                                  2  4TIME
     A                                      DSPATR(HI)
     A                                  2 28'CUSTOMER FILE MAINTENANCE'
     A                                      DSPATR(HI RI)
     A                                  2 70DATE
     A                                      EDTCDE(Y)
     A                                      DSPATR(HI)
     A                                  4 14'Customer:' DSPATR(HI UL)
     A            CUST      R        O  4 25DSPATR(HI)
     A                                  6 20'Name' DSPATR(HI)
     A            NAME      R        I  6 25
     A                                  7 17'Address' DSPATR(HI)
     A            ADDR1     R        I  7 25
     A                                  8 17'Address' DSPATR(HI)
     A            ADDR2     R        I  8 25
     A                                  9 20'City' DSPATR(HI)
     A            CITY      R        I  9 25
     A                                 10 19'State' DSPATR(HI)
     A            STATE     R        I 10 25
     A                                 10 36'Zip' DSPATR(HI)
     A            ZIP       R     Y  I 10 40
     A                                 23  2'F12 Cancel Addition'

キー順で顧客テーブルをアクセスするためのビュー

顧客テーブルを顧客番号順にアクセスするためのビュー定義です。

まだ世の中で SQL がそれほどメジャーでなかった頃、つまり RDB の標準的なインターフェイスがまだなかった頃、System i の前身である S/38 というシステムではテーブルを物理ファイル、ビューを論理ファイルと呼び、↓のような定義を用いて記述していました。

これは論理ファイルの定義で、PFILE(CUSTOMER) はビューの基底となるテーブルの指定、K CUST というのは CUST というカラムをキーとするという指示、その他はビューとして見せるカラムを指定しています。

     A*****************************************************************
     A* ファイル名: CUSMSTL1                                          *
     A* 関連プログラム: CUSMNT                                        *
     A* 関連ファイル: CUSTOMER (物理ファイル)                         *
     A* 説明: これは論理ファイルCUSMSTL1 です。これには               *
     A*       1 つのレコード様式CMLREC1 があります。                  *
     A*       これは得意先マスター・ファイル(CUSMST) の               *
     A*       得意先番号(CUST) による論理ビューです。                 *
     A*****************************************************************
     A          R CMLREC1                   PFILE(CUSTOMER)
     A            CUST
     A            NAME
     A            ADDR1
     A            ADDR2
     A            CITY
     A            STATE
     A            ZIP
     A          K CUST

プログラム

      //****************************************************************
      // プログラム名: CUSMNT                                          *
      // 関連ファイル: CUSMSTL1 (LF)                                   *
      //               MNTMENU (DSPF)                                  *
      // 説明: このプログラムは、WORKSTN ファイルを使用した            *
      //       得意先マスター・ファイル維持プログラムです。            *
      //       このプログラムでユーザーは、得意先レコードを            *
      //       追加、更新、削除、表示できます。                        *
      //        PF3 を使用してプログラムを終了します。                 *
      //****************************************************************

     Fcusmstl1  uf a e           K DISK
     Fmntmenu   cf   e             workstn indds(indicators)

      // プロトタイプ定義:
     D AddCustomer     PR
     D UpdateCustomer  PR
     D DeleteCustomer  PR
     D ShowCustomer    PR
     D SetMode         PR
     D  mode                          8a

      // フィールド定義:
     D indicators      DS
     D exitKey                         N   overlay(indicators:3)
     D disableInput                    n   overlay(indicators:4)
     D addKey                          n   overlay(indicators:5)
     D updateKey                       n   overlay(indicators:6)
     D deleteKey                       n   overlay(indicators:7)
     D displayKey                      n   overlay(indicators:8)
     D prevKey                         n   overlay(indicators:12)
     D custExists                      n   overlay(indicators:51)
     D custNotFound                    n   overlay(indicators:52)

      //*****************************************************************
      // メインライン                                                   *
      //*****************************************************************
      /free

       mode = 'DISPLAY';
       exfmt hdrscn;

       // 終了キーが押されるまでループする
       dow not exitKey;
          SetMode();

          if cust <> 0;
             if mode = 'ADD';
                AddCustomer();
             elseif mode = 'UPDATE';
                UpdateCustomer();
             elseif mode = 'DELETE';
                DeleteCustomer();
             elseif mode = 'DISPLAY';
                ShowCustomer();
             endif;
          endif;

          exfmt hdrscn;
          custExists = *off; // エラー・メッセージをオフにする
          custNotFound = *off;

       enddo;

       *inlr = *on;

      /end-free

       //****************************************************************
       // プロシージャ- AddCustomer                                     *
       // 目的- 新しい得意先をファイルに追加する                        *
       //****************************************************************
     P AddCustomer     B
     D AddCustomer     PI
      /free

          // 得意先番号は既にファイルにあるか?
          chain (cust) cmlrec1;
          if %found(cusmstl1);
             // 既に使用されている得意先番号の場合
             custExists = *on;
             return;
          endif;

          // 新しい得意先データの初期化
          custExists = *off; // エラー・メッセージをオフにする
          custNotFound = *off;
          name = *blank;
          addr1 = *blank;
          addr2 = *blank;
          city = *blank;
          state = *blank;
          zip = 0;

          // この得意先レコードの更新データを入れるためのプロンプトを出す
          exfmt cstbld;

          // よければ、得意先を得意先ファイルに追加する
          if not *in12;
             write cmlrec1;
          endif;

      /end-free
     P AddCustomer     E

       //****************************************************************
       // プロシージャ- UpdateCustomer                                  *
       // 目的- 得意先マスター・レコードを更新する                      *
       //****************************************************************
     P UpdateCustomer  B
     D UpdateCustomer  PI
      /free

          // 得意先番号の探索
          chain (cust) cmlrec1;
          if not %found(cusmstl1);
             // 得意先がファイルにない
             custNotFound = *on;
             return;
          endif;

          // この得意先の情報を表示する
          disableInput = *off;
          exfmt cstinq;

          if not prevKey;
             // ファイルの中の情報を更新する
             update cmlrec1;
          else;
             // 更新したくない場合でも、少なくとも
             // そのレコードのアンロックは行なう
             unlock cusmstl1;
          endif;

      /end-free
     P UpdateCustomer  E

       //****************************************************************
       // プロシージャ- DeleteCustomer                                  *
       // 目的- 得意先マスター・レコードを削除する                      *
       //****************************************************************
     P DeleteCustomer  B
     D DeleteCustomer  PR
      /free

          // 得意先番号の探索
          chain (cust) cmlrec1;
          if not %found(cusmstl1);
             // 得意先がファイルにない
             custNotFound = *on;
             return;
          endif;

          // この得意先の情報を表示する
          disableInput = *on;
          exfmt cstinq;

          if not prevKey;
             // 得意先レコードの削除
             delete cmlrec1;
          else;
             // 削除したくない場合でも、少なくとも
             // そのレコードのアンロックは行なう
             unlock cusmstl1;
          endif;

      /end-free
     P DeleteCustomer  E

       //****************************************************************
       // プロシージャ- ShowCustomer                                    *
       // 目的- 得意先マスター・レコードを表示する                      *
       //****************************************************************
     P ShowCustomer    B
     D ShowCustomer    PI
      /free

          // 得意先番号の探索
          chain(n) (cust) cmlrec1; // レコードをロックしない
          if not %found(cusmstl1);
             // 得意先がファイルにない
             custNotFound = *on;
             return;
          endif;

             // この得意先の情報を表示する
             disableInput = *on;
             exfmt cstinq;

      /end-free
     P ShowCustomer    E

       //****************************************************************
       // プロシージャ- SetMode                                         *
       // 目的- 維持モードの設定                                        *
       //****************************************************************
     P SetMode         B
     D SetMode         PI
      /free

          if addKey;
             mode = 'ADD';

          elseif updateKey;
             mode = 'UPDATE';

          elseif deleteKey;
             mode = 'DELETE';

          elseif displayKey;
             mode = 'DISPLAY';

          endif;

      /end-free
     P SetMode         E

画面(インターフェイス)

ユーザーがインターフェイスとして接する画面は 3つあります。

最初に顧客番号を入力する画面がまず 1つ、

該当の画面定義は↓です。

     A          R HDRSCN
     A                                      TEXT('PROMPT FOR CUST NUMBER')
     A                                      CA03(03 'END MAINTENANCE')
     A                                      CF05(05 'ADD MODE')
     A                                      CF06(06 'UPDATE MODE')
     A                                      CF07(07 'DELETE MODE')
     A                                      CF08(08 'DISPLAY MODE')
     A            MODE           8A  O  1  4DSPATR(HI)
     A                                  1 13'MODE'
     A                                      DSPATR(HI)
     A                                  2  4TIME
     A                                      DSPATR(HI)
     A                                  2 28'CUSTOMER FILE MAINTENANCE'
     A                                      DSPATR(HI RI)
     A                                  2 70DATE
     A                                      EDTCDE(Y)
     A                                      DSPATR(HI)
     A            CUST      R     Y  I 10 25DSPATR(CS)
     A                                      CHECK(RZ)
     A  51                                  ERRMSG('CUSTOMER ALREADY ON +
     A                                      FILE' 51)
     A  52                                  ERRMSG('CUSTOMER NOT ON FILE' +
     A                                      52)
     A                                 10 33'<--Enter Customer Number'
     A                                      DSPATR(HI)
     A                                 23  4'F3 End Job'
     A                                 23 21'F5 Add'
     A                                 23 34'F6 Update'
     A                                 23 50'F7 Delete'
     A                                 23 66'F8 Display'

初期画面で左上に表示される"モード"(ファンクションキーで切り替えるようになっています)と入力された顧客番号によって変わりますが、要するにより詳細な表示として出てくる以下のような画面が 2つめ、

該当の画面定義は↓です。

     A          R CSTINQ
     A                                      TEXT('DISPLAY CUST INFO')
     A                                      CA12(12 'PREVIOUS SCREEN')
     A            MODE           8A  O  1  4DSPATR(HI)
     A                                  1 13'MODE'
     A                                      DSPATR(HI)
     A                                  2  4TIME
     A                                      DSPATR(HI)
     A                                  2 28'CUSTOMER FILE MAINTENANCE'
     A                                      DSPATR(HI)
     A                                      DSPATR(RI)
     A                                  2 70DATE
     A                                      EDTCDE(Y)
     A                                      DSPATR(HI)
     A                                  4 14'Customer:'
     A                                      DSPATR(HI)
     A                                      DSPATR(UL)
     A            CUST      R        O  4 25DSPATR(HI)
     A            NAME      R        B  6 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ADDR1     R        B  7 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ADDR2     R        B  8 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            CITY      R        B  9 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            STATE     R        B 10 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ZIP       R        B 10 40DSPATR(CS)
     A                                      EDTCDE(Z)
     A  04                                  DSPATR(PR)
     A                                 23  2'F12 Cancel'
     A            MODE1          8   O 23 13

さらに、初期画面が入力モードの時のみ、以下のように入力できる項目が入力専用フィールドになっていて、さらに該当フィールドが何を指すかのテキストと共に表示される画面が 3つめとしてあります。

該当の画面定義は↓です。

     A          R CSTBLD                    TEXT('ADD CUST RECORD')
     A                                      CA12(12 'PREVIOUS SCREEN')
     A            MODE           8   O  1  4DSPATR(HI)
     A                                  1 13'MODE' DSPATR(HI)
     A                                  2  4TIME
     A                                      DSPATR(HI)
     A                                  2 28'CUSTOMER FILE MAINTENANCE'
     A                                      DSPATR(HI RI)
     A                                  2 70DATE
     A                                      EDTCDE(Y)
     A                                      DSPATR(HI)
     A                                  4 14'Customer:' DSPATR(HI UL)
     A            CUST      R        O  4 25DSPATR(HI)
     A                                  6 20'Name' DSPATR(HI)
     A            NAME      R        I  6 25
     A                                  7 17'Address' DSPATR(HI)
     A            ADDR1     R        I  7 25
     A                                  8 17'Address' DSPATR(HI)
     A            ADDR2     R        I  8 25
     A                                  9 20'City' DSPATR(HI)
     A            CITY      R        I  9 25
     A                                 10 19'State' DSPATR(HI)
     A            STATE     R        I 10 25
     A                                 10 36'Zip' DSPATR(HI)
     A            ZIP       R     Y  I 10 40
     A                                 23  2'F12 Cancel Addition'

メイン・ロジック

まず最初に表示モードにセットして初期画面を出し、そのまま DoW (Do While)ループに入ります。
最初の画面で F3 キーを押してしまえば、そのまま DoW の条件(not exitKey)にあわないのでループ自体に入りません。

       mode = 'DISPLAY';
       exfmt hdrscn;

       dow not exitKey;

受け取った画面ファイルのレコードから、キー情報を受け取って、モードをセットします。

       mode = 'DISPLAY';
       exfmt hdrscn;

       dow not exitKey;
          SetMode();

SetMode サブプロシージャの中身は↓のようなかんじです。
addKey とか updateKey とかいうのは「フリー・フォーマット RPG で対話型アプリケーション (メインメニュー)」の時と同様に RPG の D仕様書に定義されています。

     P SetMode         B
     D SetMode         PI
      /free

          if addKey;
             mode = 'ADD';

          elseif updateKey;
             mode = 'UPDATE';

          elseif deleteKey;
             mode = 'DELETE';

          elseif displayKey;
             mode = 'DISPLAY';

          endif;

      /end-free
     P SetMode         E

で、そのセットされたモードを元に、それに応じたサブプロシージャを呼び出します。
たとえば、入力フィールドである cust に何も入力しないで実行キーを押した場合には cust は "0" なのでそのまま if ブロックを抜けてしまいますし、何かが入力されていれば DoW ループの外の一番最初で 'DISPLAY' がセットされているので ShowCustomer サブプロシージャが呼び出されることになります。

モードに応じた詳細画面は、呼び出されたサブプロシージャの中で表示しています。

       mode = 'DISPLAY';
       exfmt hdrscn;

       dow not exitKey;
          SetMode();

          if cust <> 0;
             if mode = 'ADD';
                AddCustomer();
             elseif mode = 'UPDATE';
                UpdateCustomer();
             elseif mode = 'DELETE';
                DeleteCustomer();
             elseif mode = 'DISPLAY';
                ShowCustomer();
             endif;
          endif;

各処理が終わった後、改めて再度 hdrscn を exfmt してループの最初に戻ります。
hdrscn から受け取った中に F3 キーが押されたという情報があれば exitKey がオンなので、dow not exitKey の条件によってループ終了です。

       mode = 'DISPLAY';
       exfmt hdrscn;

       dow not exitKey;
          SetMode();

          if cust <> 0;
             if mode = 'ADD';
                AddCustomer();
             elseif mode = 'UPDATE';
                UpdateCustomer();
             elseif mode = 'DELETE';
                DeleteCustomer();
             elseif mode = 'DISPLAY';
                ShowCustomer();
             endif;
          endif;

          exfmt hdrscn;
          custExists = *off; // エラー・メッセージをオフにする
          custNotFound = *off;

       enddo;

exfmt 命令の結果から入力が来る、ということは何らかの新規のユーザーアクションが行われたわけです。
新規のユーザーアクションなので、エラー表示用のフラグなどをオフにし直しています。

          custExists = *off; // エラー・メッセージをオフにする
          custNotFound = *off;

サブプロシージャ内の処理

データの表示

個別の処理についてはそれほど難しくないと思いますので、代表して顧客データの表示についてのみ説明しておきたいと思います。

受け取った顧客番号をキーにして顧客ファイルを検索します。

          chain(n) (cust) cmlrec1; // レコードをロックしない

見つからなかった場合、custNotFound フラグをオンにして、このプロシージャから抜けてしまいます。

          if not %found(cusmstl1);
             // 得意先がファイルにない
             custNotFound = *on;
             return;
          endif;

custNotFound フラグ、というのは画面定義上の標識 52 のことを示しています。

     D custNotFound                    n   overlay(indicators:52)

プロシージャを抜けてしまっているので、次に実行されるのは

       exfmt hdrscn;

ですね。
画面定義の中の HDRSCN という部分を表示させる、という命令でもあるわけですが、その HDRSCN の定義の部分に↓のように、標識 52 がオンの時にエラーメッセージを表示させる旨の記述があります。

     A          R HDRSCN
    …
     A  52                                  ERRMSG('CUSTOMER NOT ON FILE' +
     A                                      52)

if ブロックを抜けてきた、ということは顧客情報が見つかった、ということですね。
顧客情報を表示する画面定義 (レコード様式、といいます) を表示します。これで、検索されたテーブルの行のデータが表示されます。(なぜ何にもしなくても表示されるかは後ほど)
また、表示のみなので disableInput フラグをオンにします。

             // この得意先の情報を表示する
             disableInput = *on;
             exfmt cstinq;

この disableInput フラグも、custNotFound フラグと同様の定義になります。

     D disableInput                    n   overlay(indicators:4)

画面定義で表示される該当部分に、該当する標識 (4) がオンの時には PR (プロテクト) という表示属性 (DiSPlay ATtRibute) になる旨の記述があるのがわかりますね。

     A          R CSTINQ
    …
     A            CUST      R        O  4 25DSPATR(HI)
     A            NAME      R        B  6 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ADDR1     R        B  7 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ADDR2     R        B  8 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            CITY      R        B  9 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            STATE     R        B 10 25DSPATR(CS)
     A  04                                  DSPATR(PR)
     A            ZIP       R        B 10 40DSPATR(CS)
     A                                      EDTCDE(Z)
     A  04                                  DSPATR(PR)

また、テーブルのカラム名とまったく同一の画面定義の表示フィールドが定義されているのがわかりますね。
これが chain 命令が成功しただけでなぜデータが表示されるか、の理由です。画面定義で別のフィールド名を使用して、chain 命令の成功後にテーブルのカラムから画面定義のフィールドに代入しても、もちろん OK です。

データの追加

データの追加を行うプロシージャの方が、↑の動きはわかりやすいと思います。

いったん画面フィールドのデータをブランク等で初期設定して表示させ、exfmt 命令の結果としてそのデータ (入力されたものがブランクのままかはわかりませんが) を write 命令でテーブルに対して書き込む、といったことを行っています。

     P AddCustomer     B
     D AddCustomer     PI
      /free

          // 得意先番号は既にファイルにあるか?
          chain (cust) cmlrec1;
          if %found(cusmstl1);
             // 既に使用されている得意先番号の場合
             custExists = *on;
             return;
          endif;

          // 新しい得意先データの初期化
          custExists = *off; // エラー・メッセージをオフにする
          custNotFound = *off;
          name = *blank;
          addr1 = *blank;
          addr2 = *blank;
          city = *blank;
          state = *blank;
          zip = 0;

          // この得意先レコードの更新データを入れるためのプロンプトを出す
          exfmt cstbld;

          // よければ、得意先を得意先ファイルに追加する
          if not *in12;
             write cmlrec1;
          endif;

      /end-free
     P AddCustomer     E

ちなみに if not *in12 というのは実質 if not prevkey という書き方と変わりませんが、これはサンプルプログラムなのでわざとこういうふうにいろんな書き方をしてあるんではないかと思います。

更新や削除については、今までの説明から充分理解できると思いますので割愛します。

[Top Pageに戻る]

Ads by TOK2