Browse com ADO

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

Moderador: Moderadores

cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Browse com ADO

Mensagem por cjp »

O que elas tem de diferente?
Ao que me parece, nada de especial.

A primeira, que quase sempre funciona, é chamada assim:

Código: Selecionar todos

consado("SELECT nrtarefa,assunto,prioridade,data,hora,tarefa FROM tarefas WHERE prioridade>0 AND soluc='N' AND (exibe='N' OR exibe='I') AND (now())>=hrexibe AND vinculo<>'MP' AND data>='"+dtsql(dtapart)+"' GROUP BY nrtarefa ORDER BY prioridade DESC,data,nrtarefa")
A segunda, que quase nunca funciona, está sendo chamada assim:

Código: Selecionar todos

         consado("select * from compras where codprod>0")
Chamadas por SET KEY, ou num prompt, ou misturadas com tbrowse?
Nenhuma delas está sendo chamada por SET KEY, só por prompt.
Lembro daquele fonte que precisou ajuda, onde misturava o tbrowse com rotina de menu.
Não é neste fonte que está dando problema não. É em outro, que eu já tinha feito antes, com base neste post.
Algo como MeuBrowse( linha, coluna, linha, coluna, { || FuncaoDeUsuario() } )
Preciso entender como fazer isso. Estou fazendo uma nova rotina, para não ter mais problema com o cursor, queria fazer já da forma correta.

A nova rotina que fiz está assim:

Código: Selecionar todos

function ADObrowse(sql)
         #include "tbrowse.ch"
         LOCAL oColumn, I, nLen, oTBrowse, oRs, nFieldLen
		 local nKey :=99999   //precisa ser private para o respsql
		 private conexao

	     @ 22,25 say "Abrindo consulta..."
		 
		 do while .t.
		    if !AdoConecta(nProvAtiv,5)
		       ?"Não conseguiu conectar; tente novamente mais tarde"
			   inkey(5)
			   return .f.
	        else
               oRS := Conexao:Execute( sql )
		    endif
	  
            if oRS:Eof()
	           @ 22,25 say "Não há nenhum item   "
		       inkey(11)
		       inkey(11)
	           return .f.
	        endif

            cls

            oTBrowse := TBrowseDB():new( 03, 3, MaxRow() - 5, 30 )

            oTBrowse:goTopBlock    := { || oRs:moveFirst() }
            oTBrowse:goBottomBlock := { || oRs:moveLast() }
            oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }
            oTBrowse:HeadSep       := Chr(196)
            oTBrowse:ColSep        := Chr(179)
            oTBrowse:FootSep       := ""
	  
            nLen := oRs:fields():count() - 1
	  
            FOR i := 0 TO nLen
                oColumn       := TBColumnNew( oRs:fields(i):name(), ADORecordSetFieldBlock( oRs, i ) )
		 
			    nFieldLen := 13
				
                oColumn:Width := Max( nFieldLen, Len( oRs:fields(i):name ) )
		 
                oTBrowse:addColumn( oColumn )
		 
            NEXT
			
			do while .t.
               oTBrowse:forceStable()
               oTBrowse:refreshCurrent()
	  
               nKey := Inkey(0)

	           set cursor on
	  
	           if nkey ==13 .and. procname(2)="CONSATIV" .and. ophrtar=5
	              ac1=oRs:Fields("acao"):Value
		          exit
               endif
	  
               IF oTBrowse:applyKey( nKey ) == TBR_EXIT
                  EXIT
               ENDIF
			enddo
			
			exit
			
         ENDDO

         oRs:Close()
         Conexao:Close()
return .t.
Por enquanto ela está servindo a apenas uma função, e está exibindo o cursor sem problema.

Vou precisar fazê-la para todas as demais funções. Qual é a melhor forma de fazer isso?
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Browse com ADO

Mensagem por JoséQuintas »

Problemas que vejo:

- Tá correndo o risco de travar é tudo, exagerando em abrir conexão
- Tá esquecendo de fechar o recordset
- Tá com o risco de erros com ADO, genérico demais, sem controle eficiente do ADO
- Tá genérico demais, sem controle eficiente do que faz browse
- Tem uma exceção com variável que pode ou não existir

Vamos por partes

