ABAP String Templates: Formatear strings con |{ }|

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

Los String Templates (tambien llamados Template Strings) permiten la creacion elegante de strings con expresiones embebidas y opciones de formateo. Se delimitan con |...| y contienen expresiones en {...}.

Sintaxis

|Texto literal { expresion } mas texto|
|{ expresion OPCION = valor }|

Principio basico

  • El texto entre |...| se interpreta como string
  • {...} contiene expresiones que se evaluan e insertan
  • Las opciones de formateo controlan la presentacion
  • Secuencias de escape para caracteres especiales: \|, \{, \}, \\, \n, \r, \t

Ejemplos

1. Interpolacion simple

DATA: lv_name TYPE string VALUE 'Max',
lv_age TYPE i VALUE 30.
" Clasico con CONCATENATE
DATA: lv_text TYPE string.
CONCATENATE 'Hola ' lv_name ', tienes ' lv_age ' anos.'
INTO lv_text.
" Moderno con String Template
DATA(lv_text2) = |Hola { lv_name }, tienes { lv_age } anos.|.
WRITE: / lv_text2. " Hola Max, tienes 30 anos.

2. Expresiones en templates

DATA: lv_a TYPE i VALUE 10,
lv_b TYPE i VALUE 5.
" Calculos directamente embebidos
DATA(lv_calc) = |{ lv_a } + { lv_b } = { lv_a + lv_b }|.
WRITE: / lv_calc. " 10 + 5 = 15
" Llamadas a metodos
DATA(lv_upper) = |Nombre: { to_upper( lv_name ) }|.
WRITE: / lv_upper. " Nombre: MAX
" Expresiones condicionales
DATA(lv_status) = |Estado: { COND #( WHEN lv_age >= 18 THEN 'Adulto' ELSE 'Menor' ) }|.

3. Formateo de numeros (WIDTH, ALIGN, PAD)

DATA: lv_num TYPE i VALUE 42.
" Ancho minimo con WIDTH
DATA(lv_w) = |Numero: { lv_num WIDTH = 10 }|.
WRITE: / lv_w. " Numero: 42
" Alineacion con 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 ]
" Caracter de relleno con PAD
DATA(lv_padded) = |{ lv_num WIDTH = 6 ALIGN = RIGHT PAD = '0' }|.
WRITE: / lv_padded. " 000042

4. Formatear decimales (DECIMALS, SIGN)

DATA: lv_amount TYPE p DECIMALS 2 VALUE '-1234.56'.
" Especificar decimales
DATA(lv_d1) = |Importe: { lv_amount DECIMALS = 2 }|.
WRITE: / lv_d1. " Importe: -1234.56
" Posicion del signo
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 (+ para positivos)
" Separador de miles
DATA: lv_big TYPE p DECIMALS 2 VALUE '1234567.89'.
DATA(lv_sep) = |{ lv_big NUMBER = USER }|. " Formato usuario (ej. 1.234.567,89)
DATA(lv_raw) = |{ lv_big NUMBER = RAW }|. " Sin formateo

5. Formateo de fechas (DATE)

DATA: lv_date TYPE d VALUE '20241115'.
" Diferentes formatos de fecha
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 }|. " Formato usuario
DATA(lv_d_env) = |{ lv_date DATE = ENVIRONMENT }|.
WRITE: / 'RAW:', lv_d_raw.
WRITE: / 'ISO:', lv_d_iso.
WRITE: / 'USER:', lv_d_user.

6. Formateo de hora (TIME)

DATA: lv_time TYPE t VALUE '143025'.
" Diferentes formatos de hora
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 }|. " Formato usuario
WRITE: / 'Hora:', lv_t_iso.

7. Formatear 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: Eliminar ceros iniciales
DATA(lv_without_zeros) = |{ lv_matnr ALPHA = OUT }|.
WRITE: / lv_without_zeros. " 12345
" Alpha IN: Anadir ceros iniciales
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 mayusculas/minusculas (CASE)

DATA: lv_text TYPE string VALUE 'Hola Mundo'.
DATA(lv_upper) = |{ lv_text CASE = UPPER }|. " HOLA MUNDO
DATA(lv_lower) = |{ lv_text CASE = LOWER }|. " hola mundo
DATA(lv_raw) = |{ lv_text CASE = RAW }|. " Hola Mundo
WRITE: / lv_upper.
WRITE: / lv_lower.

10. Secuencias de escape

" Escapar caracteres especiales
DATA(lv_pipe) = |Pipe: \| y llave: \{ \}|.
DATA(lv_newline) = |Linea 1\nLinea 2|.
DATA(lv_tab) = |Columna1\tColumna2|.
DATA(lv_backsl) = |Ruta: C:\\Carpeta\\Archivo|.
WRITE: / lv_pipe.
WRITE: / lv_newline.
WRITE: / lv_tab.

