ABAP Built-in Functions: Praktische Hilfsfunktionen

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

ABAP bietet zahlreiche Built-in Functions für häufige Operationen. Diese Funktionen können inline in Ausdrücken verwendet werden und machen den Code kompakter und lesbarer.

Tabellenoperationen

line_exists() – Prüfen ob Zeile existiert

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Prüfen, ob Zeile existiert (ohne Exception)
IF line_exists( lt_names[ 2 ] ).
WRITE: / 'Zeile 2 existiert'.
ENDIF.
" Mit Schlüssel
DATA: lt_customers TYPE SORTED TABLE OF ty_customer WITH UNIQUE KEY id.
IF line_exists( lt_customers[ id = 1001 ] ).
WRITE: / 'Kunde 1001 gefunden'.
ENDIF.
" In Bedingungen
DATA(lv_has_admin) = xsdbool( line_exists( lt_users[ role = 'ADMIN' ] ) ).

lines() – Anzahl der Zeilen

DATA: lt_items TYPE TABLE OF string.
lt_items = VALUE #( ( `A` ) ( `B` ) ( `C` ) ).
" Anzahl der Zeilen
DATA(lv_count) = lines( lt_items ).
WRITE: / 'Anzahl:', lv_count. " 3
" In Bedingungen
IF lines( lt_items ) > 0.
WRITE: / 'Tabelle ist nicht leer'.
ENDIF.
" Letzte Zeile lesen
IF lines( lt_items ) > 0.
DATA(lv_last) = lt_items[ lines( lt_items ) ].
ENDIF.

line_index() – Index einer Zeile

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Index einer Zeile ermitteln
DATA(lv_index) = line_index( lt_names[ table_line = `Bernd` ] ).
WRITE: / 'Index von Bernd:', lv_index. " 2
" Bei sortierten Tabellen mit Schlüssel
DATA: lt_sorted TYPE SORTED TABLE OF ty_customer WITH UNIQUE KEY id.
DATA(lv_cust_idx) = line_index( lt_sorted[ id = 1001 ] ).

Boolean-Funktionen

xsdbool() – Boolean-Konvertierung

DATA: lv_age TYPE i VALUE 25.
" Bedingung zu Boolean konvertieren
DATA(lv_is_adult) = xsdbool( lv_age >= 18 ).
IF lv_is_adult = abap_true.
WRITE: / 'Erwachsen'.
ENDIF.
" In Zuweisungen
DATA: lv_active TYPE abap_bool.
lv_active = xsdbool( sy-subrc = 0 ).
" Komplexe Bedingungen
DATA(lv_valid) = xsdbool(
lv_name IS NOT INITIAL AND
lv_email CS '@' AND
lv_age BETWEEN 18 AND 99
).

boolc() – Boolean zu Character

" Gibt 'X' oder ' ' zurück
DATA(lv_flag) = boolc( lv_age >= 18 ).
" Nützlich für Legacy-Felder
DATA: lv_legacy_flag TYPE c LENGTH 1.
lv_legacy_flag = boolc( lv_condition = abap_true ).

String-Funktionen

condense() – Leerzeichen entfernen

DATA: lv_text TYPE string VALUE ' Hallo Welt '.
" Führende/folgende Leerzeichen entfernen, mehrfache auf eins reduzieren
DATA(lv_condensed) = condense( lv_text ).
WRITE: / lv_condensed. " 'Hallo Welt'
" Nur führende/folgende entfernen (NO-GAPS = FALSE)
DATA(lv_trimmed) = condense( val = lv_text del = ` ` ).
" Alle Leerzeichen entfernen
DATA(lv_no_spaces) = condense( val = lv_text from = ` ` to = `` ).
WRITE: / lv_no_spaces. " 'HalloWelt'

concat_lines_of() – Tabelle zu String

DATA: lt_words TYPE TABLE OF string.
lt_words = VALUE #( ( `Eins` ) ( `Zwei` ) ( `Drei` ) ).
" Mit Separator verbinden
DATA(lv_sentence) = concat_lines_of( table = lt_words sep = `, ` ).
WRITE: / lv_sentence. " 'Eins, Zwei, Drei'
" Ohne Separator
DATA(lv_concat) = concat_lines_of( table = lt_words ).
WRITE: / lv_concat. " 'EinsZweiDrei'
" Mit Zeilenumbruch
DATA(lv_lines) = concat_lines_of( table = lt_words sep = cl_abap_char_utilities=>newline ).

to_upper() / to_lower() – Groß-/Kleinschreibung

DATA: lv_text TYPE string VALUE 'Hallo Welt'.
DATA(lv_upper) = to_upper( lv_text ).
WRITE: / lv_upper. " 'HALLO WELT'
DATA(lv_lower) = to_lower( lv_text ).
WRITE: / lv_lower. " 'hallo welt'
" In Vergleichen
IF to_upper( lv_input ) = 'JA'.
WRITE: / 'Bestätigt'.
ENDIF.

to_mixed() / from_mixed() – CamelCase

