Estruturas
Declaração de Estruturas
Estruturas Locais
TYPES: BEGIN OF ty_endereco,
rua TYPE string,
numero TYPE string,
cidade TYPE string,
codigo TYPE string,
pais TYPE land1,
END OF ty_endereco.
TYPES: BEGIN OF ty_pessoa,
id TYPE i,
nome TYPE string,
idade TYPE i,
endereco TYPE ty_endereco,
salario TYPE p DECIMALS 2,
END OF ty_pessoa.
DATA ls_pessoa TYPE ty_pessoa.
Estruturas Baseadas em DDIC
" Usar estrutura do dicionário
DATA ls_scarr TYPE scarr.
DATA ls_mara TYPE mara.
" Declaração inline com SELECT
SELECT SINGLE * FROM kna1 INTO @DATA(ls_cliente) WHERE kunnr = '0000100000'.
Inicialização de Estruturas
VALUE Constructor
" Sintaxe moderna - preenchimento completo
DATA(ls_produto) = VALUE ty_produto(
id = 1001
descricao = 'Portátil Dell'
preco = '899.99'
quantidade = 15
data_registo = sy-datum
).
" Preenchimento parcial
DATA(ls_config) = VALUE ty_config(
ativo = abap_true
" outros campos ficam com valor inicial
).
" Com BASE - manter valores existentes
ls_produto = VALUE #( BASE ls_produto
preco = '799.99' " Atualiza apenas o preço
quantidade = 20 " e a quantidade
).
CORRESPONDING
" Copiar campos com mesmo nome
TYPES: BEGIN OF ty_origem,
campo1 TYPE string,
campo2 TYPE i,
campo3 TYPE string,
END OF ty_origem.
TYPES: BEGIN OF ty_destino,
campo1 TYPE string,
campo2 TYPE i,
campo4 TYPE string,
END OF ty_destino.
DATA(ls_origem) = VALUE ty_origem(
campo1 = 'A'
campo2 = 10
campo3 = 'X'
).
" Copia campo1 e campo2
DATA(ls_destino) = CORRESPONDING #( ls_origem ).
" Com mapeamento adicional
ls_destino = CORRESPONDING #( BASE ( ls_destino ) ls_origem MAPPING campo4 = campo3 ).
Acesso a Campos
Acesso Direto
" Leitura
DATA(lv_nome) = ls_pessoa-nome.
DATA(lv_rua) = ls_pessoa-endereco-rua.
" Escrita
ls_pessoa-idade = 30.
ls_pessoa-endereco-cidade = 'Lisboa'.
" Com field-symbols
FIELD-SYMBOLS <lv_campo> TYPE any.
ASSIGN ls_pessoa-nome TO <lv_campo>.
<lv_campo> = 'João Silva'.
Acesso Dinâmico
DATA lv_nome_campo TYPE string VALUE 'NOME'.
" Atribuição dinâmica
ASSIGN COMPONENT lv_nome_campo OF STRUCTURE ls_pessoa TO FIELD-SYMBOL(<lv_valor>).
IF sy-subrc = 0.
<lv_valor> = 'Maria Santos'.
ENDIF.
" Leitura dinâmica
DATA lv_conteudo TYPE string.
ASSIGN COMPONENT 'IDADE' OF STRUCTURE ls_pessoa TO <lv_valor>.
IF sy-subrc = 0.
lv_conteudo = <lv_valor>.
ENDIF.
Estruturas Aninhadas
Definição
TYPES: BEGIN OF ty_contacto,
telefone TYPE string,
email TYPE string,
END OF ty_contacto.
TYPES: BEGIN OF ty_funcionario,
numero TYPE i,
nome TYPE string,
contacto TYPE ty_contacto,
morada TYPE ty_endereco,
END OF ty_funcionario.
Manipulação
DATA(ls_funcionario) = VALUE ty_funcionario(
numero = 12345
nome = 'Ana Costa'
contacto = VALUE #(
telefone = '+351 910000000'
email = 'ana.costa@empresa.pt'
)
morada = VALUE #(
rua = 'Rua das Flores'
numero = '123'
cidade = 'Porto'
codigo = '4000-001'
)
).
" Acesso em profundidade
WRITE: / ls_funcionario-contacto-email.
WRITE: / ls_funcionario-morada-cidade.
Operações com Estruturas
Comparação
DATA ls_pessoa1 TYPE ty_pessoa.
DATA ls_pessoa2 TYPE ty_pessoa.
ls_pessoa1 = VALUE #( id = 1 nome = 'João' idade = 25 ).
ls_pessoa2 = VALUE #( id = 1 nome = 'João' idade = 25 ).
" Comparação completa
IF ls_pessoa1 = ls_pessoa2.
WRITE: / 'Estruturas iguais'.
ENDIF.
" Comparação de campos específicos
IF ls_pessoa1-nome = ls_pessoa2-nome.
WRITE: / 'Nomes iguais'.
ENDIF.
Limpeza
" Limpar toda a estrutura
CLEAR ls_pessoa.
" Sintaxe moderna
ls_pessoa = VALUE #( ).
" Limpar campos específicos (manter outros)
ls_pessoa = VALUE #( BASE ls_pessoa
salario = 0
idade = 0
).
Move-Corresponding
" Move campos com mesmo nome
DATA ls_origem TYPE ty_pessoa.
DATA ls_destino TYPE ty_funcionario.
ls_origem = VALUE #( nome = 'Pedro' ).
MOVE-CORRESPONDING ls_origem TO ls_destino.
" ou sintaxe moderna:
ls_destino = CORRESPONDING #( ls_origem ).
Estruturas Include
TYPES: BEGIN OF ty_auditoria,
criado_por TYPE syuname,
criado_em TYPE timestamp,
alterado_por TYPE syuname,
alterado_em TYPE timestamp,
END OF ty_auditoria.
TYPES: BEGIN OF ty_documento.
INCLUDE TYPE ty_auditoria.
TYPES: numero TYPE string,
descricao TYPE string,
END OF ty_documento.
" ty_documento contém todos os campos de ty_auditoria + os próprios
Component Operator
" Acesso moderno a componentes
DATA(lv_email) = ls_funcionario-contacto-email.
" Verificar existência de componente
IF ls_funcionario CS 'NOME'. " CS = Contains String (campo existe)
WRITE: / 'Campo NOME existe'.
ENDIF.
" Número de componentes
DESCRIBE FIELD ls_funcionario COMPONENTS DATA(lv_num_campos).
Trabalhar com Includes de Tabelas DDIC
" Estrutura que usa includes do dicionário
DATA ls_vbak TYPE vbak. " Contém includes como VBAP_INCL
" Acesso normal aos campos incluídos
WRITE: / ls_vbak-vbeln. " Campo da própria estrutura
WRITE: / ls_vbak-erdat. " Campo de um include
Estruturas Deep vs. Flat
Estrutura Flat (sem tabelas internas ou referências)
TYPES: BEGIN OF ty_flat,
campo1 TYPE c LENGTH 10,
campo2 TYPE i,
campo3 TYPE p DECIMALS 2,
END OF ty_flat.
" Pode ser usada com: EXPORT/IMPORT, MOVE, operações binárias
Estrutura Deep (com tabelas internas ou strings)
TYPES: BEGIN OF ty_deep,
id TYPE i,
nome TYPE string, " STRING = deep
itens TYPE ty_t_itens, " Tabela interna = deep
END OF ty_deep.
" Requer tratamento especial em certas operações
Dicas de Boas Práticas
Nomenclatura de Tipos
- Use
ty_para tipos de estrutura:ty_cliente,ty_pedido - Use
ty_t_para tipos de tabela:ty_t_clientes,ty_t_pedidos - Seja descritivo:
ty_pessoamelhor quety_p
Performance
- Evite estruturas demasiado grandes (muitos campos desnecessários)
- Em loops, aceda diretamente aos campos necessários
- Use
CORRESPONDINGcom cuidado em loops (pode ser lento)
VALUE vs. Atribuição Individual
" ❌ Menos legível
DATA ls_cliente TYPE ty_cliente.
ls_cliente-id = 1.
ls_cliente-nome = 'João'.
ls_cliente-ativo = abap_true.
" ✅ Mais limpo
DATA(ls_cliente) = VALUE ty_cliente(
id = 1
nome = 'João'
ativo = abap_true
).
Estruturas vs. Classes
- Estruturas: dados apenas (sem comportamento)
- Classes: dados + métodos (comportamento)
- Use estruturas para DTOs (Data Transfer Objects)
- Use classes quando precisar de encapsulamento e lógica
Tags: #Fundamentos #Estruturas #Modern-ABAP