Práticas que facilitam programar Clipper/Harbour

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

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Quanto ao post anterior, de qualquer jeito, depende do programador incluir o recurso em suas práticas.

Outro exemplo: um array de coordenadas de mouse pra click, geralmente é um array multidimensional:

Código: Selecionar todos

FOR nCont = 1 TO Len( aAreaMouse )
   IF MRow() >= aAreaMouse[ nCont, 1 ] .AND. MCol() >= aAreaMouse[ nCont, 2 ] .AND. MCol()  <= aAreaMouse[ nCont, 3 ]
      nKey := aAreaMouse[ nCont, 4 ]
     EXIT
   ENDIF
NEXT

Código: Selecionar todos

FOR EACH oElement IN aAreaMouse
   IF MRow() >= oElement[ 1 ] .AND. MCol() >= oElement[ 2 ] .AND. MCol() <= oElement[ 3 ]
      nKey := oElement[ 4 ]
      EXIT
   ENDIF
NEXT
É até interessante, dá pra ter relação com um post anterior.
O "assunto" do bloco é aAreaMouse, todos os elementos do array.
E o "assunto" da rotina interna é cada um dos elementos desse array.
FOR EACH deixou isso bem claro no fonte.

Parece até que faz parte:
Acostumou a organizar o fonte e simplificar fonte, vai descobrindo técnicas/recursos que ajudam nisso.

A conclusão é que tem tudo a ver, é só começar que aos poucos tudo vém naturalmente.

Quanto a esse, pera aí que estou tentando verificar se nesse caso se aplica.
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
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Nem sempre dá pra aplicar o FOR EACH, depende muito do contexto.
E também não existe uma regra fixa de como usar.

Código: Selecionar todos

FOR nIdx := 1 to 25 STEP 2
  nLinha ++
  RestScreen(nIdx, 0, nIdx+1, 79, cTAbertura[nLinha])
  SysWait(.01)
NEXT
À primeira vista é uma rotina pra retornar textos na tela, onde aí é apenas uma página.
Sendo assim, o assunto principal seria cTAbertura.

Código: Selecionar todos

nIdx := 1
FOR EACH oElement IN cTAbertura
   RestScreen( nIdx, 0, nIdx + 1, 79, oElement )
   SysWait( .01 )
   nIdx += 2
   IF nIdx > 25
      // mudar página? ou EXIT?
     nIdx := 1
   ENDIF
NEXT
E internamente seria o controle de "quebra de página", ou algo parecido.
No meu ponto de vista, só é interessante alterar se a rotina completa tratar todo conteúdo de cTAbertura.
Vai de cada um.
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
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Práticas que facilitam programar Clipper/Harbour

Mensagem por asimoes »

Quintas,

Voltando ao assunto FOR EACH tem esses dois métodos muito úteis:

__enumIndex() equivalente a variável I:

FOR I:=1 TO Len(aVator)
NEXT
__enumIsLast() testa se i = Len(aVetor)

Código: Selecionar todos

cCampos:=""
FOR EACH aCampos IN aTheDBF
   cCampos+=IF(aCampos:__enumIndex() > 1,Space(1),"")+cNomeCampo + ' ' + cDecode + IF(!aCampos:__enumIsLast(),",",")")+ IF(!aCampos:__enumIndex(),HB_EOL(),"")
NEXT
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

São interessantes.
Mas no caso desse uso, ficou complicado de entender o fonte, eu mesmo não entendi direito.
Me parece inclusive que tem erro.

Se entendi direito, deve ser algo parecido com isto:

Código: Selecionar todos

cCampos := ""
FOR EACH cNomeCampo IN aTheDBF
    cCampos += Space(1) + cNomeCampo + ' ' + cDecode + ","
NEXT
cCampos := Ltrim( Substr( cCampos, 1, Len( cCampos ) - 1 ) ) + ")" + hb_eol()
Lembre-se o fonte é pra nós, não para o compilador.
Se ficar difícil, pior pra nós.
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
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Práticas que facilitam programar Clipper/Harbour

Mensagem por asimoes »

No meu exemplo o destaque é para

oElemento:__enumIndex() e oElemento:__enumIsLast()

Código: Selecionar todos

 aVetor:={"A", "B", "C"}
 cValor:=""
 FOR EACH oElemento IN aVetor
    cValor += oElemento + IF(!oElemento:__enumIsLast(), ",", "")
 NEXT
 cValor:=""
 FOR EACH oElemento IN aVetor
    cValor += StrZero(oElemento:__enumIndex,2)+" "+oElemento + IF(!oElemento:__enumIsLast(), ", ", "")
 NEXT
1º Resulta: A,B,C
2º Resulta: 01 A, 02 B, 03 C
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

ok, era apenas pra mostrar que existe a opção de obter mais informações da variável do FOR EACH.

Em todo caso, só pra lembrar:

Nosso maior tempo é gasto em alterações, então o fonte tem que ser voltado pra ganhar tempo em alteração.

Olhou, entendeu, alterou, fim.
Olhou, não entendeu, já se começa a perder tempo a partir daí.

Só compensa complicar em casos extremos, aonde milésimos de segundo fizerem diferença.
Ainda não peguei um caso assim.
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
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Práticas que facilitam programar Clipper/Harbour

Mensagem por asimoes »

A questão é se vai usar FOR EACH conheça bem os recursos que pode utilizar.
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Práticas que facilitam programar Clipper/Harbour

Mensagem por asimoes »

Um exemplo que está no changelog.txt

Código: Selecionar todos

       proc main()
         local v, h:={"a"=>1.000,"b"=>2.000,"c"=>3.000}
         heval( h, { |k,v,i| qout( k, v, i ) } ); ?
         for each v in h
            ? v, "=>", v:__enumKey(), v:__enumValue(), v:__enumIndex(), ;
                       valtype(v:__enumBase())
            v += 0.123
         next
         ? ;heval( h, { |k,v,i| qout( k, v, i ) } )
         return
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Acho essa invenção péssima, variável hash.
E tem gente que ainda abusa.
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

Práticas que facilitam programar Clipper/Harbour

Mensagem por fladimir »

Quintas,

Dentro das práticas q facilitam programar Clipper/Harbour vc mencionou q acha péssima etc...

Gostaria de saber pq?

Eu uso para tratar arquivos INI

Exemplo:

Código: Selecionar todos

...
	hINI := HB_ReadIni( cArqZ ) // ATENCAO É CASE SENSITIVE.

	aGet       := Inicia_Var(aGet, "MAPARES")

	aGet[D_DATAMOVZ] := CTOD( hINI["ECF"]["DATAMOVIMENTO"] ) //= 09/12/13
	aGet[D_NUMSERIE]  := hINI["ECF"]["NUMSERIE"]        //= 00000000000000000001

	*-- Verifica se a Chave existe no Hash
	if HHasKey( hINI["TOTALIZADORES"], "GRANDETOTAL" )
		aGet[D_GT_FINAL]   := StrToVal( hINI["TOTALIZADORES"]["GRANDETOTAL"]   ) 
	endif		

	aGet[D_DESCONTOS]  := StrToVal( hINI["TOTALIZADORES"]["TOTALDESCONTOS"]     ) 

...
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
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Desse jeito você não consegue validar o fonte.
Acontece isso com variável PRIVATE, PUBLIC, variável HASH, até mesmo classes e métodos.

No caso de hash, um .CH pode ajudar.
Acho até que foi feito só pra compatibilidade com xHarbour.

Quanto ao INI, não deixa de ser uma opção.
Mas prefiro XML mesmo, mais prático e com mais recursos.

