Aprenda a confeccionar qualquer tipo de relatório em ambiente de rede, por mais complexo que seja, e de processamento rápido com arquivos temporários em Clipper/xBase/Harbour.
Neste estudo de caso será feito um relátorio de devoluções de produto ao fornecedor de um período, c/ fornecedores em ordem alfabética c/ quebra por fornecedor e por ordem de compra.
Tentarei ser o mais inteligível e objetivo possível, acompanhe todo o estudo e você irá entender. Iremos trabalhar, em nosso caso, com três bases de dados do sistema.
Na estrutura deles (para nosso estudo) teriam alguns campos como:
OrdComp.dbf (OC) Estoque.dbf (ES) Fornec.dbf (FO) ================ ================ ================== OC________C__8__0 CODPROD__C__5__0 CODFORN___C__2__0 CODPROD___C__5__0 PRODUTO__C__25_0 FORNEC___C__30_0 CODFORN___C__2__0 CODFORN__C__2__0 ... QTDCOMPRA_N__8__2 QTD______N__6__0 QTDRECEB__N__8__2 VALOR____N__8__2 Index on CODFORN; QTDDEV____N__8__2 ... TO FOCFOR VALOR_____N__10_2 DCOMPRA___D__8__0 Index on CODPROD; DRECEB____D__8__0 TO ESCPROD DDEV______D__8__0 ... Index on DTOS(DDEV)+OC; TO OCDDEV
Em Modelagem de Dados: O OC é um DBF de "vários para um", pois há vários registros (produtos) para uma ordem de compra.
A relação entre OC e ES é de "um para vários", pois em uma ordem de compra há vários produtos.
A relação entre ES e FO é de "vários para um", pois há vários produtos para um só fornecedor.
Atente que as "..." (reticências), em algumas linhas do nosso estudo no programa, indicam que deve haver instruções inerentes ao programa de cada um naquele local.
Vamos ao programa:
USE ORDCOMP ALIAS OC SHARED NEW SET INDEX TO OCDDEV USE ESTOQUE ALIAS ES SHARED NEW SET INDEX TO ESCPROD USE FORNEC ALIAS FO SHARED NEW SET INDEX TO FOCFOR
Vamos colher dados do usuário p/ o nosso relatório:
DATAI := DATAF := CTOD("") @ 10,10 SAY "Data inicial:" GET DATAI @ 11,10 SAY "Data final..:" GET DATAF VALID DATAF >= DATAI READ IF LASTKEY() = 27 // ... RETURN ENDIF
Vamos dar um SOFT SEEK para reduzir drasticamente o tempo de nosso relatório.
OC->( DBSEEK( DTOS(DATAI), .T.) ) IF OC->DDEV > DATAF ALERT("Não houve devoluções a nenhum fornecedor nesse período!") // ... RETURN ENDIF
Precisaremos de um arquivo temporário para as informações que queremos armazenar e mostrar.
Veja que, trabalhando em ambiente de rede não podemos dar um nome fixo como "temp.dbf" por exemplo, pois se dois ou mais usuários pedirem este relatório ao mesmo tempo o DBCREATE() não criará um arquivo que já existe e o programa irá, no mínimo (dependendo de cada caso), duplicar as informações no temporário e bagunçar todo o relatório. Teremos, então, que criar um nome mutante para este temporário... observe:
TEMP := "TEMP"+SUBSTR( TIME(), 4, 2 )+SUBSTR( TIME(), 7, 2 ) TEMPNTX := "NTX" +SUBSTR( TIME(), 4, 2 )+SUBSTR( TIME(), 7, 2 )
As variáveis TEMP e TEMPNTX guardam o nome do temporário e do seu NTX. Depois temos a "&" e/ou os "()", para estrair esses nomes, dependendo da sintaxe do comando/função.
*** Criação do temporário *** aDBF := {} aADD( aDBF, {"OC", "C", 8, 0} ) aADD( aDBF, {"CODPROD", "C", 5, 0} ) aADD( aDBF, {"PRODUTO", "C", 25, 0} ) aADD( aDBF, {"CODFORN", "C", 2, 0} ) aADD( aDBF, {"FORNEC", "C", 30, 0} ) aADD( aDBF, {"QTDRECEB","N", 8, 2} ) aADD( aDBF, {"QTDDEV", "N", 8, 2} ) aADD( aDBF, {"VALOR", "N", 10, 2} ) aADD( aDBF, {"DCOMPRA", "D", 8, 0} ) aADD( aDBF, {"DRECEB", "D", 8, 0} ) aADD( aDBF, {"DDEV", "D", 8, 0} ) DBCREATE( &TEMP, aDBF )
Está criado o nosso temporário...
Abriremos o nosso arquivo desta forma:
USE (TEMP) ALIAS TMP EXCLUSIVE NEW INDEX ON FORNEC+OC+PRODUTO TO (TEMPNTX)
Vamos preencher as informações necessárias em nosso "temp" agora...
DO WHILE DDEV <= DATAF
Vamos mover o ponteiro de registro das outras áreas p/ que todas entrem de acordo.
ES->( DBSEEK(OC->CODPROD) ) FO->( DBSEEK(OC->CODFORN) )
Agora preencher as informações do temporário...
TMP->OC := OC->OC TMP->CODPROD := OC->CODPROD TMP->PRODUTO := ES->PRODUTO TMP->CODFORN := OC->CODFORN TMP->FORNEC := FO->FORNEC TMP->QTDRECEB := OC->QTDRECEB TMP->QTDDEV := OC->QTDDEV TMP->VALOR := OC->QTDCOMPRA/OC->VALOR TMP->DCOMPRA := OC->DCOMPRA TMP->DRECEB := OC->DRECEB TMP->DDEV := OC->DDEV OC->( DBSKIP() ) ENDDO TMP->( DBCOMMIT() )
Agora vamos ao relatório propriamente dito!
TMP->( DBGOTOP() ) cFOR := TMP->FORNEC cOC := TMP->OC LL := 100 LP := 60
Substitua pela variável do número de linhas/página da impressora atualmente configurada, caso seu sistema possua configuração múltipla de impressora.
DO WHILE !TMP->( EOF() ) IF LL >= LP //Quebra de página LL := 0 ... @ LL++,00 SAY REPLI("-",80) @ LL++,00 SAY "Fornecedor Código" @ LL++,00 SAY " Ord. Compra Data de Compra, Receb. e Devolucao" @ LL++,00 SAY " Produto Cód. Qtd.Rec. Qtd.Dev Dev.% Dev.$" @ LL++,00 SAY REPLI("-",80) @ LL++,00 SAY cFOR+" "+TMP->CODFORN @ LL++,05 SAY cOC+" "+DTOC(TMP->DCOMPRA)+", "+DTOC(TMP->DRECEB)+", "+DTOC(TMP->DDEV) @ LL,10 SAY TMP->PRODUTO @ LL,36 SAY TMP->CODPROD @ LL,42 SAY TMP->QTDRECEB @ LL,51 SAY TMP->QTDDEV DEVp := (TMP->QTDDEV*100)/QTDREC DEVv := TMP->QTDDEV*TMP->VALOR @ LL,60 SAY DEVp PICTURE "@R 999.99%" @ LL++,68 SAY DEVv PICTURE "99999.99" TMP->( DBSKIP() ) ENDIF cFOR := TMP->FORNEC cOC := TMP->OC IF cFOR # TMP->FORNEC cFOR := TMP->FORNEC cOC := TMP->OC @ LL++,00 SAY cFOR+" "+TMP->CODFORN @ LL++,05 SAY cOC+" "+DTOC(TMP->DCOMPRA)+", "+DTOC(TMP->DRECEB)+", "+DTOC(TMP->DDEV) ENDIF IF cOC # TMP->OC cOC := TMP->OC @ LL++,05 SAY cOC+" "+DTOC(TMP->DCOMPRA)+", "+DTOC(TMP->DRECEB)+", "+DTOC(TMP->DDEV) ENDIF @ LL,10 SAY TMP->PRODUTO @ LL,36 SAY TMP->CODPROD @ LL,42 SAY TMP->QTDRECEB @ LL,51 SAY TMP->QTDDEV DEVp := (TMP->QTDDEV*100)/QTDREC DEVv := TMP->QTDDEV*TMP->VALOR @ LL,60 SAY DEVp PICTURE "@R 999.99%" @ LL++,68 SAY DEVv PICTURE "99999.99" TMP->( DBSKIP() ) ENDDO
Observe que o arquivo temporário deverá ser apagado no final do programa, caso contrário com o tempo a capacidade de registros de arquivos da FAT (tabela de alocação de arquivos) estourará e nenhum outro arquivo poderá ser criado neste diretório e destarte ocasionará um erro fatal.
TMP->( DBCLOSEAREA() ) //Deve-se fechar o arquivo antes de apagá-lo TEMP += ".DBF" TEMPNTX += ".NTX" FERASE( TEMP ) FERASE( TEMPNTX ) RETURN *------------------------------
Bem, aí está o estudo completo! Espero que tenha gostado. Vamos debater o assunto? Poste seu comentário.
Comentários recentes