繰り返し処理
20.1 繰り返し処理
1. 繰り返し処理
繰り返し処理(ループ処理)は、同じ処理を複数回実行したいときに使用します。
ABAPでは、内部テーブルを順番に処理する LOOP命令 が代表的ですが、回数や条件で繰り返す DO命令、条件が成立している間だけ繰り返す WHILE命令 もよく使用します。
- DOループ命令
- WHILEループ命令
- LOOP命令
- 強制終了命令
DOループ命令
DOループ命令は、強制終了命令が発行されるまでDO~ENDDO内の処理を繰り返し行います。
強制終了命令を発行しない場合は、無限ループ状態となりますので注意が必要です。
そのため、回数が決まっている場合は DO n TIMES を優先し、回数が決められない場合でも 必ず終了条件 を入れるようにします。
- 回数を指定しないループ
- 回数を指定するループ
回数を指定しないループ
上記でも説明しましたが、強制終了命令を発行しない場合は、無限ループ状態となりますので注意が必要です。
サンプルコード:回数を指定しないループ
REPORT Z_SAMPLE201_DO.
DATA LV_COUNT TYPE I VALUE 0.
DO.
LV_COUNT += 1.
WRITE: / |DOの{ LV_COUNT }回目|.
"終了条件(ないと無限ループになる)
IF LV_COUNT = 3.
EXIT.
ENDIF.
ENDDO.
WRITE: / '処理完了'.
結果
回数を指定するループ
回数を指定するDOループは、次の通りです。指定した回数(n)分だけDO~ENDDO内の処理を繰り返し行います。
サンプルコード:回数を指定するループ
REPORT Z_SAMPLE201_DOCOUNT.
DATA LV_COUNT TYPE I VALUE 0.
START-OF-SELECTION.
DO 3 TIMES.
WRITE: / |SY-INDEX={ SY-INDEX }|.
ENDDO.
WRITE: / '処理完了'.
結果
WHILEループ命令
WHILEループ命令は、条件が真の間、WHILE~ENDWHILE内の処理を繰り返し行います。
なお、強制終了命令を使用した場合は、条件に関わらずループパスが終了します。
WHILEループ命令の構文は、以下となります。
条件式には「SY-INDEX > 10」のような限定的に成り立つ条件を指定しないと、無限ループに陥ります。
サンプルコード
REPORT Z_SAMPLE201_WHILE.
START-OF-SELECTION.
DATA LV_COUNT TYPE I VALUE 0.
WHILE LV_COUNT < 3.
LV_COUNT += 1.
WRITE: / |WHILEの{ LV_COUNT }回目|.
ENDWHILE.
WRITE: / '処理完了'.
結果
LOOP命令
LOOP命令は、「同じ処理の繰り返し」を行い、 内部テーブルから「特定のデータを抽出して処理を行う場合」に利用されます。
LOOP命令①
LOOP命令の構文は、以下となります。
<ポイント>
① LOOP処理を行う内部テーブルを指定すること
② LOOP処理で対象となるレコードを格納する構造を指定すること
LOOP命令②
LOOPでは、内部テーブルを1行1行処理をしていきます。
このとき、留意する必要があるのが、LOOP ATでは指定した内部テーブルを直接処理するのではなく、一時的に別の構造に対象の行を格納して処理を進める、という点です。
以下のようなイメージです。
内部テーブルの1行1行を、別の構造に格納して処理を進めるイメージです。
したがって、LOOP~ENDLOOPには、①対象の内部テーブルと②作業エリア(構造)の指定が
必要となるのです。
サンプルコード:LOOP命令(条件指定なし)
REPORT Z_SAMPLE201_LOOPAT.
TYPES: BEGIN OF TY_ITEM,
ITEM_NAME TYPE STRING,
ITEM_CODE TYPE N LENGTH 4,
PRICE TYPE I,
END OF TY_ITEM.
START-OF-SELECTION.
DATA LT_ITEM TYPE STANDARD TABLE OF TY_ITEM WITH EMPTY KEY.
APPEND VALUE #( ITEM_NAME = 'りんご' ITEM_CODE = '0001' PRICE = 100 ) TO LT_ITEM.
APPEND VALUE #( ITEM_NAME = 'みかん' ITEM_CODE = '0002' PRICE = 30 ) TO LT_ITEM.
APPEND VALUE #( ITEM_NAME = 'いちご' ITEM_CODE = '0003' PRICE = 80 ) TO LT_ITEM.
WRITE: / '商品名', 15 '商品コード', 30 '値段'.
ULINE.
LOOP AT LT_ITEM INTO DATA(LS_ITEM).
WRITE: / LS_ITEM-ITEM_NAME, 15 LS_ITEM-ITEM_CODE, 30 LS_ITEM-PRICE.
ENDLOOP.
結果
補足(SY-TABIXについて)
システム項目の一つで「現在ループしているテーブルの対象行」が格納されます。
LOOP文を使用するとSY-TABIX にテーブルの対象行が格納されると覚えておきましょう。
LOOP命令③
LOOP命令では、WHEREオプションを用いて処理の対象としたいレコードを特定することが可能です。
サンプルコード:LOOP命令(条件指定あり)
REPORT Z_SAMPLE201_LOOPWHERE.
TYPES: BEGIN OF TY_ITEM,
ITEM_NAME TYPE STRING,
ITEM_CODE TYPE N LENGTH 4,
PRICE TYPE I,
END OF TY_ITEM.
START-OF-SELECTION.
DATA LT_ITEM TYPE STANDARD TABLE OF TY_ITEM WITH EMPTY KEY.
CONSTANTS LC_TARGET TYPE STRING VALUE 'みかん'.
APPEND VALUE #( ITEM_NAME = 'りんご' ITEM_CODE = '0001' PRICE = 100 ) TO LT_ITEM.
APPEND VALUE #( ITEM_NAME = 'みかん' ITEM_CODE = '0002' PRICE = 30 ) TO LT_ITEM.
APPEND VALUE #( ITEM_NAME = 'いちご' ITEM_CODE = '0003' PRICE = 80 ) TO LT_ITEM.
WRITE: / '商品名', 15 '商品コード', 30 '値段'.
ULINE.
LOOP AT LT_ITEM INTO DATA(LS_ITEM) WHERE ITEM_NAME = LC_TARGET..
WRITE: / LS_ITEM-ITEM_NAME, 15 LS_ITEM-ITEM_CODE, 30 LS_ITEM-PRICE.
ENDLOOP.
結果
LOOP命令(新構文)
LOOP命令も新構文を用いることができます。構文は、以下となります。
旧構文では、作業用の構造を事前に宣言(定義)する必要がありましたが 新構文では、内部テーブルと同じ構造が自動で作成されます。
サンプルコード:LOOP命令(新構文)
REPORT Z_SAMPLE_S12_309_NEW NO STANDARD PAGE HEADING
*&---------------------------------------------------------------------*
* TYPES宣言
*&---------------------------------------------------------------------*
* 構造データ型
TYPES:
BEGIN OF TYP_ST,
NAME TYPE C LENGTH 10,
CODE TYPE C LENGTH 10,
VALUE TYPE C LENGTH 10,
END OF TYP_ST.
* テーブルデータ型
TYPES TYP_T TYPE STANDARD TABLE OF TYP_ST.
*&---------------------------------------------------------------------*
* DATA宣言
*&---------------------------------------------------------------------*
* DATA IT_TEST TYPE TYP_T.
DATA IT_TEST TYPE STANDARD TABLE OF TYP_ST.
*&---------------------------------------------------------------------*
* CONSTANTS宣言
*&---------------------------------------------------------------------*
CONSTANTS CNS_FRUIT TYPE C LENGTH 6 VALUE 'みかん'.
*&---------------------------------------------------------------------*
* LOOP命令(新構文)
*&---------------------------------------------------------------------*
START-OF-SELECTION.
* 内部テーブルにデータを追加
APPEND VALUE #( NAME = ‘りんご’ CODE = ‘0001’ VALUE = ‘100’ ) TO IT_TEST.
APPEND VALUE #( NAME = CNS_FRUIT CODE = ‘0002’ VALUE = ‘30’ ) TO IT_TEST.
APPEND VALUE #( NAME = ‘イチゴ’ CODE = ‘0003’ VALUE = ‘80’ ) TO IT_TEST.
APPEND VALUE #( NAME = CNS_FRUIT CODE = ‘0004’ VALUE = ‘31’ ) TO IT_TEST.
* 内部テーブルの結果を出力
WRITE: |商品名 商品コード 値段|.
* 今回はみかんだけ出力させる
LOOP AT IT_TEST INTO DATA(ST_TEST) WHERE NAME = CNS_FRUIT.
WRITE / ST_TEST.
ENDLOOP.
END-OF-SELECTION.
強制終了命令
単一ループパスを終了したり、ループ全体を終了したりする場合は、強制終了命令を使用します。
- CHECK命令
- CONTINUE命令
- EXIT命令
CHECK命令
CHECK命令は、条件が成立しない場合に、その時点で現在の処理ブロックから抜けます。
ループ内で使うと、「条件に合わない行はスキップする」という用途になります。(結果として次の行へ進みます)。
※ループ外でのCHECKは意図が伝わりにくく、非推奨とされるため、基本はループ内で使用します。
)
サンプルコード:CHECK命令
REPORT Z_SAMPLE201_CHECK.
TYPES: BEGIN OF TY_ITEM,
NAME TYPE STRING,
CODE TYPE N LENGTH 4,
VAL TYPE I,
END OF TY_ITEM.
START-OF-SELECTION.
DATA LT_ITEM TYPE STANDARD TABLE OF TY_ITEM WITH EMPTY KEY.
APPEND VALUE #( NAME = 'りんご' CODE = '0001' VAL = 100 ) TO LT_ITEM.
APPEND VALUE #( NAME = 'みかん' CODE = '0002' VAL = 30 ) TO LT_ITEM.
APPEND VALUE #( NAME = 'いちご' CODE = '0003' VAL = 80 ) TO LT_ITEM.
WRITE: / '(CODE=0002 の行だけ出力)'.
LOOP AT LT_ITEM INTO DATA(LS_ITEM).
CHECK LS_ITEM-CODE = '0002'.
WRITE: / |{ LS_ITEM-NAME } { LS_ITEM-CODE } { LS_ITEM-VAL }|.
ENDLOOP.
結果
CONTINUE命令
CONTINUE命令は、現在のループ1回分の処理を打ち切って、次のループへ進む命令です。
※CONTINUE命令は、ループ内でしか使えません。
サンプルコード:CONTINUE命令
REPORT Z_SAMPLE_KANDA_01 NO STANDARD PAGE HEADING.
*&---------------------------------------------------------------------*
* TYPES宣言
*&---------------------------------------------------------------------*
* 構造データ型
TYPES:
BEGIN OF TYP_ST,
NAME TYPE C LENGTH 10,
CODE TYPE C LENGTH 10,
VALUE TYPE C LENGTH 10,
END OF TYP_ST.
* テーブルデータ型
TYPES TYP_T TYPE STANDARD TABLE OF TYP_ST.
*&---------------------------------------------------------------------*
* DATA宣言
*&---------------------------------------------------------------------*
* DATA IT_TEST TYPE TYP_T.
DATA IT_TEST TYPE STANDARD TABLE OF TYP_ST.
*&---------------------------------------------------------------------*
* CHECK命令
*&---------------------------------------------------------------------*
START-OF-SELECTION.
* 内部テーブルにデータを追加
APPEND VALUE #( NAME = ‘りんご’ CODE = ‘0001’ VALUE = ‘100’ ) TO IT_TEST.
APPEND VALUE #( NAME = ‘みかん’ CODE = ‘0002’ VALUE = ‘30’ ) TO IT_TEST.
APPEND VALUE #( NAME = ‘イチゴ’ CODE = ‘0003’ VALUE = ‘80’ ) TO IT_TEST.
* 内部テーブルの結果を出力
LOOP AT IT_TEST INTO DATA(ST_TEST).
* 現在の行が2行目だった場合
IF SY-TABIX = 2.
* LOOPの先頭に戻る(3件目の処理に行く)
CONTINUE.
ENDIF.
WRITE / ST_TEST.
ENDLOOP.
END-OF-SELECTION.
結果
EXIT命令
EXIT命令を記述すると、CONTINE命令同様 ループ処理を無条件に終了します。
※EXIT命令は、ループ外にも書けますが、処理の意図が曖昧になりやすいため、「ループを抜ける目的」でループ内に書く運用を基本にします。。 動作としてはRETURNと同じですがRETURNは呼び出し元に戻る命令に対して、EXITは強制終了する命令です。
サンプルコード:EXIT命令
REPORT Z_SAMPLE201_EXIT.
TYPES: BEGIN OF TY_ITEM,
NAME TYPE STRING,
CODE TYPE N LENGTH 4,
VAL TYPE I,
END OF TY_ITEM.
START-OF-SELECTION.
DATA LT_ITEM TYPE STANDARD TABLE OF TY_ITEM WITH EMPTY KEY.
APPEND VALUE #( NAME = 'りんご' CODE = '0001' VAL = 100 ) TO LT_ITEM.
APPEND VALUE #( NAME = 'みかん' CODE = '0002' VAL = 30 ) TO LT_ITEM.
APPEND VALUE #( NAME = 'いちご' CODE = '0003' VAL = 80 ) TO LT_ITEM.
WRITE: / '(最初の1行だけ出力してループ終了)'.
LOOP AT LT_ITEM INTO DATA(LS_ITEM).
WRITE: / |{ LS_ITEM-NAME } { LS_ITEM-CODE } { LS_ITEM-VAL }|.
EXIT.
ENDLOOP.
結果