- Fica trocando de servidor dentro do aplicativo toda hora? ou trata-se de testar um servidor de cada vez?
- O comando SQL pode ser alterado? Durante o browse?
- Seria interessante usar uma classe pra tratar erros
- Talvez seja mais interessante deixar o comando SQL fora do tbrowse, junto com uma lista de campos, e só usar desse jeito em testes
- Se possível usar compilação -w3 -es2, "talvez" ela te ajude a organizar melhor o fonte, pra acrescentar opções.
- Nem sempre economizar fonte é melhor, muitas vezes mais fonte pode ajudar, principalmente organizado por "assunto".

E, vamos falar de novo, sobre coisas que já falamos.

Vamos passo a passo, mas primeiro responda as duas primeiras questões, sobre servidor e comando SQL.
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

Browse com ADO

Mensagem por JoséQuintas »

Qual a parte realmente genérica nisso tudo? o browse.
A rotina de browse separada do resto

Código: Selecionar todos

   oTBrowse := TBrowseDB():new( 03, 3, MaxRow() - 5, 30 )
   oTBrowse:goTopBlock    := { || oRs:moveFirst() }
   oTBrowse:goBottomBlock := { || oRs:moveLast() }
   oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }
   oTBrowse:HeadSep       := Chr(196)
   oTBrowse:ColSep        := Chr(179)
   oTBrowse:FootSep       := ""
   nFieldCount := oRs:Fields():Count()
   FOR nCont := 0 TO nFieldCount - 1
      oColumn       := TBColumnNew( oRs:Fields( nCont ):name(), ADORecordSetFieldBlock( oRs, nCont ) )
      nFieldLen     := 13
      oColumn:Width := Max( nFieldLen, Len( oRs:Fields( nCont ):name ) )
      oTBrowse:addColumn( oColumn )
   NEXT
   DO WHILE .T.
      oTBrowse:forceStable()
      oTBrowse:refreshCurrent()
      nKey := Inkey(0)
      IF oTBrowse:applyKey( nKey ) == TBR_EXIT
         EXIT
      ENDIF
   ENDDO
O que altera entre um browse e outro?
Posições: encima, embaixo, direita, esquerda
O recordset oRs
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

Browse com ADO

Mensagem por JoséQuintas »

Olhe que legal, um browse genérico.

Código: Selecionar todos

FUNCTION BrowseADO( nTop, nLeft, nBottom, nRight, oRs )
   
   oTBrowse := TBrowseDB():new( nTop, nLeft, nBottom, nRight )
   oTBrowse:goTopBlock    := { || oRs:moveFirst() }
   oTBrowse:goBottomBlock := { || oRs:moveLast() }
   oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }
   oTBrowse:HeadSep       := Chr(196)
   oTBrowse:ColSep        := Chr(179)
   oTBrowse:FootSep       := ""
   nFieldCount := oRs:Fields():Count()
   FOR nCont := 0 TO nFieldCount - 1
      oColumn       := TBColumnNew( oRs:Fields( nCont ):name(), ADORecordSetFieldBlock( oRs, nCont ) )
      nFieldLen     := 13
      oColumn:Width := Max( nFieldLen, Len( oRs:Fields( nCont ):name ) )
      oTBrowse:addColumn( oColumn )
   NEXT
   DO WHILE .T.
      oTBrowse:forceStable()
      oTBrowse:refreshCurrent()
      nKey := Inkey(0)
      IF oTBrowse:applyKey( nKey ) == TBR_EXIT
         EXIT
      ENDIF
   ENDDO
   
   RETURN NIL
Mas.... você pode querer opções extras... então... vamos adicionar a função de usuário.
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

Browse com ADO

Mensagem por JoséQuintas »

Olhe, agora pode acrescentar uma função pra fazer o que quiser.

Código: Selecionar todos

FUNCTION BrowseADO( nTop, nLeft, nBottom, nRight, oRs, bFuncao )
   
   oTBrowse := TBrowseDB():new( nTop, nLeft, nBottom, nRight )
   oTBrowse:goTopBlock    := { || oRs:moveFirst() }
   oTBrowse:goBottomBlock := { || oRs:moveLast() }
   oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }
   oTBrowse:HeadSep       := Chr(196)
   oTBrowse:ColSep        := Chr(179)
   oTBrowse:FootSep       := ""
   nFieldCount := oRs:Fields():Count()
   FOR nCont := 0 TO nFieldCount - 1
      oColumn       := TBColumnNew( oRs:Fields( nCont ):name(), ADORecordSetFieldBlock( oRs, nCont ) )
      nFieldLen     := 13
      oColumn:Width := Max( nFieldLen, Len( oRs:Fields( nCont ):name ) )
      oTBrowse:addColumn( oColumn )
   NEXT
   DO WHILE .T.
      oTBrowse:forceStable()
      oTBrowse:refreshCurrent()
      nKey := Inkey(0)
      IF bFuncao != NIL
         Eval( bFuncao, oRs, oTBrowse )
      ENDIF
      IF oTBrowse:applyKey( nKey ) == TBR_EXIT
         EXIT
      ENDIF
   ENDDO
   
   RETURN NIL
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

Browse com ADO

Mensagem por JoséQuintas »

Se o recordset estiver vazio... vai dar erro... então é interessante testar se existe o que navegar.
Isso interessa ao browse.
Agora com seu IF de teste, mas com o acréscimo de testar se existe algum retorno, não apenas o Eof()

Código: Selecionar todos

FUNCTION BrowseADO( nTop, nLeft, nBottom, nRight, oRs, bFuncao )
   
   IF oRs == NIL .OR. oRS:Eof()
      @ 22,25 say "Não há nenhum item   "
      Inkey(11)
      RETURN .F.
   ENDIF
   oTBrowse := TBrowseDB():new( nTop, nLeft, nBottom, nRight )
   oTBrowse:goTopBlock    := { || oRs:moveFirst() }
   oTBrowse:goBottomBlock := { || oRs:moveLast() }
   oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }
   oTBrowse:HeadSep       := Chr(196)
   oTBrowse:ColSep        := Chr(179)
   oTBrowse:FootSep       := ""
   nFieldCount := oRs:Fields():Count()
   FOR nCont := 0 TO nFieldCount - 1
      oColumn       := TBColumnNew( oRs:Fields( nCont ):name(), ADORecordSetFieldBlock( oRs, nCont ) )
      nFieldLen     := 13
      oColumn:Width := Max( nFieldLen, Len( oRs:Fields( nCont ):name ) )
      oTBrowse:addColumn( oColumn )
   NEXT
   DO WHILE .T.
      oTBrowse:forceStable()
      oTBrowse:refreshCurrent()
      nKey := Inkey(0)
      IF bFuncao != NIL
         Eval( bFuncao, oRs, oTBrowse )
      ENDIF
      IF oTBrowse:applyKey( nKey ) == TBR_EXIT
         EXIT
      ENDIF
   ENDDO
   
   RETURN NIL
encerrado o browse genérico.
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

Browse com ADO

Mensagem por JoséQuintas »

Uma última alteração: vamos passar nKey pra função, assim poderemos atribuit K_ESC pra sair.

Código: Selecionar todos

      IF bFuncao != NIL
         Eval( bFuncao, oRs, oTBrowse, @nkey )
      ENDIF
E.... pra compilar com -w3 -es2, declarar as variáveis que são de uso local.

Código: Selecionar todos

#include "tbrowse.ch"
#include "inkey.ch"

FUNCTION BrowseADO( nTop, nLeft, nBottom, nRight, oRs, bFuncao )
   
   LOCAL nKey, oTBrowse, nFieldCount, nCont, nFieldLen
   
   IF oRs == NIL .OR. oRS:Eof()
      @ 22,25 say "Não há nenhum item   "
      Inkey(11)
      RETURN .F.
   ENDIF
   oTBrowse := TBrowseDB():new( nTop, nLeft, nBottom, nRight )
   oTBrowse:goTopBlock    := { || oRs:moveFirst() }
   oTBrowse:goBottomBlock := { || oRs:moveLast() }
   oTBrowse:skipBlock     := { | n | ADORecordSetSkipper( oRs, n ) }
   oTBrowse:HeadSep       := Chr(196)
   oTBrowse:ColSep        := Chr(179)
   oTBrowse:FootSep       := ""
   nFieldCount := oRs:Fields():Count()
   FOR nCont := 0 TO nFieldCount - 1
      oColumn       := TBColumnNew( oRs:Fields( nCont ):name(), ADORecordSetFieldBlock( oRs, nCont ) )
      nFieldLen     := 13
      oColumn:Width := Max( nFieldLen, Len( oRs:Fields( nCont ):name ) )
      oTBrowse:addColumn( oColumn )
   NEXT
   DO WHILE .T.
      oTBrowse:forceStable()
      oTBrowse:refreshCurrent()
      nKey := Inkey(0)
      IF bFuncao != NIL
         Eval( bFuncao, oRs, oTBrowse, @nkey )
      ENDIF
      IF oTBrowse:applyKey( nKey ) == TBR_EXIT
         EXIT
      ENDIF
   ENDDO
   
   RETURN NIL
