busqueda incremental

busqueda incremental

Postby surGom » Mon Feb 04, 2013 12:03 am

Hola nuevamente, tengo la siguiente rutina:

Code: Select all  Expand view
function busnap(olbx,oQry,nclia,oMysql,cConsulta,larchivo)

local lacepto := .F.
local olbm, odlg
local nbut
local surge
local cSeek := ""
 
DEFAULT larchivo := .f.  

if empty(nclia)
  if !larchivo                                                               //si es que no viene de archivo maestro de clientes
    if empty(cConsulta)
      oQry := oMysql:Query( "SELECT * FROM maeclie ORDER by nape" )
   else
       oQry := oMysql:Query( "SELECT * FROM maepro ORDER by nape" )  
   endif  
 endif
 oQry:gotop()

DEFINE ICON surge resource "icoprog"

DEFINE DIALOG oDlg resource "lisbus_1" ICON surge
odlg:cCaption:= "Clientes"

   REDEFINE LISTBOX olbm FIELDS oQry:nape ID 101;
               FIELDSIZES 120  HEADERS "Razón Social";  
             ON DBLCLICK (lacepto:= .t.,odlg:end())  of odlg

             mysetother( oLbm, oQry )        //funcion hecha por williams wormar para que funcione el wbrowse de Hernán
             olbm:refresh()              
             olbm:setfocus()  
             oLbm:bkeydown :=  {|nkey,nflags| iif(nKey = VK_RETURN, nBut:setfocus(), misteclas(nkey,oLbm,oQry, @cSeek ))}
             olbm:nClrBackFocus := CLR_CYAN
             olbm:nClrForeFocus := CLR_WHITE        
             


   REDEFINE BUTTON NBUT ID 102 ACTION (lacepto := .t.,odlg:end())
 
 
   REDEFINE BUTTON ID 103 ACTION( clientes( oQry, .t.),olbm:refresh())
 


ACTIVATE DIALOG ODLG

 
ELSE                                     //si es que envío el número de código de cliente o proveedor
   if empty(cConsulta)
      oQry := oMysql:Query( "SELECT * FROM maeclie where ncli="  + alltrim(str(nclia)))
   else
       oQry := oMysql:Query( "SELECT * FROM maepro where npro="  + alltrim(str(nclia)))  
   endif  
   return oQry
ENDIF

if lacepto  
   iif(!empty(olbx),olbx:refresh(),.f.)
   return oQry
endif      
 
 RETURN NIL
 /***********************************************************************************/
Static function MisTeclas( nKey, oLbm, oQry, cSeek  )
Local cTecla := Chr( nKey )
Local cChar  := Upper( cTecla )



if nKey = 192
   nkey := 209
   cTecla := Chr( nkey )                              //letra Ñ
   cChar  := Upper( cTecla )
endif


If nKey >= 30 .AND. nKey <= 132 .or. nKey = 209
   cSeek += cChar
Elseif nkey = 8
   cSeek := ""
   oQry:gotop()
else
   return nil
EndIf

do
   if oQry:nape = cSeek
      olbm:refresh()
      exit
   endif
   oQry:skip()
until oQry:eof()
sysrefresh()

 
 
oQry:Refresh()
oLbm:Refresh(.T.)

Return NIL  

 


Esta rutina lo que hace es un diálogo con un listbox con el campo nombre en el cual hago una búsqueda incremetal sobre el mismo y al aceptar me devuelve el registro que necesito.
De esta forma cuando quiero seleccionar ya sea un cliente o proveedor, si no pongo el número del mismo se abre la ventana y escribiendo sobre el listado se va posicionando hasta que encuentro el buscado, y si no esta, presiono el boton de agregar para hacerlo.

Dos cuestiones, la primera si es posible hacerlo con un xbrowse y búsqueda incremental que trabaje tal cual esta esta rutina( es decir que vaya cambiando mientras tecleo sobre el mismo), intente hacerlo con el seek de xbrowse pero no sé como.

La segunda necesito hacer la misma rutina pero para datos del tipo

175/70/13FIRSIE
175/70/13FIRF57
185/70/13FIRSIE
195/70/14FIRF57
ETC, ETC

