Você está na página 1de 72

ABAP Training

1















Performance










ABAP Training


2


Objetivo

Troca de informaes sobre os pontos mais comuns no mercado de programao
ABAP que tem causado problemas graves de performance (clientes e parceiros)
Recomendaes SAP
Demonstrar alguns casos verdicos
Demonstrar estatsticas sobre o uso de algumas tcnicas de converso (Batch-Input,
Call Transaction, Direct Input)




1. Arquitetura Client-Server

O R/ 3 trabalha com uma filosofia de cliente/ servidor de 3 nveis:

Database server : responsvel pelo acesso e pela atualizao dos dados
Application server : responsvel pelo processamento da aplicao (tempo
despendido com a interpretao de comandos ABAP)
Frontend : responsvel pelo processamento dos grficos (tempo
despendido pelo sistema R/ 3, ou seja, o middleware e
Kernel). Kernel = conjunto de programas utilitrios que
existe dentro do R/ 3, servindo ao cumprimento de
inmeras tarefas

A alocao dos servidores de aplicao definida automaticamente no momento de
logon ( checado qual servidor est menos sobrecarregado).

Dica: Para se obter uma otimizao da performance em programas ABAP, deve-se
minimizar o tempo de acesso ao database.









ABAP Training


3


2. Grandes viles no que se refere performance

Ninhos de select
Select . Endselect ao invs de comandos que recuperem do banco de dados todos
os registros de uma nica vez
Select * ao invs de select com as colunas necessrias ao processamento
Select single sem chave completa especificada ao invs de Select up to 1 row
Selects genricos, ou seja, onde a clusula where no foi fortemente especificada,
com vrias condies, visando restringir a seleo
ndices no utilizados
Falta de ndices
Select em tabelas com alto nmero de registros utilizando clusula where baseada
em tela de seleo onde o preenchimento no obrigatrio
Definio funcional falha
Grandes tabelas do sistema: BKPF, BSEG, EKKO, EKPO, VBAK, VBAB, MKPF,
MSEG, J_1BNFDOC, J_1BNFLIN
Funes genricas, como por exemplo CLAF_CLASSIFICATION_OF_OBJECTS



ABAP Training


4

2.1. Comunicao entre o Application Server e Database Server - Transmisso de
pacotes

Premissa:
VBAK contm 1000 registros, sendo que cada registro contm 575 bytes.

Fato:
A comunicao entre o DB server e o Application server acontece em pacotes de 32.000
bytes, dependendo da rede e equipamentos de comunicao utilizados.

Select * from VBAK.

Portanto:
1000 registros x 575 bytes = 575.000 bytes
575.000 bytes / 32.000 = 20 pacotes
20 pacotes: na verdade este nmero um pouco mais alto (mais ou menos 24), uma vez
que informaes administrativas so transferidas em cada transmisso, juntamente com
os dados.
O exemplo acima tenta ilustrar que, se forem selecionadas apenas as colunas
necessrias, a transferncia de dados ser menor e, consequentemente, haver uma
reduo significativa no tempo de resposta.

2.2. Select e Logical Database

Get VBAK
Get VBAK fields vbeln auart bname kunnr

O segundo comando muito melhor que o primeiro. Porm, nem todos os logical
database suportam select em colunas. Para verificar se isso possvel, acesse a
transao SE36, coloque o nome do database no qual se deseja efetuar uma pesquisa e
escolha a opo: extras -> field selection.

ABAP Training


5

2.3. Cursor Caching

Os seguintes comandos SQL produzem o mesmo resultado, mas cada um deles requer
seu prprio cursor uma vez que os comandos no so idnticos (verifique a ordem das
colunas aps a palavra Select e na clusula WHERE):

Select vbeln auart into (vbak-vbeln, vbak-auart) from vbak
where vbeln = nnn and auart = yyyy

Select vbeln auart into (vbak-vbeln, vbak-auart) from vbak
where auart = yyyy and vbeln = nnn

Select auart vbeln into (vbak-auart, vbak- vbeln) from vbak
where vbeln = nnn and auart = yyyy

Select auart vbeln into (vbak-auart, vbak- vbeln) from vbak
where auart = yyyy and vbeln = nnn

Desnecessrios comandos Declare e Prepare podem ser evitados se os comandos SQL
so mantidos consistentes nos programas que esto sendo desenvolvidos (quando se
usar select com colunas ou declarando condies WHERE sempre use a sequncia de
campos conforme definido no Data Dictionary)

ABAP Training


6

2.4. Logical database e Tables statements
Report ZACCENTURE.
Tables: vbak, vbkd, vbpa.

Get vbak fields vbeln auart bname kunnr.
Write: vbak-vbeln, vbak-auart, . .

Get vbpa fields parvw kunnr.
Write: vbpa-parvw, vbpa-kunnr, vbkd-zterm.

Ao invs use:

Get vbak fields vbeln auart bname kunnr.
Write: vbak-vbeln, vbak-auart, . .

Get vbkd field zterm.

Get vbpa fields parvw kunnr.
Write: vbpa-parvw, vbpa-kunnr, vbkd-zterm.

OBS.: A estrutura do logical database VAV (utilizado anteriormente) VBAK VBUK
VBKD VBPA.

Se uma tabela no especificada via um carto TABLES ento o sistema
automaticamente recupera somente os campos chave para aquela tabela (aqui VBUK
no est presente no carto tables, assim somente os campos chaves so recuperados
pelo sistema).

Se uma tabela especificada via TABLES, todas as colunas so recuperadas, mesmo se
nenhum campo daquela tabela usado no programa (veja a tabela VBKD somente o
campo ZTERM deveria ser impresso).

Para evitar ter todas as colunas selecionadas da tabela, insira um comando GET para
aquela tabela, especificando os campos que sero utilizados pelo programa
posteriormente.



ABAP Training


7

2.5. Select exit versus Select . Up to 1 rows.

Vantagem em performance:
Select exit. Endselect. = 150.000 ms
Select up to 1 rows = 1.500 ms


2.6. Check inside Select endselect.

Comparao de Runtime baseada numa varredura de 57.000 registros na VBAK

Select & Check = 27.958.000 ms
Select com clusula WHERE = 3.065.000 ms

Em caso de condies de checagens muito complexas poderia ser mais rpido obter
dados do banco de dados primeiramente. SQL Trace precisa ser usado para verificar
qual mtodo o mais rpido.

Isso tambm vlido para select single.

2.7. Selects em campos sem ndices

Select-options: bname_so for vbak-bname.

Select vbeln bname . Into (vbak-vbeln ) from vbak
Where bname in bname_so order by <field> descending.

Endselect.

O sistema standard distribudo sem um ndice para o campo bname. A seleo acima
ir resultar numa varredura sequencial da tabela vbak. Isto no aceitvel num sistema
em produo. Criando um ndice na tabela vbak para o campo bname ir resolver o
problema neste caso. Exceo: tabelas cuja buferizao full ou generic (neste caso no
tem sentido pois o primeiro acesso ir trazer todos os dados para a memria. Das
prximas vezes, o sistema busca do buffer e no do database at que o dado mude
novamente).






ABAP Training


8
2.8. Select sum, avg, min, max versus ABAP calculations

Select matnr kwmeng meins into <internal table>
From vbap where . .
Collect <internal table>.
Endselect.

Ao invs use:
Select matnr sum( kwmeng ) meins into table <internal table>
From vbap where .
Group by matnr meins.

O ganho em performance para o processamento de 10.000 registros:
Select + collect = 2.370.000 ms
Select sum . Into table = 1.574.000 ms
OBS.: o group by no pode ser usado para tabelas pool e cluster.

2.9. Select sem clusula where

Select col1 col2 . Into . from vbak.
Perform calculate_stuff.
Endselect.

Um select sem clusula WHERE idnica um erro no design do programa, especialmente
se o select usado em tabelas SAP com grande crescimento/ tamanho em pouco tempo,
em geral, BKPF, BSEG, COBK, COEP, LIPK, LIPS, MKPF, MSEG, VBAK, VBAP, VBPA,
VBFA.

Programas iro rodar de forma correta e bem na entrada em produo, todavia a
performance ir decrescer medida que dados so adicionados diariamente.

2.10. Table buffering

Para analisar a buferizao de tabelas use funo de chamadas estatsticas: Transaction
ST02 -> details analysis menu -> call statistics (tables). Esta funo ajuda voc a
determinar se tabelas desenvolvidas pelo cliente so buferizadas corretamente.

Para analisar a qualidade da buferizao de tabelas use a transao ST02, d duplo click
em TABLES (generic key) e clique no pushbutton buffered objects.


Por que buferizar ?

ABAP Training


9
Usando buferizao pode-se reduzir consideravelmente o tempo que se leva para
recuperar um registro.

Tipos de buferizao:

a) full: resident buffer (100 %): o contedo de toda a tabela carregado no buffer no
primeiro acesso realizado na tabela
b) generic: uma chave genrica (primeiros n campo chaves) especificado quando
da criao da tabela, quando se mantm technical settings. Esta chave genrica
divide o contedo da tabela em chamadas reas genricas. Quando acessando
qualquer dado com uma deteminada/ especificada chave genrica, toda a rea
genrica carregada no buffer.
c) Partial (single record): somente registros nicos so lidos do banco de dados e
armazenados no buffer.

Quando bufferizar uma tabela ?

Uma tabela deveria ser buferizada quando:
Menor em tamanho (poucas linhas ou poucas colunas com tamanho de campos
pequenos)
acessada muito mais para leitura
alteraes no ocorrem frequentemente

Tabelas que so boas candidatas a buferizao:

tabelas de controle/ tabelas de customizao
small master data tables (ex.: 100 material master recores -> few changes)

Como buferizar uma tabela ?

a) Como ativar/ desativar uma buferizao:
dictionary maintenance (SE11 -> technical settings)
technical settings for a table (transaction SE13)

a) Decidindo sobre o tipo de buferizao:
full (resident = 100 %)
generic (with number of key fields for the generic key)
single records (partial buffering)




ABAP Training


10
Comandos SQL bypassing a buferizao:

select bypassing buffer
select from database views (projection views are ok)
select distinct
select count, sum, avg, min, max
select order by (outros alm da chave primria)
select for update
Clusula where contm o comando IS NULL
Comandos natives do SQL (EXEC SQL ENDEXEC) Evite esses commandos
quando estiver trabalhando com tabelas buferizadas!!!





























3. Outros responsveis pela degradao da performance

ABAP Training


11

Move corresponding interessante para pequenas tabelas ou quando alguns
campos (mas no todos) precisam ser movimentados.
No use sort - appends. Ele consome muito tempo de CPU e os resultados so
frequentemente imprevisveis.
Sempre especifique ASCENDING ou DESCENDING em processamentos com
SORT. Qualificar todos os comados SORT atravs da clusula BY <data fields>
melhora a performance e a leitura do cdigo, evitando assim que todos os campos
do registro sofram classificao
Use COMPUTE ao invs de ADD, SUB, MULTI, DIV desde que performance no
seja um grande problema. O comando COMPUTE mais fcil de implementar e
com ele a leitura do programa se torna mais fcil. A diferena em performance
minuto, todavia se o objetivo conseguir tempo de resposta de subsegundos para
transaes complexas, ento deve-se usar comandos separados
Quando da definio de uma tabela no dicionrio de dados do R/ 3 os campos chave
sempre devem ser colocados nas primeiras posies do registro da tabela
(primeiras colunas). O banco de dados comprime os dados para todos os campos da
tabela, mas a compresso no ocorre para campos chave. A compresso tambm s
possvel para as colunas aps o ltimo campo chave: isso explica o porque de
agrupar todos os campos chaves nas primeiras posies
Transparent e Pool Tables: sempre que for feito um select para buscar dados de
tabelas deste tipo pode-se qualificar a clusula WHERE com campos chave e no
chave, ou seja, quanto mais condies puderem ser definidas, melhor para a
obteno de performance. Isto permite que o banco de dados avalie os registros e
retorne somente aqueles que combinem com o critrio de seleo definido
Cluster table: ocorre exatamente o inverso: devido a forma de armazenamento
destas tabelas, na clusula WHERE deve constar apenas os campos chaves e os
demais campos devem ser checados atravs do comando CHECK. O banco de
dados no consegue processar cluster tables como ele processa transparent tables.
Forando o banco de dados a descompactar e checar campos (em caso de Select com
campos no chaves na clusula WHERE) menos eficiente, na maioria dos casos,
que qualificando somente com campos chaves e deixando o CHECK para os campos
no chave aps eles terem sido retornados. Na verdade ambos modos iro
funcionar, porm um deles ser ineficiente pois ir requerer grande parte da
memria disponvel, espao em buffer e tempo do banco de dados para
descompactar campos no chave, o que certamente ir refletir em performance. Em
algumas tabelas Cluster, mesmo a seleo com restries atravs das chaves
primrias torna-se lenta, compensando, nestes casos, a seleo da tabela inteira e
jogando-a para uma tabela interna e a partir desta fazer as restries.

ABAP Training


12
Campos que sero comparados na clusula WHERE devem ter atributos similares.
Se isso no ocorre, o sistema tem que converter o dado toda vez que a comparao
feita. Quando isso no possvel, mova o dado a ser comparado para uma rea

auxiliar, antes de efetuar a comparao (esta rea auxiliar deve ser definida com o
mesmo tipo e tamanho da coluna da tabela)
Evitar classificaes em vrias tabelas e, posteriormente, a realizao de loops. Ou
seja, evitar construes do tipo SORT tab1, SORT tab2, , e depois o LOOP tab1,
LOOP tab2 . . Isso funciona, porm ir requerer mais memria e recursos para
possuir todos os dados resultantes da classificao at que eles sejam usados. Ao
contrrio, quando se faz SORT seguido de LOOP, o espao liberado ao trmino do
loop































ABAP Training


13



4. Quando usar internal table ou Dictionary structure

Para tabelas que so usadas repetidamente ou por vrios programas, considere a
possibilidade de criar estruturas de dados no Data Dictionary (e abr-las atravs do
comando TABLES) ao invs de defin-las dentro de programas individuais (atravs do
comando DATA . ENDDATA).

Sobre estas circunstncias, o uso de tabela interna atravs do Data Dictionary
prefervel:

a tabela interna grande
a tabela acessada da mesma forma toda vez
a mesma tabela interna usada em vrios programas
o programa ir processar vrias tabelas internas ao mesmo tempo (e ento precisa
de muita memria)
o uso de memria um ponto chave para otimizao de um programa em particular

Use o comando FREE para liberar memria alocada a tabelas internas. Este comando
deve seguir o ltimo comando para processamento do dado na tabela.

Use o comando FREE sob as seguintes condies:
a tabela interna grande
a tabela interna classificada e reprocessada vrias vezes
o programa est processando vrias tabelas internas (e portanto necessita de grande
quantidade de memria)
o uso de memria importante para um programa em particular ser otimizado: um
LOOP AT . WHERE prefervel a um LOOP AT CHECK ENDLOOP
porque estar sendo reduzido o nmero de comandos a serem interpretados


ABAP Training


14

5. Processamento de grandes tabelas

5.1. Quando estiverem sendo manipuladas grandes tabelas muito importante que seja
processada a maior quantidade possvel de informao num primeiro momento e, se
possvel, eliminar qualquer outra passagem nesta mesma tabela. Muitas vezes isso
requer o uso de tabelas internas. Cada situao deve ser analisada e avalidada, para
ver qual o procedimento correto a ser tomado: se armazenar o dado ou fazer novo
acesso tabela do Data Dictionary. Considere as seguintes questes:

qual o tamanho da tabela original comparado ao subset que seria armazenado em
uma tabela interna ?
quanto espao para armazenamento seria necessrio para armazenar o dado em
uma taela interna ?

Se o processamento precisar ocorrer somente uma vez (por exemplo, armazenar alguns
dados para posterior comparao), esteja certo que isso acontecer for a de uma
estrutura em forma de looping (por exemplo, Select, Loop, Do), de forma que o
processamento no seja repetido desnecessariamente.

