Página 1 de 8

Browse com ADO

Enviado: 26 Nov 2019 13:07
por JoséQuintas
A origem é deste post, do Alexandre Santos (AlxSts)

https://pctoledo.org/forum/viewto ... sql+server

Como está na resposta de outra coisa, talvez fique difícil de ser localizado o browse para ADO.
Aqui fiz algumas mudanças.
É um browse simples, sem qualquer tipo de filtro ou opção especial.
Só usar um browse de DBFs como referência, e adicionar recursos.

Para o recordset, usei o nome de oTemporario, fica claro pra quem não usa ADO, o que ele representa.

Código: Selecionar todos

#include "tbrowse.ch"

PROCEDURE Main

 LOCAL oConexao, oTemporario, oTBrowse

 oConexao := ConexaoMySql()
 oConexao:Open()
 oTemporario := oConexao:Execute( "SELECT CODIGO, NOME, ENDERECO FROM CLIENTES ORDER BY NOME" )
 oTBrowse := { ;
   { "CODIGO", { || Pad( oTemporario:Fields( "CODIGO" ):Value, 10 ) } }, ;
   { "NOME",  { || Pad( oTemporario:Fields( "NOME" ):Value, 30 ) } }, ;
   { "ENDERECO", { || Pad( oTemporario:Fields( "ENDERECO" ):Value, 30 ) } } }
 BrowseADO( oTemporario, oTBrowse )

 oTemporario:Close()
 oConexao:Close()
 RETURN

FUNCTION BrowseADO( oTemporario, oTBrowse )

 LOCAL oBrowse, nKey, oElement

 oBrowse := TBrowseDB():new( 04, 3, MaxRow() - 7, MaxCol() - 3 )

 oBrowse:goTopBlock  := { || oTemporario:moveFirst() }
 oBrowse:goBottomBlock := { || oTemporario:moveLast() }
 oBrowse:skipBlock  := { | n | ADOSkipper( oTemporario, n ) }

 FOR EACH oElement IN oTBrowse
   oBrowse:AddColumn( TBColumnNew( oElement[ 1 ], oElement[ 2 ] ) )
 NEXT

 DO WHILE .T.
   oBrowse:forceStable()
   oBrowse:ColorRect( { oBrowse:RowPos, oBrowse:LeftVisible, oBrowse:RowPos, oBrowse:RightVisible }, { 2, 1 } )
   oBrowse:ColorRect( { oBrowse:RowPos, oBrowse:ColPos, oBrowse:RowPos, oBrowse:ColPos }, { 3, 2 } )
   oBrowse:refreshCurrent()
   nKey := Inkey(0)
   DO CASE
   CASE oBrowse:ApplyKey( nKey ) == TBR_EXIT
    EXIT
   ENDCASE
 ENDDO

 RETURN NIL

STATIC FUNCTION ADOSkipper( oTemporario, nSkip )

 LOCAL nRec := oTemporario:AbsolutePosition

 IF ! ( oTemporario:Eof )
   oTemporario:Move( nSkip )
   IF oTemporario:Eof
    oTemporario:moveLast()
   ENDIF
   IF oTemporario:Bof
    oTemporario:moveFirst()
   ENDIF
 ENDIF

 RETURN oTemporario:AbsolutePosition - nRec

FUNCTION ConexaoMySql()

 LOCAL oConexao := win_OleCreateObject( "ADODB.Connection" )

 oConexao:ConnectionString := "colocar_a_string"
 oConexao:CursorLocation := 3 // adUseClient
 oConexao:CommandTimeOut := 600
 oConexao:ConnectionTimeOut := 600
 RETURN oConexao
Provavelmente vão querer adicionar opções de:
codeblock a executar, filtrar colunas, cores no tbrowse, navegação por mouse, filtro enquanto digita, etc, mas de um modo geral isso pode ser encontrado em qualquer browse de DBF.

Browse com ADO

Enviado: 26 Nov 2019 13:13
por JoséQuintas
Pra que serve esse browse:

pode ser planilha Excel, Access, MySQL, SQL Server, Firebird, Oracle, e qualquer coisa que possua ODBC disponível.

Browse com ADO

Enviado: 26 Nov 2019 19:46
por JoséQuintas
Tem uma coisa interessante nesse browse:

Código: Selecionar todos

CASE oBrowse:ApplyKey( nKey ) == TBR_EXIT
Substitui tudo isto, ou pelo menos a parte padrão.

Código: Selecionar todos

      CASE nkey == K_CTRL_PGDN ;  oBrowse:GoBottom() ; LOOP
      CASE nkey == K_CTRL_PGUP ;  oBrowse:GoTop() ;    LOOP
      CASE nkey == K_DOWN ;       oBrowse:Down()    ;  LOOP
      CASE nkey == K_HOME ;       oBrowse:GoTop() ;    LOOP
      CASE nkey == K_END ;        oBrowse:GoBottom() ; LOOP
      CASE nkey == K_LEFT ;       oBrowse:Left() ;     LOOP
      CASE nkey == K_RIGHT ;      oBrowse:Right() ;    LOOP
      CASE nkey == K_PGDN ;       oBrowse:PageDown() ; LOOP
      CASE nkey == K_PGUP ;       oBrowse:PageUp() ;   LOOP
      CASE nkey == K_UP ;         oBrowse:Up() ;       LOOP
      CASE nKey == K_ESC;   EXIT
