Página 1 de 1

tbrowse: atualização da tela

Enviado: 06 Out 2021 12:56
por cjp
Por favor, como faço para atualizar da tela do tbrowse após teclar alguma coisa na função de usuário?
Explico melhor: queria que, quando o usuário teclasse determinadas teclas, depois de feita a alteração correspondente, o browse voltasse atualizado; sem fechar o browse.
Exemplo: digamos que o usuário tecle Alt-A, para alterar o conteúdo de algum registro. Depois de feita a alteração, queria já exibir no browse essa alteração.
Atualmente, não está exibindo. Mas está alterando corretamente. Se eu fechar e reabrir o browse, volta atualizado. Mas eu queria que ele já voltasse atualizado sem precisar fechar e reabrir, entende?
Segue meu código atual:

Código: Selecionar todos

FUNCTION browseitem(cSql)
   LOCAL oRs, aCamposList
   LOCAL oCN :=ConexaoMySQL( "...", "...", "...", "..." )
*   local tela :=savescreen(0,0,maxrow(),maxcol())

   CLS

   oCn:open()

   DO WHILE .T.
      @ 5,5 SAY Padr( "Obtendo informações...", 22 ) 
      oRs := oCn:Execute( cSql )
      IF oRs == NIL
         Hb_Alert( "Não foi possível obter dados para exibição",, "W+/B" )
		 exit
	  Endif
	  IF oRs:Eof()
	     @ 5,5 clear to 5,25
         Hb_Alert( "Não há dados para exibição",, "W+/B" )
         EXIT
      ENDIF

	  if us="I"
         aCamposList := { ;
         { "DATA_RESPOSTA", { || oRs:ToString( "DATA_RESPOSTA", 11 ) } }, ;
         { "HORA_RESPOSTA", { || oRs:ToString( "HORA_RESPOSTA", 8 ) } }, ;
         { "TEMPO_USADO", { || oRs:ToString( "TEMPO_USADO", 6 )  } }, ;
         { "NR_PONTOS", { || oRs:ToString( "NR_PONTOS", 6 )  } }, ;
         { "TEMPO_PAGO", { || oRs:ToString( "TEMPO_PAGO", 6 )  } }, ;
         { "ATIVIDADE",       { || oRs:ToString( "ATIVIDADE", 60 ) } } }
	  else
         aCamposList := { ;
         { "DATA_RESPOSTA", { || oRs:ToString( "DATA_RESPOSTA", 11 ) } }, ;
         { "HORA_RESPOSTA", { || oRs:ToString( "HORA_RESPOSTA", 8 ) } }, ;
         { "ATIVIDADE",       { || oRs:ToString( "ATIVIDADE", 60 ) } } }
	  endif

        set color to w/r
 		cls
        DispBox( 0, (maxcol()-41)/2, 5, ((maxcol()-41)/2)+44, Nil, "GR+/N" )
     	@ 1,((maxcol()-41)/2)+1 say "Item: "+cArqAtiv+if(us="I","  Cadastrado por: "+alltrim(inc),"")
		@ 2,((maxcol()-41)/2)+1 say "Assunto: "+cAssAtiv
        if us="I"		
		   @ 3,((maxcol()-41)/2)+1 say "Data do cadastro: "+dtoc(dtinclu)+" às "+hrinc
		   @ 4,((maxcol()-41)/2)+1 say "Prioridade: "+alltrim(str(nPrior))
        endif		
		
        @ 6,0 to maxrow(),maxcol() double
		
        @ maxrow()-4,1 say "Tempo máximo para este item: "+alltrim(str(int(te)))+" minutos"
		inkey(.1)
        @ maxrow()-2,1 say "R:responder;B:atualiza;setas:sobe e desce;L:localiza texto"+if(us="I" .or. us="U" .or. us="K" .or. us="M" .or. us="S",";Alt-P:ped.preferência","")+if(us="I",";Ç:na presença;H:hora-exibe;S:adia por 1 semana;X:adia por X dias","")
		if us="I"
		   @ maxrow()-1,1 say "CTRL-P:alt.prioridade;Alt-A:alt.assunto;Alt-G:alt.dtcarga;E:restaurar"
		endif
	  
		 
      tBrowseADO( oRs, aCamposList, { | oBrowse, nKey | RotinaUsuarioItem( oRs, oBrowse, nkey ) } )
	  
      oRs:Close()
      EXIT
   ENDDO
   oCn:close()
   cls

RETURN Nil