No caso de classes e métodos... vale a pena o risco.
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
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Uia, a compilação -w3 -es2 acabou de me salvar.
d:\CDROM\FONTES\HAROLDO>hbmk2 hl.hbp -comp=msvc
hbmk2: Processing environment options: -comp=msvc
hbmk2: Building sub-project (level 2): libjose.hbp
hbmk2: Processing environment options: -comp=msvc
hbmk2: Target up to date: libjose.lib
hbmk2: Compiling Harbour sources...
Harbour 3.4.0dev (0a127e0) (2016-01-15 01:54)
Copyright (c) 1999-2016, https://github.com/vszakats/harbour-core/
Compiling 'VHLAL01.prg'...
VHLAL01.prg(646) Warning W0032 Variable 'CPALAVRA' is assigned but not used in function 'MYSQLENDERECOLIKE(642)'
Apaguei uma linha a mais do fonte sem querer, aonde usava cPalavra, por isso o erro.

Se não fosse a compilação -w3 -es2, ia demorar muuuito pra descobrir isso.
Como ela avisou, o fonte anterior estava na mão.

Na correria do dia a gente não percebe esses detalhes.

A compilação -w3 -es2 não é apenas uma checagemzinha de escrever o fonte direito.
E também não é só na hora de criar um fonte novo.
É uma ajuda SEMPRE, pra qualquer alteração.
Acho que quando mencionei sobre a compilação com -w3 -es2 não chamei a atenção pra isso.

Imagine nesse caso acima, é um módulo com umas 15 opções de pesquisa diferentes, e a linha que apaguei era usada somente em uma determinada condição.
Eu iria demorar meses pra descobrir o que aconteceu.
Na compilação -w3 -es2 foi instantâneo, já mostrou no instante em que apaguei a linha.

É programar sem erros, mesmo errando.... rs
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
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

O programa git também ajuda a conferir as alterações.

Acabei de alterar na parte de cima de um jeito, e alterei a parte de baixo de outro.
alteracao.png
No fonte as coisas ficam longe, no git fica pertinho.
Dá pra conferir exatamente o que foi alterado.
Se o erro anterior passasse na compilação, talvez eu pegasse por aqui, porque ia mostrar que apaguei aquela linha.
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
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Reavaliando o post do ASimões:

Código: Selecionar todos

cCampos:=""
FOR EACH aCampos IN aTheDBF
    cCampos+=IF(aCampos:__enumIndex() > 1,Space(1),"")+cNomeCampo + ' ' + cDecode + IF(!aCampos:__enumIsLast(),",",")")+ IF(! aCampos:__enumIndex(),HB_EOL(),"")
NEXT
Sinceramente, não entendi o que ele faz, vamos por bloco.

Código: Selecionar todos

cCampos := ""
FOR EACH aCampos IN aTheDBF
    cCampos += ;
   IF(aCampos:__enumIndex() > 1, Space(1), "" ) + ;  // ok, só no primeiro não tem espaço, poderia ser AllTrim() fora do loop
   cNomeCampo + ;                                                 // de onde vém isso?
   ' ' + ;
   cDecode + ;                                                        // de onde vém isso?
   IF( ! aCampos:__enumIsLast(), ",", ")" ) + ;           // ok, no último é ")", nos demais ",", poderia trocar no final fora do loop
   IF( ! aCampos:__enumIndex(), HB_EOL(), "" )       // não sei pra que serve isto. Se __enumindex() é número, tá esquisito.
NEXT
Provavelmente era o começo da alteração, e o fonte ficou parcial.
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
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Práticas que facilitam programar Clipper/Harbour

Mensagem por JoséQuintas »

Uma pequena melhoria que uso nos GETs.
Uso um bloco alterado na GETSYS - a parte com by JPA