Dica: o operador IN consome muito tempo de mquina e no deveria ser usado em
lugar do operador EQ .

ABAP Training


15

5.2. Expresses lgicas so avaliadas da esquerda para a direita. A avaliao termina
quando o resultado final foi estabelecido (eliminao ou incluso completa). Todavia,
quando se utiliza os operadores AND ou OR (por exemplo, em IF, WHERE) o critrio
de eliminao mais comum deve ocorrer primeiramente.

Exemplo:
A seguinte tabela deve ser lida, imprimindo-se os empregados da companhia ABC na
Georgia

EMPLOYEE NAME COMPANY STATE
001 Doe, Jr. ABC TX
002 Doe, M. ABC OK
003 Jones, A. XYZ TX
004 Jones, B. ABC GA
005 Jones, C. ABC TX
006 Jones, D. XYZ GA
007 Jones, E. ABC TX
008 Smith, A. ABC GA
009 Smith, B. ABC TX
010 Smith, C. ABC OK

if company = ABC and
state = GA
write ..
endif.
isto funciona, mas tanto os campos company quanto state precisam ser avaliados para oito de
dez campos

if state = GA and
company = ABC
write ..
endif.
isto necessita menos tempo para ser processado, porque ele elimina todos os registros sem state
=GA e portanto tanto o campo company quanto state precisam ser avaliados para somente trs
registros.






ABAP Training


16
5.3. ndices secundrios:

sempre esteja certo que o seu ndice est sendo usado:
A well-defined and properly implemented index is one of the best performance
and tuning tool available. Because of the diversity of various database systems,
however, and in particular various database optimizers, it is not possible to
establish any hard-and-fast rules for creating and using database index.
Additionally, it is impossible to guarantee that the database optimizers will use
your index .
Para saber se o ndice definido est sendo usado:
* use o SQL Trace (transao ST05) para ativar e desativar o trace
* clique em trace on
* execute a transao em questo em uma outra sesso
* retorne a ST05 e clique em trace off
* clique em list trace para visualizar os resultados de seu trace
* clique em prepare, open ou reopen para selecionar o comando SQL que
ser avaliado
* clique em EXPLAIN para obter o resultado do comando SQL

ABAP Training


17

5.4. Regras gerais para criao e uso de ndices secundrios:

5.4.1. Um ndice suporta pesquisa a dados no banco de dados. Todas as tabelas
standard SAP possuem um ndice primrio, o qual consiste de campos chaves que o
usurio define quando da criao de uma tabela. Para os selects aonde a chave primria
no pode ser utilizada na clusula WHERE, ou quando selects no so qualificados, o
banco de dados pesquisa a tabela inteira (executa uma varredura sequencial).

O Dicionrio de Dados da SAP suporta at 16 ndices para cada tabela.
Geralmente, crie ndices com menos que 5 campos.

Geralmente, se uma condio inclui OR, o otimizador pra o processamento (e chama
uma varredura sequencial) to logo o primeiro OR seja encontrado. A exceo possvel
um OR que prope uma condio separada e nica para avaliao.

Exemplo:
ZTABLE definida com um ndice secundrio:

FIELD NAME TYPE LENGTH
FieldC Char 3
FieldF Char 2

Select * from ztable where
fieldc = ABC and
(fieldf = 12 or 13)
isto executado, mas no usa o ndice conforme esperado

Select * from ztable where
(fieldc = ABC and fieldf = 12) or
(fieldc = ABC and fieldf = 13)
isto executado usando o ndice

ABAP Training


18

5.4.2. Informaes gerais:
Clusulas IN so frequentemente interpretadas como condies OR e podem gerar
alguns problemas
ndices no so usados para condies IS (NOT) NULL
A maior parte dos otimizadores tem problemas com condies OR, NEQ e LIKE

Exemplo:
ZTABLE definida com um ndice secundrio

FIELD NAME TYPE LENGTH
FieldA Char 3
FieldB Char 3
FieldC Char 2
FieldD Char 4

Select * from ztable
Where fieldA = ABC and
field B = XYZ and
fieldC = 12.
isto funciona bem.

Select * from ztable
Where fieldA = ABC and
field B = XYZ and
fieldD = DEFG.

isto no usa o ndice conforme esperado e provavelmente invoca uma varredura
sequencial da tabela baseada na chave primria

ABAP Training


19

5.4.3. Considere a criao de um ndice se um ou mais condies se aplicarem:

campos no chave so repetidamente usados para fazer selees
somente uma pequena parte de uma grande tabela selecionada (< 5%)
a clusula WHERE de um comando SELECT simples
os campos que compe o ndice reduzem significativamente o conjunto de registros
em uma clusula WHERE

5.4.4. No crie ndices se uma das seguintes condies se aplicar:
a redundncia de dados de armazenamento do ndice cria problemas devido ao
tamanho da tabela ou ndice
atualizaes constantes criam excessivo overhead ou perda de performance durante
a atualizao do ndice
manuteno de um ndice (como a reorganizao) causa perda dos benefcios
esto sendo usados campos cujos valores para a maioria dos registros na tabela um
valor inicial ou tem um valor que idntico para a maioria dos registros


ABAP Training


20

6. Conceito de atualizao em update task

Para aproveitar ao mximo os recursos computacionais de cada nvel, a SAP criou um
conceito de atualizao em update task. Se for feita uma pesquisa em todos os
programas "on-line" da SAP, ser verificado que a atualizao sempre em funes
que s fazem o update, e que no retornam valores nem mesmo exceptions se estas
ocorrerem. (CALL FUNCTION .... IN UPDATE TASK).

Logo todas as aplicaes fazem todas as checagens possveis e imaginveis antes de
chamarem estas funes, ou seja, as exceptions que podem ocorrer so somentes as de
BD (por exemplo table space, ou algo no previsto). Se uma aplicao faz "n"
atualizaes, esta ir chamar "n" funes (uma para cada update de um conjunto de
tabelas) e, ao final, dar um commit work. O que o R/ 3 faz simplesmente ir criando
todos estes dados em uma espcie de log. No momento do commit work ele cria uma
outra LUW (Logical Unit of Work) no servidor de BD e passa esta tarefa para este. Note
que o programa (que esta sendo processado no servidor de aplicao), no fica
esperando a resposta se o update ocorreu corretamente ou no, ele continua o
processamento e termina a transao muitas vezes antes do servidor de DB ter
terminado o processamento.

A vantagem bvia deste processo a diminuio de gargalos via este "tratamento de
mensagens" entre as duas camadas (DB e aplicao).

Quando se utiliza o comando SET UPDATE TASK LOCAL o servidor de aplicao
passa a executar o update (ou seja, no criado uma outra LUW no servidor de DB) e
este fica esperando a resposta se tudo ocorreu OK.

Um SET UPDATE TASK LOCAL suficiente para todo o processamento do commit
ser efetuado como local. Por isso, todos os updates da SAP procuram no utilizar o
comando Set update task local. O default o SET UPDATE (em funes). Isso evita que
a performance seja degradada.


ABAP Training


21

7. Comandos Select
Visando garantir a performance e evitar problemas futuros, cuidado com os comandos
empregados. Existem alguns tipos de select mais eficientes que outros. Analise a
aplicao que ser desenvolvida e faa a melhor escolha.


ALGUNS TIPOS DE SELECT


7.1. SELECT FROM <table> INTO TABLE <INTERNAL TABLE> .
A estrutura da tabela interna deve corresponder estrutura da tabela que est sendo
acessada. O sistema l os registros em conjunto, no individualmente, e os coloca
dentro de uma internal table. Este processo mais rpido que ler individualmente
atravs de um LOOP e ir gravando os registros, um a um.

7.2. SELECT * FROM <table> APPENDING TABLE <internal table>.
L os registros e os inclui - no sobrepe - em uma internal table.

7.3. SELECT . INTO CORRESPONDING FIELDS OF TABLE <itab>.
Neste caso a estrutura da tabela interna no precisa corresponder estrutura da tabela
que est sendo acessada. <itab> o nome da internal table. Movimentar os registros
para as colunas definidas na internal table que possuam nome igual ao da tabela
acessada).
Obs.: corresponding ou appending corresponding no exigem o endselect.

7.4. SELECT .. APPENDING CORRESPONDING FIELDS OF TABLE <itab>.
L e grava (no sobrepe) os dados em uma internal table que possua nomes idnticos
aos nomes da tabela que est sendo lida.

7.5. SELECT SINGLE * FROM SPFLI WHERE ..<campo>.. EQ <contedo>
Toda vez que se usa select single * a chave primria completa deve ser especificada. Se
a chave especificada no qualificada, voc receber uma mensagem de warning e a
performance ficar prejudicada.
No caso de haver a necessidade de acessar um nico registro via select, as opes so:
select * .. seguido de comando exit OU select * up to 1 rows. Neste caso no
necessrio especificar a chave completa.


ABAP Training


22

7.6. SELECT * FROM <tabela>
Quando no se impe nenhum tipo de restrio, ocorre uma varredura sequencial dos
registros da tabela. Quando se utiliza grandes tabelas, isso obviamente afeta o runtime.

Select * seleciona todas as colunas de uma tabela. melhor sempre especificar as
colunas, pois em caso de tabelas com muitas colunas, prejudicar performance.

7.7. SELECT * FROM <tabela> WHERE <campo> eq <contedo>.
L todos os registros da tabela especificada onde o campo igual ao contedo
especificado. O ideal que se qualifique a clusula WHERE tanto mais quanto seja
possvel. Atentar que isso vlido para tabelas do tipo Pool e Transparent. Para
Cluster, seguir as recomendaes dadas anteriormente.

7.8. SELECT <a1> <a2> INTO (<f1>, <f2>, ) FROM .<tabela>
WHERE .
L as colunas especificadas (a1, a2). Aps INTO devero ser especificadas as reas de
trabalho auxiliares (f1, f2). O nmero de colunas lidas dever ser igual ao nmero de
work-areas especificadas.

7.9. SELECT * FROM <table> WHERE <table field> BETWEEN <field1> and <field2>.
Ex.: field1 = 100 e field2 = 500. Pega inclusive 100 e 500. Voc trabalha com o range.

7.10. SELECT * FROM <table> WHERE <table field> LIKE ._R%.
_ = a primeira letra no importa o que vir
a segunda dever ser R (eu defini)
% = no importa a sequncia de caracteres que vir.
(Varredura para que possa realizar a comparao)

7.11. SELECT MAX(campo)
MIN(campo)
AVG(campo)
COUNT(*) FROM <table> INTO (..,,..,.)
WHERE .

AVG e SUM: somente para campos numricos.
No se usa endselect.
Mais rpido fazer uma rotina mo que utilizar este comando.


ABAP Training


23

7.12. SELECT * FROM <table> WHERE <table field> IN (.,.).
Exemplo: select * from <table> where campo1 in (123,1000) - podem ser valores ou
literais. igual a perguntar se campo1 123 ou 1000.

7.13. SELECT * FROM <table> WHERE <table field> IN <internal table>.
Exemplo:
DATA : begin of ITAB occurs 10,
sign(1), option(2), low like sflight-price, high like sflight-price,
end of ITAB.

* RANGES: ITAB for sflight-table
Move: I to itab-sign, btto itab-option, 500 to itab-low, 1000 to itab-high.
Append itab. Move: I to itab-sign, btto itab-option, 440 to itab-low.
Append itab.

7.14. SELECT * FROM (<table>) INTO <work area>.
Exemplo: data: begin of WA,
line(100),
end of WA.

7.15. Select * from (tabname) into WA
Write .
Endselect.

Parameters: tabname(10) default SPFLI.
Obs.: especificando o nome da tabela dinamicamente no select statement sempre
consome mais tempo de CPU que especificando estaticamente no programa.

7.16. SELECT * FROM <table> FOR ALL ENTRIES IN <internal table> WHERE
campo1 = <contedo> and
campo2 =<contedo>
Defino uma tabela interna. Alimento os campos desta tabela interna. (move e append).
No meu select campo1 e campo2 sero os campos definidos e alimentados na tabela
interna.
Esta uma excelente soluo quando se trabalha com grandes tabelas.
O select for all entries simula a funcionalidade join.






ABAP Training


24
7.17. SELECT * FROM <table> ORDER BY <field1> <field2> PRIMARY KEY.
Obs.: Classifica a tabela interna numa rea auxiliar, sem afetar a tabela original. Evitar
o uso de sorts dentro de um select. Consome mais tempo que descarregar os dados em
uma tabela interna e classific-los.

7.18. SELECT carrid MIN( price ) max( price ) INTO (carrid, minimum, maximum)
FROM sflight GROUP BY carrid.
(Todos os campos que eu quero que apaream na minha lista eu preciso especificar
aps a clusula GROUP BY. Carrid, maximum e minimum so campos auxiliares. Se o
nome do database no conhecido at runtime no se pode especificar a clusula
GROUP BY).
Performance no to boa (funes MIN, MAX, etc. geram uma varredura sequencial
na tabela).

7.19. SELECT * FROM <table> BYPASSING BUFFER.
(Usado para ler diretamente da tabela original, e no do buffer).

OBS.: Select single * sempre com chave completa especificada. Particularidade do
Abap/ 4.
Select * - procurar evitar. Informar as colunas que sero necessrias, apenas.


ABAP Training


25

7. Dicas para otimizao do cdigo

- Use o comando FREE para liberar espao em internal tables; Sempre usar os
comandos Clear / Refresh aps o fim de um LOOP;
- Evite comparaes num SELECT com campos numricos versus campos
alfanumricos; o sistema perde tempo para converso;
- Testar SY-SUBRC aps cada acesso ao banco de dados;
- O comando MOVE-CORRESPONDING bom para tabelas pequenas. interessante
que a tabela interna contenha os campos na sequncia em que sero movimentados;
- Ao utilizar o comando CASE, codificar sempre a clusula WHEN OTHERS;
- Sempre identifique se um SORT ascending ou descending e especifique a clusula
BY <fields>. Caso contrrio, todos os campos sero classificados.
- Evitar lgicas do tipo IF not CPOA = CPOB. mais claro codificar IF CPOA ne
CPOB.
- Evitar construes do tipo:
SORT tabela1, SORT tabela2, SORT tabela3.
LOOP tabela1, LOOP tabela2, LOOP tabela3
Para cada SORT fazer o LOOP correspondente. A ento iniciar novo
SORT e LOOP, e assim por diante.
- Campos chave devem ser sempre os primeiros campos da tabela. Assim, todos os
demais campos sero comprimidos;
- SELECT (para Transparent e Pool Tables): a clusula WHERE deve conter,
preferencialmente, os campos chaves e demais campos que possam restringir a
pesquisa;
- SELECT (para Cluster Tables): s os campos chaves devem ser especificados na
clusula WHERE. Os demais devem ser checados atravs do comando CHECK;
- O conhecimento do contedo dos dados de uma tabela pode auxiliar no momento
da codificao do comando select. O campo que ocorrer em nmero menor de vezes
dever constar na clusula where antes daquele que ocorre um nmero maior de
vezes, caso seja necessrio satisfazer a ambas condies. Isso faz com que o
processamento seja mais gil.
- Manuseio de tabelas: Estudar a possibilidade de manuseio em tabelas internas para
agilizar o processo. Analisar tambm o uso de comando select, sendo o que melhor
se adapte a situao em questo.

ABAP Training


26

8. Ferramentas para auxliar os desenvolvedores

Existem algumas ferramentas que auxiliam os desenvolvedores a descobrir erros
(errors, warnings, etc), bem como avaliar a performance de seus programas.

Path: Tools Abap/4 Workbench Test - Runtime Analysis

Existe um pushbutton chamado Tips and Tricks Clicando-se nele poder ser feita
comparao entre comandos Select (diferentes tipos). Dando double-click sobre um dos
exemplos voc passar para outra tela, onde voc visualizar a medida do tempo em
microsegundos de ambos, servindo de base de comparao.

