Novas Sintaxes do ABAP 7.40: Guia Prático

Com as atualizações contínuas do ABAP, diversas sintaxes modernas foram introduzidas. Este guia apresenta as principais inovações do ABAP 7.40, focando em exemplos práticos para auxiliar na compreeensão e aplicação eficiente do código.

Declaração de Dados Simplificada

A nova sintaxe permite declarar variáveis diretamente no ponto de uso, reduzindo o código boilerplate.

** Declaração tradicional
DATA lv_nome TYPE string.
lv_nome = 'Maria'.

** Sintaxe 7.40 com declaração inline
DATA(lv_nome_moderno) = 'Maria'.

** Área de trabalho em loops
** Método convencional
DATA ls_funcionario LIKE LINE OF mt_funcionarios.
LOOP AT mt_funcionarios INTO ls_funcionario.
  " processamento
ENDLOOP.

** Nova abordagem com declaração inline
LOOP AT mt_funcionarios INTO DATA(ls_func).
  " processamento
ENDLOOP.

** Chamada de método com saídas inline
** Abordagem anterior
DATA lv_salario TYPE p.
DATA lv_bonus TYPE p.
obj_pessoa->calcular_remuneracao( 
    IMPORTING ev_salario = lv_salario
              ev_bonus = lv_bonus 
).

** Sintaxe 7.40
obj_pessoa->calcular_remuneracao(
    IMPORTING ev_salario = DATA(lv_sal)
              ev_bonus = DATA(lv_bon) 
).

** Atribuição de field symbols
LOOP AT mt_pedidos ASSIGNING FIELD-SYMBOL(<fs_pedido>).
  " processamento
ENDLOOP.

** SELECT com declaração de tabela inline
SELECT * FROM mara
  INTO TABLE @DATA(lt_material)
  WHERE matnr LIKE 'MAT%'.

** SELECT SINGLE com estrutura inline
SELECT SINGLE maktx AS descricao,
              meins AS unidade
  FROM makt
  WHERE spras = @sy-langu
    AND matnr = @lv_material
  INTO @DATA(ls_desc_material).</fs_pedido>

Expressões de Acesso a Tabelas Internas

As novas expresssões permitem acessar linhas de tabelas internas de forma mais concisa, com tratamento de erros explícito.

** Leitura por índice
** Forma anterior
READ TABLE mt_produtos INDEX 5 INTO ls_produto.
** Nova expressão
ls_produto = mt_produtos[ 5 ].

** Leitura com chave secundária
ls_produto = mt_produtos[ KEY chave_secundaria INDEX 3 ].

** Leitura com condições
ls_produto = mt_produtos[ codigo = 'PRD001' 
                          categoria = 'ELETRONICOS' ].

** Verificação de existência
IF line_exists( mt_clientes[ cnpj = '12.345.678/0001-99' ] ).
  " cliente encontrado
ENDIF.

** Obtenção de índice
DATA(lv_posicao) = line_index( mt_ordens[ numero = 'ORD12345' ] ).

Operador de Conversão (CONV)

O operador CONV facilita conversões de tipos de dados, tanto explícitas quanto implícitas.

** Conversão explícita para string
DATA(lv_valor_texto) = CONV string( 12345 ).

** Conversão implícita baseada no contexto
DATA: lv_quantidade TYPE i,
      lv_total TYPE p DECIMALS 2.
lv_total = CONV #( lv_quantidade * 2.5 ).

** Exemplo prático de conversão
DATA lv_codigo TYPE c LENGTH 10 VALUE 'ABC123'.
DATA(lv_codigo_longo) = cl_abap_codepage=>convert_to(
    source = CONV string( lv_codigo )
).

Operador VALUE

Utilizado para inicializar variáveis complexas de forma estruturada e legível.

** Inicialização de estrutura
TYPES: BEGIN OF ty_pedido,
         id_pedido TYPE vbeln,
         cliente TYPE kunnag,
         valor TYPE netwr,
         status TYPE char1,
       END OF ty_pedido.

DATA(ls_pedido) = VALUE ty_pedido( 
    id_pedido = '10000001'
    cliente = 'CL001'
    valor = '1500.00'
    status = 'A'
).

** Inicialização de tabela interna
TYPES ty_pedidos TYPE STANDARD TABLE OF ty_pedido WITH EMPTY KEY.
DATA(lt_pedidos) = VALUE ty_pedidos(
    ( id_pedido = '10000002' cliente = 'CL002' valor = '2300.50' status = 'B' )
    ( id_pedido = '10000003' cliente = 'CL003' valor = '870.75' status = 'A' )
).

** Criação de ranges
DATA: lt_ranges_matnr TYPE RANGE OF matnr.
lt_ranges_matnr = VALUE #( 
    sign = 'I' option = 'BT'
    ( low = '00000001' high = '00000100' )
    ( low = '00000200' high = '00000300' )
).

Operador FOR

Permite construir tabelas internas através de iterações controladas, similar a list comprehensions.

** Construção de tabela com filtro
TYPES: BEGIN OF ty_transporte,
         remessa TYPE vbeln,
         motorista TYPE char30,
         origem TYPE ort01,
         rota TYPE route,
       END OF ty_transporte.

DATA(lt_transportes) = VALUE ty_transporte_t(
    ( remessa = 'TR001' motorista = 'Carlos' origem = 'São Paulo' rota = 'R01' )
    ( remessa = 'TR002' motorista = 'Ana' origem = 'Rio' rota = 'R02' )
    ( remessa = 'TR003' motorista = 'Pedro' origem = 'Curitiba' rota = 'R01' )
).

DATA(lt_origens_r01) = VALUE ty_cidades(
    FOR ls_transp IN lt_transportes 
    WHERE ( rota = 'R01' )
    ( ls_transp-origem )
).

** Construção com índice
DATA(lt_com_indices) = VALUE ty_tabela_saida(
    FOR ls_transp IN lt_transportes INDEX INTO lv_idx
    WHERE ( rota = 'R02' )
    ( sequencia = lv_idx descricao = ls_transp-motorista )
).

** Iteração numérica
DATA(lt_números) = VALUE ty_tabela_num(
    FOR num = 10 THEN num + 5 UNTIL num > 50
    ( valor = num dobro = num * 2 )
).

Operador REDUCE

Acumula valores através de iterações, útil para cálculos agregados.

** Cálculo de soma acumulada
DATA(lt_precos) = VALUE ty_precos( 
    FOR i = 1 THEN i + 1 UNTIL i > 10
    ( valor = i * 10 )
).

DATA(lv_soma_total) = REDUCE dec( 
    INIT lv_acumulador = 0
    FOR ls_preco IN lt_precos
    NEXT lv_acumulador = lv_acumulador + ls_preco-valor 
).

** Construção de texto acumulado
DATA(lv_texto_final) = REDUCE string(
    INIT lv_buffer = ''
    FOR lv_contador = 1 THEN lv_contador + 1 UNTIL lv_contador > 5
    NEXT lv_buffer = lv_buffer && | Item { lv_contador } |
).

Operadores COND e SWITCH

Substituem estruturas IF/ELSE e CASE complexas por expressões mais concisas.

** Expressão condicional com COND
DATA(lv_status_texto) = COND string(
    WHEN ls_pedido-status = 'A' THEN 'Aprovado'
    WHEN ls_pedido-status = 'B' THEN 'Pendente'
    WHEN ls_pedido-status = 'R' THEN 'Reprovado'
    ELSE 'Desconhecido'
).

** Expressão de seleção com SWITCH
DATA(lv_idioma_sistema) = SWITCH string( sy-langu
    WHEN 'P' THEN 'Português'
    WHEN 'E' THEN 'Inglês'
    WHEN 'S' THEN 'Espanhol'
    WHEN 'D' THEN 'Alemão'
    THEN 'Outro'
).

Operador CORRESPONDING

Simplifica a cópia de dados entre estruturas com campos correspondentes.

** Cópia simples entre estruturas
TYPES: BEGIN OF ty_origem,
         campo1 TYPE char10,
         campo2 TYPE i,
       END OF ty_origem,
       BEGIN OF ty_destino,
         campo1 TYPE char10,
         campo2 TYPE i,
         campo3 TYPE dats,
       END OF ty_destino.

DATA(ls_origem) = VALUE ty_origem( campo1 = 'ABC' campo2 = 123 ).
DATA(ls_destino) = VALUE ty_destino( campo3 = sy-datum ).

** Cópia mantendo dados existentes
ls_destino = CORRESPONDING #( BASE ( ls_destino ) ls_origem ).

