ABAP String Templates : Formater des chaines avec |{ }|

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

Les String Templates (ou Template-Strings) permettent de creer elegamment des chaines de caracteres avec des expressions integrees et des options de formatage. Ils sont delimites par |...| et contiennent des expressions dans {...}.

Syntaxe

|Texte litteral { expression } suite du texte|
|{ expression OPTION = valeur }|

Principe de base

  • Le texte entre |...| est interprete comme une chaine
  • {...} contient des expressions qui sont evaluees et inserees
  • Les options de formatage controlent l’affichage
  • Sequences d’echappement pour caracteres speciaux : \|, \{, \}, \\, \n, \r, \t

Exemples

1. Interpolation simple

DATA: lv_name TYPE string VALUE 'Max',
lv_age TYPE i VALUE 30.
" Classique avec CONCATENATE
DATA: lv_text TYPE string.
CONCATENATE 'Bonjour ' lv_name ', tu as ' lv_age ' ans."
INTO lv_text.
" Moderne avec String Template
DATA(lv_text2) = |Bonjour { lv_name }, tu as { lv_age } ans.|.
WRITE: / lv_text2. " Bonjour Max, tu as 30 ans.

2. Expressions dans les templates

DATA: lv_a TYPE i VALUE 10,
lv_b TYPE i VALUE 5.
" Calculs directement integres
DATA(lv_calc) = |{ lv_a } + { lv_b } = { lv_a + lv_b }|.
WRITE: / lv_calc. " 10 + 5 = 15
" Appels de methodes
DATA(lv_upper) = |Nom : { to_upper( lv_name ) }|.
WRITE: / lv_upper. " Nom : MAX
" Expressions conditionnelles
DATA(lv_status) = |Statut : { COND #( WHEN lv_age >= 18 THEN 'Adulte' ELSE 'Mineur' ) }|.

3. Formatage des nombres (WIDTH, ALIGN, PAD)

DATA: lv_num TYPE i VALUE 42.
" Largeur minimale avec WIDTH
DATA(lv_w) = |Numero : { lv_num WIDTH = 10 }|.
WRITE: / lv_w. " Numero : 42
" Alignement avec 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 ]
" Caractere de remplissage avec PAD
DATA(lv_padded) = |{ lv_num WIDTH = 6 ALIGN = RIGHT PAD = '0' }|.
WRITE: / lv_padded. " 000042

4. Formatage des decimales (DECIMALS, SIGN)

DATA: lv_amount TYPE p DECIMALS 2 VALUE '-1234.56'.
" Specifier les decimales
DATA(lv_d1) = |Montant : { lv_amount DECIMALS = 2 }|.
WRITE: / lv_d1. " Montant : -1234.56
" Position du signe
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 (+ si positif)
" Separateur de milliers
DATA: lv_big TYPE p DECIMALS 2 VALUE '1234567.89'.
DATA(lv_sep) = |{ lv_big NUMBER = USER }|. " Format utilisateur (ex. 1.234.567,89)
DATA(lv_raw) = |{ lv_big NUMBER = RAW }|. " Sans formatage

5. Formatage de date (DATE)

DATA: lv_date TYPE d VALUE '20241115'.
" Differents formats de date
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 }|. " Format utilisateur
DATA(lv_d_env) = |{ lv_date DATE = ENVIRONMENT }|.
WRITE: / 'RAW:', lv_d_raw.
WRITE: / 'ISO:', lv_d_iso.
WRITE: / 'USER:', lv_d_user.

6. Formatage de l’heure (TIME)

DATA: lv_time TYPE t VALUE '143025'.
" Differents formats d'heure
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 }|. " Format utilisateur
WRITE: / 'Heure:', lv_t_iso.

