Clipper On Line • Ver Tópico - Browse com ADO

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

 

Browse com ADO

Mensagempor cjp » 08 Set 2020 22:48

O que elas tem de diferente?


Ao que me parece, nada de especial.

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

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:

         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:

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
cjp
Usuário Nível 5

Usuário Nível 5
 
Mensagens: 1162
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 8 vezes
Mens.Curtidas: 12 vezes

Browse com ADO

Mensagempor JoséQuintas » 08 Set 2020 23:39

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 08 Set 2020 23:55

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

   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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 08 Set 2020 23:58

Olhe que legal, um browse genérico.

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 09 Set 2020 00:00

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

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 09 Set 2020 00:03

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()

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 09 Set 2020 00:11

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

      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.

#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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 09 Set 2020 00:18

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

#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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 09 Set 2020 00:28

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

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 09 Set 2020 00:56

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

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.

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor cjp » 09 Set 2020 23:07

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
cjp
Usuário Nível 5

Usuário Nível 5
 
Mensagens: 1162
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 8 vezes
Mens.Curtidas: 12 vezes

Browse com ADO

Mensagempor JoséQuintas » 10 Set 2020 00:35

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor cjp » 10 Set 2020 01:36

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
cjp
Usuário Nível 5

Usuário Nível 5
 
Mensagens: 1162
Data de registro: 19 Nov 2010 21:29
Cidade/Estado: paraná
Curtiu: 8 vezes
Mens.Curtidas: 12 vezes

Browse com ADO

Mensagempor JoséQuintas » 10 Set 2020 21:43

test.prg
(2.98 KiB) Baixado 13 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

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 ) ) }

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

BrowseADO( 1, 1, 20, 78, oRs, oTBrowse, , { || MinhaRotina() } )


A rotina vai receber o recordset, otbrowse e nkey - a tecla

FUNCTION MinhaRotina( oRs, oTBrowse, nKey )


Nessa rotina, coloque o que quiser, vai estar com tudo na mão.

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.

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

IF LastKey() == K_ENTER
   nValor := oRs:Fields( "CODIGO" ):Value
ENDIF
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Browse com ADO

Mensagempor JoséQuintas » 10 Set 2020 21:54

O que comentei é colocar algo do tipo:

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.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 16145
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 918 vezes

Anterior Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 1 visitante


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro