IBM i (旧AS400）の自己学習メモ　RPG Ⅳプログラミング編０５　登録・更新・削除系の画面開発

# 自己学習メモインデックス

[IBM i (旧AS400）の自己学習メモ　インデックス](https://qiita.com/You_name_is_YU/items/3964849e7803c8eaf767)

# 前提

使用する技術としてはRPG Ⅳを利用しますが、ここに掲載するプログラムソースは、**フリーフォーマット**ではなく**定位置記入方式**を利用しています。
理由としては、業務で利用しているAS400のプログラムソースの資産は、全て**定位置記入方式**となっており、新機能の開発や既存機能の改修が入ったとしても、突然フリーフォーマットでコーディングされることが無さそうなので、業務に活かすための自己学習をしたいので、**定位置記入方式**を採用しています。
※ただし、一部電話番号の正規表現チェック処理の実装についてだけ、フリーフォーマットでコーディングしております。

# 概要

ここでは得意先マスタ（MTOKISKP）のマスタメンテナンス画面を作っていきます。
実際DFUでも出来ちゃうじゃん。みたいなレベルの機能ですが、登録／更新／削除の機能を１画面の機能として搭載し、入力チェックや画面制御をそれなりにちゃんと作り込みましたので、少しは参考になるレベルに仕上がったのかなと思っています。

# 得意先マスタメンテナンスの主な機能

- 得意先マスタに対する新規登録／更新／削除の一般的なマスタメンテナンス機能を実現。
- 得意先コード指定画面では、マスタメンテナンスの動作モード（登録／更新／削除）をファンクションキーで切り替えられるように実装。
- チェック処理は各項目の必須チェックに加え、電話番号の項目では正規表現によるチェック処理を、信用限度額の項目は１００万以上である数値比較チェック処理を実装。
- 動作モードに応じた画面表示制御（例えば削除モードの場合は画面下部に表示される入力項目を表示専用の項目に切り替えるなど）はある程度実装。

![as400-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/bb7e7931-c3d3-d798-0d11-a0c49d72c11b.gif)

# ソースコード

## DSPFのソース

```shell:QDSPSRC/DSP02
     A*%%TS  SD  20200503  095133  YAMAGUCHI   REL-V7R4M0  5770-WDS
     A*%%EC
     A                                      DSPSIZ(24 80 *DS3)
     A                                      CF03(03 '終了')
     A                                      CF05(05 '実行')
     A                                      CF12(12 '戻る')
     A                                      CF20(20 '削除')
     A                                      CF21(21 '登録')
     A                                      CF22(22 '更新')
     A* 得意先コード指定画面（登録／更新／削除モードの切替）
     A          R PANEL01
     A*%%TS  SD  20200503  095133  YAMAGUCHI   REL-V7R4M0  5770-WDS
     A                                      OVERLAY
     A                                  1  3'DSP02'
     A                                  1 28'得意先マスタメンテナンス'
     A                                      DSPATR(RI)
     A                                      COLOR(BLU)
     A                                  1 70DATE(*JOB *YY)
     A                                      EDTCDE(Y)
     A                                  4  2'得意先コード・・・・'
     A                                      COLOR(WHT)
     A            P1@TOKCD       5A  B  4 25COLOR(WHT)
     A            P1@MODE        6O  O  1 58DSPATR(RI)
     A                                      DSPATR(HI)
     A* 得意先情報の入力エリア
     A          R PANEL02
     A*%%TS  SD  20200503  092729  YAMAGUCHI   REL-V7R4M0  5770-WDS
     A                                      OVERLAY PROTECT
     A                                      CSRLOC(@@CSRROW @@CSRCOL)
     A            @@CSRROW       3S 0H
     A            @@CSRCOL       3S 0H
     A                                  8  2'得意先名'
     A                                      COLOR(WHT)
     A            P2@TOKNM      40O  B  8 15COLOR(WHT)
     A  50                                  DSPATR(PR)
     A                                 10  2'得意先ｶﾅ'
     A                                      COLOR(WHT)
     A            P2@TOKKANA    80   B 10 15CNTFLD(40)
     A                                      COLOR(WHT)
     A  50                                  DSPATR(PR)
     A                                 13  2'電話番号'
     A                                      COLOR(WHT)
     A            P2@TOKTEL     15   B 13 15COLOR(WHT)
     A  50                                  DSPATR(PR)
     A                                 15  2'信用限度額'
     A                                      COLOR(WHT)
     A            P2@TOKRMT      9Y 0B 15 15COLOR(WHT)
     A                                      EDTCDE(J) CHECK(RB)
     A  50                                  DSPATR(PR)
     A* ファンクションキーの説明エリア
     A          R PANEL99
     A*%%TS  SD  20200503  092729  YAMAGUCHI   REL-V7R4M0  5770-WDS
     A                                 23  2'F3=終了'
     A                                      COLOR(BLU)
     A                                 23 12'F21=登録'
     A                                      COLOR(BLU)
     A                                 23 23'F22=変更'
     A                                      COLOR(BLU)
     A                                 23 71'F20=削除'
     A                                      COLOR(BLU)
     A          R M1                        OVERLAY
     A            M1MSGID        7A  O 24  2
     A                                      DSPATR(BL HI)
     A            M1MSG         67A  O 24 10
     A                                      DSPATR(BL HI)
```

## DSPFのポイント解説

### DSPATR(PR)の定義

`DSPATR(PR)`は、入力からのフィールド内容の保護（Protect）をしてくれる属性です。
ここに標識`50`を指定して、`*IN50`が`*ON`の時だけ有効になるよう定義することで、削除モードの際に画面の入力項目を保護するようにしています。

```shell
     A  50                                  DSPATR(PR)
```

### CSRLOCによるカーソル位置定義

PANEL02（得意先情報の入力エリア）では、カーソル位置を指定するための`CSRLOC`を定義しています。
CSRLOCは行，列の位置情報を指定することで、カーソルを指定した場所に設定してくれます。

入力チェック処理を実行した際、エラー項目にカーソル位置をセットするために定義しています。

```shell
     A                                      CSRLOC(@@CSRROW @@CSRCOL)
     A            @@CSRROW       3S 0H
     A            @@CSRCOL       3S 0H
```

### CNTFLDで長い文字列の入力項目を制御

```shell
     A            P2@TOKKANA    80   B 10 15CNTFLD(40)
```

得意先名ｶﾅの項目は、得意先マスタの定義でサイズ80で定義しています。
そのため、マスタメンテナンスでの入力項目のサイズとしても80を指定するのですが、CNTFLDを定義しない場合、以下の画面イメージのように、折り返し位置がちょっとイケてない感じになってしまいます。
<img width="983" alt="スクリーンショット 2020-05-06 12.13.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/1be86067-72d3-039d-98e5-45e438469d40.png">

CNTFLD(40)と指定すると、横幅を40とした折り返し入力ができるエリアにしてくれます。
<img width="983" alt="スクリーンショット 2020-05-06 12.17.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246556/f5ee09ea-80f7-f97e-0c6a-0e4ccdc85f73.png">

## RPGのソース

以下は電話番号の正規表現チェック処理を実現している`SQLRPGLE`のソースコードです。
正規表現チェックを`定位置記入方式`で実現する方法が全く分からなかったので、フリーフォーマットのRPGプログラムとして組んでみました。
このコードの説明などについては以下記事を参考にしてください。
[IBM i (旧AS400）の自己学習メモ　RPG Ⅳプログラミング編０４　正規表現による電話番号チェック処理（RegExp_Count）](https://qiita.com/You_name_is_YU/items/3964849e7803c8eaf767)

```shell:QRPGLESRC/CHECK_TEL
     H
      * 正規表現用の変数
     D Regex           S             50A   Inz Varying
      * マッチした件数
     D Cnt             S              1S 0
      * パラメータ：電話番号
     D P@TEL           S             15A
      * パラメータ：リターンコード
     D P@RTCD          S              2A
      * パラメータリスト
     C     *ENTRY        PLIST
     C                   PARM                    P@TEL
     C                   PARM                    P@RTCD
      /Free
      //Regex = '^0¥d{1,3}-¥d{1,4}-¥d{4}$';
        Regex = '^0[0-9]{1,3}-[0-9]{1,4}-[0-9]{4}$';
        Exec Sql Set Option Commit = *None;
        Exec Sql
          Set :Cnt = RegExp_Count(Trim(:P@TEL), :Regex);
          If Cnt = 1;
            P@RTCD = 'OK';
          Else;
            P@RTCD = 'NG';
          EndIf;
         *INLR = *ON;
      /End-Free
```

得意先マスタメンテナンスの実装をしているRPGプログラムです。

```shell:QRPGLESRC/RPG02
      **********************************************************************
      *使用標識    :
      **********************************************************************
      * 03 : F3 キー終了
      * 05 : F5 キー登録・更新・削除の実行
      * 12 : F12キー前画面
      * 20 : F20キー削除モード
      * 21 : F21キー登録モード
      * 22 : F22キー更新モード
      * 50 :削除モードで画面入力項目の保護
      * 80 :登録・更新・削除の確認実行モード
      * 91 :得意先マスタから未取得
      * 99 :チェック処理エラー
      **********************************************************************
     H DATEDIT(*YMD)
      **********************************************************************
      *ファイル定義
      **********************************************************************
      *画面ファイル
     FDSP02     CF   E             WORKSTN
      *得意先マスタ
     FMTOKISKL00UF A E           K DISK
      **********************************************************************
      *ワークフィールド
      **********************************************************************
      *メインルーチン切替制御用
     D @@CTL           S              3
      * 処理モード制御用
     D @@MODE          S              3
      **********************************************************************
      *配列定義
      **********************************************************************
      *処理モード表示文字列配列
     D @@DSMODES       DS
     D                                6    INZ('登録')
     D                                6    INZ('更新')
     D                                6    INZ('削除')
     D @@MODES                        6    DIM(3) OVERLAY(@@DSMODES)
      **********************************************************************
      *パラメータリスト
      **********************************************************************
      *メッセージ用パラメータリスト
     C     PL@MSG        PLIST
     C                   PARM                    PL@MID            5
     C                   PARM                    PL@MMSG          57
      *電話番号チェック用パラメータリスト
     C     PL@TEL        PLIST
     C                   PARM                    P@TOKTEL         15
     C                   PARM                    P@RTCD            2
      **********************************************************************
      *メイン処理
      **********************************************************************
     C                   EXSR      @CHGMODE
     C     @@CTL         CASEQ     'HED'         @HED
     C     @@CTL         CASEQ     'DTL'         @DTL
     C     @@CTL         CASEQ     'END'         @END
     C                   ENDCS
      **********************************************************************
      *サブルーチン処理
      **********************************************************************
      **********************************************************************
      *得意先コード指定画面の処理
      **********************************************************************
     C     @HED          BEGSR
     C                   WRITE     PANEL99
     C                   WRITE     M1
     C                   EXFMT     PANEL01
      *キー入力に応じた処理
     C                   SELECT
      * F3キー終了
     C                   WHEN      *IN03 = *ON
     C                   EVAL      @@CTL = 'END'
      * F5キー何もしない
     C                   WHEN      *IN05 = *ON
      * F12キー何もしない
     C                   WHEN      *IN12 = *ON
      * F20キー（削除モード）
     C                   WHEN      *IN20 = *ON
     C                   EVAL      @@MODE = 'DEL'
     C                   EXSR      @CHGMODE
      * F21キー（登録モード）
     C                   WHEN      *IN21 = *ON
     C                   EVAL      @@MODE = 'REG'
     C                   EXSR      @CHGMODE
      * F22キー（更新モード）
     C                   WHEN      *IN22 = *ON
     C                   EVAL      @@MODE = 'UPD'
     C                   EXSR      @CHGMODE
      * Enterキー
     C                   OTHER
      *チェック処理
     C                   EXSR      @P1CHK
      *エラーがなければ明細を表示
     C                   IF        *IN99 = *OFF
     C                   EVAL      @@CTL = 'DTL'
     C                   ENDIF
     C                   ENDSL
     C                   ENDSR
      **********************************************************************
      *得意先情報の登録・更新画面の処理
      **********************************************************************
     C     @DTL          BEGSR
      * 画面への表示項目セット
     C                   IF        *IN80 = *OFF
     C                   EXSR      @P2SET
     C                   ENDIF
      * 画面レコード表示
     C                   WRITE     PANEL99
     C                   WRITE     M1
     C                   WRITE     PANEL01
     C                   EXFMT     PANEL02
      *キー入力に応じた処理
     C                   SELECT
      * F3キー終了
     C                   WHEN      *IN03 = *ON
     C                   EVAL      @@CTL = 'END'
      * F5キー登録・更新・削除の実行
     C                   WHEN      *IN05 = *ON
     C                   IF        *IN80 = *ON
     C                   EXSR      @EXECUTE
     C                   EXSR      @RESET
     C                   EVAL      @@CTL = 'HED'
     C                   ENDIF
      * F12キー前画面
     C                   WHEN      *IN12 = *ON
     C                   EXSR      @RESET
     C                   EVAL      @@CTL = 'HED'
      * F20/F21/F22キー無効
     C                   WHEN      *IN20 OR *IN21 OR *IN22
      * Enterキー
     C                   OTHER
      *チェック処理
     C                   EXSR      @P2CHK
      *エラーがなければ登録・更新・削除を実行可能にする
     C                   IF        *IN99 = *OFF
     C                   EVAL      *IN80 = *ON
     C                   EVAL      PL@MID = 'INF01'
     C                   EVAL      PL@MMSG = 'F5キーを押下して実行'
     C                   EXSR      @MSG
     C                   ENDIF
     C                   ENDSL
     C                   ENDSR
      **********************************************************************
      *チェック処理（得意先コード指定画面）
      **********************************************************************
     C     @P1CHK        BEGSR
      * エラー標識やエラーメッセージをクリア
     C                   EXSR      @RESET
      * 得意先コードが指定されていない場合エラー
     C                   IF        P1@TOKCD = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR01'
     C                   EVAL      PL@MMSG = '得意先コードを入力してください'
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
      * 指定された得意先コードで得意先マスタの情報を取得
      * 更新モード指定のファイルなのでロックが掛からないように(N)を指定
     C     P1@TOKCD      CHAIN(N)  MTOKISKL00                         91
      * 更新，削除モードで対象の得意先情報が無い場合エラー
     C                   IF        @@MODE = 'UPD'  OR
     C                             @@MODE = 'DEL'
     C                   IF        *IN91  = *ON
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR02'
     C                   EVAL      PL@MMSG = '得意先マスタに存在しません'
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDIF
      * 登録モードで対象の得意先情報が登録済みの場合エラー
     C                   IF        @@MODE = 'REG' AND
     C                             *IN91  = *OFF
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR03'
     C                   EVAL      PL@MMSG = '得意先マスタに登録済みです'
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDSR
      **********************************************************************
      *チェック処理（得意先情報登録・更新画面）
      **********************************************************************
     C     @P2CHK        BEGSR
      * エラー標識やエラーメッセージをクリア
     C                   EXSR      @RESET
      *** 得意先名（必須）
     C                   IF        P2@TOKNM = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR11'
     C                   EVAL      PL@MMSG = '得意先名を入力してください'
     C                   EVAL      @@CSRROW = 8
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
      *** 得意先カナ（必須）
     C                   IF        P2@TOKKANA = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR12'
     C                   EVAL      PL@MMSG = '得意先カナを入力してください'
     C                   EVAL      @@CSRROW = 10
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
      *** 電話番号（必須／正規表現）
     C                   IF        P2@TOKTEL = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR13'
     C                   EVAL      PL@MMSG = '電話番号を入力してください'
     C                   EVAL      @@CSRROW = 13
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ELSE
     C                   EVAL      P@TOKTEL = P2@TOKTEL
     C                   EVAL      P@RTCD = ''
     C                   CALL      'CHECK_TEL'   PL@TEL
     C                   IF        P@RTCD = 'NG'
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR14'
     C                   EVAL      PL@MMSG = '電話番号が不正です'
     C                   EVAL      @@CSRROW = 13
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDIF
      *** 信用限度額（１００万以上）
     C                   IF        P2@TOKRMT < 1000000
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR15'
     C                   EVAL      PL@MMSG = '信用限度額は１００万以上で' +
     C                             '入力してください'
     C                   EVAL      @@CSRROW = 15
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDSR
      **********************************************************************
      *得意先情報の登録・更新画面の項目セット処理
      **********************************************************************
     C     @P2SET        BEGSR
     C                   IF        @@MODE = 'REG'
     C*
     C                   ENDIF
      * 更新・削除モードの場合取得した得意先マスタの情報をセット
      * PANEL02で入力エラーがあった場合、データを際取得しない。
     C                   IF        @@MODE = 'UPD' OR @@MODE = 'DEL'
     C                   IF        *IN99 = *OFF
     C                   EVAL      P2@TOKNM   = TOKNM
     C                   EVAL      P2@TOKKANA = TOKKANA
     C                   EVAL      P2@TOKTEL  = TOKTEL
     C                   EVAL      P2@TOKRMT  = TOKRMT
     C                   ENDIF
     C                   ENDIF
     C                   ENDSR
      **********************************************************************
      *画面入力情報を得意先マスタの各項目にセット
      **********************************************************************
     C     @SETDATA      BEGSR
     C                   EVAL      TOKCD    = P1@TOKCD
     C                   EVAL      TOKNM    = P2@TOKNM
     C                   EVAL      TOKKANA  = P2@TOKKANA
     C                   EVAL      TOKTEL   = P2@TOKTEL
     C                   EVAL      TOKRMT   = P2@TOKRMT
     C                   ENDSR
      **********************************************************************
      *登録・更新・削除処理の実行
      **********************************************************************
     C     @EXECUTE      BEGSR
     C                   SELECT
      * 登録処理
     C                   WHEN      @@MODE = 'REG'
     C                   EXSR      @SETDATA
     C                   WRITE     MTOKISKR
      * 更新処理
     C                   WHEN      @@MODE = 'UPD'
     C     P1@TOKCD      CHAIN     MTOKISKL00                         91
     C                   IF        *IN91 = *OFF
     C                   EXSR      @SETDATA
     C                   UPDATE    MTOKISKR
     C                   ENDIF
      * 削除処理
     C                   WHEN      @@MODE = 'DEL'
     C     P1@TOKCD      CHAIN     MTOKISKL00                         91
     C                   IF        *IN91 = *OFF
     C                   DELETE    MTOKISKR
     C                   ENDIF
     C                   ENDSL
     C                   ENDSR
      **********************************************************************
      *リセット処理
      **********************************************************************
     C     @RESET        BEGSR
      *エラー情報をクリア
     C                   CLEAR                   M1
     C                   SETOFF                                       91
     C                   SETOFF                                       99
      *登録・更新・削除処理実行モードクリア
     C                   SETOFF                                       80
     C                   ENDSR
      **********************************************************************
      *モードチェンジ処理
      **********************************************************************
     C     @CHGMODE      BEGSR
     C                   EVAL      *IN50 = *OFF
     C                   SELECT
      * 登録モード
     C                   WHEN      @@MODE = 'REG'
     C                   EVAL      P1@MODE = @@MODES(1)
      * 更新モード
     C                   WHEN      @@MODE = 'UPD'
     C                   EVAL      P1@MODE = @@MODES(2)
      * 削除モード
     C                   WHEN      @@MODE = 'DEL'
     C                   EVAL      P1@MODE = @@MODES(3)
      * 削除モードの場合入力項目を保護
     C                   EVAL      *IN50 = *ON
     C                   ENDSL
     C                   ENDSR
      **********************************************************************
      *メッセージ表示処理
      **********************************************************************
     C     @MSG          BEGSR
     C                   EVAL      M1MSGID = PL@MID
     C                   EVAL      M1MSG = PL@MMSG
     C                   ENDSR
      **********************************************************************
      *終了処理
      **********************************************************************
     C     @END          BEGSR
     C                   EVAL      *INLR = *ON
     C                   RETURN
     C                   ENDSR
      **********************************************************************
      *初期設定*INZSR初期化サブルーチン
      **********************************************************************
     C     *INZSR        BEGSR
     C                   EVAL      @@CTL = 'HED'
     C                   EVAL      @@MODE = 'REG'
     C                   ENDSR
```

## RPGのポイント解説

### ファイル仕様書

得意先マスタメンテナンスの画面機能なので、ファイル・タイプに`U`を、レコードの追加に`A`を指定しています。

```shell
      *得意先マスタ
     FMTOKISKL00UF A E           K DISK
```

### 処理モード（登録，更新，削除）識別用の変数定義

`@@MODE`にはREG/UPD/DELのいずれかがセットされ、処理モードを識別します。

```shell
      * 処理モード制御用
     D @@MODE          S              3
```

### 得意先コード指定画面の処理

- F3キー押下で画面の処理終了（画面を閉じる）
- F5/F12は得意先情報入力エリアが表示された状態でのみ有効なファンクションキーなので無効化
- F21/F22/F20キーに応じた処理モードの切替
    - F21：`REG`/F22:`UPD`/F20:`DEL`を@@MODEにセット
- Enterキー押下で得意先コードの入力チェックを行い、エラーが無ければ得意先情報入力エリアを表示。

```shell
      **********************************************************************
      *得意先コード指定画面の処理
      **********************************************************************
     C     @HED          BEGSR
     C                   WRITE     PANEL99
     C                   WRITE     M1
     C                   EXFMT     PANEL01
      *キー入力に応じた処理
     C                   SELECT
      * F3キー終了
     C                   WHEN      *IN03 = *ON
     C                   EVAL      @@CTL = 'END'
      * F5キー何もしない
     C                   WHEN      *IN05 = *ON
      * F12キー何もしない
     C                   WHEN      *IN12 = *ON
      * F20キー（削除モード）
     C                   WHEN      *IN20 = *ON
     C                   EVAL      @@MODE = 'DEL'
     C                   EXSR      @CHGMODE
      * F21キー（登録モード）
     C                   WHEN      *IN21 = *ON
     C                   EVAL      @@MODE = 'REG'
     C                   EXSR      @CHGMODE
      * F22キー（更新モード）
     C                   WHEN      *IN22 = *ON
     C                   EVAL      @@MODE = 'UPD'
     C                   EXSR      @CHGMODE
      * Enterキー
     C                   OTHER
      *チェック処理
     C                   EXSR      @P1CHK
      *エラーがなければ明細を表示
     C                   IF        *IN99 = *OFF
     C                   EVAL      @@CTL = 'DTL'
     C                   ENDIF
     C                   ENDSL
     C                   ENDSR
```

### P1CHK（得意先コード入力エリアのチェック処理）

- 処理モード（登録／更新／削除）に応じてチェック処理を切り分け
- 登録モードの場合は指定された得意先コードがすでに存在しているとエラー
- 更新／削除モードの場合は指定された得意先コードが存在しない場合エラー

```shell
      **********************************************************************
      *チェック処理（得意先コード指定画面）
      **********************************************************************
     C     @P1CHK        BEGSR
      * エラー標識やエラーメッセージをクリア
     C                   EXSR      @RESET
      * 得意先コードが指定されていない場合エラー
     C                   IF        P1@TOKCD = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR01'
     C                   EVAL      PL@MMSG = '得意先コードを入力してください'
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
      * 指定された得意先コードで得意先マスタの情報を取得
      * 更新モード指定のファイルなのでロックが掛からないように(N)を指定
     C     P1@TOKCD      CHAIN(N)  MTOKISKL00                         91
      * 更新，削除モードで対象の得意先情報が無い場合エラー
     C                   IF        @@MODE = 'UPD'  OR
     C                             @@MODE = 'DEL'
     C                   IF        *IN91  = *ON
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR02'
     C                   EVAL      PL@MMSG = '得意先マスタに存在しません'
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDIF
      * 登録モードで対象の得意先情報が登録済みの場合エラー
     C                   IF        @@MODE = 'REG' AND
     C                             *IN91  = *OFF
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR03'
     C                   EVAL      PL@MMSG = '得意先マスタに登録済みです'
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDSR
```

### 得意先情報入力エリアの処理

- F3キー押下で画面処理終了
- F5キー
    - 得意先情報入力エリアで各項目の情報を入力し、Enterを押下してチェック処理を通過すると、標識`*IN80`が`*ON`になるようにして、画面下部に`F5キーを押下して実行`というメッセージを表示しています。<br>この状態でF5キーを押下した場合のみ、登録／更新／削除処理を実行するように制御しています。
- F12キー押下で得意先情報入力エリアを閉じて得意先コード入力エリアの表示に戻る
- F20/F21/F22キーはここでは無効
- Enterキー
    - 1回目のEnterキーでは、チェック処理を実行。
    - 2回目のEnterキー押下で登録／更新／削除処理を実行。

```shell
      **********************************************************************
      *得意先情報の登録・更新画面の処理
      **********************************************************************
     C     @DTL          BEGSR
      * 画面への表示項目セット
     C                   IF        *IN80 = *OFF
     C                   EXSR      @P2SET
     C                   ENDIF
      * 画面レコード表示
     C                   WRITE     PANEL99
     C                   WRITE     M1
     C                   WRITE     PANEL01
     C                   EXFMT     PANEL02
      *キー入力に応じた処理
     C                   SELECT
      * F3キー終了
     C                   WHEN      *IN03 = *ON
     C                   EVAL      @@CTL = 'END'
      * F5キー登録・更新・削除の実行
     C                   WHEN      *IN05 = *ON
     C                   IF        *IN80 = *ON
     C                   EXSR      @EXECUTE
     C                   EXSR      @RESET
     C                   EVAL      @@CTL = 'HED'
     C                   ENDIF
      * F12キー前画面
     C                   WHEN      *IN12 = *ON
     C                   EXSR      @RESET
     C                   EVAL      @@CTL = 'HED'
      * F20/F21/F22キー無効
     C                   WHEN      *IN20 OR *IN21 OR *IN22
      * Enterキー
     C                   OTHER
      *チェック処理
     C                   EXSR      @P2CHK
      *エラーがなければ登録・更新・削除を実行可能にする
     C                   IF        *IN99 = *OFF
     C                   EVAL      *IN80 = *ON
     C                   EVAL      PL@MID = 'INF01'
     C                   EVAL      PL@MMSG = 'F5キーを押下して実行'
     C                   EXSR      @MSG
     C                   ENDIF
     C                   ENDSL
     C                   ENDSR
```

### P2CHK（得意先情報入力エリアのチェック処理）

- ほとんどの項目は必須チェックのみ
- 電話番号は正規表現チェックを実行（CHECK_TELを呼び出し）
    - CHECK_TELを呼び出すためのパラメータリスト`PL@TEL`の各要素に値を設定している。
    - `CALL      'CHECK_TEL'   PL@TEL`で電話番号の正規表現チェック処理を実行。
- `@@CSRROW`, `@@CSRCOL`に行番号，列番号を指定することで、エラーとなった項目にカーソルがセットされるように対応。

```shell
      **********************************************************************
      *チェック処理（得意先情報登録・更新画面）
      **********************************************************************
     C     @P2CHK        BEGSR
      * エラー標識やエラーメッセージをクリア
     C                   EXSR      @RESET
      *** 得意先名（必須）
     C                   IF        P2@TOKNM = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR11'
     C                   EVAL      PL@MMSG = '得意先名を入力してください'
     C                   EVAL      @@CSRROW = 8
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
      *** 得意先カナ（必須）
     C                   IF        P2@TOKKANA = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR12'
     C                   EVAL      PL@MMSG = '得意先カナを入力してください'
     C                   EVAL      @@CSRROW = 10
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
      *** 電話番号（必須／正規表現）
     C                   IF        P2@TOKTEL = *Blank
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR13'
     C                   EVAL      PL@MMSG = '電話番号を入力してください'
     C                   EVAL      @@CSRROW = 13
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ELSE
     C                   EVAL      P@TOKTEL = P2@TOKTEL
     C                   EVAL      P@RTCD = ''
     C                   CALL      'CHECK_TEL'   PL@TEL
     C                   IF        P@RTCD = 'NG'
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR14'
     C                   EVAL      PL@MMSG = '電話番号が不正です'
     C                   EVAL      @@CSRROW = 13
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDIF
      *** 信用限度額（１００万以上）
     C                   IF        P2@TOKRMT < 1000000
     C                   EVAL      *IN99 = *ON
     C                   EVAL      PL@MID = 'ERR15'
     C                   EVAL      PL@MMSG = '信用限度額は１００万以上で' +
     C                             '入力してください'
     C                   EVAL      @@CSRROW = 15
     C                   EVAL      @@CSRCOL = 15
     C                   EXSR      @MSG
     C                   LEAVESR
     C                   ENDIF
     C                   ENDSR
``` 

### 登録／更新／削除処理

- 登録／更新／削除モードに応じて処理を分岐

```shell
      **********************************************************************
      *登録・更新・削除処理の実行
      **********************************************************************
     C     @EXECUTE      BEGSR
     C                   SELECT
      * 登録処理
     C                   WHEN      @@MODE = 'REG'
     C                   EXSR      @SETDATA
     C                   WRITE     MTOKISKR
      * 更新処理
     C                   WHEN      @@MODE = 'UPD'
     C     P1@TOKCD      CHAIN     MTOKISKL00                         91
     C                   IF        *IN91 = *OFF
     C                   EXSR      @SETDATA
     C                   UPDATE    MTOKISKR
     C                   ENDIF
      * 削除処理
     C                   WHEN      @@MODE = 'DEL'
     C     P1@TOKCD      CHAIN     MTOKISKL00                         91
     C                   IF        *IN91 = *OFF
     C                   DELETE    MTOKISKR
     C                   ENDIF
     C                   ENDSL
     C                   ENDSR
```

以上でマスタメンテナンス機能の実装が完了しました。
RPGプログラミングにおける画面実装では、あと重要なのが**サブファイル**というものらしいので、今後はそのサブファイルの勉強を進めていこうと思います。