7. Formatage du timestamp (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. Conversion Alpha (ALPHA)

DATA: lv_matnr TYPE string VALUE '000000000000012345'.
" Alpha OUT : Supprimer les zeros en tete
DATA(lv_without_zeros) = |{ lv_matnr ALPHA = OUT }|.
WRITE: / lv_without_zeros. " 12345
" Alpha IN : Ajouter des zeros en tete
DATA: lv_short TYPE string VALUE '12345'.
DATA(lv_with_zeros) = |{ lv_short ALPHA = IN WIDTH = 18 }|.
WRITE: / lv_with_zeros. " 000000000000012345

9. Conversion de casse (CASE)

DATA: lv_text TYPE string VALUE 'Bonjour le Monde'.
DATA(lv_upper) = |{ lv_text CASE = UPPER }|. " BONJOUR LE MONDE
DATA(lv_lower) = |{ lv_text CASE = LOWER }|. " bonjour le monde
DATA(lv_raw) = |{ lv_text CASE = RAW }|. " Bonjour le Monde
WRITE: / lv_upper.
WRITE: / lv_lower.

10. Sequences d’echappement

" Echapper les caracteres speciaux
DATA(lv_pipe) = |Pipe : \| et accolade : \{ \}|.
DATA(lv_newline) = |Ligne 1\nLigne 2|.
DATA(lv_tab) = |Colonne1\tColonne2|.
DATA(lv_backsl) = |Chemin : C:\\Dossier\\Fichier|.
WRITE: / lv_pipe.
WRITE: / lv_newline.
WRITE: / lv_tab.

11. String Templates multilignes

" Les chaines peuvent s'etendre sur plusieurs lignes
DATA(lv_multi) = |Ceci est une | &&
|chaine | &&
|multiligne.|.
" Ou avec \n pour de vrais sauts de ligne
DATA(lv_lines) = |Ligne 1\n| &&
|Ligne 2\n| &&
|Ligne 3|.
cl_demo_output=>display( lv_lines ).

12. Combinaison avec COND et SWITCH

DATA: lv_status TYPE i VALUE 2.
DATA(lv_msg) = |Statut : { SWITCH string( lv_status
WHEN 1 THEN 'Nouveau"
WHEN 2 THEN 'En cours"
WHEN 3 THEN 'Termine"
ELSE 'Inconnu"
) }|.
WRITE: / lv_msg. " Statut : En cours

13. Integrer des champs de structure

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 = 'Dupont SARL' city = 'Paris' ).
DATA(lv_info) = |Client { ls_customer-id }: { ls_customer-name } de { ls_customer-city }|.
WRITE: / lv_info. " Client 1001: Dupont SARL de Paris

14. Acces aux tables dans les templates

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Acces direct a la table
DATA(lv_first) = |Premiere entree : { lt_names[ 1 ] }|.
WRITE: / lv_first. " Premiere entree : Anna
" Avec OPTIONAL pour un acces securise
DATA(lv_safe) = |Entree : { VALUE #( lt_names[ 999 ] OPTIONAL ) }|.

15. String Templates dans les boucles

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

16. String Templates pour SQL

" Construction SQL dynamique (Attention : SQL Injection !)
DATA: lv_field TYPE string VALUE 'CARRID',
lv_value TYPE string VALUE 'LH'.
" Mieux : utiliser des parametres au lieu de la concatenation de chaines pour SQL

17. Combiner les options de formatage

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

18. Format XSD pour Boolean

DATA: lv_flag TYPE abap_bool VALUE abap_true.
" Format XSD : true/false au lieu de X/'"
DATA(lv_xsd) = |Actif : { xsdbool( lv_flag ) }|.
WRITE: / lv_xsd. " Actif : X
" Representation personnalisee
DATA(lv_custom) = |Actif : { COND #( WHEN lv_flag = abap_true THEN 'Oui' ELSE 'Non' ) }|.

Apercu des options de formatage

OptionValeursDescription
WIDTHNombreLargeur minimale
ALIGNLEFT, RIGHT, CENTERAlignement
PADCaractereCaractere de remplissage
CASEUPPER, LOWER, RAWMajuscules/minuscules
SIGNLEFT, RIGHT, LEFTPLUS, RIGHTPLUSPosition du signe
DECIMALSNombreDecimales
NUMBERRAW, USER, ENVIRONMENTFormat des nombres
DATERAW, ISO, USER, ENVIRONMENTFormat de date
TIMERAW, ISO, USER, ENVIRONMENTFormat d’heure
TIMESTAMPISO, SPACE, USERFormat timestamp
ALPHAIN, OUT, RAWConversion Alpha
CURRENCYCode deviseFormat devise
COUNTRYCode paysFormat pays

Comparaison : Classique vs. String Templates

" === CLASSIQUE ===
DATA: lv_result TYPE string.
CONCATENATE 'Client' ls_customer-id ':' ls_customer-name
INTO lv_result SEPARATED BY space.
" Ou avec &&
lv_result = 'Client ' && ls_customer-id && ': ' && ls_customer-name.
" === MODERNE AVEC STRING TEMPLATES ===
DATA(lv_result2) = |Client { ls_customer-id }: { ls_customer-name }|.

Remarques importantes / Bonnes pratiques

  • Les String Templates commencent et se terminent par | (caractere pipe).
  • Les expressions dans {...} sont evaluees a l’execution.
  • Sequences d’echappement : \| pour pipe, \{ \} pour accolades, \n pour saut de ligne.
  • Les options de formatage rendent souvent WRITE TO et les routines de conversion inutiles.
  • ALPHA = OUT est pratique pour les numeros d’article sans zeros en tete.
  • DATE = ISO fournit un format standardise (YYYY-MM-DD).
  • Combinez avec COND et SWITCH pour des textes conditionnels.
  • Les String Templates sont performants - preferez-les a CONCATENATE.
  • Attention au SQL dynamique - utilisez des parametres au lieu de l’interpolation de chaines.
  • NUMBER = USER respecte les parametres utilisateur pour les separateurs decimal/milliers.