三崎レイナ
社会人1年目。新卒でITコンサルティングファームに就職。初配属がSAPプロジェクトにアサインされる。SAPがわからないことだらけで悩んでいたところ、会社の先輩にSAPラボの所長を紹介され、毎週末に所長とSAPのお勉強中!
博士
SAPラボの所長。SAP大好き博士!SAP導入プロジェクトを構想策定~運用保守まであらゆるフェーズを数多く経験。
いまは優しきおじいちゃんだが、プロマネバリバリの時代はかなり怖かったらしい。現在は引退し、SAPの後進育成と啓蒙活動に従事中!
登場人物紹介
三崎レイナ
社会人1年目。新卒でITコンサルティングファームに就職。初配属がSAPプロジェクトにアサインされる。SAPがわからないことだらけで悩んでいたところ、会社の先輩にSAPラボの所長を紹介され、毎週末に所長とSAPのお勉強中!
博士
SAPラボの所長。SAP大好き博士!SAP導入プロジェクトを構想策定~運用保守まであらゆるフェーズを数多く経験。
いまは優しきおじいちゃんだが、プロマネバリバリの時代はかなり怖かったらしい。現在は引退し、SAPの後進育成と啓蒙活動に従事中!
この記事を読むメリット
今回はABAPの繰り返し(ループ)について説明するぞい!
ABAPでの繰り返し処理(ループ処理)は、プログラム内で同じ一連の命令を繰り返し行うために使用されます。繰り返し処理をマスターすることで、大量データの効率的な処理やコードの再利用性と可読性の向上が実現し、システム全体の性能向上や開発プロセスの効率化が期待できます。頻繁に使用されるのでしっかりマスターしておきましょう。
新着のSAPフリーランス案件
【FI】
SAP HANAバージョンアップにおける会計機能設計支援
【FI】
自動車メーカー向けS4HANA導入支援(FI/CO)
【SD】
外資系アパレル業向けSDモジュール運用保守支援
【FI】
電気機械器具向け SAP導入プロジェクト支援 FIコンサル(AA/GL/AP/AR)
【FI】
電気機械器具向け SAP導入プロジェクト支援 FI SE(基本設計者)
【FI】
食品・薬品製造販売業向けSAP運用保守支援
【MM】
【SD】
大手製造業向けECC⇒S4移行におけるグローバルテンプレート構築支援(ロジ領域)
【FI】
FI-AAモジュール 要件定義支援
【FI】
【MM】
【SD】
S4HANA導入コンサル支援(SD/MM/FI)
【CO】
【MM】
半導体製造機器製造向けSAP運用保守
繰り返し処理とは、同じ一連の命令や処理を複数回実行することを指します。これにより、データの集計や変換、処理の反復などを効率的に行うことができます。繰り返し処理は、大量のデータや複雑なロジックを扱う際に特に重要であり、コードの再利用性やメンテナンス性を向上させる効果もあります。
ABAPでは、繰り返しを実現するために、”DO命令“や”WHILE命令“を使用します。また、内部テーブルの各行に対して繰り返し処理を行うには、”LOOP命令“を使用します。その他にも”SELECT命令“や”PROVIDE命令“を使用して繰り返し処理を作成することも可能です。
まずはDO命令じゃ。
DO命令は、指定した回数だけ繰り返し処理を行うための命令だぞい!
ABAPのDO命令は、指定された回数だけ繰り返し処理を行うか、”EXIT命令”が実行されるまで繰り返し処理を行います。指定回数の繰り返し処理が必要な場合に便利ですが、回数を指定しない場合は無限ループを発生させてしまう可能性があるため、注意が必要です。
構文
DO n TIMES.
繰り返し実行する処理.
ENDDO.
※「n」は繰り返し回数を指定します。
※実行回数を指定しないパターンは、「n TIMES」の部分を省略します。
DO命令の構文ルール自体はシンプルじゃ!
DO~ENDDOでループのブロック(かたまり)を定義して、その中に繰り返したい処理を記述すればいいだけじゃ。
実際に使用例を見ていくぞい!
* DO命令を使用して1から10までの数を出力する
DATA: lv_counter TYPE i.
DO 10 TIMES.
lv_counter = sy-index.
WRITE: / '繰り返し回数:', lv_counter.
ENDDO.
このプログラムでは、DO命令を使用してから1から10までの数を出力しています。”sy-index”は現在のループインデックスを示し、1から始まります。
※SY-INDEXはシステム項目の1つで、よく使用されます。
DATA: lv_counter TYPE i VALUE 0.
DO.
lv_counter = lv_counter + 1.
WRITE: / '繰り返し回数:', lv_counter.
IF lv_counter >= 10.
EXIT.
ENDIF.
ENDDO.
このプログラムでは、DO命令内でカウントアップし、カウンターが10に達したら”EXIT命令”で繰り返しを終了します。
DO.
WRITE: / 'こんにちは!'.
ENDDO.
上記の例だと、「こんにちは!」と出力する処理が無限に繰り返されます。
無限ループを続けるとメモリが圧迫され、いずれショートダンプが起きます。
回避するためには回数を指定するか、”EXIT命令”を使用して繰り返しの終了条件を設定します。
次はWHILE命令じゃ。
WHILE命令は、指定した条件が真である限り、繰り返し処理を行うための命令だぞい!
ABAPのWHILE命令は、指定された条件が満たされている間、繰り返し処理を行います。この命令は、条件が変化するまで繰り返し処理を行いたい場合に便利です。ただし、条件が永遠に満たされ続ける場合は無限ループを発生させてしまう可能性があるため、注意が必要です。
構文
WHILE 条件.
繰り返し実行する処理.
ENDWHILE.
※DO命令は繰り返しを行う「回数」を指定しましたが、WHILE命令は繰り返し行う「条件」を指定するのが大きな違いです。
WHILE命令の構文ルールもシンプルじゃ!
WHILE~ENDWHILEでループのブロック(かたまり)を定義して、その中に繰り返したい処理を記述すればいいだけじゃ。
実際に使用例を見ていくぞい!
DATA: lv_counter TYPE i VALUE 1.
WHILE lv_counter <= 10.
WRITE: / '繰り返し回数:', lv_counter.
lv_counter = lv_counter + 1.
ENDWHILE.
このプログラムでは、lv_counterが10以下の間、繰り返し処理を行います。ループ内でカウントアップし、条件が満たされなくなるとループが終了します。
“EXIT命令”は繰り返し処理の中で非常に重要な命令なので覚えておくのじゃ!
DATA: lv_counter TYPE i VALUE 0.
WHILE lv_counter < 10.
lv_counter = lv_counter + 1.
WRITE: / lv_counter.
IF lv_counter = 5.
EXIT.
ENDIF.
ENDWHILE.
このプログラムでは、カウンターが10未満の間、繰り返し処理を行いますが、カウンターが5に達した時点で”EXIT命令”によりループを終了します。
・DO命令:固定回数の繰り返しに適している
・WHILE命令:動的条件に基づく繰り返しに適している
各命令の特性と注意点を理解し、適切なシナリオで使い分けることが、効率的なABAPプログラミングの鍵となります。
次はLOOP命令じゃ。
LOOP命令は内部テーブルの各行に対して繰り返し処理を行うために使用されるぞい!
ABAPのLOOP命令は、内部テーブルの各行に対して繰り返し処理を行うための命令です。この命令は内部テーブルのすべての行や、特定の条件を満たす行に対して処理を行う場合に便利です。ただし、内部テーブルの範囲や条件を適切に設定しないと、不要な行まで処理してしまう可能性があるため、注意が必要です。
構文
LOOP AT 内部テーブル INTO 作業領域.
繰り返し実行する処理.
ENDLOOP.
※LOOP命令は内部テーブルの各行が順番に作業領域に一時的に読み込まれ、繰り返し処理が実行されます。
まずは簡単な使用例を見ていくぞい!
DATA: lt_sflight TYPE TABLE OF sflight,
ls_row TYPE sflight.
" フィルタ条件を使用してデータを制限
SELECT * FROM sflight INTO TABLE lt_sflight UP TO 10 ROWS.
LOOP AT lt_sflight INTO ls_row.
WRITE: / ls_row-carrid, ls_row-connid, ls_row-fldate.
ENDLOOP.
このプログラムでは、SFLIGHTテーブルからデータを選択し、そのデータを内部テーブルlt_sflightに格納します。その後、LOOP命令を使用して各行をループし、航空会社ID、フライト番号、フライト日付を出力します。
例えば、フライトごとの座席数の合計を計算する場合は下記のようにコードを作成するのじゃ!
DATA: lt_sflight TYPE TABLE OF sflight,
ls_sflight TYPE sflight,
lv_total_seats TYPE i.
SELECT * FROM sflight INTO TABLE lt_sflight WHERE carrid = 'LH'.
LOOP AT lt_sflight INTO ls_sflight.
lv_total_seats = lv_total_seats + ls_sflight-seatsmax.
ENDLOOP.
WRITE: / 'Total Seats for LH:', lv_total_seats.
このプログラムでは、「carrid」が’LH’のフライトに対して座席数の合計をLOOP命令を使用して計算し、出力します。
DO命令やWHILE命令と同様、LOOP命令自体はシンプルじゃ。しかし、オプションを使用して特定の条件や範囲を設定することで、より柔軟で効率的な繰り返し処理が可能になるぞい。
特定の条件を満たす行だけを処理するために使用します。条件に合致する行だけを処理することで、不要な処理を減らすことができます。
DATA: lt_sflight TYPE TABLE OF sflight,
ls_sflight TYPE sflight.
" SFLIGHTテーブルからデータを取得
SELECT * FROM sflight INTO TABLE lt_sflight.
" WHEREオプションを使用して条件を満たす行をループ
LOOP AT lt_sflight INTO ls_sflight WHERE carrid = 'LH'.
WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDLOOP.
このプログラムでは、「carrid」が”LHの行だけをループします。
テーブルの特定の範囲の行だけを処理するために使用します。処理する行の範囲を限定することで、処理時間を短縮できます。
DATA: lt_sflight TYPE TABLE OF sflight,
ls_sflight TYPE sflight.
" SFLIGHTテーブルからデータを取得
SELECT * FROM sflight INTO TABLE lt_sflight.
" FROM/TOオプションを使用して指定した範囲の行をループ
LOOP AT lt_sflight INTO ls_sflight FROM 10 TO 20.
WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDLOOP.
この例では、内部テーブルの10行目から20行目までをループします。
フィールドシンボルはポインタのようなもので、直接データを操作でき、より柔軟なデータ操作が可能になります。
DATA: lt_sflight TYPE TABLE OF sflight.
FIELD-SYMBOLS: <fs_sflight> TYPE sflight.
" SFLIGHTテーブルからデータを取得
SELECT * FROM sflight INTO TABLE lt_sflight WHERE carrid = 'LH'.
" フィールドシンボルを使って内部テーブルの各行をループし、データを変更
LOOP AT lt_sflight ASSIGNING <fs_sflight>.
WRITE: / '最大座席数 変更前:', <fs_sflight>-seatsmax.
<fs_sflight>-seatsmax = <fs_sflight>-seatsmax + 10.
WRITE: '変更後:', <fs_sflight>-seatsmax.
ENDLOOP.
このプログラムでは、ASSIGNING句を使ってフィールドシンボルに各行を割り当て、直接内部テーブルのデータにアクセスして、各フライトの最大座席数を10増加させています。
SELECT命令は、データベーステーブルからデータを取得するための命令です。
SELECT命令で取得したデータを処理する際には、LOOP命令が頻繁に使用されますが、SELECT~ENDSELECTでブロックを作成すると、条件と一致したデータがなくなるまで1件ずつレコードの取得とブロック内に記載した処理がループして処理されます。
※ただし、SELECT~ENDSELECTはパフォーマンス悪化の原因となるため、非推奨です。
現在は非推奨の使い方の為、必ず覚える必要はないぞい!
構文
SELECT * FROM (テーブル名) INTO (変数または作業領域).
繰り返し実行する処理.
ENDSELECT.
※WHEREオプションや”SELECT SINGLE”、”UP TO n ROWS”を使用することで、繰り返し処理を行う対象のデータを絞ることができます。
* データ宣言
DATA: lv_carrid TYPE sflight-carrid, "航空会社ID
lv_connid TYPE sflight-connid, "フライト番号
lv_fldate TYPE sflight-fldate, "フライト日
lv_price TYPE sflight-price. "航空運賃
* 選択画面の宣言
PARAMETERS: p_carrid TYPE sflight-carrid. "ユーザー入力用のパラメータ
* メイン処理
START-OF-SELECTION.
* SFLIGHTテーブルからデータを選択
SELECT carrid
connid
fldate
price
INTO (lv_carrid, lv_connid, lv_fldate, lv_price)
FROM sflight
WHERE carrid = p_carrid.
* 取得したデータの出力
WRITE: / '航空会社ID:', lv_carrid,
'フライト番号:', lv_connid,
'フライト日:', lv_fldate,
'運賃:', lv_price.
ENDSELECT.
* データが見つからなかった場合のメッセージ
IF sy-subrc <> 0.
WRITE: / '指定された航空会社IDに対するフライトは見つかりませんでした。'.
ENDIF.
このプログラムは、ユーザーが入力した航空会社ID(p_carrid)に基づいて、SFLIGHTテーブルから該当するフライト情報(航空会社ID、フライト番号、フライト日、運賃)を取得し、各フライトの詳細を画面に出力します。データが見つからなかった場合には、「指定された航空会社IDに対するフライトは見つかりませんでした。」というメッセージが表示されます。
システム項目:SY-SUBRC
SELECT命令で1件でもデータを取得することができれば、「SY-SUBRC」に0が入ります。
「SY-SUBRC」が0以外の場合は対象のデータが1件も存在しなかったなどを示します。
PROVIDE~ENDPROVIDEは、複数の内部テーブルからデータを効率的に取得し、指定したキー範囲内で重複するレコードを結合して処理するための命令です。例えば、指定した期間内で2つの内部テーブルのデータをマッチングし、一致するデータを取得して処理することができます。ただし、大量のデータを処理する場合、PROVIDE命令のパフォーマンスが低下することがあり、その場合はSELECT文を使用してデータを結合した方が効率的な場合があります。
頻繁に使う命令ではないので、こんな命令もあるんだ程度で覚えておけば大丈夫だぞい!
構文
PROVIDE FIELDS (項目1 項目2…) FROM (テーブル名1) INTO (作業領域1)
VALID (フラグ1) BOUNDS (検索項目1) AND (検索項目2)
FIELDS (項目1 項目2…) FROM (テーブル名2) INTO (作業領域2)
VALID (フラグ2) BOUNDS (検索項目3) AND (検索項目4)
BETWEEN (検索範囲開始) AND (検索範囲終了).
繰り返し実行する処理.
ENDPROVIDE.
※VALID:データが有効な場合にセットされるフラグを指定します。
※BOUNDS:検索のための範囲を指定する項目を指定します。
※BETWEEN:検索する範囲を指定します。範囲外のデータは無視されます。
* 給与情報を格納する内部テーブルの定義
DATA: BEGIN OF lt_salary OCCURS 0,
salary TYPE p0008-bet01, " 給与金額
begda TYPE p0008-begda, " 開始日
endda TYPE p0008-endda, " 終了日
END OF lt_salary.
* 住所情報を格納する内部テーブルの定義
DATA: BEGIN OF lt_address OCCURS 0,
city TYPE p0006-ort01, " 都市
begda TYPE p0006-begda, " 開始日
endda TYPE p0006-endda, " 終了日
END OF lt_address.
* ワークエリアの定義
DATA: wa_salary LIKE lt_salary,
wa_address LIKE lt_address,
flag1(1) TYPE c, " フラグ1:給与情報の有効性
flag2(1) TYPE c. " フラグ2:住所情報の有効性
* 内部テーブルにデータを追加(サンプルデータ)
APPEND VALUE #( salary = '5000' begda = '20230101' endda = '20230731' ) TO lt_salary. " サンプル給与データ1
APPEND VALUE #( salary = '6000' begda = '20240101' endda = '20240731' ) TO lt_salary. " サンプル給与データ2
APPEND VALUE #( salary = '7000' begda = '20250601' endda = '20251231' ) TO lt_salary. " サンプル給与データ3
APPEND VALUE #( city = 'Tokyo' begda = '20230101' endda = '20230731' ) TO lt_address. " サンプル住所データ1
APPEND VALUE #( city = 'Osaka' begda = '20240201' endda = '20240631' ) TO lt_address. " サンプル住所データ2
APPEND VALUE #( city = 'Fukuoka' begda = '20250101' endda = '20250601' ) TO lt_address. " サンプル住所データ3
* PROVIDE命令の使用
* 指定した範囲で一致を検索する
PROVIDE FIELDS * FROM lt_salary INTO wa_salary VALID flag1 BOUNDS begda AND endda
FIELDS * FROM lt_address INTO wa_address VALID flag2 BOUNDS begda AND endda
BETWEEN '20230101' AND '20251231'.
* データの出力
WRITE: / wa_salary-begda, wa_salary-endda, " 給与データの開始日と終了日
'給与:', wa_salary-salary, flag1, " 給与金額とフラグ1
'住所:', wa_address-city, flag2. " 住所(都市)とフラグ2
ENDPROVIDE.
このプログラムは、従業員の給与情報と住所情報を保持する内部テーブルを作成し、それらのデータを範囲指定して検索・表示するものです。具体的には、指定された期間に基づいて給与と住所を一致させ、結果を出力します。
無限ループは、処理が永遠に繰り返されることを指します。この状態は、プログラム内で処理を終了するための条件が適切に設定されていないか、条件が常に真となる場合に発生します。無限ループは、その機能だけでなく、システム全体に影響を及ぼす可能性があります。例えば、サーバへの負荷をかけ続けることになり、システム全体のパフォーマンスに悪影響を与える可能性があります。
大前提として、繰り返し回数や条件を適切に指定することは、無限ループを避けるために非常に重要です。ループを抜ける条件を明確に設定することで、処理が永遠に続かず、必要なタイミングでループが終了します。
EXIT命令、CONTINUE命令、およびCHECK命令は、ループを強制的に抜けるための命令です。これらの命令を適切に使用することで、無限ループを防ぐことができます。
ABAPの繰り返し処理の、DO命令とWHILE命令、そしてLOOP命令を紹介しました。これらの命令を適切に使用することで、効率的かつ保守性の高いコードを作成することができます。
DO命令は指定回数の繰り返し処理に、WHILE命令は条件が満たされている間の繰り返し処理に適しています。一方、LOOP命令は内部テーブルの各行に対する繰り返し処理に使用されます。いずれの繰り返し命令を使用するにしても、無限ループを防ぐために、条件とループ内の処理を慎重に設計する必要があります。
この記事を通じて基本を理解した後、実際の業務シナリオでの適用方法を考えると良いぞい!
繰り返し処理をマスターすることで、より効率的なプログラムが作成できそうです!やってみます!
新着のSAPフリーランス案件
【FI】
SAP HANAバージョンアップにおける会計機能設計支援
【FI】
自動車メーカー向けS4HANA導入支援(FI/CO)
【SD】
外資系アパレル業向けSDモジュール運用保守支援
【FI】
電気機械器具向け SAP導入プロジェクト支援 FIコンサル(AA/GL/AP/AR)
【FI】
電気機械器具向け SAP導入プロジェクト支援 FI SE(基本設計者)
【FI】
食品・薬品製造販売業向けSAP運用保守支援
【MM】
【SD】
大手製造業向けECC⇒S4移行におけるグローバルテンプレート構築支援(ロジ領域)
【FI】
FI-AAモジュール 要件定義支援
【FI】
【MM】
【SD】
S4HANA導入コンサル支援(SD/MM/FI)
【CO】
【MM】
半導体製造機器製造向けSAP運用保守
SAPラボでは、SAPの知識を活かして副業をしたい方を募集してるのじゃ!
SAPラボのライターの特徴
・ライティング初心者OK!
・報酬高単価!
・業務委託契約なので副業として最適!
SAP記事執筆者としての活動実績として利用可能なので、転職時や案件探しの際に企業へのアピール材料にもなります。
募集要項
・SAP導入や運用保守プロジェクトへの参画経験1年以上
ご応募/お問合せ先
info@sap-labo.com
少しでもご興味ある方、ぜひお気軽にご連絡下さい!
新卒でSAPエンジニアとしてABAPでの新規開発や保守業務を担当。
業務内容としてはロジ系(MM/SD)がメインで、ABAPの開発が最も得意。