son códigos de producto, pero al hacerlo como más arriba no me toma los números, si los escribo con la parte superior del teclado, reconoce los números, pero se va al final del listbox, es decir presiono 1 y ya se va al final del listado, cuando tendría que esperar que marcara el segundo número para moverse. Si en cambio presiono desde el teclado numérico si es el 1 lo reconoce como "a".
Quería hacerlo con xbrowse porque quizás este problema de los números esta resuelto en el código de xbrowse en la busqueda incremental, pero sería importante poder mantener la idea del código que utilizo en clientes y proveedores.

Estoy usando la clase tymsql y xharbour

Luis
surGom
 
Posts: 639
Joined: Wed Oct 19, 2005 12:03 pm

Re: busqueda incremental

Postby Willi Quintana » Mon Feb 04, 2013 2:33 am

Prueba asi:
Code: Select all  Expand view


..
..
.
cDSeek := ""
..
.
REDEFINE LISTBOX olbm FIELDS oQry:nape ID 101;
               FIELDSIZES 120  HEADERS "Razón Social";  
               ON DBLCLICK (lacepto:= .t.,odlg:end())  of odlg
               ON CHANGE (cDSeek := "" ) ;
                SIZES 50,500 ;
                ID 200 OF oDlg

                MySetBrowse( oLbm, oQry )

                oLbm:bKeyDown := {|nKey|cDSeek := ArmaSeek(nKey, cDSeek), ;
                                              lOk := oQry:Seek(  cDSeek,  "nape" ), oLbm:Refresh() }

...
..
.

//---------------------------------------------
//--------------------------------------------------------------------------------------------------------
Function ArmaSeek(nKey, cDSeek)
local nLen, cChar

cChar := UPPER(CHR(nKey))
nLen  := LEN(cDSeek)

DO CASE
  CASE nKey = 192               // ???
    cChar := "Ñ"
  CASE nKey = 8                 // retroceso
    cChar := ""
    nLen := IF(nLen < 2, 1, nLen)
    cDSeek := SUBSTR(cDSeek, 1, nLen - 1 )
ENDCASE
cDSeek := cDSeek + cChar

Return(cDSeek)



//----------------------------------------------------------------------------------------
//------------------------------------------------------------------------
Function MySetBrowse( oBrw, oDataSource )

    local lRet := .t.
    local bGoTop, bGoBottom, bSkipper
    local cClsName

    if ValType( oBrw ) != "O" .or. ValType( oDataSource ) != "O"
        lRet := .f.
    else
        bGoTop := { || oDataSource:GoTop() }
        bGoBottom := { || oDataSource:GoBottom() }
        bSkipper := { | n | oDataSource:Skip( n ) }

        cClsName := upper( oBrw:ClassName() )

        if cClsName == "TBROWSE" // El nativo de Harbour y xHarbour
            oBrw:goTopBlock := bGoTop
            oBrw:goBottomBlock := bGoBottom
            oBrw:SkipBlock := bSkipper
        elseif cClsName $ "TWBROWSE TCBROWSE TSBROWSE TGRID TXBROWSE" // Para windows
            oBrw:cAlias := ""
            oBrw:bGoTop := bGoTop
            oBrw:bGoBottom := bGoBottom
            oBrw:bSkip := bSkipper
            if cClsName == "TXBROWSE"
                oBrw:bBof := { || oDataSource:Bof() }
                oBrw:bEof := { || oDataSource:Eof() }
                oBrw:bBookMark :={ | n | if( n == nil, oDataSource:RecNo(), ;
                                                       oDataSource:GoTo( n ) ) }
                oBrw:bKeyNo :=  { || oDataSource:RecNo() }
                oBrw:bKeyCount := { || oDataSource:RecCount() }
            else
                oBrw:bLogicLen := { || oDataSource:RecCount() }
            endif
            if oBrw:oVScroll() != nil
                oBrw:oVscroll():SetRange( 1, oDataSource:RecCount() )
            endif
            oBrw:Refresh()
        else
            oDataSource:oError:Say( "Browse no implementado en SetBrowse", .f. )
        endif
    endif

return( lRet )

 
User avatar
Willi Quintana
 
Posts: 1002
Joined: Sun Oct 09, 2005 10:41 pm
Location: Cusco - Perú

Re: busqueda incremental

