Página 1 de 1

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 03:54
por fladimir
Senhores eu estou numa situação q até consegui resolver mas de forma muito demorada...

Preciso refazer os códigos da tabela de produtos e para não perder as correspondencias trocar nas tabelas q tem movimentação dos produtos... como entrada, vendas, orcamentos etc...

Código q funciona porém muito lento:

Código: Selecionar todos

#include "common.ch"
#include "inkey.ch"

********************************************************************************
Procedure MAIN
* Reclassificar os produtos a partir de um determinado codigo e tb muda nas tabelas
********************************************************************************
local1:=""
local2:=""
local3:=""
local4:=""
local5:=""

Private cexecutavel:="csl.exe",cterminal:="01"

REQUEST DBFCDX                 // Driver para Indices  DBFCDX
RDDSETDEFAULT('DBFCDX')        // Informar no Inicio do Sistema
__KILLREAD()
set(4,iif(__setcentury(),"dd/mm/yyyy","dd/mm/yy"))

 cont:=0

 @ 10,10 SAY "DIGITE A PARTIR DE QUAL NUMERO IRA COMECAR" GET CONT VALID CONT>0
 READ

if  !file("PRODUTO.DBF")
else
   dbusearea(.t.,NIL,"Produto", .T. ,.f.,.f.)
	AbreTabelas()
   mensag("Aguarde, trocando os c¢digos","W+*/R")

   dbselectar("Produto")
   If Select('Produto')=0
    	Use produto alias produto EXCLUSIVE new
		
  	Endif
 	
	produto->(dbgotop())
   while produto->( !eof())
      local1:=produto->codpro
      local2:=strzero(cont,6)

      produto->codpro=local2

		trocacod("receber",  "codpro", local1, local2)
      trocacod("itensped", "codpro", local1, local2)
      trocacod("orcament", "codpro", local1, local2)
      trocacod("Compra",   "codpro", local1, local2)
      trocacod("Entrada",  "codpro", local1, local2)

      produto->(dbskip())
      cont++
   end
   fechatudo()
   qout("Pronto...")
end if

************************************************************************************************
Static Procedure TROCACOD(calias, ccampo, ccodigoold, ccodigonew)

   IF (Select(cAlias) == 0)
   ELSE
		MENSAG("Trocando produto c¢digo:" + cCodigoOLD + " na Tabela [" + cAlias + "]","W+*/R")
		dbselectarea(cAlias)
		DBEVAL( { || AtribuiCodigo(cAlias, cCodigoNew) }, { || codpro == ccodigoold })		
      RETURN
   ENDIF

************************************************************************************************
Static Function AtribuiCodigo(cAlias, cCodigoNew)
	&cAlias->codpro := cCodigoNew
Return	

************************************************************************************************
Static Function AbreTabelas()
	   if file("itensped.dbf")
	      dbusearea(.t.,NIL,"itensped", .T. ,.f.,.f.)
			DBCreateIndex("tmp001","itensped->codpro",{|| itensped->codpro},NIL)
	   end if
	   if file("receber.DBF")
	      dbusearea(.t.,NIL,"receber", .T. ,.f.,.f.)
	      DBCreateIndex("tmp003","receber->codpro",{||receber->codpro},NIL)
	   end if
	   if file("orcament.DBF")
	      dbusearea(.t.,NIL,"orcament", .T. ,.f.,.f.)
	      DBCreateIndex("tmp004","orcament->codpro",{|| orcament->codpro},NIL)
	   end if
	   if file("compra.DBF")
	      dbusearea(.t.,NIL,"compra", .T. ,.f.,.f.)
	      DBCreateIndex("tmp005","compra->codpro",{|| compra->codpro},NIL)
	   end if
	   if file("entrada.DBF")
	      dbusearea(.t.,NIL,"entrada", .T. ,.f.,.f.)
	      DBCreateIndex("tmp008","entrada->codpro",{|| entrada->codpro},NIL)
	   end if
Return NIL

Outra forma que esta rápida porém não funciona corretamente e não entendi porque...


Eu fiz de uma forma q era pra ter funcionado porém fica códigos de fora por exemplo tenho um produto com código 999999 e ele tem 4 lançamentos na tabela de historico porém não é trocado todos os 4 lançamentos... tem algo errado q não estou entendo acho q é no índice...

Código: Selecionar todos


********************************
procedure TROCACOD(calias, ccampo, ccodigoold, ccodigonew)
   if (Select(calias) == 0)
   else
      if (&calias->(dbSeek(ccodigoold)))
         do while (&calias->&ccampo == ccodigoold)
            &calias->&ccampo:= ccodigonew
            &calias->(dbSkip())
         enddo
      endif
      return
   endif

[]´s

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 07:52
por Jairo Maia
Olá Fladimir,
fladimir escreveu:porém não é trocado todos os 4 lançamentos
Primeiro, que acho que usar a forma Alias-> por si só já é mais lento, penso que melhor seria trabalhar de forma direta na área sempre que possível, e neste caso me parece ser.

Mas em relação ao problema, está me parecendo que você não pode usar o &calias->(dbSkip()), já que se você está dentro do laço que checa o critério, e a área está indexada pelo campo que está sendo alterado, o próximo registro do critério será o corrente, no caso que você citou sendo 4, o primeiro é alterado, o segundo pula, o terceiro é alterado, o quarto pula e sai do laço, pois o próximo registro estará fora do critério.

Penso que seja isso.

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 13:04
por JoséQuintas
O problema é trocar um código por outro que já existe, aí ferrou.