Neste mesmo path, pode-se utilizar as facilidades do Runtime Analysis para verificar a
performance de seu programa. Ao final da execuo voc poder acessar informaes
sobre o seu programa (grficos, acesso a tabelas, etc). Para tanto clique o pushbutton
ANALYSE, que somente aparecer depois que for informado o nome do programa
e/ ou transao e clicado execute.

O SQL Trace (transao ST05) outra facilidade que pode ser utilizada para trilhar a
lgica de sua aplicao e verificar possveis pontos de correo. Voc poder visualizar
os comandos de acesso a banco de dados utilizados, obter informaes sobre um
comando especfico, visualizar os ndices que esto sendo utilizados (ver tpico 5.3
sobre como utilizar o SQL Trace).

O Extended Program Check outra facilidade que deve ser empregada visando manter
o seu cdigo o mais correto possvel. Nesta opo voc poder selecionar os tens que
voc deseja que sejam checados e o sistema apontar o seu parecer. Para tanto basta
clicar os tens e o pushbutton PERFORM CHECK Selecionando uma linha voc poder
ver os detalhes, bem como posicionando o cursor em uma linha e clicando o
pushbutton DISPLAY ALL CHANGES.

ABAP Training


27

9. I nterfaces Batch ou Converses:

Segundo a documentao da SAP, existem trs mtodos para converso: Direct input,
Call transaction e o Batch Input.

Direct Input: um dos mtodos para transferncia de dados do sistema legado para
o sistema R/ 3. considerado o mtodo mais rpido. Um arquivo sequencial com
dados gerado como um arquivo texto para processamento por alguns function
modules especiais. Estas funes executam todas as checagens normais para
garantir a integridade de dados. Quando os registros so processados com sucesso,
eles so gravados diretamente nas correspondentes tabelas do banco de dados da
aplicao. Na ocorrncia de erros, os dados errados so passados para uma rotina
de manuseio de exceo. O gargalo associado com o processamento do dialog e
update so eliminados neste caso. Para todas as necessidades de transferncia de
dados, especialmente com transaes de alto volume, o direct input o mtodo mais
indicado. Nota: este mtodo deveria ser usado em todas as situaes nas quais
funes de aplicao utilizando esta tecnologia existam.

Call Transaction: o prximo mtodo mais rpido para processamento de dados do
sistema legado para o sistema R/ 3. Neste caso, o programa de transferncia de
dados processa os dados do arquivo sequencial e chama a transao desejada
usando um comando Abap. Dados de um arquivo sequencial so processados via
telas de aplicao para uma nica transao. A lgica de aplicao executa todos os
checks e a validao dos dados. Este um processamento sncrono. Quando o
processamento do dialog realizado com sucesso, o processamento do update
chamado pela aplicao correspondente para executar todas as solicitaes do banco
de dados. A escolha pode ser feita entre update sncrono ou assncrono. Nenhum
protocolo de erros ou sada para lidar com os erros fornecida por esta tcnica.
responsabilidade do programador da aplicao incorporar rotinas de execuo e
funes dos protocolos desejados como parte do programa de transferncia de
dados. A nossa recomendao usar o mtodo Call Transaction em todos os casos
em que no existe um programa Direct Input. Somente em situaes de lidar com
erros ns recomendamos que o batch-input tradicional seja realizado para posterior
processamento. Resumo: em contraste com o Batch-Input, o Call Transaction
permite que sejam passados dados diretamente ao dialog interface sem usar uma
fila. Para armazenar estes dados temporariamente, voc usa uma internal table (uma
tabela BDC, a qual tem a mesma estrutura daquela utilizada no batch-input). Antes
de entrar dados na BDC table necessrio fazer uma verificao nos dados. Call
transaction: pode ser executado imediatamente.


ABAP Training


28
Batch-Input: o batch-input tem sido tradicionalmente selecionado como um mtodo
de implementao de programas de transferncia de dados. Um benefcio que este
mtodo traz sobre o Call Transaction que o batch-input tem um utilitrio
responsvel pela administrao e gerenciamento das funes do batch-input. Alm
do mais, utilitrios existem para monitorar e dar manuteno em tarefas associadas
com este mtodo. Assim, no h necessidade de nenhuma programao adicional
para anlise de excees e funes de protocolo. Dados vindos de um arquivo
sequencial so processados via telas de aplicao e armazenados numa sesso batch-
input. Por definio, uma sesso uma coleo de dados de transao para uma ou
mais transaes. As sesses batch-input so fisicamente armazenadas pelo sistema
num banco de dados como uma fila. Estas sesses podem conter tanto registros de
dados corretos quanto incorretos. O batch-input trata tanto o update sncrono como
o assncrono. O mtodo batch-input, em contraste com o mtodo Call Transaction,
pode transferir dados do sistema legado para o sistema R/ 3 para mltiplas
transaes da aplicao. Todavia, nenhuma nova transao iniciada at que a
transao anterior tenha sido gravada no correspondente banco de dados durante o
processamento das sesses de batch-input. Tambm, sesses de batch-input no
podem ser geradas em paralelo. Ele pode ser processado de trs modos: foreground,
display erros only ou background.
Este mtodo oferece excelente capacidade para gerenciamento de erros e
detalhado para anlise do protocolo da transao.
Resumo: gerado um log e pode ser programada a execuo. Em caso de erro, o
registro pode ser corrigido e inserido novamente. Atravs deste recurso, todos os
dados so entrados na transao original SAP, ou seja, seguindo todas as
consistncias necessrias, evitando assim que erros de integridade sejam cometidos.

AVALIAO:

Sempre execute alguns testes dentro do processo de transferncia de dados e avalie
qual o mtodo mais apropriado para uso, dado o volume de dados, tamanho,
recursos e performance do sistema.

Todos os fatores sendo iguais, o mtodo Direct Input deve ser usado em todos os
casos em que tais funes estejam disponveis ou novas funes para transferncia
de dados precisem ser desenvolvidas.

Para escolher entre o Call Transaction e o Batch-Iput, sempre use o Call Transaction
primeiro e manuseie as excees ento atravs do mtodo de batch-input. Esta
estratgia altamente recomendada em implementao de solues de programao
para transferncia de dados com sistemas legados.

ABAP Training


29

10. Estudo de Caso Cliente XYZ
(Parte do relatrio de Quality Assurance da Fase III)

Dentro do escopo do XYZ seria necessrio o desenvolvimento dos seguintes tipos de
programa:

. Converses
. Reports
. Formulrios (SapScript)
. Interfaces

O trabalho baseou-se na anlise de interfaces, haja visto as converses j terem sido
processadas (na sua maioria) para atender a primeira fase de implantao do projeto.
Mesmo assim, foi analisado um programa de converso, cuja tcnica utilizada foi Batch-
Input. Quanto aos Reports, estes se encontram em fase de levantamento, no sendo
possvel, portanto, fazer qualquer tipo de validao.

Do total de interfaces desenvolvidas, buscou-se uma amostra (7 programas), utilizando-se
os seguintes critrios:

. programas considerados crticos, ou seja, que necessitam de um tempo de resposta
eficiente, pela necessidade de serem pseudo-online e seu processamento ocorrer a cada x
minutos;
. programas que manipulam quantidades elevadas de dados diariamente;
. grandes tabelas do R/ 3 (quantidade de registros versus colunas existentes);
. funes do standard que no apresentam boa performance (por serem genricas) quando
utilizadas com finalidades especficas;
. reas de aplicao diferentes (MM, FI, etc)
. desenvolvedores diferentes (foram analisados programas de diferentes pessoas).

Obs.: exclui-se de nossa anlise todos os programas de interface que encontram-se em fase
de desenvolvimento.
Alguns dados:
. Total de interfaces : 40
. Status : 03 em desenvolvimento
02 no tiveram desenvolvimento ABAP
35 esto concludas
. Programas selecionados : ZIFIT002, ZIFIT006, ZLUIZ001 (antigo ZIMMT001)
ZIMMT006, ZIMMT010, ZIPMR001

ABAP Training


30

Quanto confeco de especificao tcnica:

1. O correto seria existir uma especificao tcnica com o intuito de servir como base para
o desenvolvedor. Todavia, tal documentao est ficando pronta apenas ao trmino do
programa. Esta situao no a ideal. Todavia, se torna indispensvel a sua confeco
visando facilitar manutenes futuras;

Quanto ao esquema de testes:

1. de extrema importncia que, alm dos testes individuais, sejam realizados testes com
massa de dados real de produo, visando reproduzir um ambiente real durante a fase
de execuo das interfaces, com o objetivo de minimizar/ eliminar problemas com
performance;

2. Os testes devem englobar todas as condies lgicas possveis, e at mesmo condies
de erro. No existe esquema de stress-test (com grande volume de dados). A massa
de dados no deve ser gerado pelos desenvolvedores;

Quanto uniformidade do cdigo e ao uso da metodologia (padres) definidos na
Fase II:

1. Na amostragem analisada foi constatado que o manual de Padres no foi seguido de
forma ntegra. Em alguns casos (como por exemplo na Nomenclatura definida para
Funes) constante no manual, a forma utilizada nos programas muito mais clara que
aquela anteriormente definida. Aconselha-se alterar o manual de Padres, citando a
nova forma utilizada. No caso da definio de data-elements, este padro no foi
seguido para as tabelas analisadas. Isso tambm se aplica aos nomes definidos para as
sesses de Batch-input pesquisadas via SM35 na data de nossa visita. Estes pontos no
tem implicaes graves sobre os programas, todavia somente vale a pena a criao de
uma metodologia caso ela seja, de fato, seguida, e que esta visa facilitar o trabalho de
pesquisa/ leitura/ manuteno de programas ;

2. Ainda dentro do tpico metodologia alguns pontos deveriam estar sendo seguidos: so
os nomes de variveis. Nem todos os programas obedecem este tpico de forma integral
ou parcial. Este item muito importante, uma vez que facilita a leitura dos programas e
futuras manutenes por terceiros ou at mesmo pela equipe tcnica do XYZ;

3. Uso de mensagens fixas ao invs de text-elements, uma vez que o R/ 3 aceita vrias
linguagens e isto definido em momento de logon no sistema.

ABAP Training


31

Quanto a performance dos programas:

1. Dentro da amostra selecionada foram encontrados erros que se repetiam. So eles:

a) Ninhos de select
b) Select * ao invs de select com suas respectivas colunas
c) Falta de condies na clusula where para limitar o nmeros de registros retornados
atravs do comando Select
d) Tabelas como BKPF, BSEG, EKKO, EKPO, VBAK, VBAB, MKPF, MSEG, J_1BNFDOC,
J_1BNFLIN devem possuir, tantos campos quanto possvel para restringir a pesquisa e
busca de dados.
e) Uso da funo CLAS_CLASSIFICATION_OF_OBJECTS com finalidades especficas

Devido estrutura cliente servidor, resultados melhores de performance estaro sendo
alcanados toda vez que a comunicao entre o servidor de aplicao e o servidor de banco
de dados for minimizado.

Em vrios casos encontramos selects em tabelas grandes, como por exemplo, a BKPF,
trazendo-se todos os registros que atendessem a uma nica condio (por exemplo, cdigo
da transao). de extrema importncia que, em casos de tabelas grandes (tanto em termos
de volume quanto em termos de quantidade de colunas) sejam recuperadas apenas as
informaes necessrias ao atendimento do propsito do programa (colunas e condies).
Deve-se lembrar que, com o passar do tempo, a quantidade de dados presentes nestas
tabelas estar crescendo; em contrapartida, haver uma reduo da performance caso o
programa no esteja fazendo selees adequadas. Uma forma de se obter maior seleo
inserindo um delimitador do tipo DATA, campos que estejam presentes no somente na
tabela acessada mas tambm na prxima que se deseja acessar.

Dentro do exemplo acima, em forma de um ninho de Selects, feito um outro Select para a
tabela BSEG. Ou seja, para cada registro da BKPF ser acessada a tabela BSEG. Esta mesma
situao pode aparece em vrios nveis, o que resulta num caos em termos de performance,
medida que temos a base de dados sendo acrescida.

Alm das precaues anteriores, as quais devem ser aplicadas sempre que possvel, vale a
pena mencionar que o uso de tabelas internas agiliza muito o processamento. Selects que,
num nico comando, sejam responsveis por acessar a tabela, fazer a seleo do range de
dados necessrio, movimentar estes dados para uma tabela interna e gravar estes dados
tero performance superior uma situao de Select endselect e infinitamente superior a
uma situao de Select endselect em ninho.



ABAP Training


32
Ilustrando uma situao semelhante, temos:

Select * from bkpf where tcode = FB01.

Select * from bseg where bukrs = bkpf-bukrs and
belnr = bkpf-belnr and
gjahr = bkpf-gjahr.
Endselect.

Endselect.

* O primeiro comando seleciona as 79 colunas da tabela bkpf atravs do campo TCODE
que, alm de no pertencer chave primria desta tabela, tambm um critrio muito
amplo para pesquisa em tabelas deste porte. Campos como company code, data, ano fiscal,
entre outros, podem ser fortes candidados a restringir a pesquisa.

* O segundo comando seleciona as 266 colunas da tabela bseg, onde os campos bukrs,
belnr e gjahr sejam iguais tabela anterior. Como na tabela anterior no foi utilizado um
critrio de seleo mais adequado, muitos registros sero retornados da bkpf e,
consequentemente, para cada um destes registros, sero retornados n registros da BSEG.

* Ambos os selects correspondero a tantos acessos no banco de dados quantos registros
existirem.

Visando garantir melhor performance, poder-se-ia utilizar:

Select col1 col2 col3 into table tab_bkpf from bkpf where <conditions>.

Select col1 col2 col3 col4 into table tab_bseg
from bseg
for all entries in tab_bkpf
where < conditions >.

OBS.: O exemplo dado de seleo de colunas vlido. Porm, vale lembrar que no
possvel fazer select colunado de tabelas Cluster.






Algumas consideraes:

ABAP Training


33

* Ambos os selects correspondero a um nico acesso no banco de dados.
* O primeiro comando select j seleciona, move e grava os dados numa tabela interna.
* O segundo select ser baseado no resultado, j em tabela interna, do primeiro select.
* So selecionadas apenas as colunas realmente necessrias. Assim, os pacotes transmitidos
entre o servidor de banco de dados e o servidor de aplicao so menores, agilizando
portanto a transferncia.
* tab_bkpf e tab_bseg so tabelas internas.

Outros erros que devem ser evitados:

a) Hard Code
Alguns programas foram desenvolvidos baseando-se apenas na configurao atual do
sistema R/ 3. Com isso, aparecem algumas checagens de forma fixa, por exemplo,
checagens de centros (campo werks), conta contbil, etc., o que invalida os programas caso
seja alterada a configurao.

b) Tabela de contadores idealizada para controle de processamentos e reprocessamentos
no totalmente confivel
Foi criada uma tabela para controle do processamento, visando controlar quais registros
foram ou no processados em caso de alguma interrupo. O objetivo permitir
reprocessamentos parciais. Tendo em mente que as transaes esto sendo chamadas via
Call transaction, tcnica esta que possui um commit prprio, e que a atualizao da tabela
de controle est num outro commit, poder ocorrer situaes onde a tabela de controle no
representa exatamente o que aconteceu.

Necessidades:

a) Stress-test
b) Testes integrados










Comentrios/Recomendaes:


ABAP Training


34
O ponto mais crtico est associado ao tpico de performance. necessrio fazer reviso em
todos os programas de interface, visando detectar situaes semelhantes descrita
anteriormente e providenciar as adequaes necessrias.

Outro ponto de fundamental importncia se refere aos testes. A garantia do bom
funcionamento do programa e a minimizao de problemas com performance somente
ocorrer caso seja realizado testes com massa de dados real, ou seja, volumes prximos ao
esperado em ambiente produtivo, cobrindo as situaes que possam ocorrer.


Restries:

Caso ocorra a entrada em produo sem a alteraes nos programas, a performance ser
decrescente, medida que as bases de dados forem crescendo. Tambm no se pode
garantir que todas as interfaces pseudo-online sero processadas e finalizadas dentro do
tempo estipulado (por exemplo, a cada 5 minutos, etc).


