ABAP String Templates: Strings mit |{ }| formatieren

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

String Templates (auch Template-Strings) ermöglichen die elegante Erstellung von Strings mit eingebetteten Ausdrücken und Formatierungsoptionen. Sie werden mit |...| begrenzt und enthalten Ausdrücke in {...}.

Syntax

|Literaler Text { ausdruck } weiterer Text|
|{ ausdruck OPTION = wert }|

Grundprinzip

  • Text zwischen |...| wird als String interpretiert
  • {...} enthält Ausdrücke, die ausgewertet und eingefügt werden
  • Formatierungsoptionen steuern die Darstellung
  • Escape-Sequenzen für Sonderzeichen: \|, \{, \}, \\, \n, \r, \t

Beispiele

1. Einfache Interpolation

DATA: lv_name TYPE string VALUE 'Max',
lv_age TYPE i VALUE 30.
" Klassisch mit CONCATENATE
DATA: lv_text TYPE string.
CONCATENATE 'Hallo ' lv_name ', du bist ' lv_age ' Jahre alt.'
INTO lv_text.
" Modern mit String Template
DATA(lv_text2) = |Hallo { lv_name }, du bist { lv_age } Jahre alt.|.
WRITE: / lv_text2. " Hallo Max, du bist 30 Jahre alt.

2. Ausdrücke in Templates

DATA: lv_a TYPE i VALUE 10,
lv_b TYPE i VALUE 5.
" Berechnungen direkt einbetten
DATA(lv_calc) = |{ lv_a } + { lv_b } = { lv_a + lv_b }|.
WRITE: / lv_calc. " 10 + 5 = 15
" Methodenaufrufe
DATA(lv_upper) = |Name: { to_upper( lv_name ) }|.
WRITE: / lv_upper. " Name: MAX
" Konditionelle Ausdrücke
DATA(lv_status) = |Status: { COND #( WHEN lv_age >= 18 THEN 'Erwachsen' ELSE 'Minderjährig' ) }|.

3. Zahlenformatierung (WIDTH, ALIGN, PAD)

DATA: lv_num TYPE i VALUE 42.
" Mindestbreite mit WIDTH
DATA(lv_w) = |Nummer: { lv_num WIDTH = 10 }|.
WRITE: / lv_w. " Nummer: 42
" Ausrichtung mit ALIGN
DATA(lv_left) = |[{ lv_num WIDTH = 10 ALIGN = LEFT }]|.
DATA(lv_right) = |[{ lv_num WIDTH = 10 ALIGN = RIGHT }]|.
DATA(lv_center) = |[{ lv_num WIDTH = 10 ALIGN = CENTER }]|.
WRITE: / lv_left. " [42 ]
WRITE: / lv_right. " [ 42]
WRITE: / lv_center. " [ 42 ]
" Füllzeichen mit PAD
DATA(lv_padded) = |{ lv_num WIDTH = 6 ALIGN = RIGHT PAD = '0' }|.
WRITE: / lv_padded. " 000042

4. Dezimalzahlen formatieren (DECIMALS, SIGN)

DATA: lv_amount TYPE p DECIMALS 2 VALUE '-1234.56'.
" Dezimalstellen angeben
DATA(lv_d1) = |Betrag: { lv_amount DECIMALS = 2 }|.
WRITE: / lv_d1. " Betrag: -1234.56
" Vorzeichen-Position
DATA(lv_sign_left) = |{ lv_amount SIGN = LEFT }|. " -1234.56
DATA(lv_sign_right) = |{ lv_amount SIGN = RIGHT }|. " 1234.56-
DATA(lv_sign_leftplus) = |{ lv_amount SIGN = LEFTPLUS }|. " -1234.56 (+ bei positiv)
" Tausendertrennzeichen
DATA: lv_big TYPE p DECIMALS 2 VALUE '1234567.89'.
DATA(lv_sep) = |{ lv_big NUMBER = USER }|. " Benutzerformat (z.B. 1.234.567,89)
DATA(lv_raw) = |{ lv_big NUMBER = RAW }|. " Ohne Formatierung

5. Datumsformatierung (DATE)

DATA: lv_date TYPE d VALUE '20241115'.
" Verschiedene Datumsformate
DATA(lv_d_raw) = |{ lv_date DATE = RAW }|. " 20241115
DATA(lv_d_iso) = |{ lv_date DATE = ISO }|. " 2024-11-15
DATA(lv_d_user) = |{ lv_date DATE = USER }|. " Benutzerformat
DATA(lv_d_env) = |{ lv_date DATE = ENVIRONMENT }|.
WRITE: / 'RAW:', lv_d_raw.
WRITE: / 'ISO:', lv_d_iso.
WRITE: / 'USER:', lv_d_user.

6. Zeitformatierung (TIME)

DATA: lv_time TYPE t VALUE '143025'.
" Verschiedene Zeitformate
DATA(lv_t_raw) = |{ lv_time TIME = RAW }|. " 143025
DATA(lv_t_iso) = |{ lv_time TIME = ISO }|. " 14:30:25
DATA(lv_t_user) = |{ lv_time TIME = USER }|. " Benutzerformat
WRITE: / 'Uhrzeit:', lv_t_iso.

7. Timestamp formatieren (TIMESTAMP)

DATA: lv_ts TYPE timestamp.
GET TIME STAMP FIELD lv_ts.
DATA(lv_ts_iso) = |{ lv_ts TIMESTAMP = ISO }|.
DATA(lv_ts_space) = |{ lv_ts TIMESTAMP = SPACE }|.
DATA(lv_ts_user) = |{ lv_ts TIMESTAMP = USER }|.
WRITE: / 'Timestamp:', lv_ts_iso.

8. Alpha-Konvertierung (ALPHA)

DATA: lv_matnr TYPE string VALUE '000000000000012345'.
" Alpha OUT: Führende Nullen entfernen
DATA(lv_without_zeros) = |{ lv_matnr ALPHA = OUT }|.
WRITE: / lv_without_zeros. " 12345
" Alpha IN: Führende Nullen hinzufügen
DATA: lv_short TYPE string VALUE '12345'.
DATA(lv_with_zeros) = |{ lv_short ALPHA = IN WIDTH = 18 }|.
WRITE: / lv_with_zeros. " 000000000000012345

9. Case-Konvertierung (CASE)

DATA: lv_text TYPE string VALUE 'Hallo Welt'.
DATA(lv_upper) = |{ lv_text CASE = UPPER }|. " HALLO WELT
DATA(lv_lower) = |{ lv_text CASE = LOWER }|. " hallo welt
DATA(lv_raw) = |{ lv_text CASE = RAW }|. " Hallo Welt
WRITE: / lv_upper.
WRITE: / lv_lower.

10. Escape-Sequenzen

" Sonderzeichen escapen
DATA(lv_pipe) = |Pipe: \| und geschweifte Klammer: \{ \}|.
DATA(lv_newline) = |Zeile 1\nZeile 2|.
DATA(lv_tab) = |Spalte1\tSpalte2|.
DATA(lv_backsl) = |Pfad: C:\\Ordner\\Datei|.
WRITE: / lv_pipe.
WRITE: / lv_newline.
WRITE: / lv_tab.

11. Mehrzeilige String Templates

" Strings können über mehrere Zeilen gehen
DATA(lv_multi) = |Dies ist ein | &&
|mehrzeiliger | &&
|String.|.
" Oder mit \n für tatsächliche Zeilenumbrüche
DATA(lv_lines) = |Zeile 1\n| &&
|Zeile 2\n| &&
|Zeile 3|.
cl_demo_output=>display( lv_lines ).

12. Kombination mit COND und SWITCH

DATA: lv_status TYPE i VALUE 2.
DATA(lv_msg) = |Status: { SWITCH string( lv_status
WHEN 1 THEN 'Neu'
WHEN 2 THEN 'In Bearbeitung'
WHEN 3 THEN 'Abgeschlossen'
ELSE 'Unbekannt'
) }|.
WRITE: / lv_msg. " Status: In Bearbeitung

13. Strukturfelder einbetten

TYPES: BEGIN OF ty_customer,
id TYPE i,
name TYPE string,
city TYPE string,
END OF ty_customer.
DATA: ls_customer TYPE ty_customer.
ls_customer = VALUE #( id = 1001 name = 'Müller GmbH' city = 'Berlin' ).
DATA(lv_info) = |Kunde { ls_customer-id }: { ls_customer-name } aus { ls_customer-city }|.
WRITE: / lv_info. " Kunde 1001: Müller GmbH aus Berlin

14. Tabellenzugriff in Templates

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Direkter Tabellenzugriff
DATA(lv_first) = |Erster Eintrag: { lt_names[ 1 ] }|.
WRITE: / lv_first. " Erster Eintrag: Anna
" Mit OPTIONAL für sichere Zugriffe
DATA(lv_safe) = |Eintrag: { VALUE #( lt_names[ 999 ] OPTIONAL ) }|.

15. String Templates in Schleifen

LOOP AT lt_names INTO DATA(lv_name).
DATA(lv_line) = |{ sy-tabix }. { lv_name }|.
WRITE: / lv_line.
ENDLOOP.
" Ausgabe:
" 1. Anna
" 2. Bernd
" 3. Clara

16. String Templates für SQL

" Dynamisches SQL zusammenbauen (Vorsicht: SQL Injection!)
DATA: lv_field TYPE string VALUE 'CARRID',
lv_value TYPE string VALUE 'LH'.
" Besser: Parameter verwenden statt String-Konkatenation für SQL

17. Formatierungsoptionen kombinieren

DATA: lv_price TYPE p DECIMALS 2 VALUE '1234.50'.
DATA(lv_formatted) = |Preis: { lv_price
DECIMALS = 2
SIGN = LEFT
WIDTH = 12
ALIGN = RIGHT
PAD = ' '
} EUR|.
WRITE: / lv_formatted. " Preis: 1234.50 EUR

18. XSD-Format für Boolean

DATA: lv_flag TYPE abap_bool VALUE abap_true.
" XSD-Format: true/false statt X/''
DATA(lv_xsd) = |Aktiv: { xsdbool( lv_flag ) }|.
WRITE: / lv_xsd. " Aktiv: X
" Eigene Darstellung
DATA(lv_custom) = |Aktiv: { COND #( WHEN lv_flag = abap_true THEN 'Ja' ELSE 'Nein' ) }|.

Formatierungsoptionen Übersicht

OptionWerteBeschreibung
WIDTHZahlMindestbreite
ALIGNLEFT, RIGHT, CENTERAusrichtung
PADZeichenFüllzeichen
CASEUPPER, LOWER, RAWGroß-/Kleinschreibung
SIGNLEFT, RIGHT, LEFTPLUS, RIGHTPLUSVorzeichenposition
DECIMALSZahlDezimalstellen
NUMBERRAW, USER, ENVIRONMENTZahlenformat
DATERAW, ISO, USER, ENVIRONMENTDatumsformat
TIMERAW, ISO, USER, ENVIRONMENTZeitformat
TIMESTAMPISO, SPACE, USERTimestamp-Format
ALPHAIN, OUT, RAWAlpha-Konvertierung
CURRENCYWährungscodeWährungsformat
COUNTRYLändercodeLänderformat

Vergleich: Klassisch vs. String Templates

" === KLASSISCH ===
DATA: lv_result TYPE string.
CONCATENATE 'Kunde' ls_customer-id ':' ls_customer-name
INTO lv_result SEPARATED BY space.
" Oder mit &&
lv_result = 'Kunde ' && ls_customer-id && ': ' && ls_customer-name.
" === MODERN MIT STRING TEMPLATES ===
DATA(lv_result2) = |Kunde { ls_customer-id }: { ls_customer-name }|.

Wichtige Hinweise / Best Practice

  • String Templates beginnen und enden mit | (Pipe-Zeichen).
  • Ausdrücke in {...} werden zur Laufzeit ausgewertet.
  • Escape-Sequenzen: \| für Pipe, \{ \} für Klammern, \n für Zeilenumbruch.
  • Formatierungsoptionen machen WRITE TO und Konvertierungsroutinen oft überflüssig.
  • ALPHA = OUT ist praktisch für Materialnummern ohne führende Nullen.
  • DATE = ISO liefert standardisiertes Format (YYYY-MM-DD).
  • Kombinieren Sie mit COND und SWITCH für bedingte Texte.
  • String Templates sind performant – bevorzugen Sie sie gegenüber CONCATENATE.
  • Vorsicht bei dynamischem SQL – verwenden Sie Parameter statt String-Interpolation.
  • NUMBER = USER respektiert die Benutzereinstellungen für Dezimal-/Tausendertrennzeichen.