Página 1 de 1

WITH OBJECT e codeblocks

Enviado: 07 Nov 2019 22:22
por JoséQuintas
Acabo de ter este problema.

Assim funciona:

Código: Selecionar todos

      cnMySql:cSql := "SELECT IDTRANSP, TPNOME, TPENDERECO, TPCIDADE, TPUF FROM JPTRANSP ORDER BY TPNOME"
      cnMySql:Execute()
      oTBrowse := { ;
         { "CODIGO",   { || StrZero( cnMySql:Number( "IDTRANSP" ), 6 ) } }, ;
         { "NOME",     { || cnMySql:String( "TPNOME", 30 ) } }, ;
         { "ENDERECO", { || cnMySql:String( "TPENDERECO", 30 ) } }, ;
         { "CIDADE",   { || cnMySql:String( "TPCIDADE", 21 ) } }, ;
         { "UF",       { || cnMySql:String( "TPUF", 2 ) } } }
   ADOBrowse( cnMySql, oTBrowse )
Mas assim não:

Código: Selecionar todos

   WITH OBJECT cnMySql
      :cSql := "SELECT IDTRANSP, TPNOME, TPENDERECO, TPCIDADE, TPUF FROM JPTRANSP ORDER BY TPNOME"
      :Execute()
      oTBrowse := { ;
         { "CODIGO",   { || StrZero( :Number( "IDTRANSP" ), 6 ) } }, ;
         { "NOME",     { || :String( "TPNOME", 30 ) } }, ;
         { "ENDERECO", { || :String( "TPENDERECO", 30 ) } }, ;
         { "CIDADE",   { || :String( "TPCIDADE", 21 ) } }, ;
         { "UF",       { || :String( "TPUF", 2 ) } } }
   ENDWITH
   ADOBrowse( cnMySql, oTBrowse )
É chato não poder tirar proveito do WITH OBJECT pra codeblocks.
Postei no Harbour users, mas não sei se pode ser alterado.

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 10:29
por asimoes
Quintas,
Onde ocorre o problema?

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 10:50
por JoséQuintas
Depois na hora de usar no tbrowse, dá erro de método não existente.

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 10:57
por asimoes
Fiz esse teste e para mim funcionou:

Código: Selecionar todos

  WITH OBJECT oTeste := ClTeste():New()
      :CODIGO := 1
      oTBrowse := { ;
                    { "CODIGO",   { || StrZero( :CODIGO, 6 ) } } ;
                  }
   END
   

CREATE CLASS ClTeste
     
   EXPORTED :
   
   VAR CODIGO AS INTEGER INIT 0
   
ENDCLASS   

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 11:12
por asimoes
Realmente tem um problema na execução com codeblock
assim funccionou:

Código: Selecionar todos

   WITH OBJECT oTeste := ClTeste():New()
      :CODIGO := 1
      oTBrowse := { ;
                    { "CODIGO",   { || StrZero( oTeste:CODIGO, 6 ) } } ;
                  }
   END
  
   FOR EACH oElemento IN oTBrowse
      otb := Eval( oElemento[2] )
   NEXT

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 11:37
por JoséQuintas
Normal ok.
browse1.png
com WITH OBJECT
browse2.png
browse2.png (10.42 KiB) Exibido 1288 vezes

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 11:56
por asimoes
Considera o nome da variável e não o seu conteúdo com WITH OBJECT

:CODIGO interpreta como nome de variável/método no CODEBLOCK, assim oTeste:CODIGO considera o valor

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 13:07
por JoséQuintas
Tentei simular o problema, mas num teste simples funciona.

Código: Selecionar todos

#include "hbclass.ch"

FUNCTION MAIN()

   LOCAL cnMySql := ADOClass():New( { 10, 20 } ), bCode

   CLS
   WITH OBJECT cnMySql
      bCode := { || cnMySql:Test( 1 ) }
      ? Test( bCode )
      bCode := { || :Test( 1 ) }
      ? Test( bCode )
   ENDWITH

   Inkey(0)

   RETURN NIL

CREATE CLASS ADOClass
   METHOD New( x ) INLINE ::Rs := x, SELF
   METHOD Test( nValue ) INLINE ::Rs[ nValue ]
   VAR Rs
   ENDCLASS