Postby surGom » Tue Feb 05, 2013 10:29 am

Gracias Willy la función que envié funciona correctamente cuando trato con el teclado alfabético, estas es la imagen de lo que hace

Image
si no se visualiza:

http://www.4shared.com/photo/cigHFKhw/muestra.html

el problema lo tengo con este tipo de datos

Image
ó
http://www.4shared.com/photo/MLkr9NJn/muestra1.html

no logro que haga la búsqueda incremental en este caso. Cuando aprieto una tecla (el 1) directamente va hacia el final del listado. Bueno es lo que escribí anteriormente.

al comenzar la aplicación declaro


REQUEST HB_Lang_ES // Para establecer idioma de Mensajes, fechas, etc..*/
REQUEST HB_CODEPAGE_ESWIN // Para establecer código de página a Español (Ordenación, etc..)*/

así y todo para la letra Ñ tuve que hacer la salvedad de cambiar el valor de teclado para que la encontrara en el listado.

Trabajando con dbf uso la misma rutina salvo que en vez de llamar a mis teclas uso la función dbfseek(), quedando así

Code: Select all  Expand view
            oLbm:bSeek := {|lRet| oLbm:DbfSeek(.T.) }
             oLbm:bkeydown :=  {|nkey,nflags| iif(nKey = VK_RETURN, nBut:setfocus(),.f.)}


sin necesidad de redefinir la letra Ñ. Posiblemente sea que no tengo bien declarado el idioma en la base de sql...
está como utf8_spanish_ci

Por eso creía que con xBrowse podía hacer lo mismo con el metodo seek, los ejemplos que ví son haciendo un say-get externo al browse y mi idea es hacerlo tal cual muestro en la figura (tecleando sobre el mismo)

Luis
surGom
 
Posts: 639
Joined: Wed Oct 19, 2005 12:03 pm

Re: busqueda incremental

Postby surGom » Tue Feb 05, 2013 11:17 am

Hice una prueba en vez de utilizar una tabla mysql cree una base de datos dbf y funciona correctamente utilizando la teclas teclas numéricas, a que se debe la diferencias de comportamiento??

http://www.4shared.com/photo/oaV-K1EN/muestra3.html

Luis
surGom
 
Posts: 639
Joined: Wed Oct 19, 2005 12:03 pm

Re: busqueda incremental

Postby surGom » Tue Feb 05, 2013 3:29 pm

Bueno le encontré la sguiente solución, que seguramente no es la óptima, pero funciona perfectamente

Code: Select all  Expand view
function bprodu(olbx,oQdetalle,oMysql)
local oDlg
local lacepto := .f.


oQdetalle := oMysql:Query( "SELECT * FROM producto ORDER by codigo" )

oQdetalle:gotop()

DEFINE DIALOG oDlg resource "lisbus_1"
odlg:cCaption:= "Productos"

   REDEFINE LISTBOX olbm FIELDS oQdetalle:codigo ID 101;
               FIELDSIZES 120  HEADERS "Código";  
               ON DBLCLICK (lacepto:= .t.,odlg:end())  of odlg

             mysetother( oLbm, oQdetalle )
         olbm:refresh()              
             olbm:setfocus()  
         olbm:bseek :={|lret| buspro(oLbm,oQdetalle )}
         oLbm:bkeydown :=  {|nkey,nflags| iif(nKey = VK_RETURN, nBut:setfocus(),.f. )}
             olbm:nClrBackFocus := CLR_CYAN
             olbm:nClrForeFocus := CLR_WHITE        
             


   REDEFINE BUTTON NBUT ID 102 ACTION (lacepto := .t.,odlg:end())
 
 
   REDEFINE BUTTON ID 103 ACTION( produ( oQdetalle, .t.),olbm:refresh())
 


ACTIVATE DIALOG ODLG

if lacepto  
   iif(!empty(olbx),olbx:refresh(),.f.)
   return oQdetalle
endif  
 
return nil

 /******************************************************************/
Static function buspro( oLbm, oQdetalle)
local cBusco

do
   if substr(oQdetalle:codigo,1,len(olbm:cbuffer)) = olbm:cbuffer
      olbm:refresh()
      exit
   endif
   oQdetalle:skip()
until oQdetalle:eof()
sysrefresh()
 