Acaba deixando a rotina de browse mais enxuta.
Não sei se alguém reparou nisso.
É o que digo sempre: todo fonte pode ter dicas interessantes, é sempre bom olhar com atenção.

Browse com ADO

Enviado: 27 Nov 2019 12:49
por JoséQuintas
Nota: editei o fonte anterior, estava com um erro no BrowseADO(), pra não gerar problemas depois.

Aqui um exemplo completo, que basta compilar.

Código: Selecionar todos

#include "tbrowse.ch"
#include "directry.ch"
#define AD_BIGINT   20
#define AD_DATE     7
#define AD_VARCHAR  200

PROCEDURE Main

   LOCAL oTemporario, oTBrowse, oFile, aList

   SetMode( 40, 100 )
   SetCOlor( "W/B","N/w",,,"W/B" )
   CLS
   // cria estrutura
   oTemporario := win_OleCreateObject( "ADODB.Recordset" )
   WITH OBJECT oTemporario:Fields
      :Append( "NOME", AD_VARCHAR, 100 )
      :Append( "TAMANHO", AD_BIGINT, 11 )
      :Append( "DATA", AD_DATE )
      :Append( "HORA", AD_VARCHAR, 8 )
   ENDWITH
   // grava informação
   WITH OBJECT oTemporario
      :Open()
      aList := Directory( "*.*" )
      FOR EACH oFile IN aList
         :AddNew()
         :Fields( "NOME" ):Value := oFile[ F_NAME ]
         :Fields( "TAMANHO" ):Value := oFile[ F_SIZE ]
         :Fields( "DATA" ):Value := oFile[ F_DATE ]
         :Fields( "HORA" ):Value := oFile[ F_TIME ]
         :Update()
      NEXT
   ENDWITH
   oTemporario:MoveFirst()

   oTBrowse := { ;
      { "NOME",     { || Pad( oTemporario:Fields( "NOME" ):Value, 20 ) } }, ;
      { "TAMANHO",  { || Str( oTemporario:Fields( "TAMANHO" ):Value, 20 ) } }, ;
      { "DATA",     { || oTemporario:Fields( "DATA" ):Value } }, ;
      { "HORA",     { || oTemporario:Fields( "HORA" ):Value } } }
   BrowseADO( oTemporario, oTBrowse )

   oTemporario:Close()

   RETURN

FUNCTION BrowseADO( oTemporario, oTBrowse )

   LOCAL oBrowse, nKey, oElement

   oBrowse := TBrowseDB():new( 04, 3, MaxRow() - 7, MaxCol() - 3 )

   oBrowse:goTopBlock  := { || oTemporario:moveFirst() }
   oBrowse:goBottomBlock := { || oTemporario:moveLast() }
   oBrowse:skipBlock  := { | n | ADOSkipper( oTemporario, n ) }

   FOR EACH oElement IN oTBrowse
      oBrowse:AddColumn( TBColumnNew( oElement[ 1 ], oElement[ 2 ] ) )
   NEXT

   DO WHILE .T.
      oBrowse:forceStable()
//      oBrowse:ColorRect( { oBrowse:RowPos, oBrowse:LeftVisible, oBrowse:RowPos, oBrowse:RightVisible }, { 2, 1 } )
//      oBrowse:ColorRect( { oBrowse:RowPos, oBrowse:ColPos, oBrowse:RowPos, oBrowse:ColPos }, { 3, 2 } )
//      oBrowse:refreshCurrent()
      nKey := Inkey(0)
      DO CASE
      CASE oBrowse:ApplyKey( nKey ) == TBR_EXIT
         EXIT
      ENDCASE
   ENDDO

   RETURN NIL

STATIC FUNCTION ADOSkipper( oTemporario, nSkip )

   LOCAL nRec := oTemporario:AbsolutePosition

   IF ! ( oTemporario:Eof )
      oTemporario:Move( nSkip )
      IF oTemporario:Eof
         oTemporario:moveLast()
      ENDIF
      IF oTemporario:Bof
         oTemporario:moveFirst()
      ENDIF
   ENDIF

   RETURN oTemporario:AbsolutePosition - nRec
test1.png
test2.png

Browse com ADO

Enviado: 27 Nov 2019 13:06
por JoséQuintas
Faltou acrescentar:

Como dá pra perceber, dá pra usar ADO pra temporários também.
Gostei tanto do browse com ADO, que comecei a usar em outras situações.
Não precisa arquivo em disco, e o Windows se vira com isso.