11. String Templates multilinea

" Los strings pueden extenderse en varias lineas
DATA(lv_multi) = |Este es un | &&
|string | &&
|multilinea.|.
" O con \n para saltos de linea reales
DATA(lv_lines) = |Linea 1\n| &&
|Linea 2\n| &&
|Linea 3|.
cl_demo_output=>display( lv_lines ).

12. Combinacion con COND y SWITCH

DATA: lv_status TYPE i VALUE 2.
DATA(lv_msg) = |Estado: { SWITCH string( lv_status
WHEN 1 THEN 'Nuevo'
WHEN 2 THEN 'En proceso'
WHEN 3 THEN 'Completado'
ELSE 'Desconocido'
) }|.
WRITE: / lv_msg. " Estado: En proceso

13. Embeber campos de estructura

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 = 'Garcia S.L.' city = 'Madrid' ).
DATA(lv_info) = |Cliente { ls_customer-id }: { ls_customer-name } de { ls_customer-city }|.
WRITE: / lv_info. " Cliente 1001: Garcia S.L. de Madrid

14. Acceso a tablas en templates

DATA: lt_names TYPE TABLE OF string.
lt_names = VALUE #( ( `Ana` ) ( `Berto` ) ( `Clara` ) ).
" Acceso directo a tabla
DATA(lv_first) = |Primera entrada: { lt_names[ 1 ] }|.
WRITE: / lv_first. " Primera entrada: Ana
" Con OPTIONAL para accesos seguros
DATA(lv_safe) = |Entrada: { VALUE #( lt_names[ 999 ] OPTIONAL ) }|.

15. String Templates en bucles

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

16. String Templates para SQL

" Construir SQL dinamico (Cuidado: SQL Injection!)
DATA: lv_field TYPE string VALUE 'CARRID',
lv_value TYPE string VALUE 'LH'.
" Mejor: Usar parametros en lugar de concatenacion de strings para SQL

17. Combinar opciones de formateo

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

18. Formato XSD para Boolean

DATA: lv_flag TYPE abap_bool VALUE abap_true.
" Formato XSD: true/false en lugar de X/''
DATA(lv_xsd) = |Activo: { xsdbool( lv_flag ) }|.
WRITE: / lv_xsd. " Activo: X
" Representacion personalizada
DATA(lv_custom) = |Activo: { COND #( WHEN lv_flag = abap_true THEN 'Si' ELSE 'No' ) }|.

Resumen de opciones de formateo

OpcionValoresDescripcion
WIDTHNumeroAncho minimo
ALIGNLEFT, RIGHT, CENTERAlineacion
PADCaracterCaracter de relleno
CASEUPPER, LOWER, RAWMayusculas/minusculas
SIGNLEFT, RIGHT, LEFTPLUS, RIGHTPLUSPosicion del signo
DECIMALSNumeroDecimales
NUMBERRAW, USER, ENVIRONMENTFormato numerico
DATERAW, ISO, USER, ENVIRONMENTFormato fecha
TIMERAW, ISO, USER, ENVIRONMENTFormato hora
TIMESTAMPISO, SPACE, USERFormato timestamp
ALPHAIN, OUT, RAWConversion Alpha
CURRENCYCodigo monedaFormato moneda
COUNTRYCodigo paisFormato pais

Comparacion: Clasico vs. String Templates

" === CLASICO ===
DATA: lv_result TYPE string.
CONCATENATE 'Cliente' ls_customer-id ':' ls_customer-name
INTO lv_result SEPARATED BY space.
" O con &&
lv_result = 'Cliente ' && ls_customer-id && ': ' && ls_customer-name.
" === MODERNO CON STRING TEMPLATES ===
DATA(lv_result2) = |Cliente { ls_customer-id }: { ls_customer-name }|.

Notas importantes / Mejores practicas

  • Los String Templates comienzan y terminan con | (caracter pipe).
  • Las expresiones en {...} se evaluan en tiempo de ejecucion.
  • Secuencias de escape: \| para pipe, \{ \} para llaves, \n para salto de linea.
  • Las opciones de formateo hacen innecesarios WRITE TO y rutinas de conversion en muchos casos.
  • ALPHA = OUT es practico para numeros de material sin ceros iniciales.
  • DATE = ISO proporciona formato estandarizado (YYYY-MM-DD).
  • Combine con COND y SWITCH para textos condicionales.
  • Los String Templates son eficientes - prefieralos sobre CONCATENATE.
  • Cuidado con SQL dinamico - use parametros en lugar de interpolacion de strings.
  • NUMBER = USER respeta la configuracion del usuario para separadores decimal/miles.