FUNCTION Test( bCode )

   RETURN Eval( bCode )

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 13:24
por JoséQuintas
Num mais complicado também.

Código: Selecionar todos

#include "hbclass.ch"

FUNCTION MAIN()

   LOCAL cnMySql := ADOClass():New(), oTBrowse

   CLS
   cnMySql:Execute()
   WITH OBJECT cnMySql
      oTBrowse := { ;
         { "test1", { || cnMySql:Test( 1 ) } }, ;
         { "Test2", { || cnMySql:Test( 2 ) } } }
   ENDWITH
   Test( cnMySql, oTBrowse )

   Inkey(0)

   RETURN NIL

CREATE CLASS ADOClass
   VAR Rs
   METHOD Test( nValue ) INLINE ::Rs[ nValue ]
   METHOD Execute() INLINE ::Rs := { 10, 20 }
   ENDCLASS

FUNCTION Test( cnMySql, oTBrowse )

   LOCAL aVar := {}, oElement

   FOR EACH oElement IN oTBrowse
      AAdd( aVar, { oElement[ 1 ], oElement[ 2 ] } )
   NEXT
   DoEval( aVar )
   HB_SYMBOL_UNUSED( cnMySql )

   RETURN NIL

FUNCTION DoEval( aVar )

   LOCAL oElement

   FOR EACH oElement IN aVar
      ? Eval( oElement[ 2 ] )
   NEXT

   RETURN NIL

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 13:26
por JoséQuintas
Correção: no mais complicado aconteceu o mesmo erro do ADO.

Código: Selecionar todos

#include "hbclass.ch"

FUNCTION MAIN()

   LOCAL cnMySql := ADOClass():New(), oTBrowse

   CLS
   cnMySql:Execute()
   WITH OBJECT cnMySql
      oTBrowse := { ;
         { "test1", { || :Test( 1 ) } }, ;
         { "Test2", { || :Test( 2 ) } } }
   ENDWITH
   Test( cnMySql, oTBrowse )

   Inkey(0)

   RETURN NIL

CREATE CLASS ADOClass
   VAR Rs
   METHOD Test( nValue ) INLINE ::Rs[ nValue ]
   METHOD Execute() INLINE ::Rs := { 10, 20 }
   ENDCLASS

FUNCTION Test( cnMySql, oTBrowse )

   LOCAL aVar := {}, oElement

   FOR EACH oElement IN oTBrowse
      AAdd( aVar, { oElement[ 1 ], oElement[ 2 ] } )
   NEXT
   DoEval( aVar )
   HB_SYMBOL_UNUSED( cnMySql )

   RETURN NIL

FUNCTION DoEval( aVar )

   LOCAL oElement

   FOR EACH oElement IN aVar
      ? Eval( oElement[ 2 ] )
   NEXT

   RETURN NIL
SYSTEM ERROR
Error BASE/1004 No exported method: TEST
Called from TEST(0)
Called from (b)MAIN(12)
Called from DOEVAL(43)
Called from TEST(33)
Called from MAIN(14)

WITH OBJECT e codeblocks

Enviado: 08 Nov 2019 15:07
por JoséQuintas
Resolvido, após comentários no harbour-users.

Pensei que WITH OBJECT era traduzido pelo pré-compilador, então não fazia diferença depois.

Mas é traduzido em run-time, como se fosse criada uma variável local (pointer) indicando a variável original.
Resultado: só existe entre WITH OBJECT/ENDWITH

Solução: chamar o tbrowse dentro do WITH OBJECT/ENDWITH

ao invés disto:

Código: Selecionar todos

   WITH OBJECT cnMySql
      oTBrowse := { ;
         { "test1", { || :Test( 1 ) } }, ;
         { "Test2", { || :Test( 2 ) } } }
   ENDWITH
   Test( cnMySql, oTBrowse )
]

usar isto:

Código: Selecionar todos

   WITH OBJECT cnMySql
      oTBrowse := { ;
         { "test1", { || :Test( 1 ) } }, ;
         { "Test2", { || :Test( 2 ) } } }
      Test( cnMySql, oTBrowse )
   ENDWITH