Clipper On Line • Ver Tópico - Uma mudança de hoje: FOR EACH

Uma mudança de hoje: FOR EACH

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

 

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 13 Jan 2016 22:19

Alterei uma rotina pra FOR EACH, e na hora de decidir se simplifiquei ou não, só sobrou rir... rs
Gostei principalmente dos GETs, eliminando problemas com array

calculo.png


Na parte de cima são extratos pra pagamento
Na parte de baixo são cheques emitidos

A intenção é mostrar em cada extrato, quanto os cheques causaram de baixa, e qual o saldo restante.

antes da alteração

CREATE CLASS CalculaBaixaExtratoClass
   VAR mExtrato
   VAR mBaixa
   VAR mSaldo
   VAR mCheque
   VAR mTexto       INIT Space(50)
   VAR mSomaExtrato INIT 0
   VAR mSomaBaixa   INIT 0
   VAR mSomaSaldo   INIT 0
   VAR mSomaCheque  INIT 0
   VAR mSaldoCheque INIT 0
   METHOD Init()
   METHOD Calcula()
   END CLASS

METHOD Init() CLASS CalculaBaixaExtratoClass
   ::mExtrato := Array(10)
   ::mBaixa   := Array(10)
   ::mSaldo   := Array(10)
   ::mCheque  := Array(10)
   Afill( ::mExtrato, 0 )
   Afill( ::mBaixa, 0 )
   Afill( ::mSaldo, 0 )
   Afill( ::mCheque, 0 )
   RETURN SELF

METHOD Calcula() CLASS CalculaBaixaExtratoClass

   LOCAL mTotal := 0, nCont

   FOR nCont = 1 TO 10
      mTotal += ::mCheque[ nCont ]
   NEXT
   FOR nCont = 1 TO 10
      IF ::mExtrato[ nCont ] == mTotal
         ::mBaixa[ nCont ] := mTotal
         ::mSaldo[ nCont ] := 0
         mTotal          := 0
      ELSEIF ::mExtrato[ nCont ] > mTotal
         ::mBaixa[ nCont ] := mTotal
         ::mSaldo[ nCont ] := ::mExtrato[ nCont ] - ::mBaixa[nCont ]
         mTotal          := 0
      ELSE
         ::mBaixa[ nCont ] := ::mExtrato[ nCont ]
         ::mSaldo[ nCont ] := 0
         mTotal -= ::mBaixa[ nCont ]
      ENDIF
   NEXT
   ::mSomaExtrato := 0
   ::mSomaBaixa   := 0
   ::mSomaCheque  := 0
   ::mSomaSaldo   := 0
   FOR nCont = 1 TO Len( ::mExtrato )
      ::mSomaExtrato += ::mExtrato[ nCont ]
      ::mSomaBaixa   += ::mBaixa[ nCont ]
      ::mSomaSaldo   += ::mSaldo[ nCont ]
      ::mSomaCheque  += ::mCheque[ nCont ]
   NEXT
   ::mSaldoCheque := ::mSomaCheque - ::mSomaBaixa

   IF ::mSaldoCheque != 0
      ::mTexto := Pad( "FALTA OU SOBRA VALOR DE CHEQUE", 50 )
   ELSE
      ::mTexto := Space(50)
   ENDIF
   RETURN .T.