Agora sim, parece que ficou bom.
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

Browse com ADO

Mensagem por JoséQuintas »

Agora a rotina geral, mas falta dizer sobre a conexão e sobre o comando SQL.

Código: Selecionar todos

#include "inkey.ch"

FUNCTION ADObrowse( SQL )

   LOCAL oColumn, I, nLen, oTBrowse, oRs, nFieldLen
   LOCAL nKey := 99999   //precisa ser private para o respsql
   PRIVATE conexao

   @ 22,25 SAY "Abrindo consulta..."

   DO WHILE .T.
      IF ! AdoConecta( nProvAtiv, 5 )
         ?"Não conseguiu conectar; tente novamente mais tarde"
         Inkey(5)
         RETURN .f.
      ELSE
         oRS := Conexao:Execute( sql )
      ENDIF
      CLS
      BrowseADO( 3, 3, MaxRow() - 5, 30, oRs, { || RotinaDaqui() } )
      EXIT

   ENDDO

   oRs:Close()
   Conexao:Close()

   RETURN .t.

STATIC FUNCTION RotinaDaqui( oRs, oTBrowse, nKey )

   IF nkey == K_ENTER .AND. ProcName(2) = "CONSATIV" .AND. ophrtar == 5
      ac1 = oRs:Fields( "acao" ):Value
      nKey := K_ESC
   ENDIF

   RETURN NIL
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

Browse com ADO

Mensagem por JoséQuintas »

Supondo que seja sempre a mesma conexão, a rotina principal fica assim:

Código: Selecionar todos

FUNCTION ADObrowse( SQL )

   LOCAL oColumn, I, nLen, oTBrowse, oRs, nFieldLen
   LOCAL nKey := 99999   //precisa ser private para o respsql
   PRIVATE conexao

   @ 22,25 SAY "Abrindo consulta..."
   IF ! ADOConecta( nProvAtiv, 5 )
      ? "Não conseguiu conectar; tente novamente mais tarde"
      Inkey(5)
      RETURN .f.
   ENDIF   

   DO WHILE .T.
      CLS
      oRS := Conexao:Execute( sql )
      BrowseADO( 3, 3, MaxRow() - 5, 30, oRs, { || RotinaDaqui() } )
      oRs:Close()
      EXIT
   ENDDO

   Conexao:Close()

   RETURN .T.
Não conectou... sai fora, pronto resolvida a questão.

pegou o recordset.... depois que não precisa mais pode fechar, pra jogar fora.

Abrir conexão no início e fechar no final... ainda é muito, mas tudo bem.
Ficar abrindo e fechando no Windows, pode travar placa de rede, internet, etc. , o ideal é reduzir ao máximo o abre/fecha de conexão.
Aqui abro a conexão quando o aplicativo abre, e fecho quando o aplicativo fecha.
Por enquanto não tenho uso via internet... e por enquanto desse jeito resolve.

Resultado:
- um browse genérico
- Uma rotina que executa o comando SQL e chama o browse

Talvez fosse melhor essa rotina receber o codeblock/função de usuário, já que a RotinaDaqui() parece não ter a ver com o restante.
Mas pra isso precisaria do tbrowse também..... aí precisaria de mais ajustes.
Aliás... é sair do browse com ENTER.... era só sair, nem precisava da função de usuário.
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

Browse com ADO

Mensagem por JoséQuintas »

Meu browse genérico tem mais opções, mas é bem parecido com esse.
Uma parte dele.

Código: Selecionar todos

FUNCTION BrowseADORC( nTop, nLeft, nBottom, nRight, cnSQL, oTBrowse, cFilterKey, bKeyboard, bUserFunction, nFixToCol, cAddFilter )

   LOCAL nKey := 0, oBrowse, bAction, nMRow, nMCol, cTimeLimit
   LOCAL cFilter := "", lAddFilter := .F.

   hb_Default( @cAddFilter, "" )
   IF ! Empty( cAddFilter )
      lAddFilter := .T.
      ADOFilter( cnSQL, cFilterkey, cFilter, cAddFilter )
   ENDIF
   oBrowse := TBrowseDb():New( nTop, nLeft, nBottom, nRight )
   oBrowse:HeadSep       := Chr(196)
   oBrowse:ColSep        := Chr(179)
   oBrowse:FootSep       := ""
   oBrowse:FrameColor    := "2/1"
   oBrowse:HeaderColor   := "7/8"
   oBrowse:GoTopBlock    := { || cnSQL:MoveFirst() }
   oBrowse:GoBottomBlock := { || cnSQL:MoveLast() }
   oBrowse:SkipBlock     := { | n | cnSQLBrowseSkipper( cnSQL, n ) }
   IF nFixToCol != NIL
      oBrowse:freeze := nFixToCol
   ENDIF
