http://www.fpress.com/
selector2.zip
Por Francisco San Pablo
Nota: para que el ejemplo funcione
correctamente se tiene que adaptar el path que se encuentra en el programa
inicio.prg
Hace dos meses publicamos una Clase Grid
que te permitía volcar el resultado de cualquier select en ese Grid y haciendo
doble click ir al registro señalado por el usuario.
La ventaja
de esa clase es su carácter genérico (vale para cualquier Select, con
cualesquiera número de campos) y opcionalmente le podías decir si querías que
te mostrara un campo o no.
Los que
miraron el código en detalle ya se apercibieron como una de las claves era el
uso de una clase TextBox personalizada en el Grid.
Una
carencia, que algún lector nos comentó de ese Grid era la inexistencia de un
‘Buscador’: cuando el número de registros es pequeño, el usuario puede hacer un
Scroll y localizar el registro que le interesa. Pero cuando el número de
registros devuelto es muy grande entonces el usuario no puede ir uno a uno para
localizar el registro que le interesa sino que tiene que tener algún tipo de
opción que le permite de forma rápida acceder al registro que cumpla las
características.

La opción no sólo sería el poder acceder de forma
rápida sino que también que fuera general de forma que sirva para cualquier Grid
sin tener que tocar una sola línea de código y por ende que sirva para
cualquier SELECT o consulta que uno haga.
En los
fuentes tienes el código de este artículo. Lo mejor, como siempre, es verlo
funcionando y después de ver su utilidad mirar el código.
Una vez
‘bajado’ y ejecutada la Select escribe directamente en el teclado cualquier
palabra y verás que se te activará un buscador. Pero lo mejor es que ese
buscador es para el campo que está seleccionado, por tanto te sirve para hacer
búsquedas por campo.
No pongo todo el código pues me parece que sería demasiado largo pero si te pongo las líneas que me parecen más interesantes:
DO CASE
*- Si pulsa botón delete ó
retroceso
CASE INLIST( nKeyCode, 7, 127 )
NODEFAULT
*- Si pulsa { ó
CTRL+TAB, no hace nada
CASE nKeyCode = 123 OR
;
(nShiftAltCtrl = 2 AND nKeyCode = 148)
*- Si la tecla pulsada es una
tecla válida para empezar
*- busqueda
CASE BETWEEN(nKeyCode, 32, 255)
NODEFAULT
LOCAL lcClaveBusca, lcOperador,
lcNombreCampo,;
lcTabla, nTiempoPasado
*- Si no existe el objeto, es la primera vez que utiliza
*- la búsqueda
IF TYPE('THIS.oFormBusq') <> 'O'
THIS.oFormBusq =
CREATEOBJECT('dlgBusqueda', THIS.ControlSource, ;
'Buscador', .F.)
ENDIF
this.oFormBusq.mAsigValores(nKeyCode)
this.oFormBusq.Show()
*- F3
CASE nKeyCode = -2 AND nShiftAltCtrl = 0
IF TYPE('THIS.oFormBusq') = 'O'
this.oFormBusq.mBuscaDeNuevo()
ENDIF
ENDCASE
Este es un resumen
del código que se debe poner en el método KeyPress de la clase TextBox para
lanzar el buscador cuando el usuario pulse cualquier tecla pero con la salvedad
de que si se pulsa Tabulador ó Escape o Retroceder, entonces el buscador no
debe lanzarse.
También
el Buscador se guarda en una variable que hace que la segunda vez que se vuelva
a instanciar ya no tenga que crearse sino que puede reutilizar el objeto. De
esta forma la instanciación es más rápida.
Otro
pequeño truco para lograr más rápidas instanciaciones es en vez de borrar los
objetos, esconderlos con un Thisform.Hide() de esta forma luego cuando tiene
que volverlo a mostrar es mucho más rápido pues ya lo tiene presente aunque el
usuario no lo ve.
El resto del código pertenece ya propiamente al Buscador. Voy a trascribir unicamente el que construye la Select y permite realizar la búsqueda:
lcSelecEjec = [ SELECT recno()
;
FROM ] + lcDbf + ;
[ WHERE ] + ;
lcCampoSelec + [ lcExpBusq ] + ;
THISFORM.cOldFilter + ;
IIF(THISFORM.lActivoIndex,' ORDER BY ' + lcCampo + ;
IIF( DESCENDING(TAGNO(lcCampo)), ' DESC ', ''), '' ) + ;
[ INTO ARRAY THISFORM.ga___Busca ]
&lcSelecEjec
IF _TALLY > 0
GO ( THISFORM.ga___Busca(THISFORM.nContRegis) ) IN (lcTabla)
ELSE
lcMensaje = ""
llEncontrado = .F.
DO CASE
*- Si el tipo del campo es numérico
CASE TYPE( 'lcExpBusqueda' ) $ "YNFBI"
lcMensaje = PADR(lcExpBusqueda,20)
CASE TYPE( 'lcExpBusqueda' ) $ "C"
lcMensaje = ALLTRIM(lcExpBusqueda)
CASE TYPE( 'lcExpBusqueda' ) $ "TD"
lcMensaje = DTOC(lcExpBusqueda)
CASE TYPE( 'lcExpBusqueda' ) $ "L"
lcMensaje = ""
ENDCASE
IF SET("BELL")="ON"
?? CHR(7)
ENDIF
ENDIF
ENDIF
ENDIF
WAIT CLEAR
THISFORM.HIDE()
IF NOT llEncontrado
MESSAGEBOX(" No se encontró : " + lcMensaje, 64,
'Aviso')
ENDIF
En este código se ve cómo la búsqueda es genérica y por tanto se adapta a cualquier necesidad y según el tipo de dato se comporta de forma diferente. Al final el Thisform.Hide() y la opción del Messagebox para el caso de que no se encuentre nada.
Creo que es mejor que al que le interese este tipo de funcionalidad se baje el código y lo mire. A mi me ha resuelto definitivamente las búsquedas en los Grids de una forma genérica y fácil que puedo incorporar a todas mis aplicaciones sin tocar una sola línea de código.
FoxPress – Noviembre de 2000
© 2000 FoxPress. All rights reserved