Parecer:

De uma forma geral pode-se dizer que o desenvovimento est bom, porm caso os
programas no sejam revisados e adequados, certamente ocorrero problemas de
performance aps a implantao.

QUADRO RESUMO DA SITUAO DO PROJETO DA XYZ

Tpico Status
Confeco de especificao tcnica
Validado com restries
Esquema de testes No validado
Uniformidade do cdigo-metodologia-
padres
Validado com restries
Performance Validado com restries, desde
que os programas sejam
revisados e alterados
Outros erros No se aplica

ABAP Training


35

11. Estudo de Caso - Cliente ABC
(Parte do relatrio de Quality Assurance da Fase III)

SITUAO ATUAL

Dentro do escopo da ABC seria necessrio o desenvolvimento dos seguintes tipos de
programa:

. Converses
. Reports
. Formulrios (SapScript)
. Interfaces

Obs.: No houve necessidade de programas online.

Devido a alguns problemas, que sero detalhados mais adiante, o cronograma inicial cuja
expectativa era conter apenas 26 gaps sofreu alteraes em termos de volume de
desenvolvimentos e tambm um atraso, estando neste momento a maioria dos programas
em fase de desenvolvimento e/ ou testes. Novos desenvolvimentos tambm foram
incorporados ao projeto (cerca de oito novos programas foram criados). Assim sendo,
optou-se por fazer o QA sobre os programas em 24.06.98, independente de no estarem
concludos, uma vez que em caso da necessidade de efetuar algum tipo de correo,
haveria ainda seis dias corridos antes da data de implantao.

Dado a esta situao, ressalta-se tambm que o coordenador de ABAP (parceiro da SAP)
ainda no teve tempo hbil para fazer a reviso dos programas que foram desenvolvidos,
verificando o cumprimento de normas, padres e situaes cuja performance no fosse
satisfatria, antes que os programas fossem apresentados ao Quality Assurance da SAP. A
grande preocupao, no momento, a confeco dos programas.

Essa situao de anlise de programas em desenvolvimento atpica, uma vez que nossa
anlise deveria se basear apenas sobre os programas j concludos e revisados pelo parceiro
de implementao, mas dada a situao, isso no foi possvel.

Alguns dados (dados aproximados, uma vez que o cronograma do projeto e status no
estavam atualizados):
. Total de programas : 34
. Status

ABAP Training


36

1. Converses - Cargas automticas:
. Cadastro de cdigo NBM : converso realizada
. Cadastro de taxas de cmbio : converso realizada
. Cadastro de Materiais (inicial) : converso realizada
. Cadastro de Fornecedores (inicial) : converso realizada

. Cadastro de Contas a Pagar (inicial) : programa em fase de testes
. Atualizao de Estoques : em desenvolvimento-80 % j realizado
. Atualizao de Pedidos : em desenvolvimento-80 % j realizado

2. Interfaces (em ordem de prioridade):
. Estoques (SAP -> DISPO/ OP) : em desenvolvimento
. Livros Fiscais (SAP->PRECIS) : em desenvolvimento
. Pedidos (SAP -> AVERAGE) : em desenvolvimento
. Contas a Pagar (SAP -> BAYMAP) : em desenvolvimento
. Movimentos de Materiais (SAP -> BAYMAP): em desenvolvimento

. Fornecedores (SAP -> BAYMAP) : no desenvolvido
. Moedas (SAP -> AVERAGE) : no desenvolvido

Obs.: Interfaces de Estoques e Livros Fiscais so indispensveis para a data de implantao
(01.07.98), no mnimo. As demais devem ser disponibilizadas logo aps, para uso no
decorrer do ms de julho.

3. SapScripts:
. Certificado de Qualidade : desenvolvido
. Certificado de Anlise : desenvolvido
. Pedidos : em testes
. Cotaes : em testes
. Requisies : no ser desenvolvido

4. Relatrios:
. Relatrio de Confirmao de ordem de processo (1 e 2): desenvolvido
. Relatrio de produo diria e mensal : aguarda definio de uma das
interfaces para ser desenvolvido
. Relatrio sntese de estoque : no ser desenvolvido. Ser
utilizado relatrio standard do R/ 3.





ABAP Training


37
5. Matchcodes:
.Lote na ordem de processo : ser desenvolvido
. Ordens no liberadas : ser desenvolvido
. Ordens no confirmadas : ser desenvolvido
. Materiais por grupo de listas tcnicas : desenvolvido
. Fornecedores CGC/ CPF : desenvolvido

Panorama das atividades:

O trabalho baseou-se na anlise de interfaces, e de alguns relatrios j concludos, haja visto
a maioria dos programas de converso j terem sido processados antes do Quality
Assurance da Fase III. Mesmo assim, foi analisado um programa de converso, cujas
tcnicas utilizadas foram Batch-Input/ Call Transaction. Posteriormente, obteve-se a
informao de que estes mesmos programas sero utilizados para as interfaces inbound
(carga de dados do sistema R/ 3 a partir do sistema legado). Neste caso, sero
encaminhados somente os dados alterados e/ ou os dados novos. Como a carga de dados
inicial apresentou tempo de processamento considerado baixo pela equipe da ABC,
utilizando os mesmos programas e com volume de dados superior ao que existir na
execuo das interfaces, este item no se torna preocupante.

Do total de interfaces desenvolvidas, buscou-se uma amostra (11 programas), utilizando-se
os seguintes critrios:
. programas considerados crticos, ou seja, que necessitam de um tempo de resposta
eficiente, pela necessidade de serem pseudo-online e seu processamento ocorrer a cada x
minutos;
. programas que manipulam quantidades elevadas de dados diariamente;
. grandes tabelas do R/ 3 (quantidade de registros versus colunas existentes);
. funes do standard que no apresentam boa performance (por serem genricas) quando
utilizadas com finalidades especficas;
. reas de aplicao diferentes (MM, FI, etc)
. desenvolvedores diferentes (foram analisados programas de diferentes pessoas).

. Programas selecionados : ZAFIB001 - Converso
ZACII001 - Include do programa anterior

ZAFII001 - Interface para lanamentos contbeis
ZAPPR001 - Relatrio de confirmao da ordem de
Processo
ZAPPR002 - Listagem do cadastro de material


ZAMMI001 - Interface para movimento de materiais

ABAP Training


38
M. BAYMAP
ZAMMI002 - Interface para livros fiscais
ZAMMI003 - Interfaces para pedidos de compras
ZAMMI010 - Interface para movimento de materiais
M. BAYMAP
ZAMMI020 - Interface para livros fiscais
ZAMMI030 - Interfaces para pedidos de compras
ZAPPI001 - Interface para produo de materiais

Obs.: Dos programas relacionados anteriormente, apenas os programas ZAPPR001 e 002
tinham status concludo. Todos os programas foram analisados a partir de verses
existentes no ambiente de desenvolvimento da ABC.

Quanto confeco de especificao funcional/tcnica:

1. O correto seria existir uma especificao tcnica com o intuito de servir como base para
o desenvolvedor. Todavia, devido ao aumento do nmero de programas a serem
desenvolvidos (entre programas novos e programas para correo de cargas j
realizadas/ programas para auxiliar na conferncia, problemas com o ambiente R/ 3 que
tem apresentado short dumps em transaes standard) tal documentao ficar pronta
apenas ao trmino dos desenvolvimentos. Esta situao no a ideal. Todavia, se torna
indispensvel a sua confeco visando facilitar manutenes futuras. O coordenador do
projeto est realizando um levantamento junto equipe funcional e fornecendo as
informaes necessrias para que os desenvolvedores ABAP possam realizar suas
atividades.

Quanto documentao do projeto (cronogramas, relatrios de controle e
acompanhamento):

1. Estes documentos no esto sofrendo atualizao

Quanto ao esquema de testes:

1. de extrema importncia que, alm dos testes individuais, sejam realizados testes com
massa de dados real de produo, visando reproduzir um ambiente real durante a fase
de execuo das interfaces, com o objetivo de minimizar/ eliminar problemas com
performance. Na ABC no esto sendo feitos testes com alto volume de dados. Isso
acaba mascarando problemas que podem vir a ocorrer no futuro, caso haja um aumento
significativo nos dados;

2. Os testes devem englobar todas as condies lgicas possveis, e at mesmo condies
de erro. No existe esquema de stress-test (com grande volume de dados). A massa

ABAP Training


39
de dados no deve ser gerado pelos desenvolvedores nesta etapa de testes finais, pr-
produo.

Quanto uniformidade do cdigo e ao uso da metodologia (padres) definidos na
Fase II:

Foi estabelecido na fase II de QA que a metodologia e padres seriam adotados do parceiro
de implementao.

1. Na amostragem analisada foi constatado que o manual de Padres no foi seguido de
forma ntegra. Algumas das diferenas so demonstradas abaixo

. nome de programa: no manual estava estabelecido que a composio seria:
Z23456789, onde Z = fixo, 2 e 3 = ao mdulo SAP (FI, MM, PP, etc), 4 a 6 = gap de origem, 7
= B (batch-input) ou I (interface) ou R (relatrio) ou S (Sapscript), 8 e 9 = nmero sequencial
referente ao gap. Na verdade, os programas desenvolvidos no esto obedecendo este
padro;

. classes de desenvolvimento: de fato, obedeceu a estrutura definida anteriormente, ou
seja, uma por mdulo. Todavia, existem programas que no esto na sua classe de
desenvolvimento correta (exemplo, programa de FI na classe de MM);

. nome de variveis: notamos que a atribuio de nomes para tabelas internas,
parameters, select-options, constants e types nem sempre estiveram padronizadas entre os
programas. Este item importante, na medida que facilita a leitura dos programas e futuras
manutenes por terceiros ou at mesmo pela equipe tcnica da ABC;

. existem forms sem nenhum contedo sendo chamados pelos programas;
. existem variveis definidas que no esto sendo utilizadas;
. certificar-se que tabelas definidas com clusula occurs de forma fixa no iro
estourar.









Quanto a performance dos programas:

ABAP Training


40

1. Dentro da amostra selecionada foram encontrados erros que se repetiam. So eles:

a) Ninhos de select
b) Select * ao invs de select com suas respectivas colunas
c) Falta de mais condies na clusula where para limitar o nmeros de registros
retornados atravs do comando Select
d) Tabelas como BKPF, BSEG, EKKO, EKPO, VBAK, VBAB, MKPF, MSEG, J_1BNFDOC,
J_1BNFLIN devem possuir tantos campos quanto possvel para restringir a pesquisa e
busca de dados

Devido estrutura cliente servidor, resultados melhores de performance estaro sendo
alcanados toda vez que a comunicao entre o servidor de aplicao e o servidor de banco
de dados for minimizado.

Em vrios casos encontramos selects em tabelas grandes, como por exemplo, a BSEG,
trazendo-se todos os registros que atendessem a uma nica condio. de extrema
importncia que, em casos de tabelas grandes (tanto em termos de volume quanto em
termos de quantidade de colunas) sejam recuperadas apenas as informaes necessrias ao
atendimento do propsito do programa (colunas e condies). Deve-se lembrar que, com o
passar do tempo, a quantidade de dados presentes nestas tabelas estar crescendo; em
contrapartida, haver uma reduo da performance caso o programa no esteja fazendo
selees adequadas. Uma forma de se obter maior seleo inserindo um delimitador do
tipo DATA, campos que estejam presentes no somente na tabela acessada mas tambm na
prxima que se deseja acessar, etc.

Num outro programa existe um ninho de Selects em trs nveis. Para cada registro da tabela
J_1BNFDOC feito um ou mais acessos na tabela J_1BNFLIN e um ou mais acessos na
tabela J_1BNFSTX. Ninhos como este, com o crescimento na base de dados, trar resultados
desfavorveis performance. Esta mesma situao se repete em outros programas.

Alm das precaues anteriores, as quais devem ser sempre tomadas, vale a pena
mencionar que o uso de tabelas internas agiliza muito o processamento. Selects que, num
nico comando, seja responsvel por acessar a tabela, fazer a seleo do range de dados
necessrio, movimentar estes dados para uma tabela interna e gravar estes dados tero
performance superior uma situao de Select endselect e infinitamente superior a uma
situao de Select endselect em ninho.



Ilustrando situao semelhante, com grandes tabelas do sistema, temos:


ABAP Training


41
Select * from bkpf where condition = XXXX.

Select * from bseg where bukrs = bkpf-bukrs and
belnr = bkpf-belnr and
gjahr = bkpf-gjahr.
Endselect.

Endselect.

* O primeiro comando seleciona as 79 colunas da tabela bkpf atravs do campo <condition>
que um critrio muito amplo para pesquisa em tabelas deste porte. Campos como
company code, data, ano fiscal, entre outros, podem ser fortes candidados a restringir a
pesquisa.

* O segundo comando seleciona as 266 colunas da tabela bseg, onde os campos bukrs,
belnr e gjahr sejam iguais tabela anterior. Como na tabela anterior no foi utilizado um
critrio de seleo mais adequado, muitos registros sero retornados da bkpf e,
consequentemente, para cada um destes registros, sero retornados n registros da BSEG.

* Ambos os selects correspondero a tantos acessos no banco de dados quantos registros
existirem.

Visando garantir melhor performance, poder-se-ia utilizar:

Select col1 col2 col3, into table tab_bkpf from bkpf where <conditions>.

Select col1 col2 col3 col4 into table tab_bseg
from bseg
for all entries in tab_bkpf
where < conditions >.









Algumas consideraes:

* Ambos os selects correspondero a um nico acesso no banco de dados.

ABAP Training


42
* O primeiro comando select j seleciona, move e grava os dados numa tabela interna.
* O segundo select ser baseado no resultado, j em tabela interna, do primeiro select.
* So selecionadas apenas as colunas realmente necessrias. Assim, os pacotes transmitidos
entre o servidor de banco de dados e o servidor de aplicao so menores, agilizando
portanto a transferncia.
* tab_bkpf e tab_bseg so tabelas internas.


Exemplificando atravs de um trecho do programa ZAFII001:

Select mblnr bldat budat into table tab01
From bkpf where budat in s_budat

Loop at tab01.
Select * from bseg where mblnr eq tab01-mblnr.
Move-corresponding tab01 to tab02.
Move-corresponding mseg to tab02.
Append tab02. Clear tab02.
Endselect.
Endloop.

O primeiro select faz um nico acesso ao servidor de banco de dados, trazendo todos os
dados necessrios de uma nica vez. (OK)

O select * na tabela bseg est dentro de um loop. Ou seja, este comando estar trazendo
todas as colunas desta tabela, que uma das maiores do sistema R/ 3. Ser movimentado
atravs do comando move-corresponding os campos cujos nomes sejam semelhantes de
tab01 e mseg. Este comando no oferece boa performance (gasta tempo identificando a
igualdade no nome dos campos).

Alternativa: O loop na tab01 indica que, para cada registro da tab01 (tabela interna), ser
acessado um registro na bseg. Ento, seria melhor proceder conforme abaixo:






Select mblnr bldat budat into table tab01 from bkpf where <conditions>.

Select col1 col2 col3 col4 into table tab_bseg (*)
from bseg

ABAP Training


43
for all entries in tab01
where < conditions >.


Ou seja, evitar select * trazendo somente os campos necessrios e fazer um nico acesso
tabela BSEG, trazendo todos os registros importantes para o processamento. Colocar
tambm mais selees, objetivando restringir a quantidade de dados trazidos no primeiro
select para, consequentemente, restringir a quantidade de dados trazidos no segundo
select. Pode-se pensar em trazer todos os dados da BSEG para a prpria tab01, atravs de
appending corresponding fields os table . .
Ver help online para maiores detalhes sobre os comandos, em caso de dvidas.

Este recurso de for all entries baseado na tabela anterior pode ser usado sempre,
principalmente nos casos onde performance for um fator crtico. Normalmente, os casos de
selects encadeados em forma de ninhos podem usar tal facilidade com uma incrvel
melhoria na performance.




Classificao dos programas ps-anlise:

Exemplos de programas que encontram-se na situao de ninhos de select: ZAMMI020,
ZAMMI030, ZAMMI002, ZAMMI003.

Exemplos de programas que encontram-se na situao de vrios acessos entre o servidor de
aplicao e o servidor de banco de dados: ZAMMI010.

Exemplos de programas que selecionam todas as colunas das tabelas acessadas: ZAFII001,
ZAMMI002, ZAMMI003.

Exemplos de programas que no acessam, selecionam, movimentam e gravam num nico
comando select: ZAFII001.




Necessidades:

a) Stress-test
b) Testes integrados


ABAP Training


44
Comentrios/Recomendaes:

O ponto mais crtico est associado ao tpico de performance. necessrio fazer reviso em
todos os programas, visando detectar situaes semelhantes descrita anteriormente e
providenciar as adequaes necessrias.

Outro ponto de fundamental importncia se refere aos testes. A garantia do bom
funcionamento do programa e a minimizao de problemas com performance aps entrada
em produo somente ocorrer caso seja realizado testes com massa de dados real, ou seja,
volumes prximos ao esperado em ambiente produtivo, cobrindo as situaes que possam
ocorrer.


Restries:

Caso ocorra a entrada em produo sem a alteraes nos programas, a performance ser
decrescente, medida que as bases de dados forem crescendo. Tambm no se pode
garantir que todas as interfaces pseudo-online sero processadas e finalizadas dentro do
tempo estipulado (por exemplo, a cada x minutos, etc).

A documentao dos programas dever ser providenciada, mesmo que aps entrada
em produo, visando facilitar trabalhos de manutenes futuras.

Testes com massas de dados real ou com alto volume de dados eliminam/ minimizam
os problemas com performance. A entrada em produo, na maioria dos casos, no
comprometida. Porm, aps alguns meses, pode-se ter um decrscimo significativo na
performance.

O atraso no cronograma deveu-se ao aumento do nmero de desenvolvimentos,
problemas com o ambiente R/ 3 da ABC, que apresentava short dump em transaes online,
o que impossibilitava configuraes, entrada de dados para testes, etc. Outro ponto que
trouxe dificuldades para a equipe ABAP do parceiro de implementao foi a inexistncia
de formulrios (Sapscripts) da localizao no ambiente que eles estavam utilizando, sendo
necessrio desenvolv-los a partir de cpia de outros clientes. Principalmente devido ao
problema de dumps em transaes standard, a equipe de ABAP foi inmeras vezes
interrompida para auxiliar os funcionais, tentando driblar o problema, para que o projeto
sofresse menor impacto.

Obteve-se a informao que o material de Quality Assurance da Fase II apenas foi entregue
equipe de desenvolvimento ABAP a cerca de uma semana atrs. Vale ressaltar que este
material altamente tcnico, e basicamente voltado equipe do projeto ABAP. O fato da
equipe no ter feito a leitura deste material desde o incio do projeto traz alguns pontos

ABAP Training


45
negativos. Estes s no foram maiores dada a experincia da equipe em outros projetos.
Mesmo assim, certas irregularidades poderiam ter sido evitadas.



Parecer:

De uma forma geral pode-se dizer que o desenvovimento est bom, porm caso os
programas no sejam revisados e adequados, certamente ocorrero problemas de
performance aps a implantao.
Um ponto positivo que todos os programas possuem lgica simples e fcil para
manutenes futuras, se houver necessidade.

ABAP Training


46

3 . QUADRO RESUMO DA SITUAO DO PROJETO

Tpico Status
Confeco de especificao tcnica
Validado com restries: o
formato da especificao
tcnica foi validado no
Quality Assurance da Fase
I I , porm nesta fase no se
pde ver as especificaes
concludas.
Esquema de testes No validado.
So necessrios testes com alto
volume de dados.
Uniformidade do cdigo-metodologia-
padres
Validado com restries.
Performance Validado com restries, desde
que os programas sejam
revisados e alterados no que se
refere questes de
performance. Ponto
fundamental e indispensvel
para correo antes da entrada
em produo.
Outros erros No se aplica
Observao:

Valer muito pouco todo este trabalho se a configurao da mquina no estiver
correta. necessrio que ocorra uma visita de basis se o problema de performance no
est num programa em especfico, mas em vrios.

ABAP Training


47
Anlise de casos reais programas com problemas:

1.Performance ruim seleo de dados

*- Tabelas Internas --------------------------------------------------- *

* Tabela de OV's incompletas.
DATA: I_ZPTES_ESPECIF LIKE ZPTES_ESPECIF OCCURS 100 WITH HEADER LINE.

* Tabela de OV's serem especificadas.
DATA: BEGIN OF I_ESPECIF OCCURS 100.
INCLUDE STRUCTURE ZPTES_ESPECIF.
DATA: FLAG. "// O valor 'X' indica que o
"// registro dever ser
"// atualizado.
DATA: END OF I_ESPECIF.

* Tabela p/ atualizao das Ordens de Venda.
DATA: BEGIN OF I_ATUALIZA OCCURS 100,
VBELN LIKE VBAP-VBELN, "// Documento de venda.
POSNR LIKE VBAP-POSNR, "// Item do documento.
MTVO LIKE ZPTES_ESPECIF -MOTIVO. "// Motivo da
"// impossibilidade de
"// completar a OV.
DATA: END OF I_ATUALIZA.

* Mestre de clientes (parte geral).
DATA: BEGIN OF I_KNA1 OCCURS 100,
KUNNR LIKE KNA1-KUNNR, "// N cliente.
NAME1 LIKE KNA1-NAME1. "// Nome do cliente.
DATA: END OF I_KNA1.

* Documento de vendas: dados de cabealho.
DATA: BEGIN OF I_VBAK OCCURS 100,
VBELN LIKE VBAK-VBELN, "// Documento de venda.
ERDAT LIKE VBAK-ERDAT, "// Data criao do registro.
ERZET LIKE VBAK-ERZET, "// Hora do registro.
ERNAM LIKE VBAK-ERNAM, "// Nome do responsvel.
VBTYP LIKE VBAK-VBTYP, "// Ctg.documento de vendas e
"// distribuio.
KUNNR LIKE KNA1-KUNNR, "// Cliente
VKGRP LIKE VBAK-VKGRP. "// Grupo de trabalho
DATA: END OF I_VBAK.

* Documento de vendas: dados de item.
DATA: BEGIN OF I_VBAP OCCURS 100,
VBELN LIKE VBAP-VBELN, "// Documento de venda.
POSNR LIKE VBAP-POSNR, "// Item do documento.
MATNR LIKE VBAP-MATNR, "// N do material.
OBJNR LIKE VBAP-OBJNR, "// N objeto a nvel de item.
CUOBJ LIKE VBAP-CUOBJ. "// Configurao.
DATA: END OF I_VBAP.

* Cpia de I_VBAP p/ melhor performance.
DATA: I_VBAP_AUX LIKE I_VBAP OCCURS 100 WITH HEADER LINE.

* Status individual por objeto.
DATA: BEGIN OF I_JEST OCCURS 100,
OBJNR LIKE JEST-OBJNR, "// N objeto.
STAT LIKE JEST-STAT. "// Status individual de um
"// objeto.
DATA: END OF I_JEST.

* Textos relativos a status de usurio.
DATA: BEGIN OF I_TJ30T OCCURS 100,
ESTAT LIKE TJ30T-ESTAT, "// Status do usurio.
TXT04 LIKE TJ30T-TXT04. "// Status individual de um

ABAP Training


48
"// objeto (forma breve).
DATA: END OF I_TJ30T.

* Textos relativos a status do sistema.
DATA: BEGIN OF I_TJ02T OCCURS 100,
ISTAT LIKE TJ02T-ISTAT, "// Status do sistema.
TXT04 LIKE TJ02T-TXT04. "// Status individual de um
"// objeto (forma breve).
DATA: END OF I_TJ02T.

* Dados do usurio.
DATA: BEGIN OF I_USER_ADDR OCCURS 100,
BNAME LIKE USER_ADDR -BNAME, "// Nome do usurio no
"// cadastro.
NAME_FIRST LIKE USER_ADDR -NAME_FIRST. "// Nome.
DATA: END OF I_USER_ADDR.

* Caractersticas.
DATA: BEGIN OF I_CABN OCCURS 100,
ATINN LIKE CABN-ATINN, "// Valor da caracterstica
ATNAM LIKE CABN-ATNAM. "// Nome da caracterstica
DATA: END OF I_CABN.

* Descricao das Caractersticas e Valor.
DATA: BEGIN OF I_CARACT OCCURS 20,
NOME LIKE CABN-ATNAM, "// Nome da caraterstica
VALOR LIKE ZPTES_ESPECIF -CANAL. "// Valor da caracterstica
DATA: END OF I_CARACT.

* Tabela com nomes das caractersticas.
RANGES: R_ATNAM FOR CABN-ATNAM.





*&--------------------------------------------------------------------- *
*& Form f_seleciona_dados
*&--------------------------------------------------------------------- *
* Seleciona os dados, carregando os mesmos nas tabelas internas.
*---------------------------------------------------------------------- *
FORM F_SELECIONA_DADOS.

* Recupera as ordens de venda do tipo make to order.
select vbeln posnr matnr objnr cuobj
from vbap
into table i_vbap
where pstyv = c_tac
or pstyv = c_ytac
or pstyv = c_ztac.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

* Grava os documentos em i_vbap_aux, e apaga os registros duplicados.
i_vbap_aux[] = i_vbap[].
delete adjacent duplicates from i_vbap_aux comparing vbeln.

* Obtem os tipos de documentos (ordem ou contrato).
select vbeln erdat erzet ernam vbtyp kunnr vkgrp
from vbak
into table i_vbak
for all entries in i_vbap_aux
where vbeln = i_vbap_aux-vbeln.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

ABAP Training


49

* Obtem a descrio do cliente.
select kunnr name1
from kna1
into table i_kna1
for all entries in i_vbak
where kunnr = i_vbak-kunnr.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* Obtem a chave de pesquisa para os s tatus.
select objnr stat
from jest
into table i_jest
for all entries in i_vbap
where objnr = i_vbap-objnr
and inact <> c_x.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no par metro indicado.


* Obtem o status do usurio. (I_JEST -STAT(1) = 'E')
select estat txt04
from tj30t
into table i_tj30t
for all entries in i_jest
where estat = i_jest-stat
and spras = sy-langu.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* Obtem o status do sistema. (I_JEST -STAT(1) = 'I')
select istat txt04
from tj02t
into table i_tj02t
for all entries in i_jest
where istat = i_jest-stat
and spras = sy-langu.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

* Obtem o nome do usurio que criou a ordem.
select bname name_first
from user_addr
into table i_user_addr
for all entries in i_vbak
where bname = i_vbak-ernam.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

* Obtem os itens a serem especificados.
select *
from zptes_especif
into table i_zptes_especif.

perform f_carregar_caracteristicas. "// Carrega a tabela i_cabn.

ENDFORM. "// f_seleciona_dados

ABAP Training


50





Performance melhorada seleo de dados


* Tabela de OV's incompletas.
DATA: I_ZPTES_ESPECIF LIKE ZPTES_ESPECIF OCCURS 100 WITH HEADER LINE.

* Tabela de OV's serem especificadas.
DATA: BEGIN OF I_ESPECIF OCCURS 100.
INCLUDE STRUCTURE ZPTES_ESPECIF.
DATA: FLAG. "// O valor 'X' indica que o
"// registro dever ser
"// atualizado.
DATA: END OF I_ESPECIF.

* Tabela p/ atualizao das Ordens de Venda.
DATA: BEGIN OF I_ATUALIZA OCCURS 100,
VBELN LIKE VBAP-VBELN, "// Documento de venda.
POSNR LIKE VBAP-POSNR, "// Item do documento.
MTVO LIKE ZPTES_ESPECIF -MOTIVO. "// Motivo da
"// impossibilidade de
"// completar a OV.
DATA: END OF I_ATUALIZA.

* Mestre de clientes (parte geral).
DATA: BEGIN OF I_KNA1 OCCURS 100,
KUNNR LIKE KNA1-KUNNR, "// N cliente.
NAME1 LIKE KNA1-NAME1. "// Nome do cliente.
DATA: END OF I_KNA1.

* Documento de vendas: dados de cabealho.
DATA: BEGIN OF I_VBAK OCCURS 5000,
VBELN LIKE VBAK-VBELN, "// Documento de venda.
ERDAT LIKE VBAK-ERDAT, "// Data criao do registro.
ERZET LIKE VBAK-ERZET, "// Hora do registro.
ERNAM LIKE VBAK-ERNAM, "// Nome do responsvel.
VBTYP LIKE VBAK-VBTYP, "// Ctg.documento de vendas e
"// distribuio.
KUNNR LIKE KNA1-KUNNR, "// Cliente
VKGRP LIKE VBAK-VKGRP. "// Grupo de trabalho
DATA: END OF I_VBAK.

* Documento de vendas: dados de item.
DATA: BEGIN OF I_VBAP OCCURS 10000,
VBELN LIKE VBAP-VBELN, "// Documento de v enda.
POSNR LIKE VBAP-POSNR, "// Item do documento.
MATNR LIKE VBAP-MATNR, "// N do material.
OBJNR LIKE VBAP-OBJNR, "// N objeto a nvel de item.
CUOBJ LIKE VBAP-CUOBJ. "// Configurao.
DATA: END OF I_VBAP.

* Cpia de I_VBAP p/ melhor performance.
DATA: I_VBAP_AUX LIKE I_VBAP OCCURS 10000 WITH HEADER LINE.

* Ordens de Venda
DATA: BEGIN OF I_ordem OCCURS 10000,
vbeln LIKE vbap-vbeln, "// Documento de venda
posnr LIKE vbap-posnr. "// Item Documento de venda
DATA: END OF I_ordem.


* Status individual por objeto.

ABAP Training


51
DATA: BEGIN OF I_JEST OCCURS 100000,
OBJNR LIKE JEST-OBJNR, "// N objeto.
STAT LIKE JEST-STAT. "// Status individua l de um
"// objeto.
DATA: END OF I_JEST.

* Status individual por objeto.
DATA: BEGIN OF I_JEST_aux OCCURS 100000,
OBJNR LIKE JEST-OBJNR, "// N objeto.
STAT LIKE JEST-STAT. "// Status individual de um
"// objeto.
DATA: END OF I_JEST_aux.

* Histrico de modificaes no satus do usurio/sistema.
DATA: BEGIN OF I_JCDS OCCURS 1000,
STAT LIKE JCDS-STAT, " Status do usurio.
CHGNR LIKE JCDS-CHGNR. " Nmero da modificao
DATA: END OF I_JCDS.

* Textos relativos a status de usurio.
DATA: BEGIN OF I_TJ30T occurs 100,
ESTAT LIKE TJ30T-ESTAT, "// Status do usurio.
TXT04 LIKE TJ30T-TXT04. "// Status individual de um
"// objeto (forma breve).
DATA: END OF I_TJ30T.

* Textos relativos a status do sistema.
DATA: BEGIN OF I_TJ02T,
ISTAT LIKE TJ02T-ISTAT, "// Status do sistema.
TXT04 LIKE TJ02T-TXT04. "// Status individual de um
"// objeto (forma breve).
DATA: END OF I_TJ02T.

* Dados do usurio.
DATA: BEGIN OF I_USER_ADDR OCCURS 100,
BNAME LIKE USER_ADDR -BNAME, "// Nome do usurio no
"// cadastro.
NAME_FIRST LIKE USER_ADDR -NAME_FIRST. "// Nome.
DATA: END OF I_USER_ADDR.

* Caractersticas.
DATA: BEGIN OF I_CABN OCCURS 100,
ATINN LIKE CABN-ATINN, "// Valor da caracterstica
ATNAM LIKE CABN-ATNAM. "// Nome da caracterstica
DATA: END OF I_CABN.