esse acima é pra casos como este, de pedidos
browse1.png
Já o outro, não tem tbrowse, usa o acima, apenas ele coloca visual e usa a tela completa.

Código: Selecionar todos

FUNCTION BrowseADO( cnSQL, oTBrowse, cFilterKey, bKeyboard, bUserFunction, nFixToCol, cAddFilter )

   LOCAL nTop := 5, nLeft := 0, nBottom := MaxRow() - 3, nRight := MaxCol(), cColorAnt := SetColor()
   LOCAL oFrm

   hb_Default( @cAddFilter, "" )
   IF cnSQL == NIL
      MsgStop( "Não há informações para serem mostradas" )
      RETURN NIL
   ENDIF
   SetColor( SetColorBox() )
   IF Len( appForms() ) > 0
      Atail( AppForms()):GuiHide()
   ENDIF
   oFrm := frmGuiClass():New()
   oFrm:lNavigate := .F.
   oFrm:cOptions  := "C"
   AAdd( oFrm:acMenuOptions, "<Ctrl-PgUp>Primeiro" )
   AAdd( oFrm:acMenuOptions, "<PgUp>Pág.Ant" )
   Aadd( oFrm:acMenuOptions, "<Up>Sobe" )
   AAdd( oFrm:acMenuOptions, "<Down>Desce" )
   AAdd( oFrm:acMenuOptions, "<PgDn>Pág.Seg" )
   AAdd( oFrm:acMenuOptions, "<Ctrl-PgDn>Último" )
browse2.png
O mesmo tbrowse atende os dois casos.
É o único tbrowse pra ADO do aplicativo inteiro.
Tenho outro, mas é pra DBF, se é que não é o que retirei a imagem acima... é que o resultado é o mesmo.
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/
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Browse com ADO

Mensagem por cjp »

Testei o teu modelo, mas o Enter não funcionou, não sai do browse.

Respondendo às tuas perguntas:
- Fica trocando de servidor dentro do aplicativo toda hora? ou trata-se de testar um servidor de cada vez?
Não é teste. Uso dois servidores ao mesmo tempo. Então, cada função chama um servidor diferente.
- O comando SQL pode ser alterado? Durante o browse?
Durante o browse não. O comando SQL é o mesmo para cada edição do browse. De um browse pra outro, aí sim, o comando SQL muda.
O que altera entre um browse e outro?
Se vc está falando entre uma função e outra que chama o browse, a mudança no browse é nas funções de usuário. Para uma função, a tecla Enter faz uma coisa; para outra, faz outra coisa. Para uma função, uso apenas o Enter e o Esc; para outra, uso várias teclas. E assim por diante.
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Browse com ADO

Mensagem por JoséQuintas »

cjp escreveu:Se vc está falando entre uma função e outra que chama o browse, a mudança no browse é nas funções de usuário. Para uma função, a tecla Enter faz uma coisa; para outra, faz outra coisa. Para uma função, uso apenas o Enter e o Esc; para outra, uso várias teclas. E assim por diante.
Tá, mas.... sempre que aperta a tecla, abandona o browse?
Porque se não for assim, é colocar na função de usuário.
Não precisa sair do browse pra executar outras coisas, a não ser que o browse realmente não interesse mais.
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/
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Browse com ADO

Mensagem por cjp »

No caso desta função que estou testando, o browse não interessa mais. Só quero pegar o valor do campo acao para ac1.
Em outras funções será diferente.
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Browse com ADO

Mensagem por JoséQuintas »

test.prg
(2.98 KiB) Baixado 386 vezes
Salve exatamente como está aí.

Detalhes importantes dos parâmetros:

nTop, nLeft, nBottom, nRight - são as coordenadas linha/coluna
oADO - é o recordset, a consulta
oTBrowse - isso vai ser novidade (pra você), pode achar mais trabalhoso, mas vai facilitar muita coisa
bKeyboard - se quiser que a rotina faça KEYBOARD da chave ao teclar ENTER
bUserFunction - função de usuário pra adicionar recursos

De um modo geral, não é nada diferente do tbrowse normal, apenas fica mais "padrão".
Usando ADO diretamente isso NÃO serve pra consulta vazia.

