Fonctions intégrées ABAP : Fonctions utilitaires pratiques

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

ABAP offre de nombreuses fonctions intégrées pour les opérations courantes. Ces fonctions peuvent être utilisées en ligne dans des expressions et rendent le code plus compact et lisible.

Opérations sur les tables

line_exists() – Vérifier si une ligne existe

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Vérifier si la ligne existe (sans exception)
IF line_exists( lt_names[ 2 ] ).
WRITE: / 'La ligne 2 existe'.
ENDIF.
" Avec une clé
DATA: lt_customers TYPE SORTED TABLE OF ty_customer WITH UNIQUE KEY id.
IF line_exists( lt_customers[ id = 1001 ] ).
WRITE: / 'Client 1001 trouvé'.
ENDIF.
" Dans les conditions
DATA(lv_has_admin) = xsdbool( line_exists( lt_users[ role = 'ADMIN' ] ) ).

lines() – Nombre de lignes

DATA: lt_items TYPE TABLE OF string.
lt_items = VALUE #( ( `A` ) ( `B` ) ( `C` ) ).
" Nombre de lignes
DATA(lv_count) = lines( lt_items ).
WRITE: / 'Nombre:', lv_count. " 3
" Dans les conditions
IF lines( lt_items ) > 0.
WRITE: / 'La table n''est pas vide'.
ENDIF.
" Lire la dernière ligne
IF lines( lt_items ) > 0.
DATA(lv_last) = lt_items[ lines( lt_items ) ].
ENDIF.

line_index() – Index d’une ligne

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Déterminer l'index d'une ligne
DATA(lv_index) = line_index( lt_names[ table_line = `Bernd` ] ).
WRITE: / 'Index de Bernd:', lv_index. " 2
" Pour les tables triées avec clé
DATA: lt_sorted TYPE SORTED TABLE OF ty_customer WITH UNIQUE KEY id.
DATA(lv_cust_idx) = line_index( lt_sorted[ id = 1001 ] ).

Fonctions booléennes

xsdbool() – Conversion booléenne

DATA: lv_age TYPE i VALUE 25.
" Convertir une condition en booléen
DATA(lv_is_adult) = xsdbool( lv_age >= 18 ).
IF lv_is_adult = abap_true.
WRITE: / 'Adulte'.
ENDIF.
" Dans les affectations
DATA: lv_active TYPE abap_bool.
lv_active = xsdbool( sy-subrc = 0 ).
" Conditions complexes
DATA(lv_valid) = xsdbool(
lv_name IS NOT INITIAL AND
lv_email CS '@' AND
lv_age BETWEEN 18 AND 99
).

boolc() – Booléen vers caractère

" Retourne 'X' ou ' "
DATA(lv_flag) = boolc( lv_age >= 18 ).
" Utile pour les champs legacy
DATA: lv_legacy_flag TYPE c LENGTH 1.
lv_legacy_flag = boolc( lv_condition = abap_true ).

Fonctions de chaîne de caractères

condense() – Supprimer les espaces

DATA: lv_text TYPE string VALUE ' Bonjour Monde '.
" Supprimer les espaces de début/fin, réduire les multiples à un seul
DATA(lv_condensed) = condense( lv_text ).
WRITE: / lv_condensed. " 'Bonjour Monde"
" Supprimer uniquement les espaces de début/fin (NO-GAPS = FALSE)
DATA(lv_trimmed) = condense( val = lv_text del = ` ` ).
" Supprimer tous les espaces
DATA(lv_no_spaces) = condense( val = lv_text from = ` ` to = `` ).
WRITE: / lv_no_spaces. " 'BonjourMonde"

concat_lines_of() – Table vers chaîne

DATA: lt_words TYPE TABLE OF string.
lt_words = VALUE #( ( `Un` ) ( `Deux` ) ( `Trois` ) ).
" Joindre avec un séparateur
DATA(lv_sentence) = concat_lines_of( table = lt_words sep = `, ` ).
WRITE: / lv_sentence. " 'Un, Deux, Trois"
" Sans séparateur
DATA(lv_concat) = concat_lines_of( table = lt_words ).
WRITE: / lv_concat. " 'UnDeuxTrois"
" Avec saut de ligne
DATA(lv_lines) = concat_lines_of( table = lt_words sep = cl_abap_char_utilities=>newline ).

to_upper() / to_lower() – Majuscules/Minuscules

DATA: lv_text TYPE string VALUE 'Bonjour Monde'.
DATA(lv_upper) = to_upper( lv_text ).
WRITE: / lv_upper. " 'BONJOUR MONDE"
DATA(lv_lower) = to_lower( lv_text ).
WRITE: / lv_lower. " 'bonjour monde"
" Dans les comparaisons
IF to_upper( lv_input ) = 'OUI'.
WRITE: / 'Confirmé'.
ENDIF.

to_mixed() / from_mixed() – CamelCase

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

shift_left() / shift_right() – Décalage

DATA: lv_num TYPE string VALUE '000123'.
" Supprimer les caractères de début
DATA(lv_shifted) = shift_left( val = lv_num sub = '0' ).
WRITE: / lv_shifted. " '123"
" Décaler de n positions
DATA(lv_shift2) = shift_left( val = 'ABCDEF' places = 2 ).
WRITE: / lv_shift2. " 'CDEF"
" Décaler vers la droite (avec remplissage)
DATA(lv_right) = shift_right( val = '123' places = 5 ).

reverse() – Inverser une chaîne

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

escape() – Échapper les caractères

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

repeat() – Répéter des caractères

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

substring() – Sous-chaîne

DATA: lv_text TYPE string VALUE 'Hello World'.
" À partir de la position 7 (basé sur 0)
DATA(lv_sub1) = substring( val = lv_text off = 6 ).
WRITE: / lv_sub1. " 'World"
" À partir de la position avec longueur
DATA(lv_sub2) = substring( val = lv_text off = 0 len = 5 ).
WRITE: / lv_sub2. " 'Hello"
" Raccourcis
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() – Longueur de chaîne

DATA: lv_text TYPE string VALUE 'Salut'.
DATA(lv_len) = strlen( lv_text ).
WRITE: / 'Longueur:', lv_len. " 5
" Pour tout type de caractère
DATA: lv_char TYPE c LENGTH 10 VALUE 'Test'.
DATA(lv_numchar) = numofchar( lv_char ). " 4 (sans les espaces finaux)

contains() / matches() – Recherche

DATA: lv_email TYPE string VALUE '[email protected]'.
" Contient une sous-chaîne ?
IF contains( val = lv_email sub = '@' ).
WRITE: / 'E-mail valide (contient @)'.
ENDIF.
" Commence par ?
IF contains( val = lv_email start = 'test' ).
WRITE: / 'Commence par test'.
ENDIF.
" Se termine par ?
IF contains( val = lv_email end = '.com' ).
WRITE: / 'Se termine par .com'.
ENDIF.
" Correspondance Regex
IF matches( val = lv_email regex = '^\w+@\w+\.\w+$' ).
WRITE: / 'Format e-mail correct'.
ENDIF.

find() / count() – Rechercher et compter

DATA: lv_text TYPE string VALUE 'ABAP est super, ABAP est génial'.
" Trouver la position
DATA(lv_pos) = find( val = lv_text sub = 'est' ).
WRITE: / 'Position:', lv_pos. " 5
" Compter toutes les occurrences
DATA(lv_count) = count( val = lv_text sub = 'ABAP' ).
WRITE: / 'Nombre:', lv_count. " 2
" Avec Regex
DATA(lv_regex_count) = count( val = lv_text regex = '\best\b' ).

replace() – Remplacer

DATA: lv_text TYPE string VALUE 'Bonjour Monde'.
" Remplacer la première occurrence
DATA(lv_new1) = replace( val = lv_text sub = 'Monde' with = 'ABAP' ).
WRITE: / lv_new1. " 'Bonjour ABAP"
" Remplacer toutes les occurrences
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"
" Avec Regex
DATA(lv_digits) = replace( val = 'abc123def' regex = '\d+' with = 'XXX' ).
WRITE: / lv_digits. " 'abcXXXdef"

