モダン ABAP の文字列処理

ABAP プログラミングでは、事前定義 ABAP データ型の c や string、ABAP ディクショナリデータ型 の CHAR や STRING を使って文字列を処理する。

c や CHAR は、固定長の領域に文字列を格納する。変数宣言やドメインで定義した長さ(文字数)で文字列が処理される。

以下のコードでは、文字列変数 gdf_value をデータ型 c、長さ 5 で定義して、最初に 4 文字の文字列、次に 6 文字の文字列を変数 gdf_value に代入している。

DATA gdf_value TYPE c LENGTH 5 VALUE space.

.... 

gdf_value = 'abcd'.    "4 文字代入

WRITE gdf_value.

gdf_value = 'abcdef'.  "6 文字代入

WRITE: / gdf_value.

実行結果は、以下のようになる。

文字長 5 の変数 gdf_value に対して、最初に代入した文字列 'abcd' は 4 文字なので、文字列全体が正しく一覧画面に表示されるが、次に代入した文字列 'abcdef' は 6 文字なので、最後の文字 f が欠けた状態で表示される。

一方、string や STRING は、可変長の領域に文字列を格納する。代入された文字列に応じて領域の大きさが調整されます。

変数 gdf_value をデータ型 string に変更すると、

DATA gdf_value TYPE string VALUE space.

実行結果は、以下のようになる。

代入された文字列に合わせて変数 gdf_value の領域が可変するので、文字列 'abcdef' が正しく表示されています。

多くの SAP 標準アプリケーションでは、文字列データを固定長で管理しているので、 ABAP でアドオン開発する際も、固定長の c や CHAR を使った文字列処理が一般的でした。しかし、モダン ABAP では、一般的なプログラミング言語のように、文字列を可変長で処理することを想定して機能拡張が行われています。

例えば、2 章で変数のインライン宣言を学習しましたが、代入する文字列を`(バッククォート)で囲んで指定すると、データ型 string の文字列変数が自動生成されます。

上記のコードを変更して、文字列を代入する変数 ldf_value をインライン宣言します。まず、代入する文字列を従来の '(シングルクォート)で囲んで記述します。

DATA(ldf_value) = 'abcd'.  "シングルクォートで 4 文字代入

WRITE ldf_value.

ldf_value = 'abcdef'.      "6 文字代入

WRITE: / ldf_value.

実行結果は、以下のようになります。

インライン宣言した変数 ldf_value は、最初の文字列 'abcd' に合わせて長さ 4 のデータ型 c で生成されます。従って、次に代入した文字列 'abcdef' の 5 文字目以降が欠けて表示されています。

続いて、インライン宣言の文字列を `(バッククォート)で書き換えます。

DATA(ldf_value) = `abcd`.  "バッククォートで 4 文字代入

....

実行結果は、以下のようになります。

文字列 `abcd` がバッククォートで囲まれているので、インライン宣言の変数 ldf_value はデータ型 string で生成されます。従って、次に代入した文字列 'abcdef' も正しく表示されます。

なお、インライン宣言以外でも、モダン ABAP で文字列を記述する際には、固定長には ' (シングルクォート)、可変長には `(バッククォート)を使い分けることが推奨されています。

文字列関数とは

モダン ABAP では、文字列を処理するための関数が追加されています。関数Function)とは、Returning パラメーターを持つクラスのメソッドのように、sy処理結果を = の左辺に返す組み込み機能で、式指向コーディングで演算子と組み合わせて使用できる仕組みです。

従来の ABAP コーディングでは、REPLACE や TRANSLATE、CONDENSE 等のステートメントを使って文字列を処理していました。しかし、こうしたステートメントは、式(Expression)のなかに組み込んで使用できないので、モダン ABAP で式指向コーディングを行うために、文字列処理のステートメントを代替する関数が提供されました。

関数は、関数名の後に ( ) を記述し、( ) のなかに関数に引き渡す値を指定します。また、関数で処理された結果は、関数名の前に記述した = の左辺に引き渡されます。ABAP プログラミング基礎の 23 章で学習したメソッドの Functional Method Call と同様の使い方が可能です。

主な文字列関数は、以下の通りです。

