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 CONCATENATEDATA: lv_text TYPE string.CONCATENATE 'Bonjour ' lv_name ', tu as ' lv_age ' ans." INTO lv_text.
" Moderne avec String TemplateDATA(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 integresDATA(lv_calc) = |{ lv_a } + { lv_b } = { lv_a + lv_b }|.WRITE: / lv_calc. " 10 + 5 = 15
" Appels de methodesDATA(lv_upper) = |Nom : { to_upper( lv_name ) }|.WRITE: / lv_upper. " Nom : MAX
" Expressions conditionnellesDATA(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 WIDTHDATA(lv_w) = |Numero : { lv_num WIDTH = 10 }|.WRITE: / lv_w. " Numero : 42
" Alignement avec ALIGNDATA(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 PADDATA(lv_padded) = |{ lv_num WIDTH = 6 ALIGN = RIGHT PAD = '0' }|.WRITE: / lv_padded. " 0000424. Formatage des decimales (DECIMALS, SIGN)
DATA: lv_amount TYPE p DECIMALS 2 VALUE '-1234.56'.
" Specifier les decimalesDATA(lv_d1) = |Montant : { lv_amount DECIMALS = 2 }|.WRITE: / lv_d1. " Montant : -1234.56
" Position du signeDATA(lv_sign_left) = |{ lv_amount SIGN = LEFT }|. " -1234.56DATA(lv_sign_right) = |{ lv_amount SIGN = RIGHT }|. " 1234.56-DATA(lv_sign_leftplus) = |{ lv_amount SIGN = LEFTPLUS }|. " -1234.56 (+ si positif)
" Separateur de milliersDATA: 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 formatage5. Formatage de date (DATE)
DATA: lv_date TYPE d VALUE '20241115'.
" Differents formats de dateDATA(lv_d_raw) = |{ lv_date DATE = RAW }|. " 20241115DATA(lv_d_iso) = |{ lv_date DATE = ISO }|. " 2024-11-15DATA(lv_d_user) = |{ lv_date DATE = USER }|. " Format utilisateurDATA(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'heureDATA(lv_t_raw) = |{ lv_time TIME = RAW }|. " 143025DATA(lv_t_iso) = |{ lv_time TIME = ISO }|. " 14:30:25DATA(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 teteDATA(lv_without_zeros) = |{ lv_matnr ALPHA = OUT }|.WRITE: / lv_without_zeros. " 12345
" Alpha IN : Ajouter des zeros en teteDATA: lv_short TYPE string VALUE '12345'.DATA(lv_with_zeros) = |{ lv_short ALPHA = IN WIDTH = 18 }|.WRITE: / lv_with_zeros. " 0000000000000123459. Conversion de casse (CASE)
DATA: lv_text TYPE string VALUE 'Bonjour le Monde'.
DATA(lv_upper) = |{ lv_text CASE = UPPER }|. " BONJOUR LE MONDEDATA(lv_lower) = |{ lv_text CASE = LOWER }|. " bonjour le mondeDATA(lv_raw) = |{ lv_text CASE = RAW }|. " Bonjour le Monde
WRITE: / lv_upper.WRITE: / lv_lower.10. Sequences d’echappement
" Echapper les caracteres speciauxDATA(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 lignesDATA(lv_multi) = |Ceci est une | && |chaine | && |multiligne.|.
" Ou avec \n pour de vrais sauts de ligneDATA(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 cours13. 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 Paris14. Acces aux tables dans les templates
DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Anna` ) ( `Bernd` ) ( `Clara` ) ).
" Acces direct a la tableDATA(lv_first) = |Premiere entree : { lt_names[ 1 ] }|.WRITE: / lv_first. " Premiere entree : Anna
" Avec OPTIONAL pour un acces securiseDATA(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. Clara16. 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 SQL17. 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 EUR18. 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 personnaliseeDATA(lv_custom) = |Actif : { COND #( WHEN lv_flag = abap_true THEN 'Oui' ELSE 'Non' ) }|.Apercu des options de formatage
| Option | Valeurs | Description |
|---|---|---|
WIDTH | Nombre | Largeur minimale |
ALIGN | LEFT, RIGHT, CENTER | Alignement |
PAD | Caractere | Caractere de remplissage |
CASE | UPPER, LOWER, RAW | Majuscules/minuscules |
SIGN | LEFT, RIGHT, LEFTPLUS, RIGHTPLUS | Position du signe |
DECIMALS | Nombre | Decimales |
NUMBER | RAW, USER, ENVIRONMENT | Format des nombres |
DATE | RAW, ISO, USER, ENVIRONMENT | Format de date |
TIME | RAW, ISO, USER, ENVIRONMENT | Format d’heure |
TIMESTAMP | ISO, SPACE, USER | Format timestamp |
ALPHA | IN, OUT, RAW | Conversion Alpha |
CURRENCY | Code devise | Format devise |
COUNTRY | Code pays | Format 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,\npour saut de ligne. - Les options de formatage rendent souvent
WRITE TOet les routines de conversion inutiles. ALPHA = OUTest pratique pour les numeros d’article sans zeros en tete.DATE = ISOfournit un format standardise (YYYY-MM-DD).- Combinez avec
CONDetSWITCHpour 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 = USERrespecte les parametres utilisateur pour les separateurs decimal/milliers.