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 conditionsDATA(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 lignesDATA(lv_count) = lines( lt_items ).WRITE: / 'Nombre:', lv_count. " 3
" Dans les conditionsIF lines( lt_items ) > 0. WRITE: / 'La table n''est pas vide'.ENDIF.
" Lire la dernière ligneIF 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 ligneDATA(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éenDATA(lv_is_adult) = xsdbool( lv_age >= 18 ).
IF lv_is_adult = abap_true. WRITE: / 'Adulte'.ENDIF.
" Dans les affectationsDATA: lv_active TYPE abap_bool.lv_active = xsdbool( sy-subrc = 0 ).
" Conditions complexesDATA(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 legacyDATA: 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 seulDATA(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 espacesDATA(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éparateurDATA(lv_sentence) = concat_lines_of( table = lt_words sep = `, ` ).WRITE: / lv_sentence. " 'Un, Deux, Trois"
" Sans séparateurDATA(lv_concat) = concat_lines_of( table = lt_words ).WRITE: / lv_concat. " 'UnDeuxTrois"
" Avec saut de ligneDATA(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 comparaisonsIF to_upper( lv_input ) = 'OUI'. WRITE: / 'Confirmé'.ENDIF.to_mixed() / from_mixed() – CamelCase
" Vers CamelCaseDATA(lv_camel) = to_mixed( val = 'CUSTOMER_ORDER_ID' sep = '_' ).WRITE: / lv_camel. " 'CustomerOrderId"
" Depuis CamelCaseDATA(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ébutDATA(lv_shifted) = shift_left( val = lv_num sub = '0' ).WRITE: / lv_shifted. " '123"
" Décaler de n positionsDATA(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 HTMLDATA(lv_escaped) = escape( val = lv_html format = cl_abap_format=>e_html_text ).WRITE: / lv_escaped. " '<div>Test & "Valeur"</div>"
" Échapper RegexDATA(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 longueurDATA(lv_sub2) = substring( val = lv_text off = 0 len = 5 ).WRITE: / lv_sub2. " 'Hello"
" RaccourcisDATA(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èreDATA: lv_char TYPE c LENGTH 10 VALUE 'Test'.DATA(lv_numchar) = numofchar( lv_char ). " 4 (sans les espaces finaux)contains() / matches() – Recherche
" 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 RegexIF 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 positionDATA(lv_pos) = find( val = lv_text sub = 'est' ).WRITE: / 'Position:', lv_pos. " 5
" Compter toutes les occurrencesDATA(lv_count) = count( val = lv_text sub = 'ABAP' ).WRITE: / 'Nombre:', lv_count. " 2
" Avec RegexDATA(lv_regex_count) = count( val = lv_text regex = '\best\b' ).replace() – Remplacer
DATA: lv_text TYPE string VALUE 'Bonjour Monde'.
" Remplacer la première occurrenceDATA(lv_new1) = replace( val = lv_text sub = 'Monde' with = 'ABAP' ).WRITE: / lv_new1. " 'Bonjour ABAP"
" Remplacer toutes les occurrencesDATA: 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 RegexDATA(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. " 42sign() – Signe
DATA(lv_sign1) = sign( -5 ). " -1DATA(lv_sign2) = sign( 0 ). " 0DATA(lv_sign3) = sign( 10 ). " 1ceil() / 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 multipleDATA(lv_round_5) = round( val = 127 dec = 0 prec = 5 ). " 125nmin() / 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 valeursDATA(lv_max3) = nmax( val1 = 10 val2 = 25 val3 = 15 ).WRITE: / 'Max:', lv_max3. " 25ipow() – Puissance (entier)
DATA(lv_power) = ipow( base = 2 exp = 10 ).WRITE: / lv_power. " 1024frac() – Partie décimale
DATA: lv_num TYPE p DECIMALS 2 VALUE '3.75'.
DATA(lv_frac) = frac( lv_num ).WRITE: / lv_frac. " 0.75Fonctions date/heure
utclong_current() – Horodatage actuel
DATA(lv_timestamp) = utclong_current( ).WRITE: / lv_timestamp. " 2024-11-24 10:30:00.1234567utclong_add() – Ajouter du temps
DATA(lv_now) = utclong_current( ).
" Ajouter 1 jourDATA(lv_tomorrow) = utclong_add( val = lv_now days = 1).
" Ajouter 2 heuresDATA(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 secondesDATA(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 typeDATA(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égorie | Fonctions |
|---|---|
| Tables | lines(), line_exists(), line_index() |
| Booléen | xsdbool(), boolc() |
| Manipulation de chaînes | condense(), to_upper(), to_lower(), to_mixed(), from_mixed() |
| Recherche de chaînes | contains(), matches(), find(), count() |
| Extraction de chaînes | substring(), substring_before(), substring_after(), segment() |
| Divers chaînes | concat_lines_of(), escape(), repeat(), reverse(), replace(), strlen() |
| Numérique | abs(), sign(), ceil(), floor(), trunc(), round(), nmin(), nmax(), ipow(), frac() |
| Date/Heure | utclong_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()retourneabap_true/abap_false– idéal pour les expressions booléennes.condense()remplace l’instructionCONDENSEdans 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/LOWERest une instruction.- Combinez avec les
String Templatespour 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
CONVlorsqu’une conversion de type est nécessaire.