関数名機能代替ステートメント
replace文字列置換REPLACE
to_lower小文字変換TRANSLATE .... TO LOWER CASE
to_upper大文字変換TRANSLATE .... TO UPPER CASE
condense半角スペース除去CONDENSE
count文字列カウント
find文字列位置取得
contains文字列存在確認
strlen文字数カウント
substring文字列切り出し

replace 関数を使った文字列置換

従来のコーディングでは、変数に格納された文字列を置き換える際に REPLACE ステートメントを使用していました。

以下は、ABAP プログラミング基礎 10 章の「2. 文字列の置き換え」の項で学習した REPLACE ステートメントのサンプルコードです。事前定義 ABAP データ型 c の変数 gdf_value に格納された文字列 'abcdefg' の 'cde' の部分を 'ZZZ' に置き換えて 'abZZZfg' にする処理を記述しています。

DATA gdf_value TYPE c LENGTH 7 VALUE 'abcdefg'.

.... 

REPLACE 'cde' IN gdf_value WITH 'ZZZ'.

この処理を replace 関数を使って書き換えられます。replace 関数の基本形は以下の通りです。

replace( val = 処理対象の文字列 sub = 置換前の文字列 with = 置換後の文字列 )

関数名の replace の直後に (、半角スペース、処理対象の文字列を引き渡すためのパラメーター名 val、前後に半角スペースを挟んで = を記述し、処理対象の文字列や変数名を指定します。

次に、半角スペースを挟んで、処理対象の文字列に含まれる置き換え前の文字列を指定するパラメーター名 sub、前後に半角スペースを挟んで =、その後に置換前の文字列を指定します。

続いて、半角スペースを挟んで、置換後の文字列を指定するパラメーター名 with、前後に半角スペースを挟んで =、その後に置き換え後の文字列を指定し、最後に半角スペースを挟んで ) を記述します。

なお、replace の前に = を指定すると、左辺に文字列置換の結果が返されます。また、パラメーターに引き渡す文字列を変数で指定できます。

上記の REPLACE ステートメントを replace 関数に書き換えると、以下のようになります。

gdf_value = replace( val = gdf_value sub = 'cde' with = 'ZZZ' ).

REPLACE の後に記述した置換前の文字列を sub パラメーター、IN 句で指定した処理対象の変数を val パラメーター、WITH 句で指定した置換後の文字列を with パラメーターで指定しています。

また、REPLACE ステートメントと同様に、文字列置換の結果をそのまま元の変数に上書きするため、左辺に処理対象の変数 gdf_value を指定しています。なお、replace 関数を使えば、処理対象の変数を上書きしないで、置換後の文字列を別の変数に代入できます。以下のコードは、置換後の文字列をインライン宣言した変数 ldf_result に代入しています。

DATA(ldf_result) = replace( val = gdf_value sub = 'cde' with = 'ZZZ' ).

to_lower と to_upper 関数を使った文字列変換

to_lower 関数は、アルファベットの文字列を小文字に変換し、to_upper 関数は大文字に変換します。従来の TRANSLATE ステートメントを代替します。

以下は、ABAP プログラミング基礎 10 章の「3. 文字列の変換」の項で学習した TRANSLATE ステートメントのサンプルコードです。事前定義 ABAP データ型 c の変数 gdf_value に文字列 'aBcDeFg' が更新されている場合、TO  LOWER CASE 句を指定すると gdf_value の値が 'abcdefg' に、TO UPER CASE 句を指定すると gdf_value の値が 'ABCDEFG' に変換されます。

TRANSLATE gdf_value TO LOWER CASE.

TRANSLATE gdf_value TO UPPER CASE.

to_lower、to_upper 関数の基本形は以下の通りです。

to_lower( val = 処理対象の文字列 ) または、 to_lower( 処理対象の文字列 )

to_upper( val = 処理対象の文字列 ) または、 to_upper( 処理対象の文字列 )

関数名の直後に (、半角スペース、処理対象の文字列を引き渡すためのパラメーター名 val、前後に半角スペースを挟んで =、処理対象の文字列を指定して、最後に半角スペースを挟んで ) を記述します。なお、( ) で指定するパラメーターが1つなので val = の記述を省略できます。また、パラメーターに引き渡す文字列を変数で指定できます。関数名の前に = を指定すると、左辺に文字列変換の結果が返されます。

上記の TRANSLATE ステートメントを関数で書き換えると、以下のようになります。

gdf_value = to_lower( gdf_value ).