segment() – Diviser une chaîne

DATA: lv_path TYPE string VALUE '/usr/local/bin/app'.
" Extraire un segment (basé sur 1)
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' (dernier)

Fonctions numériques

abs() – Valeur absolue

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

sign() – Signe

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

ceil() / floor() / trunc() – Arrondi

DATA: lv_num TYPE p DECIMALS 2 VALUE '3.7'.
DATA(lv_ceil) = ceil( lv_num ). " 4 (arrondir vers le haut)
DATA(lv_floor) = floor( lv_num ). " 3 (arrondir vers le bas)
DATA(lv_trunc) = trunc( lv_num ). " 3 (tronquer)

round() – Arrondir

DATA: lv_num TYPE p DECIMALS 4 VALUE '3.14159'.
DATA(lv_rounded) = round( val = lv_num dec = 2 ).
WRITE: / lv_rounded. " 3.14
" Arrondir à un multiple
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
" Plus de 2 valeurs
DATA(lv_max3) = nmax( val1 = 10 val2 = 25 val3 = 15 ).
WRITE: / 'Max:', lv_max3. " 25

ipow() – Puissance (entier)

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

frac() – Partie décimale

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

Fonctions date/heure

utclong_current() – Horodatage actuel

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

utclong_add() – Ajouter du temps

DATA(lv_now) = utclong_current( ).
" Ajouter 1 jour
DATA(lv_tomorrow) = utclong_add(
val = lv_now
days = 1
).
" Ajouter 2 heures
DATA(lv_later) = utclong_add(
val = lv_now
hours = 2
).

utclong_diff() – Différence de temps

DATA: lv_start TYPE utclong,
lv_end TYPE utclong.
" Différence en secondes
DATA(lv_seconds) = utclong_diff(
high = lv_end
low = lv_start
).

Fonctions de type

cl_abap_typedescr – Informations de type

DATA: lv_string TYPE string VALUE 'Test'.
" Déterminer le nom du type
DATA(lo_type) = cl_abap_typedescr=>describe_by_data( lv_string ).
WRITE: / 'Type:', lo_type->get_relative_name( ). " 'STRING"
WRITE: / 'Kind:', lo_type->kind. " 'E' (Elementary)

Aperçu par catégorie

CatégorieFonctions
Tableslines(), line_exists(), line_index()
Booléenxsdbool(), boolc()
Manipulation de chaînescondense(), to_upper(), to_lower(), to_mixed(), from_mixed()
Recherche de chaînescontains(), matches(), find(), count()
Extraction de chaînessubstring(), substring_before(), substring_after(), segment()
Divers chaînesconcat_lines_of(), escape(), repeat(), reverse(), replace(), strlen()
Numériqueabs(), sign(), ceil(), floor(), trunc(), round(), nmin(), nmax(), ipow(), frac()
Date/Heureutclong_current(), utclong_add(), utclong_diff()

Remarques importantes / Bonnes pratiques

  • Les fonctions intégrées sont performantes – préférez-les aux implémentations personnalisées.
  • line_exists() évite les exceptions lors de l’accès aux tables – mieux que TRY-CATCH.
  • xsdbool() retourne abap_true/abap_false – idéal pour les expressions booléennes.
  • condense() remplace l’instruction CONDENSE dans les expressions.
  • concat_lines_of() remplace les constructions LOOP complexes pour la concaténation de chaînes.
  • to_upper()/to_lower() sont des fonctions – TRANSLATE ... TO UPPER/LOWER est une instruction.
  • Combinez avec les String Templates pour un formatage lisible.
  • nmin()/nmax() supportent jusqu’à 9 valeurs.
  • matches() pour les vérifications Regex, contains() pour les recherches simples de sous-chaînes.
  • Utilisez CONV lorsqu’une conversion de type est nécessaire.