Código: Selecionar todos

   DO WHILE ! nPos == 0
      aVarGet := Array( Len( GetList ) )  // by JPA to otimize screen update
      FOR EACH oElement IN GetList        // by JPA to otimize screen update
         aVarGet[ oElement:__EnumIndex ] := oElement:VarGet()
      NEXT

      // GET NEXT GET from list and post it as the active GET
      PostActiveGet( oGet := GetList[ nPos ] )

      // Read the GET
      IF ( VALTYPE( oGet:reader ) == "B" )
         EVAL( oGet:reader, oGet )    // Use custom reader block
      ELSE
         GetReader( oGet, lIsMouse )            // Use standard reader
      ENDIF

      FOR EACH oElement IN GetList // by JPA to otimize screen update
         IF aVarGet[ oElement:__EnumIndex ] != oElement:VarGet()
            oElement:Display()
         ENDIF
      NEXT
      // Move to NEXT GET based on EXIT condition
      nPos := Settle( GetList, nPos )

   ENDDO
Nada demais, só atualiza a tela caso o conteúdo do GET tenha sido alterado.

Muito útil quando a digitação altera o conteúdo de outros GETs, porque na GETSYS normal isso só acontece se passar pelo GET.

Código: Selecionar todos

#include "hbclass.ch"
PROCEDURE Main

SetMode( 35, 100 )
SetColor( "W/B,N/W,,,W/B" )
CLS
Nota := NotaClass():New()
@ 1, 0 SAY "Valor da Nota:" GET Nota:Valor VALID Nota:CalculaImpostos()
@ 2, 0 SAY "Base ICMS....:" GET Nota:IcmBase WHEN .F.
@ 3, 0 SAY "Base Reducao.:" GET Nota:IcmReducao VALID Nota:CalculaImpostos()
@ 4, 0 SAY "Alíquota.....:" GET Nota:IcmAliquota VALID Nota:CalculaImpostos()
@ 5, 0 SAY "Valor ICMS...:" GET Nota:IcmValor WHEN .F.
@ 6, 0 SAY "Base ST......:" GET Nota:StBase WHEN .F.
@ 7, 0 SAY "IVA..........:" GET Nota:StIVA VALID Nota:CalculaImpostos()
@ 8, 0 SAY "Aliq.ST......:" GET Nota:StAliquota VALID Nota:CalculaImpostos()
@ 9, 0 SAY "Valor ST.....:" GET Nota:StValor WHEN .F.
READ

CREATE CLASS NotaClass
   VAR Valor       INIT 0
   VAR IcmBase     INIT 0
   VAR IcmReducao  INIT 0
   VAR IcmAliquota INIT 0
   VAR IcmValor    INIT 0
   VAR StBase      INIT 0
   VAR StIVA       INIT 0
   VAR StAliquota  INIT 0
   VAR StValor     INIT 0
   METHOD CalculaImpostos()
   END CLASS

METHOD CalculaImpostos()

   ::IcmBase := ::Valor - ( Int( ::Valor * ::IcmReducao ) / 100 )
   ::IcmValor := Int( ::IcmBase * ::IcmAliquota ) / 100
   ::StBase := ::IcmBase + ( Int( ::IcmBase * ::StIVA / 100 ) )
   ::StValor := Max( 0, Int( ::StBase * ::StAliquota ) / 100 - ::IcmValor )
   SetPos( 11, 0 )
   ? "Icmbase:", ::IcmBase, "STBase", ::StBase
   RETURN .T.
Sem alterar a getsys, valores errados na tela, ou necessidade de fonte adicional:

Código: Selecionar todos

Valor da Nota:        100
Base ICMS....:        100.00
Base Reducao.:         20
Alφquota.....:         10
Valor ICMS...:          8.00
Base ST......:         80.00
IVA..........:         50
Aliq.ST......:         10
Valor ST.....:          4.00


Icmbase:         80.00 STBase        120.00
Até lembrei das estorinhas de criança, que tinham o "moral da estória".
Acho que isso era algo do tipo: "use a cabeça e pense".

Qual o moral da estória aqui:
Problema resolvido de vez, sem complicar os fontes de trabalho.
Se é pra complicar, que seja pra simplificar.
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/
Responder