A compilação está dizendo que a variável está na função, mas não está sendo usada.
Se antes dava falta da variável, e agora diz que não está em uso.... provavelmente você apagou o que estava lá antes.
Realmente, eu tinha apagado para poder compilar meu sistema. Recoloquei.
Ainda deu dois erros na compilação, em obrowse e nkey (vide imagem anexa). Troquei obrowse por otbrowse e comentei nkey, para poder compilar. Compilou, mas deu o seguinte erro na execução (creio que pela falta de nkey, ou por eu ter colocado essa parte adicional no lugar errado), que não sei resolver:
Error BASE/1004 Método não exportado: STABLE
Posto a função da forma como está agora, para vc me corrigir se for possível:
Código: Selecionar todos
/*
Exibição das linhas de um Record set ADO usando TBrowseDB()
Alexandre Santos
Compilar: Hbmk2 tbado hbwin.hbc
*/
#pragma -w3
#pragma -es2
#include "tbrowse.ch"
#include "inkey.ch"
#include "setcurs.ch"
#include "hbgtinfo.ch"
#include "box.ch"
#include "set.ch"
#include "hbclass.ch"
REQUEST HB_CODEPAGE_PTISO
FUNCTION Tbrowseado(cSql)
LOCAL oRs, oTBrowse
LOCAL oCN :=ConexaoMySQL( "mysql.xxx.com.br", "xxx", "xxx", "xxx" )
local tela :=savescreen(0,0,maxrow(),maxcol())
Set( _SET_CODEPAGE, "PTISO" )
Set( _SET_EVENTMASK, INKEY_ALL + HB_INKEY_GTEVENT - INKEY_MOVE )
SET DATE BRITISH
* hb_gtInfo( HB_GTI_WINTITLE , "TBrowse colorBlock() com Acesso ao MySQL via ADO" )
* hb_gtInfo( HB_GTI_FONTNAME , "Lucida Console" )
SetColor( "W/B","N/W",,,"W/B" )
CLS
oCn:open()
DO WHILE .T.
@ 4, MaxRow() SAY Padr( "Obtendo informações...", 22 ) COLOR "W/W"
oRs := oCn:Execute( cSql )
SuperADO( oRs )
IF oRs == NIL .OR. oRs:Eof()
Hb_Alert( "Não foi possível obter dados para exibição",, "W+/B" )
EXIT
ENDIF
oTBrowse := { ;
{ "DATA", { || oRs:ToDate( "DATA" ) } }, ;
{ "HORA", { || oRs:ToString( "HORA", 8 ) } }, ;
{ "COMIDA", { || oRs:ToString( "COMIDA", 30 ) }, { | x | If( At( "TOTAL ", Upper( x ) ) > 0, { 5, 5 }, { 1, 2 } ) } }, ;
{ "QUANTIDADE", { || oRs:ToString( "QUANTIDADE", 20 ) } }, ;
{ "PONTOS", { || oRs:ToStr( "PONTOS", 6 ) } }, ;
{ "ID", { || oRs:ToStr( "ID", 6 ) } } }
tBrowseADO2( oRs, oTBrowse, { | oTBrowse, nKey | TestUser( oRs, oTBrowse, nkey ) } )
* tBrowseADO2( oRs, oTBrowse )
* IF Alert( "Fechar?", { " Não ", " Sim " }, "W+/N" ) == 2
oRs:Close()
EXIT
* ENDIF
* EXIT
ENDDO
oCn:close()
rest scre from tela
RETURN Nil
FUNCTION tBrowseADO2( oRs, oTBrowse, TestUser )
LOCAL oTbr, nKey, oColumn, aItem, nLen, I
oTbr := TBrowse():new( 02, 3, MaxRow() - 3, MaxCol() - 3 )
oTbr:headSep := Chr(196) + Chr(194) + Chr(196)
oTbr:colSep := " " + Chr(179) + " "
oTbr:footSep := Chr(196) + Chr(193) + Chr(196)
oTbr:goTopBlock := { || oRs:moveFirst() }
oTbr:goBottomBlock := { || oRs:moveLast() }
oTbr:skipBlock := { |n| ADORecordSetSkipper( oRs,n ) }
oTbr:colorSpec := "W/B,W+/N,N/W*,W+/R,R+/B,R/W*"
IF oTBrowse == Nil
// create TBColumn objects and add them to TBrowse object - zero based
nLen := oRs:fields():count() - 1
FOR i := 0 TO nLen
// add code block for individual columns of the record set
oColumn := TBColumnNew( oRs:fields(i):name(), ADORecordSetFieldBlock( oRs, i ) )
// Column widths. For some data types, definedSize returns -1...
oColumn:width := Max( Min( oRs:Fields(i):definedSize,50), Len( oRs:fields(i):name ) ) + 5
// Add new column to TBrowse
oTbr:addColumn( oColumn )
NEXT
ELSE
FOR EACH aItem IN oTBrowse
oColumn := TBColumnNew( aItem[1], aItem[2] )
IF Len( aItem ) > 2
oColumn:ColorBlock := aItem[3]
ENDIF
oTbr:AddColumn( oColumn )
NEXT
ENDIF
// border
DispBox( oTbr:nTop - 1, oTbr:nLeft - 1, oTbr:nBottom + 3, oTbr:nRight + 1, B_SINGLE )
DO WHILE .T.
IF oTbr:applyKey( nKey ) == TBR_EXIT
EXIT
ENDIF
IF TestUser != NIL
DO WHILE ! oTBrowse:Stable
oTBrowse:Stabilize()
ENDDO
Eval( TestUser, oTBrowse, oRs, nKey )
oTBrowse:RefreshAll()
ENDIF
*nKey := 0
oTbr:refreshCurrent()
DO WHILE ! oTbr:Stable()
oTbr:Stabilize()
ENDDO
// Paint TBrowse current line...
//oTbr:ColorRect( { oTbr:RowPos, oTbr:LeftVisible, oTbr:RowPos, oTbr:RightVisible }, { 2, 1 } )
@ MaxRow() - 1, 3 SAY Padr( " Registro " + Ltrim( Str( oRs:AbsolutePosition ) ) + " de " + Ltrim( Str( oRs:recordCount ) ) + " ", 20 ) COLOR "N/W"
nKey := Inkey(0)
IF oTbr:applyKey( nKey ) == TBR_EXIT
EXIT
ENDIF
ENDDO
RETURN Nil
STATIC FUNCTION ADORecordSetFieldBlock( oRs, i, xVal )
LOCAL bRet
IF xVal == NIL
IF oRs:Eof()
bRet := { || Space( Max( oRs:Fields( i ):DefinedSize , Len( oRs:Fields( i ):name ) ) ) }
ELSE
bRet := { || oRs:Fields( i ):value }
ENDIF
ELSE
bRet := { |xVal| oRs:Fields( i ):Value := xVal }
ENDIF
RETURN bRet
STATIC FUNCTION ADORecordSetSkipper(oRecordSet,nSkip)
LOCAL nRec := oRecordSet:AbsolutePosition
IF ! ( oRecordSet:eof )
oRecordSet:Move( nSkip )
IF oRecordSet:eof
oRecordSet:moveLast()
ENDIF
IF oRecordSet:bof
oRecordSet:moveFirst()
ENDIF
ENDIF
RETURN (oRecordSet:AbsolutePosition - nRec)
STATIC FUNCTION ConexaoMySQL( cServer, cDatabase, cUser, cPassword )
LOCAL oCn := win_OleCreateObject("ADODB.Connection")
oCn:ConnectionString := "DRIVER={MariaDB ODBC 3.1 Driver};TCPIP=1;SERVER=" + ;
cServer + ";Database=" + cDatabase + ";UID=" + cUser + ";PWD=" + cPassword + ";PORT=3306"
oCn:CursorLocation := 3
RETURN oCn
FUNCTION SuperADO( oRs )
__ObjAddMethod( oRs, "TOSTRING", @ADOToString() )
__ObjAddMethod( oRs, "TONUMBER", @ADOToNumber() )
__ObjAddMethod( oRs, "TODATE", @ADOToDate() )
__ObjAddMethod( oRs, "TOSTR", @ADOToStr() )
RETURN Nil
STATIC FUNCTION ADOToDate( cField )
LOCAL x, Self := QSelf()
x := ::Fields( cField ):Value
IF ValType( x ) != "D"
x := Ctod("")
ENDIF
RETURN x
STATIC FUNCTION ADOToString( cField, nLen )
LOCAL x, Self := QSelf()
x := ::Fields( cField ):Value
IF ValType( x ) != "C"
x := ""
ENDIF
IF nLen != Nil
x := Pad( x, nLen )
ENDIF
RETURN x
STATIC FUNCTION ADOToNumber( cField )
LOCAL x, Self := QSelf()
x := ::Fields( cField ):Value
IF ValType( x ) != "N"
x := 0
ENDIF
RETURN x
STATIC FUNCTION ADOToStr( cField, nLen, nDec )
LOCAL x, Self := QSelf()
x := ::Fields( cField ):Value
IF ValType( x ) != "N"
x := 0
ENDIF
IF nLen == Nil
x := Str( x )
ELSEIF nDec == Nil
x := Str( x, nLen )
ELSE
x := Str( x, nLen, nDec )
ENDIF
RETURN x
STATIC FUNCTION TestUser( oRs, oTBrowse, nKey )
IF nKey == K_F5
Alert( "Foi teclado F5" )
Alert( oRs:ToString( "COMIDA" ) )
oTBrowse:RefreshAll()
ENDIF
RETURN 1
Eu também demorei pra entender codeblock.
Considere que é uma função sem nome.
{ | a, b | a * b }
Isso seria meio equivalente a:
Expandir visualizacaoVer codigo
1 FUNCTION SemNome( a, b )
2 RETURN a * b
3
É como se estivesse criando uma função sem nome, o próprio codeblock vai ser a função.
Entendi esta parte. Pela primeira vez eu vejo uma explicação simples sobre codeblock.
Acho incrível esta dúvida ainda estar rodando em círculos desde 22/07/2021... e sem progresso. Acho que só alguém conectando aí e fazendo pra você...
Disse que comprou o livro... por que não o lê? Ensina quase tudo sobre code blocks. Não são os programadores que chamam de code block. É a linguagem que define este nome. Se tivesse estudado, já saberia pelo menos o formato de um code block...
Postei um exemplo simples e funcional, que depois foi completamente descaracterizado e transformado em algo mais complexo. Você adotou a segunda opção. Ora, se não consegue entender as coisas mais simples, por que escolher as mais complicadas? Quando postei meu exemplo, ainda escrevi: "Segue o código. Estude, adapte à tua necessidade e informe se funcionou.". Se você continuar no chute, colando código pra ver se funciona, vai ser difícil... a solução é estudar.
Code blocks realmente são bem abstratos, difíceis de entender se não estudar. Sugiro que você estude o assunto e faça um tutorial do uso e depois poste no fórum para ajudar quem ainda não entende do assunto.
Espero que não se importe com a crítica pois ela é construtiva e tem a intenção de te ajudar a mudar o teu patamar de conhecimento e passar de alguém que depende de uma "muleta" chamada fórum e passar a ajudar os que conhecem um pouco menos.
Comprei o livro, e estou lendo. Mas o livro tem 334 páginas. Gostaria muito de lê-lo num só dia (já foi tempo em que eu cheguei a ler livros desse tamanho num só dia), mas infelizmente meu trabalho não me permite. Não sou profissional da área da informática. Só consigo mexer nisso esta hora (meia noite em diante). Então, infelizmente, vou levar muitos dias, talvez meses, para terminar de ler o livro.
E não creio que apenas lendo o livro eu vá conseguir entender tudo de code block e tbrowse, a ponto de não precisar mais de ajuda e começar a ajudar os outros nessa área. Até chegar a esse ponto, creio que ainda vou precisar de muita ajuda.
O exemplo que vc postou funcionou bem, mas, ao colocar no meu sistema (que está realmente muito confuso), não funcionou.
Aceito sua crítica e te entendo. Não quero incomodar ninguém. Mas acho que o espírito do fórum é este: quem sabe mais ajuda quem está aprendendo. Não quero que ninguém faça pra mim, quero aprender. Mas é difícil aprender coisa difícil assim sem ajuda. Então, sigo contando com a vossa ajuda. Se não puderem me ajudar, compreendo, paciência.