STATIC FUNCTION RotinaUsuarioItem( oRs, oBrowse, nKey )
       local nPt, dDt, cHr, cCom, cQuant
	   local cod :=oRs:Fields("id"):Value

	   If (upper(chr(nkey)) =="R" .or. ((us="U" .or. us="I") .and. nkey==275))
	      if nkey=275
		     nTecla2=275
		  endif
		  chmfunc("respsql",,"S")
		  keyb chr(27)
	  
	  elseif nkey==288 .and. us="I" //Alt-D
		     @ maxrow()-5,1 clear to maxrow()-1,maxcol()-1
			 conf="N"
			 @ maxrow()-3,1 say "Apagar o seguinte registro:"
			 @ maxrow()-2,1 say oRs:Fields("atividade"):Value
			 @ maxrow()-1,20 say "Confirma?"get conf pict "@!"
			 read
			 if conf="S"
			    nrc=oRs:Fields("id"):Value
	            if !exqado("DELETE FROM tarefas WHERE id="+alltrim(str(nrc)),nProvTar) //nrtarefa='"+cArqAtiv+"' AND tarefa='"+tardelreg+"' AND data='"+alltrim(str(year(dt)))+"-"+substr(dtoc(dt),4,2)+"-"+substr(dtoc(dt),1,2)+"' AND hora='"+hr+"'")
			  	   ?"Não apagou"
				   inkey(5)
			    endif
			 endif   
				
	  elseif nkey==281  //Alt-P
		     chmfunc("novacadprefproc",cArqAtiv,"S")

	  elseif nkey==286 //Alt-A
		     chmfunc("novaaltassunto",,"S")

			 
       ENDIF
RETURN 1   

FUNCTION TBrowseADO( oRs, aCamposList, bExecutaRotinaUsuario )
   LOCAL oBrowse, nKey

   SuperADO( oRs )
   
   oBrowse := CriaBrowse( oRs, aCamposList )

   if procname(1)#"BROWSEITEM"
      DispBox( oBrowse:nTop - 1, oBrowse:nLeft - 1, oBrowse:nBottom + 3, oBrowse:nRight + 1, B_SINGLE )
   endif

   DO WHILE .T.
      oBrowse:refreshCurrent()
      DO WHILE ! oBrowse:Stable()
         oBrowse:Stabilize()
      ENDDO
      // Paint TBrowse current line...
      //oBrowse:ColorRect( { oBrowse:RowPos, oBrowse:LeftVisible, oBrowse:RowPos, oBrowse: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 oBrowse:applyKey( nKey ) == TBR_EXIT
         EXIT
      ENDIF
      IF bExecutaRotinaUsuario != NIL
         DO WHILE ! oBrowse:Stable
            oBrowse:Stabilize()
         ENDDO
         Eval( bExecutaRotinaUsuario, oBrowse, nKey )
         oBrowse:RefreshAll()
      ENDIF
   ENDDO
RETURN Nil

STATIC FUNCTION CriaBrowse( oRs, aCamposList )
   LOCAL oBrowse, oColumn, aItem, nLen, nCont

   if procname(2)="BROWSEITEM"
      oBrowse := TBrowse():new( 07, 2, MaxRow() - 5, MaxCol() - 2 )
   else
      oBrowse := TBrowse():new( 02, 3, MaxRow() - 3, MaxCol() - 3 )
   endif
   
   oBrowse:headSep       := Chr(196) + Chr(194) + Chr(196)
   oBrowse:colSep        := " " + Chr(179) + " "
   oBrowse:footSep       := Chr(196) + Chr(193) + Chr(196)
   oBrowse:goTopBlock    := { || oRs:moveFirst() }
   oBrowse:goBottomBlock := { || oRs:moveLast() }
   oBrowse:skipBlock     := { |n| ADORecordSetSkipper( oRs,n ) }
   
   if procname(2)#"BROWSEITEM"
      oBrowse:colorSpec     := "W/B,W+/N,N/W*,W+/R,R+/B,R/W*"
   endif

   if us#"I" .and. (procname(1)="ENTERITEM" .or. procname(2)="ENTERITEM" .or. procname(3)="ENTERITEM" .or. procname(4)="ENTERITEM" .or. procname(5)="ENTERITEM" .or. procname(6)="ENTERITEM" .or. procname(7)="ENTERITEM")
	  keysec(-18,115,-1,.t.)
   else
	  keysec(27,1200,-1,.t.)
   endif
		 
   IF aCamposList == Nil
      nLen := oRs:fields():count() - 1
      FOR nCont := 0 TO nLen
         oColumn := TBColumnNew( oRs:fields( nCont ):name(), ADORecordSetFieldBlock( oRs, nCont ) )
         oColumn:width := Max( Min( oRs:Fields( nCont ):definedSize,50), Len( oRs:fields( nCont ):name ) ) + 5
         oBrowse:addColumn( oColumn )
      NEXT
   ELSE
      FOR EACH aItem IN aCamposList
         oColumn := TBColumnNew( aItem[1], aItem[2] )
         IF Len( aItem ) > 2
            oColumn:ColorBlock := aItem[3]
         ENDIF
         oBrowse:AddColumn( oColumn )
      NEXT
   ENDIF