" Zu CamelCase
DATA(lv_camel) = to_mixed( val = 'CUSTOMER_ORDER_ID' sep = '_' ).
WRITE: / lv_camel. " 'CustomerOrderId'
" Von CamelCase
DATA(lv_snake) = from_mixed( val = 'CustomerOrderId' sep = '_' ).
WRITE: / lv_snake. " 'customer_order_id'

shift_left() / shift_right() – Verschieben

DATA: lv_num TYPE string VALUE '000123'.
" Führende Zeichen entfernen
DATA(lv_shifted) = shift_left( val = lv_num sub = '0' ).
WRITE: / lv_shifted. " '123'
" Um n Stellen verschieben
DATA(lv_shift2) = shift_left( val = 'ABCDEF' places = 2 ).
WRITE: / lv_shift2. " 'CDEF'
" Nach rechts verschieben (mit Füllung)
DATA(lv_right) = shift_right( val = '123' places = 5 ).

reverse() – String umkehren

DATA(lv_reversed) = reverse( 'ABAP' ).
WRITE: / lv_reversed. " 'PABA'

escape() – Zeichen escapen

DATA: lv_html TYPE string VALUE '<div>Test & "Wert"</div>'.
" HTML escapen
DATA(lv_escaped) = escape( val = lv_html format = cl_abap_format=>e_html_text ).
WRITE: / lv_escaped. " '&lt;div&gt;Test &amp; &quot;Wert&quot;&lt;/div&gt;'
" Regex escapen
DATA(lv_regex_safe) = escape( val = 'a.b*c?' format = cl_abap_format=>e_regex ).

repeat() – Zeichen wiederholen

DATA(lv_line) = repeat( val = '-' occ = 50 ).
WRITE: / lv_line. " '--------------------------------------------------'
DATA(lv_spaces) = repeat( val = ` ` occ = 10 ).

substring() – Teilstring

DATA: lv_text TYPE string VALUE 'Hello World'.
" Ab Position 7 (0-basiert)
DATA(lv_sub1) = substring( val = lv_text off = 6 ).
WRITE: / lv_sub1. " 'World'
" Ab Position mit Länge
DATA(lv_sub2) = substring( val = lv_text off = 0 len = 5 ).
WRITE: / lv_sub2. " 'Hello'
" Shortcuts
DATA(lv_before) = substring_before( val = lv_text sub = ' ' ). " 'Hello'
DATA(lv_after) = substring_after( val = lv_text sub = ' ' ). " 'World'
DATA(lv_from) = substring_from( val = lv_text sub = 'Wo' ). " 'World'
DATA(lv_to) = substring_to( val = lv_text sub = 'o ' ). " 'Hello '

strlen() / numofchar() – Stringlänge

DATA: lv_text TYPE string VALUE 'Hallo'.
DATA(lv_len) = strlen( lv_text ).
WRITE: / 'Länge:', lv_len. " 5
" Für beliebige Zeichentypen
DATA: lv_char TYPE c LENGTH 10 VALUE 'Test'.
DATA(lv_numchar) = numofchar( lv_char ). " 4 (ohne trailing spaces)

contains() / matches() – Suche

DATA: lv_email TYPE string VALUE 'test@example.com'.
" Enthält Substring?
IF contains( val = lv_email sub = '@' ).
WRITE: / 'Gültige E-Mail (enthält @)'.
ENDIF.
" Startet mit?
IF contains( val = lv_email start = 'test' ).
WRITE: / 'Beginnt mit test'.
ENDIF.
" Endet mit?
IF contains( val = lv_email end = '.com' ).
WRITE: / 'Endet mit .com'.
ENDIF.
" Regex-Match
IF matches( val = lv_email regex = '^\w+@\w+\.\w+$' ).
WRITE: / 'E-Mail-Format korrekt'.
ENDIF.

find() / count() – Suchen und Zählen

DATA: lv_text TYPE string VALUE 'ABAP ist super, ABAP ist toll'.
" Position finden
DATA(lv_pos) = find( val = lv_text sub = 'ist' ).
WRITE: / 'Position:', lv_pos. " 5
" Alle Vorkommen zählen
DATA(lv_count) = count( val = lv_text sub = 'ABAP' ).
WRITE: / 'Anzahl:', lv_count. " 2
" Mit Regex
DATA(lv_regex_count) = count( val = lv_text regex = '\bist\b' ).

replace() – Ersetzen

DATA: lv_text TYPE string VALUE 'Hallo Welt'.
" Erstes Vorkommen ersetzen
DATA(lv_new1) = replace( val = lv_text sub = 'Welt' with = 'ABAP' ).
WRITE: / lv_new1. " 'Hallo ABAP'
" Alle Vorkommen ersetzen
DATA: lv_multi TYPE string VALUE 'a-b-c-d'.
DATA(lv_new2) = replace( val = lv_multi sub = '-' with = '_' occ = 0 ).
WRITE: / lv_new2. " 'a_b_c_d'
" Mit Regex
DATA(lv_digits) = replace( val = 'abc123def' regex = '\d+' with = 'XXX' ).
WRITE: / lv_digits. " 'abcXXXdef'

segment() – String aufteilen

DATA: lv_path TYPE string VALUE '/usr/local/bin/app'.
" Segment extrahieren (1-basiert)
DATA(lv_seg1) = segment( val = lv_path index = 1 sep = '/' ). " ''
DATA(lv_seg2) = segment( val = lv_path index = 2 sep = '/' ). " 'usr'
DATA(lv_seg3) = segment( val = lv_path index = -1 sep = '/' ). " 'app' (letztes)

Numerische Funktionen

abs() – Absolutwert

DATA(lv_abs) = abs( -42 ).
WRITE: / lv_abs. " 42

sign() – Vorzeichen

DATA(lv_sign1) = sign( -5 ). " -1
DATA(lv_sign2) = sign( 0 ). " 0
DATA(lv_sign3) = sign( 10 ). " 1

ceil() / floor() / trunc() – Rundung

DATA: lv_num TYPE p DECIMALS 2 VALUE '3.7'.
DATA(lv_ceil) = ceil( lv_num ). " 4 (aufrunden)
DATA(lv_floor) = floor( lv_num ). " 3 (abrunden)
DATA(lv_trunc) = trunc( lv_num ). " 3 (abschneiden)

round() – Runden

DATA: lv_num TYPE p DECIMALS 4 VALUE '3.14159'.
DATA(lv_rounded) = round( val = lv_num dec = 2 ).
WRITE: / lv_rounded. " 3.14
" Auf Vielfaches runden
DATA(lv_round_5) = round( val = 127 dec = 0 prec = 5 ). " 125

nmin() / nmax() – Minimum/Maximum

DATA(lv_min) = nmin( val1 = 10 val2 = 5 ).
WRITE: / 'Min:', lv_min. " 5
DATA(lv_max) = nmax( val1 = 10 val2 = 5 ).
WRITE: / 'Max:', lv_max. " 10
" Mehr als 2 Werte
DATA(lv_max3) = nmax( val1 = 10 val2 = 25 val3 = 15 ).
WRITE: / 'Max:', lv_max3. " 25

ipow() – Potenz (Integer)

DATA(lv_power) = ipow( base = 2 exp = 10 ).
WRITE: / lv_power. " 1024

frac() – Nachkommastellen

DATA: lv_num TYPE p DECIMALS 2 VALUE '3.75'.
DATA(lv_frac) = frac( lv_num ).
WRITE: / lv_frac. " 0.75

Datums-/Zeitfunktionen

utclong_current() – Aktueller Zeitstempel

DATA(lv_timestamp) = utclong_current( ).
WRITE: / lv_timestamp. " 2024-11-24 10:30:00.1234567

utclong_add() – Zeit addieren

DATA(lv_now) = utclong_current( ).
" 1 Tag addieren
DATA(lv_tomorrow) = utclong_add(
val = lv_now
days = 1
).
" 2 Stunden addieren
DATA(lv_later) = utclong_add(
val = lv_now
hours = 2
).

utclong_diff() – Zeitdifferenz

DATA: lv_start TYPE utclong,
lv_end TYPE utclong.
" Differenz in Sekunden
DATA(lv_seconds) = utclong_diff(
high = lv_end
low = lv_start
).

Typfunktionen

cl_abap_typedescr – Typinformationen

DATA: lv_string TYPE string VALUE 'Test'.
" Typnamen ermitteln
DATA(lo_type) = cl_abap_typedescr=>describe_by_data( lv_string ).
WRITE: / 'Typ:', lo_type->get_relative_name( ). " 'STRING'
WRITE: / 'Kind:', lo_type->kind. " 'E' (Elementary)

Übersicht nach Kategorie

KategorieFunktionen
Tabellenlines(), line_exists(), line_index()
Booleanxsdbool(), boolc()
String-Manipulationcondense(), to_upper(), to_lower(), to_mixed(), from_mixed()
String-Suchecontains(), matches(), find(), count()
String-Extraktionsubstring(), substring_before(), substring_after(), segment()
String-Sonstigesconcat_lines_of(), escape(), repeat(), reverse(), replace(), strlen()
Numerischabs(), sign(), ceil(), floor(), trunc(), round(), nmin(), nmax(), ipow(), frac()
Datum/Zeitutclong_current(), utclong_add(), utclong_diff()

Wichtige Hinweise / Best Practice

  • Built-in Functions sind performant – bevorzugen Sie sie gegenüber eigenen Implementierungen.
  • line_exists() vermeidet Exceptions bei Tabellenzugriff – besser als TRY-CATCH.
  • xsdbool() liefert abap_true/abap_false – ideal für boolean-Ausdrücke.
  • condense() ersetzt CONDENSE-Statement in Ausdrücken.
  • concat_lines_of() ersetzt komplexe LOOP-Konstrukte für String-Verkettung.
  • to_upper()/to_lower() sind Funktionen – TRANSLATE ... TO UPPER/LOWER ist Statement.
  • Kombinieren Sie mit String Templates für lesbare Formatierung.
  • nmin()/nmax() unterstützen bis zu 9 Werte.
  • matches() für Regex-Prüfungen, contains() für einfache Substring-Suche.
  • Nutzen Sie CONV wenn Typkonvertierung nötig ist.