ABAP COND y SWITCH: Expresiones condicionales inline

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

Las expresiones COND y SWITCH permiten asignaciones condicionales de valores inline, sin necesidad de bloques IF o CASE separados. Devuelven un valor y pueden usarse en cualquier lugar donde se espere un valor.

COND – Expresiones condicionales (como IF)

La expresión COND evalúa condiciones y devuelve el valor correspondiente.

Sintaxis

COND <tipo>(
WHEN <condicion1> THEN <valor1>
[ WHEN <condicion2> THEN <valor2> ]
[ ELSE <valor_por_defecto> ]
)

Ejemplos de COND

1. Condición simple

DATA: lv_age TYPE i VALUE 25.
" Clásico con IF
DATA: lv_status TYPE string.
IF lv_age >= 18.
lv_status = 'Adulto'.
ELSE.
lv_status = 'Menor de edad'.
ENDIF.
" Moderno con COND
DATA(lv_status2) = COND string(
WHEN lv_age >= 18 THEN 'Adulto'
ELSE 'Menor de edad'
).

2. Múltiples condiciones

DATA: lv_score TYPE i VALUE 75.
DATA(lv_grade) = COND string(
WHEN lv_score >= 90 THEN 'Sobresaliente'
WHEN lv_score >= 80 THEN 'Notable'
WHEN lv_score >= 70 THEN 'Bien'
WHEN lv_score >= 60 THEN 'Suficiente'
ELSE 'No aprobado'
).
WRITE: / 'Calificación:', lv_grade. " Bien

3. COND en cálculos

DATA: lv_quantity TYPE i VALUE 150.
" Escala de descuentos
DATA(lv_discount) = COND decfloat16(
WHEN lv_quantity >= 100 THEN '0.15' " 15%
WHEN lv_quantity >= 50 THEN '0.10' " 10%
WHEN lv_quantity >= 10 THEN '0.05' " 5%
ELSE '0.00'
).
DATA(lv_price) = 100 * ( 1 - lv_discount ).

4. COND con condiciones complejas

DATA: lv_age TYPE i VALUE 25,
lv_member TYPE abap_bool VALUE abap_true.
DATA(lv_ticket_price) = COND i(
WHEN lv_age < 6 THEN 0 " Niños gratis
WHEN lv_age < 18 OR lv_age >= 65 THEN 10 " Reducido
WHEN lv_member = abap_true THEN 15 " Miembros
ELSE 20 " Precio normal
).

5. COND para campos de estructura

TYPES: BEGIN OF ty_result,
status TYPE string,
message TYPE string,
END OF ty_result.
DATA: lv_code TYPE i VALUE 200.
DATA(ls_result) = COND ty_result(
WHEN lv_code = 200 THEN VALUE #( status = 'OK' message = 'Exitoso' )
WHEN lv_code = 404 THEN VALUE #( status = 'ERROR' message = 'No encontrado' )
WHEN lv_code = 500 THEN VALUE #( status = 'ERROR' message = 'Error de servidor' )
ELSE VALUE #( status = 'UNKNOWN' message = 'Código desconocido' )
).

6. COND con LET (variables locales)

DATA(lv_message) = COND string(
LET today = sy-datum
age = 30
IN
WHEN today+4(2) = '12' THEN |Diciembre, { age } años|
ELSE |Mes normal, { age } años|
).

7. COND con THROW (lanzar Exception)

DATA: lv_divisor TYPE i VALUE 0.
DATA(lv_result) = COND i(
WHEN lv_divisor <> 0 THEN 100 / lv_divisor
ELSE THROW cx_sy_zerodivide( )
).

SWITCH – Bifurcación basada en valores (como CASE)

La expresión SWITCH compara un valor con múltiples posibilidades.

Sintaxis

SWITCH <tipo>( <operando>
WHEN <valor1> THEN <resultado1>
[ WHEN <valor2> THEN <resultado2> ]
[ ELSE <valor_por_defecto> ]
)

Ejemplos de SWITCH

1. SWITCH simple

DATA: lv_day TYPE i VALUE 3.
" Clásico con CASE
DATA: lv_name TYPE string.
CASE lv_day.
WHEN 1. lv_name = 'Lunes'.
WHEN 2. lv_name = 'Martes'.
WHEN 3. lv_name = 'Miércoles'.
WHEN OTHERS. lv_name = 'Desconocido'.
ENDCASE.
" Moderno con SWITCH
DATA(lv_name2) = SWITCH string( lv_day
WHEN 1 THEN 'Lunes'
WHEN 2 THEN 'Martes'
WHEN 3 THEN 'Miércoles'
WHEN 4 THEN 'Jueves'
WHEN 5 THEN 'Viernes'
WHEN 6 THEN 'Sábado'
WHEN 7 THEN 'Domingo'
ELSE 'Inválido'
).

2. SWITCH con múltiples valores por WHEN