FUNCTION CalculaBaixaExtrato()

   LOCAL GetList := {}, oVal := CalculaBaixaExtratoClass():New()

   wSave()
   Cls()
   @ 2, 1              SAY "Valor extrato 1.:" GET oVal:mExtrato[ 1 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row(), Col() + 2  SAY "Baixar:"           GET oVal:mBaixa[ 1 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 2  SAY "Saldo:"            GET oVal:mSaldo[ 1 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 1, 1      SAY "Valor extrato 2.:" GET oVal:mExtrato[ 2 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row(), Col() + 2  SAY "Baixar:"           GET oVal:mBaixa[ 2 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 2  SAY "Saldo:"            GET oVal:mSaldo[ 2 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 1, 1      SAY "Valor extrato 3.:" GET oVal:mExtrato[ 3 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row(), Col() + 2  SAY "Baixar:"           GET oVal:mBaixa[ 3 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 2  SAY "Saldo:"            GET oVal:mSaldo[ 3 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 1, 1      SAY "Valor extrato 4.:" GET oVal:mExtrato[ 4 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row(), Col() + 2  SAY "Baixar:"           GET oVal:mBaixa[ 4 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 2  SAY "Saldo:"            GET oVal:mSaldo[ 4 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 1, 1      SAY "Valor extrato 5.:" GET oVal:mExtrato[ 5 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row(), Col() + 2  SAY "Baixar:"           GET oVal:mBaixa[ 5 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 2  SAY "Saldo:"            GET oVal:mSaldo[ 5 ]   PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 2, 1      SAY "Somas"
   @ Row(), Col() + 13 GET oVal:mSomaExtrato PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 10 GET oVal:mSomaBaixa   PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 9  GET oVal:mSomaSaldo   PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 2, 1      SAY "Cheque 1........:" GET oVal:mCheque[ 1 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 1, 1      SAY "Cheque 2........:" GET oVal:mCheque[ 2 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 1, 1      SAY "Cheque 3........:" GET oVal:mCheque[ 3 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 1, 1      SAY "Cheque 4........:" GET oVal:mCheque[ 4 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 1, 1      SAY "Cheque 5........:" GET oVal:mCheque[ 5 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 1, 1      SAY "Cheque 6........:" GET oVal:mCheque[ 6 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 1, 1      SAY "Cheque 7........:" GET oVal:mCheque[ 7 ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   @ Row() + 2, 5      SAY "Soma Cheque:"      GET oVal:mSomaCheque  PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 3  SAY "Saldo em cheque:"  GET oVal:mSaldoCheque PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 2, 20 GET oVal:mTexto WHEN .F.
   READ
   wRestore()
   RETURN NIL


depois da alteração

#define V_EXTRATO 1
#define V_BAIXA   2
#define V_SALDO   3
#define V_CHEQUE  4

CREATE CLASS CalculaBaixaExtratoClass
   VAR mLancto
   VAR mSoma        INIT { 0, 0, 0, 0 }
   VAR mTexto       INIT Space(50)
   METHOD Init()
   METHOD Calcula()
   END CLASS

METHOD Init() CLASS CalculaBaixaExtratoClass

   LOCAL oElement

   ::mLancto := Array(10)
   FOR EACH oElement IN ::mLancto
      oElement := { 0, 0, 0, 0 }
   NEXT
   RETURN SELF

METHOD Calcula() CLASS CalculaBaixaExtratoClass

   LOCAL mTotal := 0, oElement

   FOR EACH oElement IN ::mLancto
      mTotal += oElement[ V_CHEQUE ]
   NEXT
   FOR EACH oElement IN ::mLancto
      IF oElement[ V_EXTRATO ] == mTotal
         oElement[ V_BAIXA ] := mTotal
         oElement[ V_SALDO ] := 0
         mTotal              := 0
      ELSEIF oElement[ V_EXTRATO ] > mTotal
         oElement[ V_BAIXA ] := mTotal
         oElement[ V_SALDO ] := oElement[ V_EXTRATO ] - oElement[ V_BAIXA ]
         mTotal              := 0
      ELSE
         oElement[ V_BAIXA ] := oElement[ V_EXTRATO ]
         oElement[ V_SALDO ] := 0
         mTotal -= oElement[ V_BAIXA ]
      ENDIF
   NEXT
   ::mSoma := { 0, 0, 0, 0 }
   FOR EACH oElement IN ::mLancto
      ::mSoma[ V_EXTRATO ] += oElement[ V_EXTRATO ]
      ::mSoma[ V_BAIXA   ] += oElement[ V_BAIXA   ]
      ::mSoma[ V_CHEQUE  ] += oElement[ V_CHEQUE  ]
      ::mSoma[ V_SALDO   ] += oElement[ V_SALDO   ]
   NEXT
   ::mSoma[ V_SALDO ] := ::mSoma[ V_CHEQUE ] - ::mSoma[ V_BAIXA ]

   IF ::mSoma[ V_SALDO ] != 0
      ::mTexto := Pad( "FALTA OU SOBRA VALOR DE CHEQUE", 50 )
   ELSE
      ::mTexto := Space(50)
   ENDIF
   RETURN .T.

FUNCTION CalculaBaixaExtrato()

   LOCAL GetList := {}, oElement, oVal := CalculaBaixaExtratoClass():New()

   wSave()
   Cls()
   @ 1, 0 SAY ""
   FOR EACH oElement IN oVal:mLancto
      @ Row() + 1, 1      SAY "Valor extrato:" GET oElement[ V_EXTRATO ] PICTURE "999,999,999.99" VALID oVal:Calcula()
      @ Row(), Col() + 2  SAY "Baixar:"        GET oElement[ V_BAIXA   ] PICTURE "999,999,999.99" WHEN .F.
      @ Row(), Col() + 2  SAY "Saldo:"         GET oElement[ V_SALDO   ] PICTURE "999,999,999.99" WHEN .F.
   NEXT
   @ Row() + 2, 1         SAY "Somas"
   @ Row(), Col() + 10    GET oVal:mSoma[ V_EXTRATO ] PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 10    GET oVal:mSoma[ V_BAIXA   ] PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 9     GET oVal:mSoma[ V_SALDO   ] PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 1, 0         SAY ""
   FOR EACH oElement IN oVal:mLancto
      @ Row() + 1, 1      SAY "Cheque .........:" GET oElement[ V_CHEQUE ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   NEXT
   @ Row() + 2, 5      SAY "Soma Cheque:"      GET oVal:mSoma[ V_CHEQUE ] PICTURE "999,999,999.99" WHEN .F.
   @ Row(), Col() + 3  SAY "Saldo em cheque:"  GET oVal:mSoma[ V_SALDO  ] PICTURE "999,999,999.99" WHEN .F.
   @ Row() + 2, 20 GET oVal:mTexto WHEN .F.
   READ
   wRestore()
   RETURN NIL


Nota:
Aqui funcionou, mas cai naquilo da minha GETSYS atualizar os GETs automaticamente, afinal toda tela é atualizada durante a digitação.
Pra ficar igual, teria que passar GetList como parâmetro nos VALID, e na rotina de cálculo fazer o get:Display() pra toda GetList.
Mas a intenção é mostrar a mudança do fonte usando FOR EACH.
É um fonte totalmente fora do normal.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 13 Jan 2016 22:37

Destaque:

FOR EACH pra atribuir valores e pra GETs... achei muito legal.
Nesta parte, atribui valor pra cada elemento do array

mLancto := Array(10)
FOR EACH oElement IN mLancto
   oElement := { 0, 0, 0, 0 }
NEXT


Nesta parte, GET pra cada elemento do array

   FOR EACH oElement IN oVal:mLancto
      @ Row() + 1, 1      SAY "Cheque .........:" GET oElement[ V_CHEQUE ] PICTURE "999,999,999.99" VALID oVal:Calcula()
   NEXT


Mas ficou sem o contador pro texto (cheque 1,2,3,4...)
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 13 Jan 2016 22:49

Esqueci de mencionar:
Antes da alteração eram 5 extratos e 7 cheques.
Agora são 10 de cada.
No final, agora tem 18 GETs a mais. (em cada extrato são 3 GETs.)

Por causa do FOR EACH, agora o limite é apenas a tela. Basta definir o tamanho do array, e não precisa alterar mais nada no fonte.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor microvolution » 21 Jan 2016 23:45

professor, boa noite!
você só posta "trem chick no úrtimo" no qual percebo que estou "anos luz" atrás de V.Sas.
Enquanto que para você é como "soltar pipa", pra mim é como "não saber andar de bicicleta (nunca ter andado)" e já querer começar "andando já de uma roda"!!! :%
Tenho que me reciclar mesmo... afinal, fiquei muitos anos com um mesmo código (apesar de ser muito bem funcional) mas, ultrapassadérrimo!
ah! nem sei o que é FOR EACH!!!
:-O
mais uma vez, parabéns!
Grato,
MICROVOLUTION - 16 anos Evoluindo Com Você!


Você já leu a Bíblia hoje?
João 3:16 - Porque Deus amou ao mundo de tal maneira que deu seu Único Filho para que todo aquele que nEle crê não pereça mas tenha a Vida Eterna!
microvolution
Usuário Nível 5

Usuário Nível 5
 
Mensagens: 1175
Data de registro: 02 Set 2011 22:17
Curtiu: 59 vezes
Mens.Curtidas: 17 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 22 Jan 2016 05:41

É só olhar a classe pensando num programa normal com variáveis públicas.
O que é METHOD, considerar FUNCTION.

Simplificando sobre o FOR EACH: Compare:

FOR nCont = 1 TO Len( SalaDeAula )
   PuxaOrelha( SalaDeAula[ nCont ] )
NEXT


FOR EACH Aluno IN SalaDeAula
   PuxaOrelha( Aluno )
NEXT
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor fladimir » 22 Jan 2016 17:22

Essa explicação com Aluno e Sala de Aula matou a pau...

:-Y :{
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 de usuário

fladimir
Colaborador

Colaborador
 
Mensagens: 2434
Data de registro: 15 Nov 2006 19:21
Curtiu: 28 vezes
Mens.Curtidas: 157 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 22 Jan 2016 18:46

Veio como inspiração durante o post, e mostra exatamente a mudança do FOR EACH no fonte.

Acaba ficando bem claro o que está sendo tratado dentro do bloco.
E nem precisa saber quantos são, ou qual o número de cada um, basta saber que vai ser feito pra todos.

Se reparar direito, com FOR/NEXT nem dá pra saber do que se trata, ele é que tá mais difícil de entender.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor fladimir » 25 Jul 2016 02:20

Como simplificar a rotina abaixo com FOR... EACH ?

Ela esta funcionando (falta alguns detalhes mas a ideia central esta ok)... Exemplo o cliente faz N orçamentos para Y Clientes e cada cliente pode ser de 1 cidade... preciso gerar um relatório com os produtos agrupados por cidade independente do cliente...

Da forma abaixo (ainda não finalizada) esta gerando um Array muldimensional com as cidades e os produtos agrupados por cidade


... Rotina q gera relatorio
   local aCidades, nPosCidade, TT

   aCidades := {}
   while Orcam->(!EOF())
      
      if Clientes->( dbseek(Orcam->CodCli) )
         cCidade := Clientes->Cidade
      else
         cCidade := padc('NAO LOCALIZADA', 25)
      endif

      nPosCidade := 0
      TT := 1
      if empty(aCidades)
         aadd(aCidades, { cCidade, { {'', '', 0, 0, 0} } } )
         nPosCidade := 1

      else
         lNao_e_Igual := .T.
         for TT:= 1 TO LEN(aCidades)     
            if aCidades[TT,1] == cCidade 
               lNao_e_Igual := .F.
               nPosCidade := TT
               EXIT
            endif
         next
   
         if lNao_e_Igual                      &&-- SE a VARREDURA nao encontrou NADA / Ai adiciona
            aadd(aCidades, { cCidade, { {'', '', 0, 0, 0} } } )
            nPosCidade := len(aCidades)               
         endif
      endif
      Vequestaodosprodutosnessacidade(@aCidades, nPosCidade)
      Orcam->(dbskip())
   end

//--> no final tenho um Array com as cidades e cada cidade com seus produtos agrupados
...

static function Vequestaodosprodutosnessacidade(aCidades, nPosCidade)
   local nI, aProdutosCid, lNotEqual

   aProdutosCid := aCidades[nPosCidade][2] && array dos produtos

   lNotEqual := .T.
   for nI:= 1 TO LEN(aProdutosCid)             
      if aProdutosCid[nI][1] == Orcam->CodProd         //-- se encontrar igualdade cai fora
         aCidades[nPosCidade][2][nI][3] += Orcam->QTDE
         aCidades[nPosCidade][2][nI][4] += Orcam->vl_total
         lNotEqual := .F.
         EXIT
      endif
   next

   if lNotEqual                      //-- SE a VARREDURA nao encontrou NADA / Ai adiciona
      aadd(aCidades[nPosCidade][2], { Orcam->CodProd,;
                                      Orcam->descricao,;
                                      Orcam->qtde,;
                                      Orcam->vl_total,;
                                      Produto->Estoque  } )
   endif
return
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 de usuário

fladimir
Colaborador

Colaborador
 
Mensagens: 2434
Data de registro: 15 Nov 2006 19:21
Curtiu: 28 vezes
Mens.Curtidas: 157 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 25 Jul 2016 03:27

Acho que está vendo do modo errado.
Não precisa nem FOR EACH e nem FOR NEXT.
Direto no post, sem testar, mais ou menos isto:

... Rotina q gera relatorio
local aCidades, nPosCidade, TT

aCidades := {}
while Orcam->(!EOF())
 
  if Clientes->( dbseek(Orcam->CodCli) )
   cCidade := Clientes->Cidade
  else
   cCidade := padc('NAO LOCALIZADA', 25)
  endif

  nPosCidade := AScan( aCidades, { | oElemento | oElemento[ 1 ] == cCidade } )
   IF nPosCidade == 0
      aadd(aCidades, { cCidade, {} )
     nPosCidade := Len( aCidades )
ENDIF
  Vequestaodosprodutosnessacidade(@aCidades[ nPosCidade ] [ 2 ] )
  Orcam->(dbskip())
end

//--> no final tenho um Array com as cidades e cada cidade com seus produtos agrupados
...

static function Vequestaodosprodutosnessacidade( aProdutos )

LOCAL nPosProduto

nPosProduto := AScan(  aProdutos, { | oElemento | oElemento[ 1 ] == orcam->CodProd } )
IF nPosProduto == 0
   AAdd( aProdutos, { orcam->CodProd, orcam->Descricao, 0, 0, produto->Estoque } )
   nPosProduto := Len( aProdutos )
ENDIF
aProdutos[ nPosProduto ][3] += Orcam->QTDE
aProdutos[ nPosProduto ][4] += Orcam->vl_total
return


Mas considerando que deve ordenar depois, eu criaria um arquivo temporário pra isso.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor fladimir » 25 Jul 2016 09:20

Vlw Quintas.
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 de usuário

fladimir
Colaborador

Colaborador
 
Mensagens: 2434
Data de registro: 15 Nov 2006 19:21
Curtiu: 28 vezes
Mens.Curtidas: 157 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 22 Ago 2016 19:57

Já passei algumas vezes neste tópico, e sempre dá vontade de melhorar mais um pouquinho.
Então postar de vez, assim acaba com a vontade... rs

Dá pra aplicar a mesma regra nos dois casos.

   LOCAL aCidades, nPosCidade

   aCidades := {}
   DO WHILE Orcam->( ! Eof() )
       IF Clientes->( dbseek( Orcam->CodCli ) )
          cCidade := Clientes->Cidade
      ELSE
         cCidade := padc( 'NAO LOCALIZADA', 25 )
      ENDIF
      AcumulaCidade( aCidades, cCidade )
      SKIP
   ENDDO

   RETURN

STATIC FUNCTION AcumulaCidade( aCidades, cCidade )

   LOCAL nPos

   nPos := AScan( aCidades, { | oElemento | oElemento[ 1 ] == cCidade } )
   IF nPos == 0
      aadd(aCidades, { cCidade, {} )
      nPos := Len( aCidades )
   ENDIF
   AcumulaProduto( aCidades[ nPos, 2 ] )

   RETURN NIL

STATIC FUNCTION AcumulaProduto( aProdutos )

   LOCAL nPos

   nPos := AScan( aProdutos, { | oElemento | oElemento[ 1 ] == orcam->CodProd } )
   IF nPos == 0
      AAdd( aProdutos, { orcam->CodProd, orcam->Descricao, 0, 0, produto->Estoque } )
      nPos := Len( aProdutos )
   ENDIF
   aProdutos[ nPos, 3 ] += Orcam->QTDE
   aProdutos[ nPos, 4 ] += Orcam->vl_total

   RETURN NIL


Aqui dá pra perceber regrinhas tradicionais interessantes:

- Um problemão dividido em probleminhas
- Cada "bloco" tratando do seu assunto
- Variáveis locais, cada rotina tem suas variáveis, acabou simplificando o uso de variáveis também
- Rotinas pequenas, de fácil manutenção, deixa visível o processo da rotina

Depois de anos sem ver o fonte, uma olhada rápida e já dá pra alterar.

Ou... um fonte pensando no programador, que é quem olha o fonte.
Sinceramente, ninguém nunca me falou isso desse jeito, antes eu pensava que tudo isso era só pro compilador trabalhar melhor, e não dava atenção.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Uma mudança de hoje: FOR EACH

Mensagempor fladimir » 22 Ago 2016 20:53

vlw
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 de usuário

fladimir
Colaborador

Colaborador
 
Mensagens: 2434
Data de registro: 15 Nov 2006 19:21
Curtiu: 28 vezes
Mens.Curtidas: 157 vezes

Uma mudança de hoje: FOR EACH

Mensagempor xfurlan » 23 Ago 2016 12:42

Muito bom mesmo, gostei.
Assim voce não programou só para otimizações, ma tambem para facilitar compreensão que por sua vez facilita alterações futuras.
Aquele abraço.
xfurlan
xfurlan
Usuário Nível 1

Usuário Nível 1
 
Mensagens: 3
Data de registro: 13 Ago 2016 17:19
Cidade/Estado: Osasco
Curtiu: 53 vezes
Mens.Curtidas: 4 vezes

Uma mudança de hoje: FOR EACH

Mensagempor sambomb » 23 Ago 2016 17:31

Poderia construir esses ajustes em torno de um Objeto.
Por exemplo, esses métodos de acumular por cidade, produto, poderia preencher os valores para todos a serem acumulados enquanto obtem os dados e um método do objeto retornar as informações.
Imagem

Rca Sistemas - Itaocara - RJ
Avatar de usuário

sambomb
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 250
Data de registro: 24 Out 2008 16:02
Cidade/Estado: Itaocara - RJ - Brasil
Curtiu: 16 vezes
Mens.Curtidas: 10 vezes

Uma mudança de hoje: FOR EACH

Mensagempor JoséQuintas » 15 Set 2016 08:46

A de hoje:
A primeira coisa foi pensar num FOR/EACH pra simplificar, pra pegar o arquivo de data mais recente.

   LOCAL nCont, nNumFile, cDateTime, acFileList, mEmail

   acFileList := Directory( AppEmpresaApelido() + "-backup*.zip" )
   IF Len( acFileList ) == 0
      MsgStop( "Crie primeiro o arquivo na opção de backup!" )
      RETURN
   ENDIF
   nNumFile  := 0
   cDateTime := "000000000:00:00"
   FOR nCont = 1 TO Len( acFileList )
      IF Dtos( acFileList[ nCont, 3 ] ) + acFileList[ nCont, 4 ] > cDateTime
         nNumFile := nCont
         cDateTime := Dtos( acFileList[ nCont, 3 ] ) + acFileList[ nCont, 4 ]
      ENDIF
   NEXT
   SayScroll( "O arquivo que será transmitido é " + acFileList[nNumFile,1] )
   SayScroll( "Foi criado em " + Dtoc( acFileList[ nNumFile, 3 ] ) + " " + acFileList[ nNumFile, 4 ] )
   SayScroll( "Seu tamanho é de " + LTrim( Str( Int( acFileList[ nNumFile, 2 ] / 1024 ) ) ) + " kb " )
   SayScroll()
   IF Int( acFileList[ nNumFile, 2 ] / 1000 ) > 20000
      SayScroll( "ATENÇÃO!!! A central de emails pode recusar o tamanho acima de 2mb!",, .T. )
      SayScroll()
   ENDIF
   IF ! MsgYesNo( "Confirma o envio do backup de " + Dtoc( acFileList[ nNumFile, 3 ] ) + " para JPA?" )
     RETURN
   ENDIF
   IF ( Date() - acFileList[ nNumFile, 3 ] ) > 1
      IF ! MsgYesNo( "ATENÇÃO!!! Backup tem mais de um dia " + Dtoc( acFileList[ nNumFile, 3 ] ) + ". Continua?" )
         RETURN
      ENDIF
   ENDIF


Alterei a referência para o elemento do array ao invés da posição, e no final, o ASort simplificou mais do que FOR/EACH.
Até variáveis, reduziu de 5 pra 3.

   LOCAL acFileList, mEmail, aFileToSend

   acFileList := Directory( AppEmpresaApelido() + "-backup*.zip" )
   IF Len( acFileList ) == 0
      MsgStop( "Crie primeiro o arquivo na opção de backup!" )
      RETURN
   ENDIF
   ASort( acFileList, , , { | a, b | Dtos( a[ F_DATE ] ) + a[ F_TIME ] > Dtos( b[ F_DATE ] ) + b[ F_TIME ] } )
   aFileToSend := acFileList[ 1 ]
   SayScroll( "O arquivo que será transmitido é " + aFileToSend[ F_NAME ] )
   SayScroll( "Foi criado em " + Dtoc( aFileToSend[ F_DATE] ) + " " + aFileToSend[ F_TIME ] )
   SayScroll( "Seu tamanho é de " + LTrim( Str( Int( aFileToSend[ F_SIZE ] / 1024 ) ) ) + " kb " )
   SayScroll()
   IF Int( aFileToSend[ F_SIZE ] / 1000 ) > 20000
      SayScroll( "ATENÇÃO!!! A central de emails pode recusar o tamanho acima de 2mb!",, .T. )
      SayScroll()
   ENDIF
   IF ! MsgYesNo( "Confirma o envio do backup de " + Dtoc( aFileToSend[ F_DATE ] ) + " para JPA?" )
     RETURN
   ENDIF
   IF ( Date() - aFileToSend[ F_DATE ] ) > 1
      IF ! MsgYesNo( "ATENÇÃO!!! Backup tem mais de um dia " + Dtoc( aFileToSend[ F_DATE ] ) + ". Continua?" )
         RETURN
      ENDIF
   ENDIF
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18113
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1213 vezes

Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 4 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro