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

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

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

Mensagem 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
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
Avatar do usuário
Jairo Maia
Moderador
Moderador
Mensagens: 2785
Registrado em: 16 Ago 2010 13:46
Localização: Campinas-SP

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

Mensagem 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.
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

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

Mensagem 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
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

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

Mensagem 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
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
Imatech
Usuário Nível 3
Usuário Nível 3
Mensagens: 350
Registrado em: 24 Ago 2010 23:48
Localização: Goiânia-GO

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

Mensagem 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

M., Ronaldo

by: IMATECH

IMATION TECNOLOGIA
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

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

Mensagem 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.
[]´s
Alexandre Santos (AlxSts)
sambomb
Usuário Nível 3
Usuário Nível 3
Mensagens: 250
Registrado em: 24 Out 2008 17:02
Localização: Itaocara - RJ - Brasil

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

Mensagem 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()
Imagem

Rca Sistemas - Itaocara - RJ
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

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

Mensagem por alxsts »

Olá!

Neste exemplo do Samir, se trocar o array por hash melhora a performance.
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
Jairo Maia
Moderador
Moderador
Mensagens: 2785
Registrado em: 16 Ago 2010 13:46
Localização: Campinas-SP

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

Mensagem 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
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

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

Mensagem 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
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
sambomb
Usuário Nível 3
Usuário Nível 3
Mensagens: 250
Registrado em: 24 Out 2008 17:02
Localização: Itaocara - RJ - Brasil

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

Mensagem 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?
Imagem

Rca Sistemas - Itaocara - RJ
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

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

Mensagem 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.
[]´s
Alexandre Santos (AlxSts)
Responder