Arquivos Temporários

 
Elucidação total em estudo de caso.

Aprenda a confeccionar qualquer tipo de relatório em ambiente de rede, por mais complexo que seja, e de processamento rápido.

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.