gdf_value = to_upper( gdf_value ).

TRANSLATE の後に記述した処理対象の変数名を ( ) の中に指定しています。また、文字列変換の結果をそのまま元の変数に上書きするため、左辺に処理対象の変数 gdf_value を指定しています。なお、translate 関数と同様に、変換結果を別の変数に代入することも可能です。

condense 関数を使った半角スペース除去

condense 関数は、文字列の前後の半角スペースを削除し、文字列中の連続する半角スペースを1文字分のスペースに圧縮します。従来の CONDENSE ステートメントを代替します。

以下は、ABAP プログラミング基礎 10 章の「7. 半角スペースの除去」の項で学習した CONDENSE ステートメントのサンプルコードです。例えば、変数 gdf_value に文字列 ' AB  C  ' が更新されている場合、CONDENSE ステートメントで 'A' の前、'C' 後の半角スペースが削除され、'B' と 'C' の間にある2文字分の半角スペースを1文字分に圧縮されて 'AB C' に変換されます。

CONDENSE gdf_value.

condense 関数の基本形は以下の通りです。

condense( val = 処理対象の文字列 ) または、 condense( 処理対象の文字列 )

関数名 condense の直後に (、半角スペース、処理対象の文字列を引き渡すためのパラメーター名 val、前後に半角スペースを挟んで =、処理対象の文字列や変数名を指定して、最後に半角スペースを挟んで ) を記述します。なお、この記述方法の場合は、val = の記述を省略できます。また、パラメーターに引き渡す文字列を変数で指定できます。condense の前に = を指定すると、左辺に半角スペースが除去された文字列が返されます。

上記の CONDENSE ステートメントを condense 関数で書き換えると、以下のようになります。

gdf_value = condense( gdf_value ).

CONDENSE の後に記述した処理対象の変数名を ( ) の中に指定しています。なお、このコードでは、処理結果を元の変数に上書きしていますが、前述の文字列関数と同様に、処理結果を別の変数に代入することも可能です。

CONDENSE ステートメントで NO-GAPS 句を追加すると、文字列のすべての半角スぺースが除去されます。以下のコードでは、変数 gdf_value の文字列が ' AB  C  ' から 'ABC' に変換されます。

CONDENSE gdf_value NO-GAPS.

condense 関数で同様の処理を行うには、以下のように記述します。

condense( val = 処理対象の文字列 from = ` ` to = `` )

( ) の中で、val パラメーターで処理対象の文字列を指定した後で、半角スペースを挟んで from、前後に半角スペースを挟んで =、その後に `(バッククォート)、半角スペース、`(バッククォート) を記述します。処理対象の文字列は変数でも指定できます。

続いて、半角スペースを挟んで to、前後に半角スペースを挟んで =、その後に ``(バッククォートを2つ連続)、最後に半角スペースを挟んで ) を記述します。

上記の CONDENSE .... NO GAPS ステートメントを書き換えると、以下のようになります。

gdf_value = condense( val = gdf_value from = ` ` to = `` ). 

関数を使った文字列確認

count は、指定した文字や文字列が、確認対象の文字列の中にいくつ含まれているかを確認する関数です。基本形は以下の通りです。

count( val = 確認対象の文字列 sub = 指定の文字や文字列 )

関数名 count の直後に (、半角スペース、確認対象の文字列を引き渡すためのパラメーター名 val、前後に半角スペースを挟んで =、処理対象の文字列や変数名を指定します。

続いて、半角スペースを挟んで特定文字列を指定するパラメーター名 sub、前後に半角スペースを挟んで =、指定の文字や文字列、半角スペースを挟んで、最後に ) を記述します。

パラメーターで引き渡す文字列は変数で指定できます。なお、count の前に = を指定すると、確認結果が整数値で左辺に返されます。

以下のコードは、文字列 'ABAP' の中に 'A' がいくつ含まれているのかを count 関数を使って確認しています。

DATA(ldf_count) = count( val = 'ABAP' sub = 'A' ).

val パラメーターに確認対象の文字列 'ABAP' を、sub パラメーターには 'A' を指定しています。コードを実行すると、左辺にインライン宣言した変数 ldf_count に 2 が代入されます。

次のコードは、count 関数を使って住所の判定を行っています。変数 gdf_value に更新された住所情報に「港区」の文字列が 1 つ以上含まれている = count 関数の戻り値が 0 より大きい場合は、一覧画面に「これは、港区の住所です。」を表示します。