oQdetalle:Refresh()
oLbm:Refresh(.T.)

Return NIL  
/


Luis
surGom
 
Posts: 639
Joined: Wed Oct 19, 2005 12:03 pm

Re: busqueda incremental

Postby Francisco Horta » Sat Feb 09, 2013 6:58 pm

Luis, yo lo hago asi:

oQry := oApp:oServer:Query("SELECT * FROM " + cTmp + " ORDER BY nombre")

DEFINE DIALOG oDlg SIZE 440,540 PIXEL FONT oFont TITLE "Terapeutas Disponibles de las " + oView:ConvertTime( nTimeFrom - 1 ) + " a las " + oView:ConvertTime( nTimeTo + 1 )

oDlg:lHelpIcon := .f.

@ 10,10 SAY oSay PROMPT cBusca OF oDlg SIZE 200,12 PIXEL COLOR CLR_YELLOW,CLR_GRAY BORDER

@ 30,10 XBROWSE oBrw ;
SIZE 200,200 PIXEL ;
OF oDlg

oBrw:SetMySql( oQry, .F. )

oBrw:bKeyDown := { |nKey| IF( nKey == VK_RETURN,(lOk:=.T.,oDlg:End()),;
IF( nKey<>13, ( SeekProd(nKey,@oQry,LOWER(cTmp),"nombre",oBrw,@cBusca,,,@lKeyboard),oSay:Refresh() ),)) }




*---------------------------------------
* FUNCION: SeekProd
* Descripcion: Busqueda Incremental
* Fecha: 19/12/2011
*---------------------------------------
FUNCTION SeekProd(nKey,oQry2,oTabla,oOrden,oLbx,cbusca,cSelect,cWhere,lKeyboard)
Local cQuery,campo
DEFAULT cSelect := "*",;
cWhere := ""

IF nKey == 91
IF !lKeyboard
oLbx:Keydown( VK_BACK )
lKeyboard := .t.
ENDIF
oLbx:Refresh(.T.)
oLbx:SetFocus()
RETURN NIL
ENDIF
MsgBeep()
IF nKey=8
cbusca:= SubStr(cbusca,1,Len(cbusca)-1)
IF Empty(cWhere)
oQry2:cQuery:="SELECT "+ cSelect + " FROM "+oTabla+" WHERE "+oOrden+" LIKE '%"+UPPER(cBusca)+"%' ORDER BY "+oOrden //+" LIMIT 100"
ELSE
oQry2:cQuery:="SELECT "+ cSelect + " FROM "+oTabla+" "+cWhere+" AND "+oOrden+" LIKE '%"+UPPER(cBusca)+"%' ORDER BY "+oOrden //+" LIMIT 100"
ENDIF
oQry2:Refresh()
oQry2:GoTop()
ELSE
If nKey=190
cbusca :=cbusca + "."
ElseIF nKey = 192 .OR. nKey = 164 .OR. nKey = 165
cbusca := cbusca + "Ñ"
Else
cbusca := cbusca + Upper(chr(nkey))
Endif
IF Empty(cWhere)
oQry2:cQuery:="SELECT "+ cSelect +" FROM "+oTabla+" WHERE "+oOrden+" LIKE '%"+UPPER(cBusca)+"%' ORDER BY "+oOrden //+" LIMIT 100"
ELSE
oQry2:cQuery:="SELECT "+ cSelect + " FROM "+oTabla+" "+cWhere+" AND "+oOrden+" LIKE '%"+UPPER(cBusca)+"%' ORDER BY "+oOrden //+" LIMIT 100"
ENDIF
oQry2:Refresh()
oQry2:GoTop()
ENDIF
oLbx:Refresh(.T.)
oLbx:SetFocus()

RETURN NIL


saludos
paco
____________________
Paco
Francisco Horta
 
Posts: 845
Joined: Sun Oct 09, 2005 5:36 pm
Location: la laguna, mexico.

Re: busqueda incremental

Postby surGom » Sat Feb 09, 2013 8:08 pm

Gracias Paco voy a adaptarla a mi programa, ya que se ve mucho mejor que la que hice para salir del paso.


Luis
surGom
 
Posts: 639
Joined: Wed Oct 19, 2005 12:03 pm


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 92 guests