Quando virar programa gráfico... só usar algum grid/browse equivalente pra ADO...

Pra usar MySQL ou SQL Server ou outro.... não precisa criar nem gravar no temporário, vém pronto do MySQL ou outro.

Algo mais legal ainda:
NÃO vou usar, mas..... no VB6 tem o Crystal Reports e o outro da Microsoft, pra gerar relatórios a partir do recordset ADO.
Poderia ter relatórios automáticos a partir desses recordsets !!!
Ou talvez NET mesmo, já que é grátis... quem sabe....

Browse com ADO

Enviado: 05 Dez 2019 12:53
por JoséQuintas
Esse negócio do browse ADO tá muito legal.

Imaginem substituir tudo que é Achoice()* por esse browse.....

Se pesquisar pela inicial já era interessante.... filtrar por qualquer texto é muito melhor...

E fica tudo padronizado, pro usuário ficar craque nisso.... ou sentir falta do recurso, se trocar de aplicativo... rs

Browse com ADO

Enviado: 15 Dez 2019 00:35
por cjp
Por favor, preciso de ajuda neste Browse com ADO, com um pequeno detalhe:

Meu código:

Código: Selecionar todos

      oTBrowse := TBrowseDB():new( 05, 3, MaxRow() - 7, MaxCol() - 2 )

      oTBrowse:goTopBlock    := { || oRs:moveFirst() }
      oTBrowse:goBottomBlock := { || oRs:moveLast() }
      oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }

      nLen := oRs:fields():count() - 1
      FOR i := 0 TO nLen
         oColumn       := TBColumnNew( oRs:fields(i):name(), ADORecordSetFieldBlock( oRs, i ) )
         oColumn:width := Max( Min( oRs:Fields(i):definedSize,50), Len( oRs:fields(i):name ) )
         oTBrowse:addColumn( oColumn )
      NEXT
Só preciso alterar uma pequena coisa: alterar o campo data (primeiro campo), que não está aparecendo completo. Imagino que o problema seja nesta linha:

Código: Selecionar todos

         oColumn:width := Max( Min( oRs:Fields(i):definedSize,50), Len( oRs:fields(i):name ) )
Mas não sei como alterá-la para corrigir este problema.

Podem me ajudar?

Browse com ADO

Enviado: 15 Dez 2019 11:24
por JoséQuintas
O Browse deste post não tem esse problema.

A saída pra esse outro é ir ajustando conforme a necessidade.
Exemplo:

Código: Selecionar todos

IF ValType( oRs:Fields(i):Value ) != "D"
   nFieldLen := Min( oRs:Fields(I):DefinedSize, 50 )
   oColumn:Width := Max( nFieldLen, Len( oRs:fields(i):name ) )
ENDIF
ou

Código: Selecionar todos

IF ValType( oRs:Fields(i):Value ) == "D"
   nFieldLen := Len( Dtoc( Date() ) )
ELSE
   nFieldLen := Min( oRs:Fields(I):DefinedSize, 50 )
ENDIF
oColumn:Width := Max( nFieldLen, Len( oRs:fields(i):name ) )

Browse com ADO

Enviado: 15 Dez 2019 14:56
por cjp
Resolveu, muito obrigado.

Browse com ADO

Enviado: 16 Dez 2019 16:23
por cjp
Teria como colocar divisores entre as colunas, como no velho browse()?

Browse com ADO

Enviado: 16 Dez 2019 23:13
por JoséQuintas
Sim, é só usar as variáveis que existem no tbrowse pra isso.

Código: Selecionar todos

   oBrowse:HeadSep       := Chr(196)
   oBrowse:ColSep        := Chr(179)
   oBrowse:FootSep       := ""

Browse com ADO

Enviado: 17 Dez 2019 00:53
por cjp
Deu certo, muito obrigado.

Browse com ADO

Enviado: 18 Dez 2019 23:29
por cjp
Estou tentando expandir meu uso desse browse, e surgiram duas necessidades:

1) como faço para mostrar no browse apenas alguns campos, não todos?

2) como faço para editar um registro? Na verdade só preciso ler o registro inteiro, não quero alterá-lo.

Browse com ADO

Enviado: 19 Dez 2019 14:39
por JoséQuintas
cjp escreveu:1) como faço para mostrar no browse apenas alguns campos, não todos?
Caso não tenha percebido, o browse deste post é pra isso.
cjp escreveu:2) como faço para editar um registro? Na verdade só preciso ler o registro inteiro, não quero alterá-lo.
Acho que quer ter acesso ao registro atual.
Como o recordset fica na variável, é só usar a variável.

Browse com ADO

Enviado: 21 Dez 2019 00:55
por cjp
Desculpe, eu não fui claro antes.

Eu preciso editar um campo, mas o problema é saber qual é o campo escolhido pelo usuário para isso.

No velho dbedit(), usava modo e coluna para isso. No tbrowse tem algo semelhante?