DATA: gdf_value TYPE c LENGTH 100 VALUE space,

....

DATA(ldf_count) = count( val = gdf_value sub = '港区' ).

IF ldf_count > 0.

  WRITE: / 'これは、港区の住所です。'.

ENDIF.

なお、count 関数は式指向でコードできるので、IF ステートメントに組み込んで簡潔に記述できます。

IF count( val = gdf_value sub = '港区' ) > 0.

  WRITE: / 'これは、港区の住所です。'.

ENDIF.

find は、指定した文字や文字列が、確認対象の文字列の何文字目にあるのかを確認する関数です。基本形は以下の通りです。

find( val = 確認対象の文字列 sub = 指定の文字や文字列 )

記述方法は、count 関数と同様です。find の前に = を指定すると、確認結果が整数値で左辺に返されます。文字列の1文字目にある場合は 0、2文字目は 1 、3文字目は 2、、、、のように 文字位置から 1 を引いた値が返されます。なお、指定した文字が存在しない場合は、-1 が返されます。

以下のコードは、文字列 'ABAP' の中にある 'A' と 'Z' の位置を確認しています。

DATA(ldf_find_a) = find( val = 'ABAP' sub = 'A' ).

DATA(ldf_find_z) = find( val = 'ABAP' sub = 'Z' ).

文字列 'ABAP' の中には複数の 'A' が存在するので、最初の 'A' の位置が左辺に返されます。最初の 'A' は 1 文字目なので、変数 ldf_find_a には、0 が代入されます。また、文字列 'ABAP' には 'Z' が含まれていないので、変数 ldf_find_z の方には -1 が代入されます。

次のコードは、count 関数を使った住所判定のコードを find 関数で書き換えています。変数 gdf_value に更新された住所情報に「港区」の文字列が含まれている = count 関数の戻り値が -1 より大きい場合に、「これは、港区の住所です。」を一覧画面に表示します。

IF find( val = gdf_value sub = '港区' ) > -1.

  WRITE: / 'これは、港区の住所です。'.

ENDIF.

contains は、指定した文字や文字列が確認対象の文字列に含まれているかどうかを確認して、true(真)または false(偽)で結果を返す関数です。基本形は以下の通りです。

contains( val = 確認対象の文字列 sub = 指定の文字や文字列 )

記述方法は、count や find 関数と同様ですが、countains の前に = を指定しないで、条件判断の式に組み込んで使用します。指定した文字が含まれている場合は true、含まれていない場合は false と判断されます。

以下のコードは、前述の住所判定の処理を contains 関数で書き換えています。contains 関数自体で条件判断のロジックを代替できるので、count や find 関数のような戻り値を判断するコードが不要です。

IF contains( val = gdf_value sub = '港区' ).

  WRITE: / 'これは、港区の住所です。'.

ENDIF.

関数を使った文字列抽出

strlen は、文字列の長さ(文字数)を確認する関数です。基本形は以下の通りです。

strlen( 処理対象の文字列 )

関数名 strlen の直後に (、半角スペース、文字数を確認する文字列を指定し、最後に半角スペースを挟んで ) を記述します。パラメーター名は記述しません。文字列は変数で指定できます。

strlen の前に = を指定すると、文字数果が整数値で左辺に返されます。なお、文字列の先頭や、文字列の間に半角スペースがある場合は、半角スペースも文字として識別されます。

以下のコードは、文字列 ’abcdef' を '(シングルクォート)で囲って指定し、 strlen 関数を使って文字数を確認しています。変数 ldf_result には 6 が代入されます。

data(ldf_result) = strlen( 'abcdef' ).

次のコードは、a の前と、各文字の間、f の後に半角スペースを挟んだ文字列 ' a b c d e f ' を ' で囲って文字数を確認しています。6 文字のアルファベットと、a の前と文字の間に挟まれた 6 つの半角スペースを合わせた 12 が変数 ldf_result に代入されます。

data(ldf_result) = strlen( ' a b c d e f ' ).

なお、string 型の文字列の場合は、文字列の最後にある半角スペースも文字として識別されるので注意が必要です。