DATA: lv_month TYPE i VALUE 7.
DATA(lv_season) = SWITCH string( lv_month
WHEN 3 OR 4 OR 5 THEN 'Primavera'
WHEN 6 OR 7 OR 8 THEN 'Verano'
WHEN 9 OR 10 OR 11 THEN 'Otoño'
WHEN 12 OR 1 OR 2 THEN 'Invierno'
ELSE 'Mes inválido'
).

3. SWITCH para códigos de estado

DATA: lv_status TYPE c LENGTH 1 VALUE 'A'.
DATA(lv_description) = SWITCH string( lv_status
WHEN 'A' THEN 'Activo'
WHEN 'I' THEN 'Inactivo'
WHEN 'P' THEN 'Pendiente'
WHEN 'C' THEN 'Completado'
WHEN 'X' THEN 'Cancelado'
ELSE 'Desconocido'
).

4. SWITCH con estructuras

TYPES: BEGIN OF ty_config,
color TYPE string,
size TYPE i,
enabled TYPE abap_bool,
END OF ty_config.
DATA: lv_mode TYPE string VALUE 'DARK'.
DATA(ls_config) = SWITCH ty_config( lv_mode
WHEN 'LIGHT' THEN VALUE #( color = 'white' size = 12 enabled = abap_true )
WHEN 'DARK' THEN VALUE #( color = 'black' size = 14 enabled = abap_true )
WHEN 'HIGH_CONTRAST' THEN VALUE #( color = 'yellow' size = 16 enabled = abap_true )
ELSE VALUE #( color = 'gray' size = 12 enabled = abap_false )
).

5. SWITCH para Enumerations

TYPES: BEGIN OF ENUM ty_order_status,
new,
processing,
shipped,
delivered,
cancelled,
END OF ENUM ty_order_status.
DATA: lv_status TYPE ty_order_status VALUE ty_order_status-shipped.
DATA(lv_icon) = SWITCH string( lv_status
WHEN ty_order_status-new THEN '📝'
WHEN ty_order_status-processing THEN '⚙️'
WHEN ty_order_status-shipped THEN '📦'
WHEN ty_order_status-delivered THEN '✅'
WHEN ty_order_status-cancelled THEN '❌'
).

6. SWITCH con THROW

DATA: lv_action TYPE string VALUE 'INVALID'.
DATA(lv_result) = SWITCH string( lv_action
WHEN 'CREATE' THEN 'Crear'
WHEN 'UPDATE' THEN 'Actualizar'
WHEN 'DELETE' THEN 'Eliminar'
ELSE THROW cx_parameter_invalid( parameter = 'ACTION' )
).

COND vs. SWITCH

AspectoCONDSWITCH
ComparaciónCondiciones arbitrariasUn operando contra valores
Equivale aIF…ELSEIF…ELSECASE…WHEN…ENDCASE
FlexibilidadMayor (condiciones complejas)Más simple para comparación de valores
LegibilidadCon condiciones complejasCon muchos valores individuales
" COND: Para rangos y condiciones complejas
DATA(lv_category) = COND string(
WHEN lv_age < 18 THEN 'Niño'
WHEN lv_age < 65 THEN 'Adulto'
ELSE 'Senior'
).
" SWITCH: Para valores discretos
DATA(lv_day_name) = SWITCH string( lv_day_number
WHEN 1 THEN 'Lunes'
WHEN 2 THEN 'Martes'
" ...
).

Anidamiento

DATA: lv_type TYPE string VALUE 'CUSTOMER',
lv_active TYPE abap_bool VALUE abap_true.
DATA(lv_label) = SWITCH string( lv_type
WHEN 'CUSTOMER' THEN COND #(
WHEN lv_active = abap_true THEN 'Cliente activo'
ELSE 'Cliente inactivo'
)
WHEN 'SUPPLIER' THEN COND #(
WHEN lv_active = abap_true THEN 'Proveedor activo'
ELSE 'Proveedor inactivo'
)
ELSE 'Desconocido'
).

En llamadas a métodos

" Directamente como parámetro
CALL METHOD lo_logger->log(
iv_level = COND #( WHEN lv_error = abap_true THEN 'ERROR' ELSE 'INFO' )
iv_message = |Status: { lv_status }|
).
" Como valor de retorno
METHODS get_status_text
RETURNING VALUE(rv_text) TYPE string.
METHOD get_status_text.
rv_text = SWITCH #( mv_status
WHEN 'A' THEN 'Activo'
WHEN 'I' THEN 'Inactivo'
ELSE 'Desconocido'
).
ENDMETHOD.

Notas importantes / Mejores prácticas

  • Use COND para verificaciones de rangos y condiciones complejas.
  • Use SWITCH para comparaciones de valores discretos (como enums, códigos de estado).
  • ELSE es opcional – sin ELSE, se devuelve el valor inicial si no hay coincidencia.
  • THROW permite lanzar Exceptions como resultado.
  • Combine con VALUE para estructuras y tablas.
  • Evite anidamiento demasiado profundo – use métodos cuando sea complejo.
  • # deriva el tipo del contexto (p.ej. en asignaciones).
  • Use LET para variables auxiliares locales dentro de la expresión.