* Descricao das Caractersticas e Valor.
DATA: BEGIN OF I_CARACT OCCURS 20,
NOME LIKE CABN-ATNAM, "// Nome da caraterstic a
VALOR LIKE ZPTES_ESPECIF -CANAL. "// Valor da caracterstica
DATA: END OF I_CARACT.

* Tabela com nomes das caractersticas.
RANGES: R_ATNAM FOR CABN-ATNAM.





*&--------------------------------------------------------------------- *
*& Form f_seleciona_dados
*&--------------------------------------------------------------------- *
* Seleciona os dados, carregando os mesmos nas tabelas internas.
*---------------------------------------------------------------------- *
FORM F_SELECIONA_DADOS.

* Obtem o status do usurio. (I_JEST -STAT(1) = 'E')
select estat txt04
from tj30t

ABAP Training


52
into table i_tj30t
where spras = sy-langu
and ( txt04 = c_spec
or txt04 = c_lcot
or txt04 = c_pcot ).


if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* Obtem o status do sistema. (I_JEST -STAT(1) = 'I')
select istat txt04
up to 1 rows
from tj02t
into i_tj02t
where spras = sy-langu
and txt04 = c_incompleto.
endselect.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


read table i_tj30t with key txt04 = c_spec.
if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* Obtem a chave de pesquisa para os status.
select objnr stat
from jest
into table i_jest
where ( STAT = i_tj30t-estat or
STAT = i_tj02t-istat )
and inact <> c_x.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* ordena a tabela i_jest.
sort i_jest by objnr stat.

* seleo das OVs incompletas.

i_jest_aux[] = i_jest[].

loop at i_jest. "leitura da tabela de Status individual por objeto
read table i_jest_aux with key objnr = i_jest -objnr
stat = i_tj30t -estat.
if sy-subrc eq c_zero.
read table i_jest_aux with key objnr = i_jest -objnr
stat = i_tj02t -istat.
if sy-subrc eq c_zero.
i_ordem-vbeln = i_jest-objnr+2(10).
i_ordem-posnr = i_jest-objnr+12(6).
append i_ordem.
clear i_ordem.
endif.
endif.
endloop. " fim da leitura da tab de Status indiv. por objeto

* elimina registros duplicados da tabela.
delete adjacent duplicates from i_ordem.
if i_ordem[] is initial.

ABAP Training


53
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* Recupera as ordens de venda do tipo make to order cujo status seja
* incompleta

select vbeln posnr matnr objnr cuobj
from vbap
into table i_vbap
for all entries in i_ordem
where vbeln = i_ordem-vbeln
and posnr = i_ordem-posnr
and ( pstyv = c_tac
or pstyv = c_ytac
or pstyv = c_ztac ).

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.


* Obtem os tipos de documentos (ordem ou contrato).
select vbeln erdat erzet ernam vbtyp kunnr vkgrp
from vbak
into table i_vbak
for all entries in i_vbap_aux
where vbeln = i_vbap_aux-vbeln.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

* Obtem a descrio do cliente.
select kunnr name1
from kna1
into table i_kna1
for all entries in i_vbak
where kunnr = i_vbak-kunnr.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

* Obtem o nome do usurio que criou a ordem.
select bname name_first
from user_addr
into table i_user_addr
for all entries in i_vbak
where bname = i_vbak-ernam.

if sy-subrc ne c_zero.
message e007(zp_abap).
endif. "// No existe dados no parmetro indicado.

* Obtem os itens a serem especificados.
select *
from zptes_especif
into table i_zptes_especif.

perform f_carregar_caracteristicas. "// Carrega a tabela i_cabn.

ENDFORM. "// f_seleciona_dados






ABAP Training


54
2. Performance Ruim Lgica errada

* Corte externo ao - I_T320_ACO.
DATA: BEGIN OF I_T320_ACO OCCURS 100,
WERKS LIKE T320-WERKS, "/ / Material.
LGORT LIKE T320-LGORT. "/ / Depsito.
DATA: END OF I_T320_ACO.

** Corte externo ao - I_T320_NACO.
*DATA: BEGIN OF I_T320_NACO OCCURS 100,
* WERKS LIKE T320-WERKS, "/ / Material.
* LGORT LIKE T320-LGORT. "/ / Depsito.
*DATA: END OF I_T320_NACO.

* Quanto ao - I_LQUA_ACO.
DATA: BEGIN OF I_LQUA_ACO OCCURS 100,
LGNUM LIKE LQUA-LGNUM, "/ / Sist de depsito
MATNR LIKE LQUA-MATNR, "/ / Material
WERKS LIKE LQUA-WERKS, "/ / Centro
CHARG LIKE LQUA-CHARG, "/ / N lote de produo
LGTYP LIKE LQUA-LGTYP, "/ / Tipo de Depos.
LGPLA LIKE LQUA-LGPLA, "/ / Pos.Depos.
LGORT LIKE LQUA-LGORT. "/ / Depsito.
DATA: END OF I_LQUA_ACO.

* Totalizador1 AO - MSLB +S692
DATA: BEGIN OF I_TOTALIZADOR1_ACO OCCURS 100,
MATNR LIKE MARA-MATNR, "/ / Material.
MATKL LIKE MARA-MATKL, "/ / Centro.
MTART LIKE MARA-MTART, "/ / Tipo de Material.
WERKS_MSLB LIKE MSLB-WERKS, "/ / Centro.
CHARG_MSLB LIKE MSLB-CHARG, "/ / Lote.
LIFNR LIKE MSLB-LIFNR, "/ / Depsito.
LBLAB LIKE MSLB-LBLAB, "/ / Lote.
LBINS LIKE MSLB-LBINS, "/ / Utilizao Livre.
VBELN_S692 LIKE S692-VBELN, "/ / Em contr.qualid.
POSNR_S692 LIKE S692-POSNR, "/ / Bloqueado
EBELN LIKE S692-EBELN, "/ / Devoluo
ENSAIO TYPE C. "/ / Ensaio
DATA: END OF I_TOTALIZADOR1_ACO.

* Totalizador2 AO - MARA +MSKA
DATA: BEGIN OF I_TOTALIZADOR2_ACO OCCURS 100,
MATNR LIKE MARA-MATNR, "/ / Material.
MATKL LIKE MARA-MATKL, "/ / Centro.
MTART LIKE MARA-MTART, "/ / Tipo de Material.
WERKS_MCHB LIKE MCHB-WERKS, "/ / Centro.
LGORT_MCHB LIKE MCHB-LGORT, "/ / Depsito.
CHARG_MCHB LIKE MCHB-CHARG, "/ / Lote.
CLABS LIKE MCHB-CLABS, "/ / Utilizao livre
CINSM LIKE MCHB-CINSM, "/ / Em contr.Qualid.
CSPEM LIKE MCHB-CSPEM, "/ / Bloqueado
CRETM LIKE MCHB-CRETM, "/ / Devoluo
CHARG_MSKA LIKE MSKA-CHARG, "/ / Lote.
WERKS_MSKA LIKE MSKA-WERKS, "/ / Centro.
LGORT_MSKA LIKE MSKA-LGORT, "/ / Depsito.
VBELN_MSKA LIKE MSKA-VBELN, "/ / Ordem.
POSNR_MSKA LIKE MSKA-POSNR, "/ / Item.
KALAB LIKE MSKA-KALAB, "/ / Estq.aval de utilizao livre
KAINS LIKE MSKA-KAINS, "/ / Estq.em controle de qualidade

ABAP Training


55
KASPE LIKE MSKA-KASPE, "/ / Estoque bloqueado
LGTYP LIKE LQUA-LGTYP, "/ / Tipo de depsito
LGPLA LIKE LQUA-LGPLA, "/ / Posio no depsito
LGNUM LIKE LQUA-LGNUM, "/ / Sistema de depsito
TPTAB(4) TYPE C. "/ / Tabela de origem dos dados
DATA: END OF I_TOTALIZADOR2_ACO.

*----------------------------------------------------------------------*
* Form F_SELECIONA_DADOS_ACO
*----------------------------------------------------------------------*
* Seleciona os dados para os parmetros indicados na tela - ao.
*----------------------------------------------------------------------*
FORM F_SELECIONA_DADOS_ACO.

* Seleo dos materiais
* Seleo dos dados de material - Ao
* MARA
select matnr
matkl
mtart
from mara
into table i_mara_aco
where matkl between c_500 and c_504.

*--------------------------------------------
* Seleo dos lotes
* Seleo dos lotes de material - Ao
* MCHB
if not i_mara_aco[] is initial.
select matnr
werks
lgort
charg
clabs
cinsm
cspem
cretm
from mchb
into table i_mchb_aco
for all entries in i_mara_aco
where matnr =i_mara_aco-matnr
and ( clabs <>c_zero
or cinsm <>c_zero
or cspem <>c_zero ).
endif.

*------------------------------------------------
* Seleo dos Estoque de ordens-cliente
* Dados ordem/ itens para os materiais - Ao
* MSKA
if not i_mara_aco[] is initial.
select matnr
charg
werks
lgort
vbeln
posnr
kalab
kains
kaspe
from mska

ABAP Training


56
into table i_mska_aco
for all entries in i_mara_aco
where matnr =i_mara_aco-matnr
and ( kalab <>c_zero
or kains <>c_zero
or kaspe <>c_zero ).
endif.

*---------------------------------------------------
* Seleo dos estoques especiais junto ao fornecedor
* Estoques especiais junto ao fornecedor - Ao
* MSLB
if not i_mara_aco[] is initial.
select matnr
werks
charg
lifnr
lblab
lbins
from mslb
into table i_mslb_aco
for all entries in i_mara_aco
where matnr =i_mara_aco-matnr
and ( lblab <>c_zero
or lbins <>c_zero ).
endif.


*-----------------------------------------------------
* Corte Externo
* Corte Externo - Ao
* S692
if not i_mslb_aco[] is initial.
select matnr
charg
vbeln
posnr
ebeln
from s692
into table i_s692_aco
for all entries in i_mslb_aco
where matnr =i_mslb_aco-matnr
and charg =i_mslb_aco-charg.
endif.
*------------------------------------------------------
* Atribuio depsito IM a sistema de depsito WM
* Atribuio depsito IM a sistema de depsito WM - Ao T320 - mchb
if not i_mchb_aco[] is initial.
select werks
lgort
from t320
into table i_t320_aco
for all entries in i_mchb_aco
where werks =i_mchb_aco-werks
and lgort =i_mchb_aco-lgort.
endif.

* Seleo da t320 - mska
if not i_mska_aco[] is initial.
select werks
lgort

ABAP Training


57
from t320
appending table i_t320_aco
for all entries in i_mska_aco
where werks =i_mska_aco-werks
and lgort =i_mska_aco-lgort.
endif.

* Ordena a tabela
sort i_t320_aco by werks lgort.

* Deleta os itens adjacentes.
delete adjacent duplicates from i_t320_aco comparing werks lgort.


*-----------------------------------------------------------
* Quanto - Ao
* Seleo do sistema de depsito
* LQUA
refresh i_lqua_aco.
if not i_t320_aco[] is initial.
select lgnum
matnr
werks
charg
lgtyp
lgpla
lgort
from lqua
into table i_lqua_aco
for all entries in i_t320_aco
where werks =i_t320_aco-werks
and lgort =i_t320_aco-lgort
and mgewi ne 0.
endif.

ENDFORM. " F_SELECIONA_DADOS

*----------------------------------------------------------------------*
* Form F_BUSCA_MATERIAL_ACO
*----------------------------------------------------------------------*
* Grava os dados para material ao.
*----------------------------------------------------------------------*
* Monta os Totalizadores - (Corte Externo)
* Servios Externos
* Seleo das Ordens de Venda
FORM F_BUSCA_MATERIAL_ACO.

* Declara as variveis locais
data : v_code like qapp-vcode,
v_flag type c.

* Seleo do totalizador 1 - ms lb +s692 - i_totalizador1_aco
* -----------------------------------------------------------
clear i_totalizador1_aco.
loop at i_mslb_aco.
* limpa as variaveis
clear v_code.
clear v_flag.

read table i_s692_aco with key matnr =i_mslb_aco-matnr
charg =i_mslb_aco-charg.

ABAP Training


58
if sy-subrc eq c_zero.
i_totalizador1_aco-matnr =i_mslb_aco-matnr.
i_totalizador1_aco-werks_mslb =i_mslb_aco-werks.
i_totalizador1_aco-charg_mslb =i_mslb_aco-charg.
i_totalizador1_aco-lifnr =i_mslb_aco-lifnr.
i_totalizador1_aco-lblab =i_mslb_aco-lblab.
i_totalizador1_aco-lbins =i_mslb_aco-lbins.
i_totalizador1_aco-vbeln_s692 =i_s692_aco-vbeln.
i_totalizador1_aco-posnr_s692 =i_s692_aco-posnr.
i_totalizador1_aco-ebeln =i_s692_aco-ebeln.

* Verifica se o lote e de uma bobina - comea com nmero
if i_totalizador1_aco-charg_mslb+0(1) CO '0123456789'.
select single
vcode
from
qapp
into v_code
where usern1 =i_totalizador1_aco-charg_mslb.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.
else. " placa
select single
vcode
from
qapp
into v_code
where userc1 =i_totalizador1_aco-charg_mslb.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.
endif.
else.
i_totalizador1_aco-matnr =i_mslb_aco-matnr.
i_totalizador1_aco-werks_mslb =i_mslb_aco-werks.
i_totalizador1_aco-charg_mslb =i_mslb_aco-charg.
i_totalizador1_aco-lifnr =i_mslb_aco-lifnr.
i_totalizador1_aco-lblab =i_mslb_aco-lblab.
i_totalizador1_aco-lbins =i_mslb_aco-lbins.
i_totalizador1_aco-vbeln_s692 =''.
i_totalizador1_aco-posnr_s692 =''.
i_totalizador1_aco-ebeln =i_s692_aco-ebeln.

* Verifica se o lote e de uma bobina - comea com nmero
if i_totalizador1_aco-charg_mslb+0(1) CO '0123456789'.
select single
vcode
from
qapp
into v_code
where usern1 =i_totalizador1_aco-charg_mslb.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.

ABAP Training


59
else. " placa
select single
vcode
from
qapp
into v_code
where userc1 =i_totalizador1_aco-charg_mslb.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.
endif.
endif.



* Verifica se achou a lote ou no.
if v_flag ='T'.
if v_code is initial.
i_totalizador1_aco-ensaio ='S'.
else.
i_totalizador1_aco-ensaio ='N'.
endif.
else.
i_totalizador1_aco-ensaio ='N'.
endif.

* Acrescenta os dados da mara ao totalizador 1
read table i_mara_aco with key matnr =i_mslb_aco-matnr.
if sy-subrc eq c_zero.
i_totalizador1_aco-matkl =i_mara_aco-matkl.
i_totalizador1_aco-mtart =i_mara_aco-mtart.
endif.
append i_totalizador1_aco.
endloop. loop at i_mslb_aco.

clear i_totalizador2_aco.
* Seleo do totalizador2 - juno da mchb +mska - i_totalizador2_aco
* ---------------------------------------------------------------------
loop at i_mska_aco.
i_totalizador2_aco-matnr =i_mska_aco-matnr.
i_totalizador2_aco-charg_mska =i_mska_aco-charg.
i_totalizador2_aco-werks_mska =i_mska_aco-werks.
i_totalizador2_aco-lgort_mska =i_mska_aco-lgort.
i_totalizador2_aco-vbeln_mska =i_mska_aco-vbeln.
i_totalizador2_aco-posnr_mska =i_mska_aco-posnr.
i_totalizador2_aco-kalab =i_mska_aco-kalab.
i_totalizador2_aco-kains =i_mska_aco-kains.
i_totalizador2_aco-kaspe =i_mska_aco-kaspe.
i_totalizador2_aco-tptab ='MSKA'.
append i_totalizador2_aco.
endloop.