次のコードは、a の前と、各文字の間、f の後に半角スペースを挟んだ文字列 ` a b c d e f ` を `(バッククォート)で囲って文字数を確認しています。f の後にある半角スペースもカウントされるので、変数 ldf_result には 13 が代入されます。

data(ldf_result) = strlen( ` a b c d e f ` ).

substring は、文字列の一部を抽出する関数です。基本形は以下の通りです。

substring( val = 抽出元の文字列 off = 抽出の開始位置 len = 抽出する文字数 )

関数名 substring の直後に (、半角スペース、抽出元の文字列を引き渡すためのパラメーター名 val、前後に半角スペースを挟んで =、抽出元の文字列や変数名を指定します。

次に、半角スペースを挟んで、抽出する文字列の開始位置(オフセット)を指定するパラメーター名 off、前後に半角スペースを挟んで =、抽出を開始する文字位置を整数値で指定します。文字位置は、find 関数の戻り値と同様に、1 文字目であれば 0、2 文字目では 1 、3 文字目は 2、、、のように 1 を引いた値で指定します。

続いて、半角スペースを挟んで、抽出する文字列の長さ(文字数)を指定するパラメーター名 len、前後の最後に半角スペースを挟んで =、抽出する文字数を整数値で指定し、半角スペースを挟んで、最後に ) を記述します。

substring の前に = を指定すると、抽出された文字列が左辺に返されます。なお、抽出元の文字列を '(シングルクォート)で囲んだ場合でも、戻り値の文字列は string 型になります。

以下のコードは、文字列 `abcdef` を抽出元にして、 2文字目の b から 3 文字分の文字列 `bcd` を抽出しています。

data(ldf_back) = substring( val = `abcdef` off = 1 len = 3 ).

次のコードは、変数 gdf_value に港区の住所が格納されていた場合に、港区の後に続く町名や番地の文字列を抽出して変数 ldf_street に代入しています。

IF contains( val = gdf_value sub = '港区' ).

  ....

  data(ldf_off) = find( val = gdf_value sub = '港区' ) + 2.

  data(ldf_len) = strlen( gdf_value ) - ldf_off.

  DATA(ldf_street) = substring( val = gdf_value off = ldf_off len = ldf_len ).

  WRITE: / '町名以降の住所は、', ldf_street, 'です。'.

ENDIF.

まず、conains 関数を使って、変数 gdf_value に格納された住所に「港区」の文字列が含まれているかを確認しています。

次に、find 関数を使って、文字列「港区」の開始位置を確認し、開始位置から「港区」の 2 文字分を加算した位置 = 町名の開始位置を変数 ldf_off に代入しています。

続いて、strlen 関数を使って、変数 gdf_value に格納された住所全体の文字数を取得し、住所全体の文字数から町名の開始位置を減算した数 = 町名以降の文字数を変数 ldf_len に代入しています。

そして、substring 関数で、off パラメーターに町名の開始位置、len パラメーターに町名以降の文字数を指定し、抽出した文字列を変数 ldf_street に代入して、最後に一覧画面に表示しています。

&& 演算子を使った文字列結合

&& は、文字列を結合するための演算子です。従来の CONCATENATE ステートメントを代替します。式指向のコーディングで文字列を結合できます。

以下のコードは、従来のコーディングでデータ型 c の変数に格納された文字列を結合しています。

DATA: gdf_value  TYPE c LENGTH 100 VALUE space,

    gdf_text_1 TYPE c LENGTH 20  VALUE '東京都',

      gdf_text_2 TYPE c LENGTH 20  VALUE '港区',

      gdf_text_3 TYPE c LENGTH 20  VALUE '三田',
   
      gdf_text_4 TYPE c LENGTH 20  VALUE '1-4-28'.  

....

CONCATENATE gdf_text_1 gdf_text_2 gdf_text_3 gdf_text_4 INTO gdf_value.

このコードを実行すると、変数 gdf_value には、文字列 '東京都港区三田1-4-28' が代入されます。

文字列を結合する処理を && 演算子を使って記述できます。基本形は以下の通りです。

1 つ目の文字列1 && 2 つ目の文字列 ....

結合したい文字列の間に && を記述します。&& の前後には半角スペースを挟みます。なお、文字列を変数で指定できます。1つ目の文字列の前に = を指定すると、左辺に結合された文字列が返ります。

上記の CONCATENATE ステートメントを && 演算子で書き換えると、以下のようになります。

gdf_value = gdf_text_1 && gdf_text_2 && gdf_text_3 && gdf_text_4.

CONCATENATE ステートメントと同様に、結合する文字列の後に含まれる半角スペースは無視されるので、文字列 '東京都港区三田1-4-28' が変数 gdf_value に代入されます。

左辺に変数をインライン宣言すると、結合する文字列のデータ型に関係なく、string 型で変数が生成されます。以下のコードでは、結合する 4 つの文字列変数のデータ型が c ですが、

DATA: gdf_text_1 TYPE c LENGTH 20 VALUE '東京都',

      gdf_text_2 TYPE c LENGTH 20 VALUE '港区',

      gdf_text_3 TYPE c LENGTH 20 VALUE '三田',
   
      gdf_text_4 TYPE c LENGTH 20 VALUE '1-4-28'.  

....

DATA(ldf_value) = gdf_text_1 && gdf_text_2 && gdf_text_3 && gdf_text_4.

以下のように、インライン宣言で生成される変数 ldf_value のデータ型は string になります。

また、結合する文字列が string 型で、文字列の後に半角スペースが意図的に挿入されている場合は、半角スペースも含めて文字列が結合されるので注意が必要です。

例えば、以下のコードを実行すると、

DATA: gdf_string_1 TYPE string VALUE `東京都 `,

      gdf_string_2 TYPE string VALUE `港区 `,

      gdf_string_3 TYPE string VALUE `三田 `,
   
      gdf_string_4 TYPE string VALUE `1-4-28 `.  

....

DATA(ldf_value) = 
  gdf_string_1 && gdf_string_2 && gdf_string_3 && gdf_string_4.

変数 ldf_value には、文字列 `東京都 港区 三田 1-4-28 `が代入されます。

文字列テンプレート

文字列テンプレート(String Template)機能を使うと、変数の値や式の実行結果を文字列の中に簡易に埋め込めます。文字列の前後に |(パイプ)を挟み、埋め込む変数や式を { } (波括弧)で囲んで、文字列テンプレートを作成します。

以下のコードは、文字列テンプレートで文字列を編集して、インライン宣言した変数 ldf_string に代入します。まず、元の文字列「名前は、です。」を | で囲んで、テンプレートを定義しています。

DATA(ldf_string) = |名前は、です。|.

この文字列テンプレートにデータ型 c の変数 gdf_name の値を埋め込みます。埋め込む位置に { } で囲んで変数名 gdf_name を指定します。なお、{ と後と } の前には半角スペースを挟みます。

DATA gdf_name TYPE c LENGTH 20 value '大谷翔平'.

....

DATA(ldf_string) = |名前は、{ gdf_name }です。|.

このコードを実行すると、変数 ldf_string には、文字列「名前は、大谷翔平です。」が代入されます。なお、変数 gdf_name の長さは 20 ですが、値の後の不要な半角スペースは除去されて文字列に埋め込まれます。また、文字列テンプレートの左辺をインライン宣言すると、string 型で変数が生成されます。

文字列テンプレートは、複数の変数を組み込んで、文字列を結合することも可能です。

以下のコードは、文字列テンプレートを使って、4 つの変数に格納された文字列を1つにまとめて変数 ldf_string に代入しています。

DATA: gdf_text_1 TYPE c LENGTH 20 VALUE '東京都',

      gdf_text_2 TYPE c LENGTH 20 VALUE '港区',

      gdf_text_3 TYPE c LENGTH 20 VALUE '三田',
   
      gdf_text_4 TYPE c LENGTH 20 VALUE '1-4-28'.  

....

DATA(ldf_string) = |{ gdf_text_1 }{ gdf_text_2 }{ gdf_text_3 }{ gdf_text_4 }|.

このコードを実行すると、変数 ldf_string には、文字列「東京都港区三田1-4-28」が代入されます。これは、&& 演算子を使った以下のコードと同じに処理結果になります。

DATA(ldf_string) = gdf_text_1 && gdf_text_2 && gdf_text_3 && gdf_text_4.

文字列テンプレートを使って、文字以外の値も埋め込めます。

以下のコードは、従来のコーディングで、文字列にデータ型 i の変数の値を埋め込んでいます。変数 gdf_height の値をデータ型 string に代入して文字列に変換してから、文字列結合で値を埋め込んでいます。

DATA: gdf_name     TYPE c LENGTH 20 value '大谷翔平',
    
      gdf_height   TYPE i           value 193,

      gdf_height_s TYPE string,

      gdf_string   TYPE string.

....

MOVE gdf_height TO gdf_height_s.  "代入で数値を文字列に変換

CONCATENATE '名前は、' gdf_name  'で、身長は、' gdf_height_s 'です。' INTO gdf_string.

文字列テンプレートを使って書き直すと、以下のようになります。

DATA(ldf_string) = |名前は、{ gdf_name }で、身長は、{ gdf_height }です。|.

テンプレートの中にデータ型 i の変数を指定すれば、自動的に整数値が文字列に変換されます。変数 ldf_string には、文字列「名前は、大谷翔平で、身長は、193です。」が代入されます。

文字列テンプレートに式を組み込んで、実行結果を文字列に埋め込めます。

以下のコードは、選択画面で指定された底辺と高さの値を使って四角形の面積を計算し、計算結果を一覧画面に表示しています。

DATA: gdf_area   TYPE i,      

      gdf_area_s TYPE string, 

      gdf_string TYPE string.  

....

PARAMETERS: p_base   TYPE i OBLIGATORY,  "底辺

            p_height TYPE i OBLIGATORY.  "高さ

....

gdf_area = p_base * p_height.  "面積を計算

MOVE gdf_area TO gdf_area_s.   "計算結果を文字列に変換

CONCATENATE '四角形の面積は、  "表示文章を編集
            ' gdf_area_s  
            'です。' 
            INTO gdf_string.

WRITE gdf_string.

面積の計算と計算結果の文字列変換、そして一覧画面に表示する文章の編集までの処理を、以下のように文字列テンプレートで置き換えられます。

DATA(ldf_string) = |四角形の面積は、{ p_base * p_height } です。|.

面積の計算式を { } で囲んで文字列テンプレートに組み込んでいます。計算結果が文字列に変換され、前後の文字列と結合されて、インライン宣言された変数 ldf_string に代入されます。例えば、選択画面の底辺項目(p_base)に 2、高さ項目(p_height)に 5 が入力された場合、文字列テンプレートで「四角形の面積は、10 です。」が編集されて一覧画面に表示されます。

文字列テンプレートには、様々なオプションが用意されています。

例えば、CASE オプションを使うと、大文字または小文字に変換して文字列を挿入できます。基本形は以下の通りです。

{ 変数名 CASE = UPPER または LOWER または RAW }

{、半角スペース、変数名の後に、前後に半角スペースを挟んで =、その後に、大文字に変換する場合は UPPER、小文字に変換する場合は LOWER、変換しない場合は RAW を指定し、半角スペースを挟んで } で閉じます。なお、変数名の代わりに文字列を指定できます。文字列は、'(シングルクォート)または `(バッククォート)で囲んで記述します。