RETURN oBrowse

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

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



tbrowse: atualização da tela

Enviado: 06 Out 2021 18:33
por alxsts
Olá!

Faça a alteração mostrada abaixo e veja se funciona.

Código: Selecionar todos

STATIC FUNCTION RotinaUsuarioItem( oRs, oBrowse, nKey )
   local nPt, dDt, cHr, cCom, cQuant
  local cod :=oRs:Fields("id"):Value

  If (upper(chr(nkey)) =="R" .or. ((us="U" .or. us="I") .and. nkey==275))

   // ...
      // ...
         // ...
            // ...
 elseif nkey==286 //Alt-A
       chmfunc("novaaltassunto",,"S")

       // Adicione esta linha abaixo
       oRs:requery()
      
   ENDIF
RETURN 1
Não sei se vai funcionar porque você criou o recordset através do método Execute da conexão (oRs := oCn:Execute( cSql )) ao invés de criar separadamente (oRs := win_OleCreateObject("ADODB.RecordSet")) e depois fazer o execute. Não sei se o oRs := oCn:Execute( cSql ) alimenta o oRS com a string de conexão que foi passada ao objeto Connection...

tbrowse: atualização da tela

Enviado: 06 Out 2021 23:24
por cjp
Resolveu, muito obrigado.

tbrowse: atualização da tela

Enviado: 07 Out 2021 12:06
por JoséQuintas
Vou testar esse também.
Aqui eu fazia o select novamente, aproveitando que a string SQL ficava na classe.

Acabo de acrescentar pra testar

Código: Selecionar todos

   METHOD Requery()                            INLINE ::Rs:Requery()

tbrowse: atualização da tela

Enviado: 07 Out 2021 13:36
por JoséQuintas
Adorei isso.
Muito mais rápido do que refazer o comando.
Valeu.

Nota: eu já disse por aqui que uso poucos recursos do ADO. Nem sabia que no modo adUseClient haviam mais possibilidades.

tbrowse: atualização da tela

Enviado: 07 Out 2021 13:39
por alxsts
Olá!
cjp escreveu:Resolveu, muito obrigado.
Se resolveu, tudo bem. Mas, o importante aqui é que você tenha entendido a questão. Poderia dizer porque não funcionava? E porque a solução aplicada resolveu o caso?
alxsts escreveu:Não sei se o oRs := oCn:Execute( cSql ) alimenta o oRS com a string de conexão que foi passada ao objeto Connection...
Se funcionou, é porque ele transfere a connection string para o recordset.

tbrowse: atualização da tela

Enviado: 07 Out 2021 14:42
por cjp
Se resolveu, tudo bem. Mas, o importante aqui é que você tenha entendido a questão. Poderia dizer porque não funcionava? E porque a solução aplicada resolveu o caso?
Não tenho certeza se entendi bem, mas vamos tentar:

Aparentemente, o os:Requery() vai refazer a query, atualizando-a, estou certo?
Antes não funcionava porque minha função alterava a tabela, mas não alterava a consulta atual.
Se eu estiver certo, a solução resolveu o caso porque agora ele está refazendo a consulta, trazendo para o tbrowse a consulta atualizada.
Está certo?

tbrowse: atualização da tela

Enviado: 07 Out 2021 15:10
por JoséQuintas
cjp escreveu:Antes não funcionava porque minha função alterava a tabela, mas não alterava a consulta atual.
Se eu estiver certo, a solução resolveu o caso porque agora ele está refazendo a consulta, trazendo para o tbrowse a consulta atualizada.
Está certo?
É isso mesmo.
O recordset não é atualizado automático.
Mas a chamada a :Requery() faz isso.

tbrowse: atualização da tela

Enviado: 07 Out 2021 16:37
por cjp
Então que bom que estou começando a entender isso.

tbrowse: atualização da tela

Enviado: 08 Out 2021 12:10
por alxsts
Olá!
cjp escreveu:Está certo?
Perfeito! Dependendo das configurações do recordset, quando ele é carregado, passa a ser como uma foto (snapshot) da fonte de dados no momento da carga. Se a fonte de dados é alterada, é preciso tirar uma nova foto. Lembrando que o novo conteúdo reflete também as alterações que outros usuários fizeram, caso estejam acessando a fonte de dados.

Na prática,

Código: Selecionar todos

oRs:requery()
é o mesmo que

Código: Selecionar todos

oRs:close()
oRs:open()