** Criação de nova estrutura baseada em existente
DATA(ls_nova) = CORRESPONDING ty_destino( 
    BASE VALUE ty_destino( campo3 = '20240101' )
    ls_origem 
).

Processamento de Strings com Templates

A sintaxe de template literals permite construir strings complexas de forma mais intuitiva.

** Concatenação tradicional vs template
** Método antigo
CONCATENATE 'Produto:' lv_produto 'Quantidade:' lv_qtd
    INTO lv_mensagem SEPARATED BY space.

** Novo método com template
lv_mensagem = |Produto: { lv_produto } Quantidade: { lv_qtd }|.

** Formatação de campos
WRITE: / |{ 'Esquerda' WIDTH = 20 ALIGN = LEFT PAD = '-' }|.
WRITE: / |{ 'Centro' WIDTH = 20 ALIGN = CENTER PAD = '*' }|.
WRITE: / |{ 'Direita' WIDTH = 20 ALIGN = RIGHT PAD = '=' }|.

** Formatação de números e datas
DATA(lv_valor_formatado) = |R$ { lv_valor DECIMALS = 2 }|.
DATA(lv_data_formatada) = |{ sy-datum DATE = ENVIRONMENT }|.

** Remoção de zeros à esquerda
DATA(lv_codigo_original) = '000012345'.
DATA(lv_codigo_limpo) = |{ lv_codigo_original ALPHA = OUT }|.

** Conversão de horário para formato 24h
DATA(lv_hora_atual) = |{ sy-timlo TIME = ISO }|.

Loop com Agrupamento

A sintaxe GROUP BY permite processar dados agrupados diretamente nos loops.

** Agrupamento por múltiplas chaves
TYPES: BEGIN OF ty_funcionario,
         nome TYPE char30,
         departamento TYPE char20,
         cargo TYPE char20,
         salario TYPE p DECIMALS 2,
       END OF ty_funcionario.

DATA(lt_funcionarios) = VALUE ty_tabela_func(
    ( nome = 'João' departamento = 'TI' cargo = 'Analista' salario = 5000 )
    ( nome = 'Maria' departamento = 'RH' cargo = 'Gerente' salario = 7500 )
    ( nome = 'Pedro' departamento = 'TI' cargo = 'Desenvolvedor' salario = 4500 )
).

LOOP AT lt_funcionarios INTO DATA(ls_func)
    GROUP BY ( dept = ls_func-departamento 
               cargo_grupo = ls_func-cargo
               tamanho_grupo = GROUP SIZE )
    INTO DATA(ls_grupo).
    
    DATA(lv_salario_medio) = 0.
    WRITE: / |Departamento: { ls_grupo-dept } - Cargo: { ls_grupo-cargo_grupo }|.
    
    LOOP AT GROUP ls_grupo INTO DATA(ls_membro).
        lv_salario_medio = lv_salario_medio + ls_membro-salario.
        WRITE: / 5 ls_membro-nome.
    ENDLOOP.
    
    lv_salario_medio = lv_salario_medio / ls_grupo-tamanho_grupo.
    WRITE: / 5 |Salário médio: { lv_salario_medio }|.
    SKIP 1.
ENDLOOP.

Operador FILTER

Seleciona linhas de tabelas internas com base em critérios de outra tabela.

** Filtragem usando tabela de critérios
TYPES: BEGIN OF ty_filtro,
         cidade_origem TYPE ort01,
         cidade_destino TYPE ort01,
         prioridade TYPE i,
       END OF ty_filtro.

DATA: lt_voos TYPE STANDARD TABLE OF spfli.
SELECT * FROM spfli INTO TABLE lt_voos.

DATA(lt_filtros) = VALUE ty_tabela_filtro(
    ( cidade_origem = 'NEW YORK' cidade_destino = 'LOS ANGELES' prioridade = 1 )
    ( cidade_origem = 'FRANKFURT' cidade_destino = 'LONDON' prioridade = 2 )
).

DATA(lt_voos_filtrados) = FILTER #( lt_voos IN lt_filtros
    WHERE cityfrom = cidade_origem 
      AND cityto = cidade_destino 
).

Tags: ABAP SAP ABAP740 NovasSintaxes OperadorVALUE

Publicado em 7-22 01:20