Uma das rotinas que mencionou não ter funcionado é normal.
Do While codigo=codigodigitado .....
replace ....

Uma vez que trocou o código, o próximo registro deixa de ser o que era antes.

Uma opção seria:

indexar o arquivo pelo código

Código: Selecionar todos

Do While .t.
   Seek CodigoVelho
   If Eof()
      Exit
   Endif
   Replace CodigoVelho With CodigoNovo
Enddo

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 14:00
por fladimir
Obrigado colegas pelas respostas...

Todas as tabelas estão indexadas pelo código...

resolvi assim:

Código: Selecionar todos

******************************************************************************************
PROCEDURE TROCACOD(CALIAS, CCAMPO, CCODIGOOLD, CCODIGONEW)

   IF (SELECT(CALIAS) == 0)
   ELSE
		MENSAG("Trocando produto c¢digo:" + cCodigoOLD + " na Tabela [" + cAlias + "]","W+*/R")
		WHILE .T.
			IF &CALIAS->( DBSEEK(CCODIGOOLD) )
      	   DO WHILE (&CALIAS->&CCAMPO == CCODIGOOLD)
         		&CALIAS->&CCAMPO:= CCODIGONEW
           		&CALIAS->(DBSKIP())
         	ENDDO
      	ELSE
      		EXIT
			ENDIF
      END
      RETURN
   ENDIF

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 14:25
por Imatech
Olá Fladimir !
.
.
.
Uma regra universal para se obter corrupção de índices: Alterar o valor de qualquer campo nessa condição ( indexado :^| )
.
.
.
Sugestão: Remova/Destrua os índices antes de alterar o valor de qquer campo indexado...
.
.
.
Para a recomendação do Jairo, a melhoria no código é bem simples:

Código: Selecionar todos


******************************************************************************************
PROCEDURE TROCACOD( cAlias, cCampo, cCodigoOld, cCodigoNew )

   IF !( SELECT( cAlias ) == 0 )
      MENSAG( "Trocando produto c¢digo:" + cCodigoOld + " na Tabela [" + cAlias + "]", "W+*/R" )
      WHILE .T.
         IF ( cAlias )->( DBSEEK( cCodigoOld ) )
            WHILE ( ( cAlias )->( cCampo ) == cCodigoOld )
               ( cAlias )->( cCampo ):= cCodigoNew
               ( cAlias )->(DBSKIP() )
            ENDDO
         ELSE
            EXIT
         ENDIF
      ENDDO
   ENDIF
   RETURN


Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 14:37
por alxsts
Olá!

Só de retirar todos esses operadores macro já vai acelerar o processo. Se fizer a alteração dos códigos com todos os índices fechados será bem mais rápido. Depois é só fazer uma indexação geral.

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 16:49
por sambomb
Se você já tem os 2 campos você pode fazer assim....

Obs.: Dependendo do tamanho da tabela e das máquinas aonde vão ser executo o código pode substituir a lógica por uma tabela temporária indexada pelo campo CODANT

Código: Selecionar todos

//Abre tudo em modo exclusivo

Select(cPrincipal)  //ESTOQUE ?

DbGoTop()

While !Eof()

   aAdd(aReferencia,{CODANT, CODNOVO})

end

Select(cOutra1)//COMPRAS ?

DbGoTop()

While !Eof()

   nPos := aScan(aReferencia,{|X| x[1] = CODANT})

   If nPos > 0

      REPLACE CODNOVO with aReferencia[nPos,2]

   end

end

Select(cOutra2) // VENDAS ?

DbGoTop()

While !Eof()

   nPos := aScan(aReferencia,{|X| x[1] = CODANT})

   If nPos > 0

      REPLACE CODNOVO with aReferencia[nPos,2]

   end

end

....

DbCommitAll()

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 16:58
por alxsts
Olá!

Neste exemplo do Samir, se trocar o array por hash melhora a performance.

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 18:43
por Jairo Maia
Olá Fladimir,

Legal que resolveu. Mas você que já me ajudou várias vezes, na minha mensagem inicial o que eu quis dizer é que você poderia fazer de forma mais rápida assim:

Código: Selecionar todos

procedure TROCACOD(calias, ccampo, ccodigoold, ccodigonew)
    if Select(calias) > 0 .And. dbSeek(ccodigoold)
        do while &ccampo == ccodigoold
            Replace &ccampo With ccodigonew
        enddo
    endif
Return Nil

Trocar códigos produtos rápido e prático

Enviado: 09 Out 2012 18:52
por fladimir
Obrigado alxsts, do jeito q fiz da primeira vez demorou horas... qdo postei depois q resolvi demora cerca de 2minutos... depois vou testar com as dicas q vc passou....

[]´s

Trocar códigos produtos rápido e prático

Enviado: 10 Out 2012 08:06
por sambomb
alxsts escreveu:Olá!

Neste exemplo do Samir, se trocar o array por hash melhora a performance.
Realmente... neste caso o nome seria o código antigo e o conteúdo o código novo, correto?

Trocar códigos produtos rápido e prático

Enviado: 11 Out 2012 20:02
por alxsts
Olá!

Isso, exatamente. O Hash é uma estrutura tipo dicionário com pares de chaves/valores. Como você citou, a chave seria o código antigo e o valor o novo.

Depois de carregar os valores no hash, é só ler o arquivo com os códigos atuais, pesquisar o código atual no hash, pegar o novo código e gravar.