以下のコードは、文字列 `Hello World` が格納された変数 gdf_string を、文字列テンプレートの CASE オプションを使って変換しています。変数 ldf_upper には `HELLO WORLD`、ldf_lower には `hello world` が代入されます。なお、RAW が指定されているので、変数 ldf_raw には元の文字列 `Hello World` が代入されます。

DATA gdf_string TYPE string VALUE `Hello World`.

....

DATA(ldf_upper) = |{ gdf_string CASE = UPPER }|.

DATA(ldf_lower) = |{ gdf_string CASE = LOWER }|.

DATA(ldf_raw) =   |{ gdf_string CASE = RAW }|.

また、LENGTH は、変換後の文字列の長さを指定するオプションです。さらに、ALIGN オプションを追加すると、文字詰めの方向を指定できます。基本形は以下の通りです。

{ 変数名 LENGTH = 文字数 ALIGN = RIGHT または LEFT }

LENGTH の後には文字数、ALIGN の後には、RIGHT(右詰め)または LEFT(左詰め)を指定します。

以下のコードは、変数 gdf_string の文字列 `Hello World` を 20 文字の長さに変換しています。ALIGN オプションが指定されているので、変数 ldf_right には右詰めで `     Hello World` が、変数 ldf_left には左詰めで `Hello World     ` が代入されます。

DATA gdf_string TYPE string VALUE `Hello World`.

....

DATA(ldf_right) = |{ gdf_string LENGTH = 20 ALIGN = RIGHT }|.

DATA(ldf_left)  = |{ gdf_string LENGTH = 20 ALIGN = LEFT }|.

日付や時間、数値の文字列を編集するオプションも用意されています。

以下のコードは、文字列テンプレートを使って、販売伝票の情報を一覧画面に表示しています。

DATA gds_vbak TYPE vbak.  "販売伝票ヘッダー

....

DATA(ldf_string) = |伝票番号は、{ gds_vbak-vbeln } です。|.

WRITE ldf_string.

ldf_string = |登録日付は、{ gds_vbak-erdat } です。|.

WRITE / ldf_string.

ldf_string = |登録時刻は、{ gds_vbak-erzet } です。|.

WRITE / ldf_string.

ldf_string = |販売金額は、{ gds_vbak-netwr } { gds_vbak-waerk } です。|.

WRITE / ldf_string.

実行結果は、以下のようになります。

文字列テンプレートで、DATE(日付)、TIME(時刻)、NUMBER(数値)のオプションを追加し、オプション名の後に USER を指定すると、ユーザープロファイルのデフォルト設定に合わせて文字列が編集されます。基本形は以下の通りです。

{ 変数名 DATE = USER }

{ 変数名 TIME = USER }

{ 変数名 NUMBER = USER }

以下のコードは、登録日付に DATE、登録時刻に TIME、そして販売金額に NUMBER オプションを追加しています。

ldf_string = |登録日付は、{ gds_vbak-erdat DATE = USER } です。|.

....

ldf_string = |登録時刻は、{ gds_vbak-erzet TIME = USER } です。|.

....

ldf_string =
  |販売金額は、{ gds_vbak-netwr NUMBER = USER } { gds_vbak-waerk } です。|.

例えば、ユーザー管理(Tr-Cd: su01)のデフォルトタブ画面で、以下のような設定になっていた場合、

オプションを追加したコードを実行すると、結果は以下のようになります。

ユーザーのデフォルト設定に合わせて、登録日付は YYYY/MM/DD 形式、登録時刻は HH:MM:SS 形式で表示されます。また、販売金額は、3 桁区切りが ,(カンマ)、小数点は .(ピリオド)で表示されます。

ABAP プログラミング基礎の 18 章で学習したように、JPY(日本円)を含む一部の通貨の金額データは、画面等に出力する際に小数点の位置を補正する必要があります。文字列テンプレートの CURRENCY オプションを使うと、小数点を簡易に補正できます。基本形は以下の通りです。

{ 金額の変数名 CURRENCY = 通貨コードの変数名 }

金額データの変数名の後に、オプション CURRENCY 、= の後には、通貨コードが格納された変数名を指定します。なお、NUMBER 等のオプションと併用できます。

以下のコードは、販売金額の文字列テンプレートに CURRENCY オプションを追加して、販売伝票の取引通貨コードが格納された変数 gds_vbak-waerk を指定しています。

ldf_string =
  |販売金額は、{ gds_vbak-netwr NUMBER = USER CURRENCY = gds_vbak-waerk } { gds_vbak-waerk } です。|.

実行結果は、以下の通りです。

小数点位置が補正されて、販売金額の 400,000 円が正しく一覧画面に表示されます。

ALPHA は、数字文字列の先頭にある 0 を編集するオプションです。ABAP プログラミング基礎 6 章で学習した、ドメインの変換ルーチン ALPHA と同様の処理を行います。基本形は以下の通りです。

{ 変数名 ALPHA = OUT または IN }

金額データの変数名の後に、オプション ALPHA 、= の後には、文字列の先頭を 0 詰めする(= 内部値にする)場合は IN、先頭の 0 を取り除く(=外部値にする)場合は OUT を指定します。

以下のコードは、販売伝票番号の文字列テンプレートに ALPHA オプションを追加して、先頭の 0 を画面に表示しないようにしています。

DATA(ldf_string) = |伝票番号は、{ gds_vbak-vbeln ALPHA = OUT } です。|.

実行結果は、以下の通りです。

伝票番号 '0000002420' の先頭の 0 が取り除かれて '2420' で表示されます。

なお、文字列テンプレートには、他にも様々なオプションが用意されています。詳細については、SAP 社のオンラインヘルプで確認してください。

Embedded Expressions - format_options