clear i_totalizador2_aco.
loop at i_mchb_aco.
i_totalizador2_aco-matnr = i_mchb_aco-matnr.
i_totalizador2_aco-charg_mchb = i_mchb_aco-charg.
i_totalizador2_aco-werks_mchb = i_mchb_aco-werks.
i_totalizador2_aco-lgort_mchb = i_mchb_aco-lgort.
i_totalizador2_aco-clabs = i_mchb_aco-clabs.

ABAP Training


60
i_totalizador2_aco-cinsm = i_mchb_aco-cinsm.
i_totalizador2_aco-cspem = i_mchb_aco-cspem.
i_totalizador2_aco-cretm = i_mchb_aco-cretm.
i_totalizador2_aco-tptab ='MCHB'.
append i_totalizador2_aco.
endloop.

clear i_totalizador2_aco.
* Seleciona os depsitos do i_totalizador2_aco
* ---------------------------------------------------------
* Seleo dos depsitos - i_totalizador2_aco +i_t320_aco
loop at i_totalizador2_aco.
* Atribui o ndice da tabela i_totalizador2_aco
v_indice =sy-tabix.

* Acrescenta os dados da mara ao totalizador 2
read table i_mara_aco with key matnr
=i_totalizador2_aco-matnr.
if sy-subrc eq c_zero.
i_totalizador2_aco-matkl =i_mara_aco-matkl.
i_totalizador2_aco-mtart =i_mara_aco-mtart.
endif.

* Se a tabela for MSKA
if i_totalizador2_aco-tptab ='MSKA'.
read table i_t320_aco with key
werks =i_totalizador2_aco-werks_mska
lgort =i_totalizador2_aco-lgort_mska.
* Se achou dados no sistema de depsito WM
if sy-subrc eq c_zero.
loop at i_lqua_aco where
matnr =i_totalizador2_aco-matnr and
charg =i_totalizador2_aco-charg_mska.

i_totalizador2_aco-lgtyp =i_lqua_aco-lgtyp.
i_totalizador2_aco-lgpla =i_lqua_aco-lgpla.
i_totalizador2_aco-lgnum =i_lqua_aco-lgnum.

i_total_final_aco =i_totalizador2_aco.
append i_total_final_aco.
endloop. loop at i_lqua_aco
else.
i_total_final_aco =i_totalizador2_aco.
append i_total_final_aco.
endif.
else. " MCHB
read table i_t320_aco with key
werks =i_totalizador2_aco-werks_mchb
lgort =i_totalizador2_aco-lgort_mchb.
* Se achou dados no sistema de depsito WM
if sy-subrc eq c_zero.
* Busca o sistema de depsito, caso tenha movimento de WM
loop at i_lqua_aco where
matnr =i_totalizador2_aco-matnr and
charg =i_totalizador2_aco-charg_mchb.

i_totalizador2_aco-lgtyp =i_lqua_aco-lgtyp.
i_totalizador2_aco-lgpla =i_lqua_aco-lgpla.
i_totalizador2_aco-lgnum =i_lqua_aco-lgnum.

i_total_final_aco =i_totalizador2_aco.

ABAP Training


61
append i_total_final_aco.
endloop. loop at i_lqua_aco
else.
i_total_final_aco =i_totalizador2_aco.
append i_total_final_aco.
endif.
endif.
endloop. " i_totalizador2_aco

i_totalizador2_aco[] =i_total_final_aco[].

clear i_totalizador2_aco.
clear i_aco.
* Seleciona os dados com sistema de depsito <>900
loop at i_totalizador2_aco.
if i_totalizador2_aco-lgnum <>c_900.

* Se for tipo de depsito 905 e for FERT, desconsidera
if i_totalizador2_aco-lgnum =c_905 and
i_totalizador2_aco-mtart =c_fert.
continue.
endif.

i_aco-matnr =i_totalizador2_aco-matnr.
i_aco-matkl =i_totalizador2_aco-matkl.
i_aco-mtart =i_totalizador2_aco-mtart.

clear v_code.
clear v_flag.

* Se a tabela for MCHB
if i_totalizador2_aco-tptab ='MCHB'.
i_aco-werks =i_totalizador2_aco-werks_mchb.
i_aco-lgort =i_totalizador2_aco-lgort_mchb.
i_aco-charg =i_totalizador2_aco-charg_mchb.
i_aco-clabs =i_totalizador2_aco-clabs.
i_aco-cinsm =i_totalizador2_aco-cinsm.
i_aco-cspem =i_totalizador2_aco-cspem.

* Verifica se o lote e de uma bobina - comea com nmero
if i_totalizador2_aco-charg_mchb+0(1) CO '0123456789'.
select single
vcode
from
qapp
into v_code
where usern1 =i_totalizador2_aco-charg_mchb.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.
else. " placa
select single
vcode
from
qapp
into v_code
where userc1 =i_totalizador2_aco-charg_mchb.
if sy-subrc eq c_zero.
v_flag ='T'.

ABAP Training


62
else.
v_flag ='F'.
endif.
endif.
else. " MSKA
i_aco-werks =i_totalizador2_aco-werks_mska.
i_aco-charg =i_totalizador2_aco-charg_mska.
i_aco-lgort =i_totalizador2_aco-lgort_mska.
i_aco-clabs =i_totalizador2_aco-kalab.
i_aco-cinsm =i_totalizador2_aco-kains.
i_aco-cspem =i_totalizador2_aco-kaspe.

* Verifica se o lote e de uma bobina - comea com nmero
if i_totalizador2_aco-charg_mska+0(1) CO '0123456789'.
select single
vcode
from
qapp
into v_code
where usern1 =i_totalizador2_aco-charg_mska.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.
else. " placa
select single
vcode
from
qapp
into v_code
where userc1 =i_totalizador2_aco-charg_mska.
if sy-subrc eq c_zero.
v_flag ='T'.
else.
v_flag ='F'.
endif.
endif.
endif.
i_aco-cretm =i_totalizador2_aco-cretm.
i_aco-vbeln =i_totalizador2_aco-vbeln_mska.
i_aco-posnr =i_totalizador2_aco-posnr_mska.
i_aco-lgtyp =i_totalizador2_aco-lgtyp.
i_aco-lgpla =i_totalizador2_aco-lgpla.
i_aco-lgnum =i_totalizador2_aco-lgnum.

* Verifica se achou a lote ou no.
if v_flag ='T'.
if v_code is initial.
i_aco-ensaio ='S'.
else.
i_aco-ensaio ='N'.
endif.
else.
i_aco-ensaio ='N'.
endif.

* Acerta valores com sinal a esquerda
shift: i_aco-clabs right circular,
i_aco-cinsm right circular,
i_aco-cspem right circular,

ABAP Training


63
i_aco-cretm right circular.
condense: i_aco-clabs no-gaps,
i_aco-cinsm no-gaps,
i_aco-cspem no-gaps,
i_aco-cretm no-gaps.
shift: i_aco-clabs right deleting trailing space,
i_aco-cinsm right deleting trailing space,
i_aco-cspem right deleting trailing space,
i_aco-cretm right deleting trailing space.
* Grava os valores
append i_aco.
endif.
endloop. loop at i_totalizador2_aco.

clear i_totalizador1_aco.
clear i_aco.

* Acrescenta ao i_aco os valores do
* i_totalizador1_aco
loop at i_totalizador1_aco.
i_aco-matnr =i_totalizador1_aco-matnr.
i_aco-matkl =i_totalizador1_aco-matkl.
i_aco-mtart =i_totalizador1_aco-mtart.
i_aco-werks =i_totalizador1_aco-werks_mslb.
i_aco-charg =i_totalizador1_aco-charg_mslb.
i_aco-lifnr =i_totalizador1_aco-lifnr.
i_aco-lblab =i_totalizador1_aco-lblab.
i_aco-lbins =i_totalizador1_aco-lbins.
i_aco-vbeln =i_totalizador1_aco-vbeln_s692.
i_aco-posnr =i_totalizador1_aco-posnr_s692.
i_aco-ebeln =i_totalizador1_aco-ebeln.
i_aco-ensaio =i_totalizador1_aco-ensaio.
shift: i_aco-lbins right circular,
i_aco-lblab right circular.
condense: i_aco-lbins no-gaps,
i_aco-lblab no-gaps.
shift: i_aco-lbins right deleting trailing space,
i_aco-lblab right deleting trailing space.

append i_aco.
endloop.
ENDFORM. " F_BUSCA_MATERIAL_ACO





Performance Melhorada Lgica correta


* Corte externo ao - I_T320_ACO.
DATA: BEGIN OF I_T320_ACO_MSKA OCCURS 50,
WERKS LIKE T320-WERKS, "/ / Material.
LGORT LIKE T320-LGORT. "/ / Depsito.
DATA: END OF I_T320_ACO_MSKA.

DATA: BEGIN OF I_T320_ACO_MCHB OCCURS 50,
WERKS LIKE T320-WERKS, "/ / Material.

ABAP Training


64
LGORT LIKE T320-LGORT. "/ / Depsito.
DATA: END OF I_T320_ACO_MCHB.

* Quanto ao - I_LQUA_ACO.

DATA: BEGIN OF I_LQUA_ACO_MSKA OCCURS 100000,
LGNUM LIKE LQUA-LGNUM, "/ / Sist de depsito
MATNR LIKE LQUA-MATNR, "/ / Material
WERKS LIKE LQUA-WERKS, "/ / Centro
CHARG LIKE LQUA-CHARG, "/ / N lote de produo
LGTYP LIKE LQUA-LGTYP, "/ / Tipo de Depos.
LGPLA LIKE LQUA-LGPLA, "/ / Pos.Depos.
LGORT LIKE LQUA-LGORT. "/ / Depsito.
DATA: END OF I_LQUA_ACO_MSKA.

DATA: BEGIN OF I_LQUA_ACO_MCHB OCCURS 100000,
LGNUM LIKE LQUA-LGNUM, "/ / Sist de depsito
MATNR LIKE LQUA-MATNR, "/ / Material
WERKS LIKE LQUA-WERKS, "/ / Centro
CHARG LIKE LQUA-CHARG, "/ / N lote de produo
LGTYP LIKE LQUA-LGTYP, "/ / Tipo de Depos.
LGPLA LIKE LQUA-LGPLA, "/ / Pos.Depos.
LGORT LIKE LQUA-LGORT. "/ / Depsito.
DATA: END OF I_LQUA_ACO_MCHB.



* Totalizador1 AO - MSLB +S692
DATA: BEGIN OF I_TOTALIZADOR1_ACO OCCURS 10000,
MATNR LIKE MARA-MATNR, "/ / Material.
MATKL LIKE MARA-MATKL, "/ / Centro.
MTART LIKE MARA-MTART, "/ / Tipo de Material.
WERKS_MSLB LIKE MSLB-WERKS, "/ / Centro.
CHARG_MSLB LIKE MSLB-CHARG, "/ / Lote.
LIFNR LIKE MSLB-LIFNR, "/ / Depsito.
LBLAB LIKE MSLB-LBLAB, "/ / Lote.
LBINS LIKE MSLB-LBINS, "/ / Utilizao Livre.
VBELN_S692 LIKE S692-VBELN, "/ / Em contr.qualid.
POSNR_S692 LIKE S692-POSNR, "/ / Bloqueado
EBELN LIKE S692-EBELN, "/ / Devoluo
ENSAIO TYPE C. "/ / Ensaio
DATA: END OF I_TOTALIZADOR1_ACO.


* Totalizador2 AO - MARA +MSKA
DATA: BEGIN OF I_TOTALIZADOR2_ACO OCCURS 100000,
MATNR LIKE MARA-MATNR, "/ / Material.
MATKL LIKE MARA-MATKL, "/ / Centro.
MTART LIKE MARA-MTART, "/ / Tipo de Material.
WERKS_MCHB LIKE MCHB-WERKS, "/ / Centro.
LGORT_MCHB LIKE MCHB-LGORT, "/ / Depsito.
CHARG_MCHB LIKE MCHB-CHARG, "/ / Lote.
CLABS LIKE MCHB-CLABS, "/ / Utilizao livre
CINSM LIKE MCHB-CINSM, "/ / Em contr.Qualid.
CSPEM LIKE MCHB-CSPEM, "/ / Bloqueado
CRETM LIKE MCHB-CRETM, "/ / Devoluo
CHARG_MSKA LIKE MSKA-CHARG, "/ / Lote.
WERKS_MSKA LIKE MSKA-WERKS, "/ / Centro.
LGORT_MSKA LIKE MSKA-LGORT, "/ / Depsito.
VBELN_MSKA LIKE MSKA-VBELN, "/ / Ordem.
POSNR_MSKA LIKE MSKA-POSNR, "/ / Item.

ABAP Training


65
KALAB LIKE MSKA-KALAB, "/ / Estq.aval de utilizao livre
KAINS LIKE MSKA-KAINS, "/ / Estq.em controle de qualidade
KASPE LIKE MSKA-KASPE, "/ / Estoque bloqueado
LGTYP LIKE LQUA-LGTYP, "/ / Tipo de depsito
LGPLA LIKE LQUA-LGPLA, "/ / Posio no depsito
LGNUM LIKE LQUA-LGNUM, "/ / Sistema de depsito
TPTAB(4) TYPE C. "/ / Tabela de origem dos dados
DATA: END OF I_TOTALIZADOR2_ACO.

*----------------------------------------------------------------------*
* Form F_SELECIONA_DADOS_ACO
*----------------------------------------------------------------------*
* Seleciona os dados para os parmetros indicados na tela - ao.
*----------------------------------------------------------------------*
FORM F_SELECIONA_DADOS_ACO.

* Seleo dos materiais
* Seleo dos dados de material - Ao
* MARA
SELECT MATNR
MATKL
MTART
FROM MARA
INTO TABLE I_MARA_ACO
WHERE MATKL BETWEEN C_500 AND C_504.

*--------------------------------------------
* Seleo dos lotes
* Seleo dos lotes de material - Ao
* MCHB
IF NOT I_MARA_ACO[] IS INITIAL.
SELECT MATNR
WERKS
LGORT
CHARG
CLABS
CINSM
CSPEM
CRETM
FROM MCHB
INTO TABLE I_MCHB_ACO
FOR ALL ENTRIES IN I_MARA_ACO
WHERE MATNR =I_MARA_ACO-MATNR
AND ( CLABS <>C_ZERO
OR CINSM <>C_ZERO
OR CSPEM <>C_ZERO ).
ENDIF.

*------------------------------------------------
* Seleo dos Estoque de ordens-cliente
* Dados ordem/ itens para os materiais - Ao
* MSKA
IF NOT I_MARA_ACO[] IS INITIAL.
SELECT MATNR
CHARG
WERKS
LGORT
VBELN
POSNR
KALAB
KAINS

ABAP Training


66
KASPE
FROM MSKA
INTO TABLE I_MSKA_ACO
FOR ALL ENTRIES IN I_MARA_ACO
WHERE MATNR =I_MARA_ACO-MATNR
AND ( KALAB <>C_ZERO
OR KAINS <>C_ZERO
OR KASPE <>C_ZERO ).
ENDIF.

*---------------------------------------------------
* Seleo dos estoques especiais junto ao fornecedor
* Estoques especiais junto ao fornecedor - Ao
* MSLB
IF NOT I_MARA_ACO[] IS INITIAL.
SELECT MATNR
WERKS
CHARG
LIFNR
LBLAB
LBINS
FROM MSLB
INTO TABLE I_MSLB_ACO
FOR ALL ENTRIES IN I_MARA_ACO
WHERE MATNR =I_MARA_ACO-MATNR
AND ( LBLAB <>C_ZERO
OR LBINS <>C_ZERO ).
ENDIF.


*-----------------------------------------------------
* Corte Externo
* Corte Externo - Ao
* S692
IF NOT I_MSLB_ACO[] IS INITIAL.
SELECT MATNR
CHARG
VBELN
POSNR
EBELN
FROM S692
INTO TABLE I_S692_ACO
FOR ALL ENTRIES IN I_MSLB_ACO
WHERE MATNR =I_MSLB_ACO-MATNR
AND CHARG =I_MSLB_ACO-CHARG.
ENDIF.
*------------------------------------------------------
* Atribuio depsito IM a sistema de depsito WM
* Atribuio depsito IM a sistema de depsito WM - Ao T320 - mchb

