Operadores constructores VALUE, NEW, CONV, COND, SWITCH y CORRESPONDING construyen un valor en una sola expresión. Con # el tipo se toma del destino.
VALUE para estructuras 7.40 SP02 Rellena todos los campos de una vez.
Antes Copiar 1
2
3
4
5
DATA ls_direccion TYPE ty_direccion.
ls_direccion-calle = 'Gran Vía' .
ls_direccion-numero = '28' .
ls_direccion-ciudad = 'Madrid' .Ahora Copiar 1
2
3
4
DATA (ls_direccion) = VALUE ty_direccion(
calle = 'Gran Vía'
numero = '28'
ciudad = 'Madrid' ).VALUE para tablas internas y rangos 7.40 SP02 Cada línea va entre paréntesis. Los campos comunes se escriben una sola vez delante.
Antes Copiar 1
2
3
4
5
6
7
8
9
DATA lt_rango TYPE RANGE OF matnr.
DATA ls_rango LIKE LINE OF lt_rango.
ls_rango-sign = 'I' .
ls_rango-option = 'EQ' .
ls_rango-low = 'MAT-001' .
APPEND ls_rango TO lt_rango.
ls_rango-low = 'MAT-002' .
APPEND ls_rango TO lt_rango.Ahora Copiar 1
2
3
4
5
DATA lt_rango TYPE RANGE OF matnr.
lt_rango = VALUE #( sign = 'I' option = 'EQ'
( low = 'MAT-001' )
( low = 'MAT-002' ) ).NEW en lugar de CREATE OBJECT 7.40 SP02 Crea el objeto y lo asigna en una línea.
Antes Copiar 1
2
3
4
5
DATA lo_log TYPE REF TO zcl_log.
CREATE OBJECT lo_log
EXPORTING
iv_objeto = 'ZVENTAS' .Ahora Copiar 1
DATA (lo_log) = NEW zcl_log( iv_objeto = 'ZVENTAS' ).CONV para convertir al pasar parámetros 7.40 SP02 Ya no hace falta una variable auxiliar solo para cambiar el tipo.
Antes Copiar 1
2
3
4
DATA lv_texto TYPE string.
lv_texto = lv_cantidad.
lo_util->mostrar( lv_texto ).Ahora Copiar 1
lo_util->mostrar( CONV string( lv_cantidad ) ).COND en lugar de IF para asignar 7.40 SP02 Devuelve un valor según varias condiciones.
Antes Copiar 1
2
3
4
5
6
7
8
9
DATA lv_estado TYPE string.
IF lv_stock = 0 .
lv_estado = 'Agotado' .
ELSEIF lv_stock < 10 .
lv_estado = 'Pocas unidades' .
ELSE .
lv_estado = 'Disponible' .
ENDIF .Ahora Copiar 1
2
3
4
DATA (lv_estado) = COND string(
WHEN lv_stock = 0 THEN `Agotado`
WHEN lv_stock < 10 THEN `Pocas unidades`
ELSE `Disponible` ).SWITCH en lugar de CASE para asignar 7.40 SP02 Igual que COND, pero comparando un único valor.
Antes Copiar 1
2
3
4
5
6
7
8
9
10
DATA lv_saludo TYPE string.
CASE lv_idioma.
WHEN 'S' .
lv_saludo = 'Hola' .
WHEN 'E' .
lv_saludo = 'Hello' .
WHEN OTHERS .
lv_saludo = '?' .
ENDCASE .Ahora Copiar 1
2
3
4
DATA (lv_saludo) = SWITCH string( lv_idioma
WHEN 'S' THEN `Hola`
WHEN 'E' THEN `Hello`
ELSE `?` ).CORRESPONDING para tablas completas 7.40 SP05 Copia por nombre de campo entre tablas internas. MAPPING asigna campos con nombres distintos.
Antes Copiar 1
2
3
4
5
LOOP AT lt_pedidos INTO ls_pedido.
MOVE-CORRESPONDING ls_pedido TO ls_salida.
ls_salida-cliente = ls_pedido-kunnr.
APPEND ls_salida TO lt_salida.
ENDLOOP .Ahora Copiar 1
2
lt_salida = CORRESPONDING #( lt_pedidos
MAPPING cliente = kunnr ).LET para valores auxiliares 7.40 SP05 LET calcula un valor una sola vez y lo usa dentro de la expresión, sin declarar una variable aparte.
Antes Copiar 1
2
3
4
5
6
DATA lv_iva TYPE p LENGTH 15 DECIMALS 2 .
lv_iva = ls_pedido-netwr * '0.21' .
ls_factura-base = ls_pedido-netwr.
ls_factura-iva = lv_iva.
ls_factura-total = ls_pedido-netwr + lv_iva.Ahora Copiar 1
2
3
4
5
ls_factura = VALUE #(
LET iva = ls_pedido-netwr * '0.21' IN
base = ls_pedido-netwr
iva = iva
total = ls_pedido-netwr + iva ).VALUE con BASE para añadir sin borrar 7.40 SP08 Sin BASE, VALUE crea la tabla de cero. Con BASE conserva las líneas que ya tenía y añade las nuevas.
Antes Copiar 1
2
3
4
ls_mat-matnr = 'M-01' .
APPEND ls_mat TO lt_mat.
ls_mat-matnr = 'M-02' .
APPEND ls_mat TO lt_mat.Ahora Copiar 1
2
3
lt_mat = VALUE #( BASE lt_mat
( matnr = 'M-01' )
( matnr = 'M-02' ) ).Expresiones de tabla itab[ ... ] lee una línea de una tabla interna dentro de cualquier expresión. Si la línea no existe, lanza la excepción CX_SY_ITAB_LINE_NOT_FOUND.
Con OPTIONAL (desde 7.40 SP08) devuelve una línea vacía en lugar de lanzar la excepción.
Antes Copiar 1
2
3
4
5
6
7
DATA ls_cliente TYPE kna1.
READ TABLE lt_clientes INTO ls_cliente
WITH KEY kunnr = lv_kunnr.
IF sy-subrc = 0 .
lv_nombre = ls_cliente-name1.
ENDIF .Ahora Copiar 1
2
3
4
5
6
" Si no existe, lanza CX_SY_ITAB_LINE_NOT_FOUND
DATA (lv_nombre) = lt_clientes[ kunnr = lv_kunnr ]-name1.
" Si no existe, devuelve una línea vacía
DATA (ls_cliente) = VALUE kna1(
lt_clientes[ kunnr = lv_kunnr ] OPTIONAL ).Comprobar si una línea existe 7.40 SP02 line_exists( ) devuelve verdadero o falso sin leer la línea.
Antes Copiar 1
2
3
4
5
READ TABLE lt_clientes TRANSPORTING NO FIELDS
WITH KEY kunnr = lv_kunnr.
IF sy-subrc = 0 .
" el cliente ya está en la tabla
ENDIF .Ahora Copiar 1
2
3
IF line_exists( lt_clientes[ kunnr = lv_kunnr ] ).
" el cliente ya está en la tabla
ENDIF .Obtener el índice de una línea 7.40 SP02 line_index( ) devuelve la posición, o 0 si no la encuentra.
Antes Copiar 1
2
3
READ TABLE lt_clientes TRANSPORTING NO FIELDS
WITH KEY kunnr = lv_kunnr.
lv_indice = sy-tabix.Ahora Copiar 1
DATA (lv_indice) = line_index( lt_clientes[ kunnr = lv_kunnr ] ).Modificar un campo directamente 7.40 SP02 La expresión de tabla también vale como destino de una asignación.
Antes Copiar 1
2
3
4
5
6
FIELD-SYMBOLS <ls_vbap> TYPE vbap.
READ TABLE lt_vbap ASSIGNING <ls_vbap> INDEX 1 .
IF sy-subrc = 0 .
<ls_vbap>-kwmeng = 5 .
ENDIF .Ahora Copiar 1
lt_vbap[ 1 ]-kwmeng = 5 .Valor por defecto si la línea no existe 7.40 SP08 Si la línea no existe, una expresión de tabla lanza CX_SY_ITAB_LINE_NOT_FOUND. Con DEFAULT u OPTIONAL dentro de VALUE no hay excepción.
Antes Copiar 1
2
3
4
5
6
7
READ TABLE lt_clientes INTO ls_cliente
WITH KEY kunnr = lv_kunnr.
IF sy-subrc = 0 .
lv_nombre = ls_cliente-name1.
ELSE .
lv_nombre = 'Desconocido' .
ENDIF .Ahora Copiar 1
2
3
DATA (lv_nombre) = VALUE #(
lt_clientes[ kunnr = lv_kunnr ]-name1
DEFAULT 'Desconocido' ).Plantillas de texto El texto va entre barras verticales y las variables entre llaves. Llegaron en 7.02 y en 7.40 se usan en todas partes.
Montar un texto con variables 7.02 Sustituye a CONCATENATE y a las variables auxiliares para formatear números.
Antes Copiar 1
2
3
4
5
6
DATA lv_msg TYPE string.
DATA lv_num TYPE c LENGTH 10 .
WRITE lv_total TO lv_num LEFT-JUSTIFIED .
CONCATENATE 'Pedido' lv_vbeln 'con' lv_num 'posiciones'
INTO lv_msg SEPARATED BY space .Ahora Copiar 1
DATA (lv_msg) = |Pedido { lv_vbeln } con { lv_total } posiciones| .Formatos dentro de la plantilla 7.02 ALPHA, DATE, TIME, WIDTH, ALIGN, DECIMALS o CASE dan formato sin llamar a funciones.
Antes Copiar 1
2
3
4
5
6
7
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_OUTPUT'
EXPORTING
input = lv_matnr
IMPORTING
output = lv_matnr_sal.
WRITE sy-datum TO lv_fecha DD/MM/YYYY.Ahora Copiar 1
2
DATA (lv_texto) =
|Material { lv_matnr ALPHA = OUT }, fecha { sy-datum DATE = USER }| .El operador && une textos en cualquier expresión.
Antes Copiar 1
2
CONCATENATE lv_nombre lv_apellido
INTO lv_completo SEPARATED BY space .Ahora Copiar 1
lv_completo = lv_nombre && ` ` && lv_apellido.Funciones de texto en lugar de sentencias 7.02 to_upper, to_lower, condense, replace, substring o shift_left devuelven el resultado, así que se pueden anidar.
Antes Copiar 1
2
3
lv_limpio = lv_texto.
TRANSLATE lv_limpio TO UPPER CASE .
CONDENSE lv_limpio.Ahora Copiar 1
DATA (lv_limpio) = condense( to_upper( lv_texto ) ).Unir las líneas de una tabla 7.02 concat_lines_of junta todas las líneas de una tabla de textos con el separador que indiques.
Antes Copiar 1
2
3
4
5
6
7
8
LOOP AT lt_nombres INTO lv_nombre.
IF lv_lista IS INITIAL .
lv_lista = lv_nombre.
ELSE .
CONCATENATE lv_lista lv_nombre
INTO lv_lista SEPARATED BY ', ' .
ENDIF .
ENDLOOP .Ahora Copiar 1
2
DATA (lv_lista) = concat_lines_of(
table = lt_nombres sep = `, ` ).FOR, REDUCE y FILTER Recorren tablas internas dentro de una expresión: FOR construye tablas, REDUCE calcula un único valor y FILTER selecciona líneas.
Construir una tabla a partir de otra 7.40 SP05 FOR dentro de VALUE sustituye al LOOP con APPEND. Admite WHERE.
Antes Copiar 1
2
3
4
LOOP AT lt_vbap INTO ls_vbap WHERE netwr > 1000 .
ls_matnr-matnr = ls_vbap-matnr.
APPEND ls_matnr TO lt_matnr.
ENDLOOP .Ahora Copiar 1
2
3
lt_matnr = VALUE #( FOR ls_vbap IN lt_vbap
WHERE ( netwr > 1000 )
( matnr = ls_vbap-matnr ) ).Sumar con REDUCE 7.40 SP08 INIT da el valor inicial y NEXT lo actualiza en cada vuelta.
Antes Copiar 1
2
3
4
5
DATA lv_total TYPE netwr.
LOOP AT lt_vbap INTO ls_vbap.
lv_total = lv_total + ls_vbap-netwr.
ENDLOOP .Ahora Copiar 1
2
3
4
DATA (lv_total) = REDUCE netwr(
INIT suma = CONV netwr( 0 )
FOR ls_vbap IN lt_vbap
NEXT suma = suma + ls_vbap-netwr ).Filtrar líneas con FILTER 7.40 SP08 FILTER necesita una clave ordenada o hash sobre el campo filtrado; aquí, la clave secundaria k_estado.
Antes Copiar 1
2
3
LOOP AT lt_pedidos INTO ls_pedido WHERE estado = 'A' .
APPEND ls_pedido TO lt_abiertos.
ENDLOOP .Ahora Copiar 1
2
DATA (lt_abiertos) = FILTER #( lt_pedidos USING KEY k_estado
WHERE estado = 'A' ).Contar con REDUCE y una condición 7.40 SP08 FOR admite WHERE también dentro de REDUCE: aquí cuenta los pedidos abiertos sin recorrerlos a mano.
Antes Copiar 1
2
3
4
5
DATA lv_abiertos TYPE i.
LOOP AT lt_pedidos INTO ls_pedido WHERE estado = 'A' .
lv_abiertos = lv_abiertos + 1 .
ENDLOOP .Ahora Copiar 1
2
3
4
DATA (lv_abiertos) = REDUCE i(
INIT n = 0
FOR ls_pedido IN lt_pedidos WHERE ( estado = 'A' )
NEXT n = n + 1 ).Open SQL moderno Las variables de ABAP llevan @, los campos se separan con comas e INTO va al final. 7.50 añade FIELDS, UNION, expresiones @( ) y nuevas funciones SQL.
Sintaxis con @, comas e INTO al final 7.40 SP08 INTO TABLE @DATA(...) declara la tabla con los campos exactos de la consulta.
Antes Copiar 1
2
3
4
5
6
DATA lt_vbak TYPE TABLE OF vbak.
SELECT vbeln erdat kunnr
FROM vbak
INTO CORRESPONDING FIELDS OF TABLE lt_vbak
WHERE kunnr = lv_kunnr.Ahora Copiar 1
2
3
4
SELECT vbeln, erdat, kunnr
FROM vbak
WHERE kunnr = @lv_kunnr
INTO TABLE @DATA(lt_vbak).Cálculos y CASE en la base de datos 7.40 SP05 El cálculo lo hace la base de datos y no hace falta un LOOP después.
Antes Copiar 1
2
3
4
5
6
7
8
9
SELECT vbeln netwr FROM vbak INTO TABLE lt_vbak.
LOOP AT lt_vbak ASSIGNING <ls_vbak>.
IF <ls_vbak>-netwr > 10000 .
<ls_vbak>-tipo = 'GRANDE' .
ELSE .
<ls_vbak>-tipo = 'NORMAL' .
ENDIF .
ENDLOOP .Ahora Copiar 1
2
3
4
5
6
SELECT vbeln, netwr,
CASE WHEN netwr > 10000 THEN 'GRANDE'
ELSE 'NORMAL'
END AS tipo
FROM vbak
INTO TABLE @DATA(lt_vbak).FROM primero con FIELDS 7.50 Escribir antes la tabla permite al editor de Eclipse proponer los campos.
Antes Copiar 1
2
3
4
SELECT vbeln, erdat, netwr
FROM vbak
WHERE erdat >= @lv_desde
INTO TABLE @DATA(lt_vbak).Ahora Copiar 1
2
3
4
SELECT FROM vbak
FIELDS vbeln, erdat, netwr
WHERE erdat >= @lv_desde
INTO TABLE @DATA(lt_vbak).Unir dos consultas con UNION 7.50 UNION quita los duplicados; UNION ALL los mantiene. INTO va después de la última consulta.
Antes Copiar 1
2
3
4
5
6
7
SELECT kunnr name1 FROM kna1
INTO TABLE lt_socios
WHERE land1 = 'ES' .
SELECT lifnr name1 FROM lfa1
APPENDING TABLE lt_socios
WHERE land1 = 'ES' .Ahora Copiar 1
2
3
4
5
6
SELECT kunnr AS id, name1 FROM kna1
WHERE land1 = 'ES'
UNION
SELECT lifnr AS id, name1 FROM lfa1
WHERE land1 = 'ES'
INTO TABLE @DATA(lt_socios).Expresiones ABAP dentro de la consulta 7.50 @( ... ) evalúa una expresión ABAP y pasa el resultado a la consulta.
Antes Copiar 1
2
3
4
5
6
DATA lv_desde TYPE d.
lv_desde = sy-datum - 30 .
SELECT vbeln FROM vbak
INTO TABLE lt_vbeln
WHERE erdat >= lv_desde.Ahora Copiar 1
2
3
SELECT vbeln FROM vbak
WHERE erdat >= @( sy-datum - 30 )
INTO TABLE @DATA(lt_vbeln).Funciones de texto y redondeo en SQL 7.50 Nuevas funciones: CONCAT, LPAD, LENGTH, LTRIM, RTRIM, REPLACE, RIGHT, SUBSTRING y ROUND.
Antes Copiar 1
2
3
4
5
6
SELECT matnr brgew FROM mara INTO TABLE lt_mara.
LOOP AT lt_mara ASSIGNING <ls_mara>.
<ls_mara>-prefijo = <ls_mara>-matnr(3 ).
<ls_mara>-peso = round( val = <ls_mara>-brgew dec = 1 ).
ENDLOOP .Ahora Copiar 1
2
3
4
5
SELECT matnr,
substring( matnr, 1 , 3 ) AS prefijo,
round( brgew, 1 ) AS peso
FROM mara
INTO TABLE @DATA(lt_mara).Objetos, lógica y excepciones Comprobar el tipo de un objeto sin capturar excepciones, usar métodos como condiciones y lanzar excepciones con un mensaje.
Comprobar el tipo con IS INSTANCE OF 7.50 Comprueba si el cast es posible antes de hacerlo. CAST hace la conversión en la misma línea.
Antes Copiar 1
2
3
4
5
6
7
DATA lo_camion TYPE REF TO zcl_camion.
TRY .
lo_camion ?= lo_vehiculo.
lo_camion->cargar( ).
CATCH cx_sy_move_cast_error.
ENDTRY .Ahora Copiar 1
2
3
IF lo_vehiculo IS INSTANCE OF zcl_camion.
CAST zcl_camion( lo_vehiculo )->cargar( ).
ENDIF .Distinguir tipos con CASE TYPE OF 7.50 Cada WHEN TYPE comprueba un tipo y deja el objeto ya convertido en una variable.
Antes Copiar 1
2
3
4
5
6
7
8
9
10
11
12
13
DATA lo_camion TYPE REF TO zcl_camion.
DATA lo_coche TYPE REF TO zcl_coche.
TRY .
lo_camion ?= lo_vehiculo.
lo_camion->cargar( ).
CATCH cx_sy_move_cast_error.
TRY .
lo_coche ?= lo_vehiculo.
lo_coche->aparcar( ).
CATCH cx_sy_move_cast_error.
ENDTRY .
ENDTRY .Ahora Copiar 1
2
3
4
5
6
7
8
CASE TYPE OF lo_vehiculo.
WHEN TYPE zcl_camion INTO DATA (lo_camion).
lo_camion->cargar( ).
WHEN TYPE zcl_coche INTO DATA (lo_coche).
lo_coche->aparcar( ).
WHEN OTHERS .
" otro tipo de vehículo
ENDCASE .Métodos como condición y xsdbool 7.40 SP08 Un método que devuelve un valor se puede usar directamente como condición. xsdbool( ) convierte una condición en abap_true o abap_false.
Antes Copiar 1
2
3
4
5
IF lo_pedido->es_urgente( ) = abap_true.
lv_urgente = abap_true.
ELSE .
lv_urgente = abap_false.
ENDIF .Ahora Copiar 1
DATA (lv_urgente) = xsdbool( lo_pedido->es_urgente( ) ).Lanzar una excepción con un mensaje 7.50 MESSAGE asocia un mensaje de la SE91 a la excepción. La clase debe implementar IF_T100_DYN_MSG.
Antes Copiar 1
2
3
4
RAISE EXCEPTION TYPE zcx_ventas
EXPORTING
textid = zcx_ventas=>pedido_bloqueado
vbeln = lv_vbeln.Ahora Copiar 1
2
RAISE EXCEPTION TYPE zcx_ventas
MESSAGE e001(zventas) WITH lv_vbeln.