はじめに
ABAP7.4で、ABAPに色々な革新がもたらされました。
ABAP7.4は2013年にリリースされており新しいものではありませんが、私はこれまでに見たことや使ったことがありませんでした。
この記事では、筆者の独断で「便利だ」「使ってみたい」と感じた機能について紹介します。
ABAP7.4でリリースされた機能についての詳細は、末尾にあるリンクを参考にしてください。
ABAP7.4で何が良くなったのか
・変数の宣言が楽になった
・中間変数を減らせるので、コードを短くできる
紹介する機能
- 変数宣言
- 内部テーブルの操作
3. 内部テーブルの宣言
4. 内部テーブルの読み込み
5. 内部テーブルへの値の設定
6. 特定の行のインデックスを取得する(line_index)
7. 指定した行が存在するかどうかを確認する(line_exists) - 型変換
- 文字列操作
1. 変数宣言
変数の定義
<ABAP7.4より前>
・変数はプログラムやルーチンの先頭でまとめて定義する
・宣言時に型の定義が必要
DATA l_str type string.
l_str = 'hello'.
<ABAP7.4以降>
・変数は使いたい場所で宣言すればよい
・コンパイラが型を判断してくれる
DATA(l_str) = 'hello'.
メソッド呼び出し時の引数
メソッドから受け取る引数も、DATAを使用してその場で定義できます。
一方、汎用モジュールではDATAを利用した引数の定義はできませんでした。残念!
CALL METHOD cl_reca_date=>get_current_date
EXPORTING
id_timezone = sy-zonlo
IMPORTING
ed_time = DATA(l_time)
ed_date = DATA(l_date)
ed_timestamp = DATA(l_timestamp)
.
2. 内部テーブルの操作
内部テーブルの宣言
内部テーブルはDBを読み込むのに使うことが多いと思います。DATA宣言を使うと、SELECTで指定した項目を持つ内部テーブルを自動的に作ることができます。
DATA(l_mtart) = 'ROH'.
SELECT matnr, mtart FROM mara INTO TABLE @DATA(itab_mara) WHERE mtart = @l_mtart.
※SQL内で変数を使う場合は先頭に@をつけます。(データ定義か否かにかかわらず)
内部テーブルの読み込み
ワークエリアの作成
内部テーブルをループしてワークエリアに読み込むとき、内部テーブルの型を参照して自動的にワークエリアを作ることができます。
LOOP AT itab_mara INTO DATA(wa_mara).
WRITE: / wa_mara-matnr, wa-mtart.
ENDLOOP.
フィールドシンボルも使えます。
LOOP AT itab ASSIGNING FIELD-SYMBOL(<fs_mara>).
WRITE: / <fs_mara>-matnr, <fs_mara>-mtart.
ENDLOOP.
指定した行を読み込む方法
<ABAP7.4より前>
・内部テーブルを読み込む際はインデックス、またはキーを指定してワークエリアに行を格納する
DATA: wa_mara LIKE LINE OF itab_mara.
READ TABLE itab_mara INTO w_mara INDEX 1.
READ TABLE itab_mara INTO w_mara WITH KEY matnr = 'BRICK002'.
<ABAP7.4以降>
・インデックスやキーを指定して直接行にアクセスできる
" インデックスを指定
wa_mara = itab_mara[ 1 ].
" キーを指定
wa_mara = itab_mara[ matnr = 'BRICK002' ].
データが読み込めない場合、例外CX_SY_ITAB_LINE_NOT_FOUNDが発生します。
ABAP7.4 SP8からは、例外が発生しないようにOPTIONALまたはDEFAULTを指定できるようになりました(VALUE #と組み合わせること)。
OPTIONALを指定した場合は、READ TABLEで対象の行がなかった場合と同じように初期値が返されます。
wa_mara = VALUE #( itab_mara[ matnr = 'BRICK002b' ] OPTIONAL ).
内部テーブルへの値の設定
直接値を設定する
<ABAP7.4より前>
・ワークエリアで値を編集し、それを内部テーブルに格納する
DATA: lr_sel_mara TYPE RANGE OF mtart,
wa_sel_mara LIKE LINE OF lr_sel_mara.
wa_sel_mara-sign = 'I'.
wa_sel_mara-option = 'EQ'.
wa_sel_mara-low = 'ROH'.
APPEND wa_sel_mara TO lr_sel_mara.
wa_sel_mara-low = 'HAWA'.
APPEND wa_sel_mara TO lr_sel_mara.
<ABAP7.4以降>
・VALUEを使って内部テーブルに値を直接入れることができる
構文その1: VALUE <型> ((行データ1) (行データ2)...)
型を明示的に指定する方法です。
TYPES: t_sel_mara TYPE RANGE OF mtart.
DATA(lr_sel_mara2) = VALUE t_sel_mara(
( sign = 'I' option = 'EQ' low = 'ROH')
( sign = 'I' option = 'EQ' low = 'HAWA')
).
構文その2: VALUE # ((行データ1) (行データ2)...)
テーブルの型が設定先の変数から推測できる場合はこちらの構文が使えます。
DATA: lr_sel_mara3 TYPE RANGE OF mtart.
lr_sel_mara3 = VALUE #(
( sign = 'I' option = 'EQ' low = 'ROH')
( sign = 'I' option = 'EQ' low = 'HAWA')
).
sign, optionが共通の場合、次のような書き方もできます。
lr_sel_mara3 = VALUE #(
sign = 'I' option = 'EQ' ( low = 'ROH') ( low = 'HAWA')
).
特定の行のインデックスを取得する(line_index)
<ABAP7.4より前>
・READ TABLEなどで行を読み込み、sy-tabixを取得する
DATA: l_index type sy-tabix.
READ TABLE itab_mara TRANSPORTING NO FIELDS with key matnr = 'BRICK002'.
l_index = sy-tabix.
<ABAP7.4以降>
・line_index命令でインデックスを取得できる
l_index = line_index( itab_mara[ matnr = 'BRICK002' ] ).
指定した行が存在するかどうかを確認する(line_exists)
<ABAP7.4より前>
・READ TABLEして、sy-subrcの値で判断する
READ TABLE itab_mara TRANSPORTING NO FIELDS WITH KEY matnr = 'BRICK002'.
IF sy-subrc = 0.
"存在する場合の処理
ELSE.
"存在しない場合の処理
ENDIF.
<ABAP7.4以降>
・line_exists命令で判断できる
line_existsはブール値を返します。
ABAP7.4から、IF条件の結果がtureのときは if <変数> = abap_true
という風にabap_trueを書かなくてもよくなったので、以下のような簡潔な書き方ができます。
IF line_exists( itab_mara[ matnr = 'BRICK002' ] ).
"存在する場合の処理
ELSE.
"存在しない場合の処理
ENDIF.
3. 型変換
サブルーチンで受け取った引数を汎用モジュールに渡すとき、汎用モジュールの型に合わせるために中間変数を定義したことはないでしょうか?
<ABAP7.4より前>
・中間変数に引数を格納して型変換し、汎用モジュール等に渡す
DATA: im_text(50) TYPE c,
l_str TYPE string, "中間変数
l_xstr TYPE xstring.
im_text = 'Hello'.
l_str = im_text.
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = l_str
IMPORTING
buffer = l_xstr
.
<ABAP7.4以降>
・CONV命令で直接型を変換できる
・VALUEと同じく、型を明示的に指定する方法と#で暗黙的に指定する方法がある
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = CONV string( im_text ) "明示的に型を指定
IMPORTING
buffer = l_xstr
.
4. 文字列操作
文字列結合
<ABAP7.4より前>
・CONCATENATEで文字列を結合
・結合する文字列の中にクォーテーション(')を使いたい場合、エスケープする必要がある
DATA: im_comment(10) TYPE c,
l_out TYPE string.
im_comment = 'Hello!'.
CONCATENATE 'He said' '''' im_comment '''' INTO l_out SEPARATED BY space.
<ABAP7.4以降>
・||
で囲った中にリテラルや変数を直接書き込むことができる
・変数は{}
で囲む
l_out = |He said '{ im_comment }'|.
l_out2 = |Date: { sy-datum } Time: { sy-uzeit }|.
Alpha変換
Alpha変換とは、内部書式(前ゼロつき)と外部書式(前ゼロなし)の変換のことです。
<ABAP7.4より前>
・汎用モジュール'CONVERSION_EXIT_ALPHA_INPUT'/'CONVERSION_EXIT_ALPHA_OUTPUT'を使って変換する
DATA: lv_input TYPE ebeln.
DATA: lv_output TYPE ebeln.
lv_input = 12345.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING
input = lv_input
IMPORTING
output = lv_output. "0000012345
<ABAP7.4以降>
・|{ <変数> ALPHA = IN / OUT }|
で変換できる
DATA: lv_input TYPE ebeln.
DATA: lv_output TYPE ebeln.
lv_input = 12345.
lv_output = |{ lv_input alpha = IN }|. "0000012345
おわりに
ここで紹介した以外にも、ABAP7.4で登場した構文は色々あります。以下のブログがよくまとまっていておすすめなので興味のある方は読んでみてください。
ABAP 7.40 Quick Reference
参考
[ABAP News for Release 7.40 – What is ABAP 7.40?]
(https://blogs.sap.com/2013/05/22/abap-news-for-release-740-2/)
ABAP News for 7.40, SP08 – More for Internal Tables
ABAP to the Future
ABAP 7.40 Quick Reference