IF NOT I_MCHB_ACO[] IS INITIAL.
SELECT WERKS
LGORT
FROM T320
INTO TABLE I_T320_ACO_MCHB
FOR ALL ENTRIES IN I_MCHB_ACO
WHERE WERKS =I_MCHB_ACO-WERKS
AND LGORT =I_MCHB_ACO-LGORT.
ENDIF.

* Seleo da t320 - mska

ABAP Training


67
IF NOT I_MSKA_ACO[] IS INITIAL.
SELECT WERKS
LGORT
FROM T320
INTO TABLE I_T320_ACO_MSKA
FOR ALL ENTRIES IN I_MSKA_ACO
WHERE WERKS =I_MSKA_ACO-WERKS
AND LGORT =I_MSKA_ACO-LGORT.
ENDIF.

* Ordena a tabela
SORT I_T320_ACO_MCHB BY WERKS LGORT.
SORT I_T320_ACO_MSKA BY WERKS LGORT.


* Deleta os itens duplicados.
DELETE ADJACENT DUPLICATES FROM I_T320_ACO_MCHB COMPARING WERKS LGORT.
DELETE ADJACENT DUPLICATES FROM I_T320_ACO_MSKA COMPARING WERKS LGORT.

*-----------------------------------------------------------
* Quanto - Ao
* Seleo do sistema de depsito
* LQUA

REFRESH I_LQUA_ACO_MCHB.
REFRESH I_LQUA_ACO_MSKA.

IF NOT I_T320_ACO_MCHB[] IS INITIAL.
SELECT LGNUM
MATNR
WERKS
CHARG
LGTYP
LGPLA
LGORT
FROM LQUA
INTO TABLE I_LQUA_ACO_MCHB
FOR ALL ENTRIES IN I_T320_ACO_MCHB
WHERE WERKS =I_T320_ACO_MCHB-WERKS
AND LGORT =I_T320_ACO_MCHB-LGORT
AND MGEWI NE 0.
ENDIF.

IF NOT I_T320_ACO_MSKA[] IS INITIAL.
SELECT LGNUM
MATNR
WERKS
CHARG
LGTYP
LGPLA
LGORT
FROM LQUA
INTO TABLE I_LQUA_ACO_MSKA
FOR ALL ENTRIES IN I_T320_ACO_MSKA
WHERE WERKS =I_T320_ACO_MSKA-WERKS
AND LGORT =I_T320_ACO_MSKA-LGORT
AND MGEWI NE 0.
ENDIF.


* Seleciona dados da QAPP

ABAP Training


68
SELECT USERC1
USERN1
VCODE
FROM QAPP
INTO TABLE I_QAPP.

DELETE ADJACENT DUPLICATES FROM I_QAPP.

ENDFORM. " F_SELECIONA_DADOS

*----------------------------------------------------------------------*
* Form F_BUSCA_MATERIAL_ACO
*----------------------------------------------------------------------*
* Grava os dados para material ao.
*----------------------------------------------------------------------*
* Monta os Totalizadores - (Corte Externo)
* Servios Externos
* Seleo das Ordens de Venda
FORM F_BUSCA_MATERIAL_ACO.

* Declara as variveis locais
DATA : V_CODE LIKE QAPP-VCODE,
V_FLAG TYPE C.

* ordena a tabela i_mara
sort i_mara_aco by matnr.

* Seleo do totalizador 1 - ms lb +s692 - i_totalizador1_aco
* -----------------------------------------------------------
CLEAR I_TOTALIZADOR1_ACO.
LOOP AT I_MSLB_ACO.
* limpa as variaveis
CLEAR V_CODE.
CLEAR V_FLAG.

READ TABLE I_S692_ACO WITH KEY MATNR =I_MSLB_ACO-MATNR
CHARG =I_MSLB_ACO-CHARG.
IF SY-SUBRC EQ C_ZERO.
I_TOTALIZADOR1_ACO-MATNR =I_MSLB_ACO-MATNR.
I_TOTALIZADOR1_ACO-WERKS_MSLB =I_MSLB_ACO-WERKS.
I_TOTALIZADOR1_ACO-CHARG_MSLB =I_MSLB_ACO-CHARG.
I_TOTALIZADOR1_ACO-LIFNR =I_MSLB_ACO-LIFNR.
I_TOTALIZADOR1_ACO-LBLAB =I_MSLB_ACO-LBLAB.
I_TOTALIZADOR1_ACO-LBINS =I_MSLB_ACO-LBINS.
I_TOTALIZADOR1_ACO-VBELN_S692 =I_S692_ACO-VBELN.
I_TOTALIZADOR1_ACO-POSNR_S692 =I_S692_ACO-POSNR.
I_TOTALIZADOR1_ACO-EBELN =I_S692_ACO-EBELN.


* Verifica se o lote e de uma bobina - comea com nmero
IF I_TOTALIZADOR1_ACO-CHARG_MSLB+0(1) CO '0123456789'.

READ TABLE I_QAPP WITH KEY
USERN1 =I_TOTALIZADOR1_ACO-CHARG_MSLB.

IF SY-SUBRC EQ C_ZERO.
V_FLAG ='T'.
ELSE.
V_FLAG ='F'.
ENDIF.
ELSE. " placa

ABAP Training


69


READ TABLE I_QAPP WITH KEY
USERC1 =I_TOTALIZADOR1_ACO-CHARG_MSLB.

IF SY-SUBRC EQ C_ZERO.
V_FLAG ='T'.
ELSE.
V_FLAG ='F'.
ENDIF.
ENDIF.
ELSE.
I_TOTALIZADOR1_ACO-MATNR =I_MSLB_ACO-MATNR.
I_TOTALIZADOR1_ACO-WERKS_MSLB =I_MSLB_ACO-WERKS.
I_TOTALIZADOR1_ACO-CHARG_MSLB =I_MSLB_ACO-CHARG.
I_TOTALIZADOR1_ACO-LIFNR =I_MSLB_ACO-LIFNR.
I_TOTALIZADOR1_ACO-LBLAB =I_MSLB_ACO-LBLAB.
I_TOTALIZADOR1_ACO-LBINS =I_MSLB_ACO-LBINS.
I_TOTALIZADOR1_ACO-VBELN_S692 =''.
I_TOTALIZADOR1_ACO-POSNR_S692 =''.
I_TOTALIZADOR1_ACO-EBELN =I_S692_ACO-EBELN.


* Verifica se o lote e de uma bobina - comea com nmero
IF I_TOTALIZADOR1_ACO-CHARG_MSLB+0(1) CO '0123456789'.

READ TABLE I_QAPP WITH KEY
USERN1 =I_TOTALIZADOR1_ACO-CHARG_MSLB.

IF SY-SUBRC EQ C_ZERO.
V_FLAG ='T'.
ELSE.
V_FLAG ='F'.
ENDIF.
ELSE. " placa

READ TABLE I_QAPP WITH KEY
USERC1 =I_TOTALIZADOR1_ACO-CHARG_MSLB.

IF SY-SUBRC EQ C_ZERO.
V_FLAG ='T'.
ELSE.
V_FLAG ='F'.
ENDIF.
ENDIF.
ENDIF.

* Verifica se achou a lote ou no.
IF V_FLAG ='T'.
IF V_CODE IS INITIAL.
I_TOTALIZADOR1_ACO-ENSAIO ='S'.
ELSE.
I_TOTALIZADOR1_ACO-ENSAIO ='N'.
ENDIF.
ELSE.
I_TOTALIZADOR1_ACO-ENSAIO ='N'.
ENDIF.

* Acrescenta os dados da mara ao totalizador 1
READ TABLE I_MARA_ACO WITH KEY MATNR =I_MSLB_ACO-MATNR binary search.
IF SY-SUBRC EQ C_ZERO.

ABAP Training


70

I_TOTALIZADOR1_ACO-MATKL =I_MARA_ACO-MATKL.

I_TOTALIZADOR1_ACO-MTART =I_MARA_ACO-MTART.

ENDIF.

APPEND I_TOTALIZADOR1_ACO.
ENDLOOP. loop at I_MSLB_ACO


CLEAR I_TOTALIZADOR2_ACO.
* Seleo do totalizador2 - juno da mchb +mska - i_totalizador2_aco
* ---------------------------------------------------------------------
LOOP AT I_MSKA_ACO.
I_TOTALIZADOR2_ACO-MATNR =I_MSKA_ACO-MATNR.
I_TOTALIZADOR2_ACO-CHARG_MSKA =I_MSKA_ACO-CHARG.
I_TOTALIZADOR2_ACO-WERKS_MSKA =I_MSKA_ACO-WERKS.
I_TOTALIZADOR2_ACO-LGORT_MSKA =I_MSKA_ACO-LGORT.
I_TOTALIZADOR2_ACO-VBELN_MSKA =I_MSKA_ACO-VBELN.
I_TOTALIZADOR2_ACO-POSNR_MSKA =I_MSKA_ACO-POSNR.
I_TOTALIZADOR2_ACO-KALAB =I_MSKA_ACO-KALAB.
I_TOTALIZADOR2_ACO-KAINS =I_MSKA_ACO-KAINS.
I_TOTALIZADOR2_ACO-KASPE =I_MSKA_ACO-KASPE.
I_TOTALIZADOR2_ACO-TPTAB ='MSKA'.
APPEND I_TOTALIZADOR2_ACO.
ENDLOOP.

CLEAR I_TOTALIZADOR2_ACO.
LOOP AT I_MCHB_ACO.
I_TOTALIZADOR2_ACO-MATNR = I_MCHB_ACO-MATNR.
I_TOTALIZADOR2_ACO-CHARG_MCHB = I_MCHB_ACO-CHARG.
I_TOTALIZADOR2_ACO-WERKS_MCHB = I_MCHB_ACO-WERKS.
I_TOTALIZADOR2_ACO-LGORT_MCHB = I_MCHB_ACO-LGORT.
I_TOTALIZADOR2_ACO-CLABS = I_MCHB_ACO-CLABS.
I_TOTALIZADOR2_ACO-CINSM = I_MCHB_ACO-CINSM.
I_TOTALIZADOR2_ACO-CSPEM = I_MCHB_ACO-CSPEM.
I_TOTALIZADOR2_ACO-CRETM = I_MCHB_ACO-CRETM.
I_TOTALIZADOR2_ACO-TPTAB ='MCHB'.
APPEND I_TOTALIZADOR2_ACO.
ENDLOOP.

CLEAR I_TOTALIZADOR2_ACO.

* Seleciona os depsitos do i_totalizador2_aco
SORT I_TOTALIZADOR2_ACO BY TPTAB
MATNR
CHARG_MSKA.
SORT I_LQUA_ACO_MSKA BY MATNR
CHARG.

V_INDEX =1.

LOOP AT I_TOTALIZADOR2_ACO.

IF I_TOTALIZADOR2_ACO-TPTAB ='MSKA'.
* Atribui o ndice da tabela i_totalizador2_aco
V_INDICE =SY-TABIX.

* Acrescenta os dados da mara ao totalizador 2
READ TABLE I_MARA_ACO WITH KEY MATNR =I_TOTALIZADOR2_ACO-MATNR

ABAP Training


71
binary search.
IF SY-SUBRC EQ C_ZERO.

I_TOTALIZADOR2_ACO-MATKL =I_MARA_ACO-MATKL.

I_TOTALIZADOR2_ACO-MTART =I_MARA_ACO-MTART.

ENDIF.


* Se achou dados no sistema de depsito WM
READ TABLE I_T320_ACO_MSKA WITH KEY
WERKS =I_TOTALIZADOR2_ACO-WERKS_MSKA
LGORT =I_TOTALIZADOR2_ACO-LGORT_MSKA.

* Se achou dados no sistema de depsito WM
IF SY-SUBRC EQ C_ZERO.


* Busca o ndice correto para leitura da tabela i_lqua_aco_mska
READ TABLE I_LQUA_ACO_MSKA
WITH KEY MATNR =I_TOTALIZADOR2_ACO-MATNR
CHARG =I_TOTALIZADOR2_ACO-CHARG_MSKA binary search.
IF SY-SUBRC EQ C_ZERO.
V_INDEX =SY-TABIX.
ENDIF.

LOOP AT I_LQUA_ACO_MSKA FROM V_INDEX.

IF I_LQUA_ACO_MSKA-MATNR <>I_TOTALIZADOR2_ACO-MATNR or
I_LQUA_ACO_MSKA-CHARG <>I_TOTALIZADOR2_ACO-CHARG_MSKA.

V_INDEX =SY-TABIX.
EXIT.
ENDIF.

I_TOTALIZADOR2_ACO-LGTYP =I_LQUA_ACO_MSKA-LGTYP.
I_TOTALIZADOR2_ACO-LGPLA =I_LQUA_ACO_MSKA-LGPLA.
I_TOTALIZADOR2_ACO-LGNUM =I_LQUA_ACO_MSKA-LGNUM.

I_TOTAL_FINAL_ACO =I_TOTALIZADOR2_ACO.
APPEND I_TOTAL_FINAL_ACO.
ENDLOOP.
ELSE.
I_TOTAL_FINAL_ACO =I_TOTALIZADOR2_ACO.
APPEND I_TOTAL_FINAL_ACO.

ENDIF. " Se achou dados no sistema de depsito WM
ENDIF. " if i_totalizador2_aco-tptab ='MSKA'.
ENDLOOP. LOOP AT I_TOTALIZADOR2_ACO.

SORT I_TOTALIZADOR2_ACO BY TPTAB
MATNR
CHARG_MCHB.

SORT I_LQUA_ACO_MCHB BY MATNR
CHARG.

V_INDEX =1.

*MCHB

ABAP Training


72
LOOP AT I_TOTALIZADOR2_ACO.

IF I_TOTALIZADOR2_ACO-TPTAB <>'MSKA'.

READ TABLE I_T320_ACO_MCHB WITH KEY
WERKS =I_TOTALIZADOR2_ACO-WERKS_MCHB
LGORT =I_TOTALIZADOR2_ACO-LGORT_MCHB.
* Se achou dados no sistema de depsito WM
IF SY-SUBRC EQ C_ZERO.

* Busca o ndice correto para leitura da tabela i_lqua_aco_mchb
READ TABLE I_LQUA_ACO_MCHB
WITH KEY MATNR =I_TOTALIZADOR2_ACO-MATNR
CHARG =I_TOTALIZADOR2_ACO-CHARG_MCHB binary search.
IF SY-SUBRC EQ C_ZERO.
V_INDEX =SY-TABIX..
ENDIF.


* Busca o sistema de depsito, caso tenha movimento de WM
LOOP AT I_LQUA_ACO_MCHB FROM V_INDEX.
IF I_LQUA_ACO_MCHB-MATNR <>I_TOTALIZADOR2_ACO-MATNR or
I_LQUA_ACO_MCHB-CHARG <>I_TOTALIZADOR2_ACO-CHARG_MCHB.
V_INDEX =SY-TABIX.
EXIT.
ENDIF.

I_TOTALIZADOR2_ACO-LGTYP =I_LQUA_ACO_MCHB-LGTYP.
I_TOTALIZADOR2_ACO-LGPLA =I_LQUA_ACO_MCHB-LGPLA.
I_TOTALIZADOR2_ACO-LGNUM =I_LQUA_ACO_MCHB-LGNUM.
I_TOTAL_FINAL_ACO =I_TOTALIZADOR2_ACO.
APPEND I_TOTAL_FINAL_ACO.
ENDLOOP.
ELSE.
I_TOTAL_FINAL_ACO =I_TOTALIZADOR2_ACO.
APPEND I_TOTAL_FINAL_ACO.

ENDIF.
ENDIF. " if i_totalizador2_aco-tptab <>'MSKA'.
ENDLOOP. " i_totalizador2_aco





ENDFORM. " F_BUSCA_MATERIAL_ACO