Exemplo de uso, atenção à ordem, NÃO dá pra criar o tbrowse sem ter o objecto Recordset primeiro

Código: Selecionar todos

oRs := conexao:Execute( "SELECT * FROM CLIENTES" )
oTbrowse := { ;
   { "CODIGO", { || Str( Rs:Fields( "CODIGO" ):Value, 5 ) } }, ;
   { "NOME",    { || Pad( Rs:Fields( "NOME" ):Value, 30 ) } }, ;
   { "ENDERECO", { || Pad( Rs:Fields( "ENDERECO" ):Value, 30 ) } } }
BrowseADO( 1, 1, 20, 78, oRs, oTBrowse )
oRs:Close()
Dá mais trabalho não ser automático? sim, mas tem controle total sobre as colunas.
Pode buscar mais campos do que mostra na tela, bom pra ter informação sem mostrar para o usuário.
Bom... esse é o primeiro, ESC ou ENTER sai fora.


Quer que o browse digite automaticamente alguma coisa.
Passe pra ele o codeblock que ele vai digitar.

{ || Ltrim( Str( rs:Fields( "CODIGO" ):Value ) ) }

Código: Selecionar todos

BrowseADO( 1, 1, 20, 78, oRs, oTBrowse, { || Ltrim( Str( rs:Fields( "CODIGO" ):Value ) ) } )

Quer que ele faça outras coisas, não apenas o normal: passe pra ele o codeblock da função

Código: Selecionar todos

BrowseADO( 1, 1, 20, 78, oRs, oTBrowse, , { || MinhaRotina() } )
A rotina vai receber o recordset, otbrowse e nkey - a tecla

Código: Selecionar todos

FUNCTION MinhaRotina( oRs, oTBrowse, nKey )
Nessa rotina, coloque o que quiser, vai estar com tudo na mão.

Código: Selecionar todos

FUNCTION MinhaRotina( oRs, oTBrowse, nKey )

DO CASE
CASE nKey == K_ENTER
   // mostra outra janela
CASE nKey == K_INS
   // inclui
CASE nKey == K_DEL
   IF MsgYesNo( "Quer excluir mesmo?" )
      Excluir( oRs:Fields( "CODIGO" ):Value )
   ENDIF
ENDCASE
RETURN NIL
Com o ADO diretamente vai ficar limitado.

Aqui tenho uma classe que junta tudo: conexao e recordset e até o comando usado pra retornar o recordset.
No caso de exclusão, por exemplo, eu refaço a pesquisa.
E acaba ficando disponível conexão e recordset ao mesmo tempo.
Posso fazer oADO:ExecuteCmd( "DELETE FROM ...." ) ou qualquer outra coisa.

No seu caso, vai ficar sem esse recurso, e só vai ter se sair do browse e reabrir.

Até poderia passar também a conexão por parâmetro, fazer nova consulta, trocar o recordset e invalidar o tbrowse, pra ele se remontar sozinho, também seria uma opção.

Então... basicamente esse é somente pra consulta.

Faltou:
Quer o tbrowse pra pegar um valor?
Mesmo inicial, apenas consulte o resultado, já que o recordset vai estar posicionado aonde teclaram ENTER.

Código: Selecionar todos

BrowseADO( 1, 1, 20, 78, oRs, oTBrowse )

IF LastKey() == K_ENTER
   nValor := oRs:Fields( "CODIGO" ):Value
ENDIF
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

Browse com ADO

Mensagem por JoséQuintas »

O que comentei é colocar algo do tipo:

Código: Selecionar todos

IF oTBrowse == NIL
   nLen := oRs:fields():count() - 1
   FOR nCont := 0 TO nLen
      oColumn       := TBColumnNew( oRs:fields(i):name(), ADORecordSetFieldBlock( oRs, i ) )
	nFieldLen := 13
	oColumn:Width := Max( nFieldLen, Len( oRs:fields(i):name ) )
	oTBrowse:addColumn( oColumn )   
   NEXT
ELSE
   FOR EACH oElement IN oTBrowse
      oThisColumn := tbColumnNew( oElement[ 1 ], oElement[ 2 ] )
      IF Len( oElement ) > 2
         oThisColumn:ColorBlock := oElement[ 3 ]
      ENDIF
      oBrowse:AddColumn( oThisColumn )
   NEXT
ENDIF
Desse jeito vai poder usar passando ou não aquele array pra tbrowse.
Volta a ter sua opção automática, além da opção "nova".
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