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
).