PDA

Ver la Versión Completa : Búsqueda "incremental" en una base de datos


loquillo3
07-11-2007, 02:48:23
Hola,
De antemano le anticipo que si este hilo no va aqui lo muevan al debido lugar donde debe de ir.

Lo que intento hacer es realizar una busqueda que cuando vaya poniendo las letras me vaya apareciendo los resultados.

Ejemplo: Si busco un registro por nombre. Busco el nombre Manuel peo que me aparezcan los demas que empieza con m y a medida que siga poniendo las demas letras se vaya reduciendo la lista hasta quedar el que busco.


Salu2.

dec
07-11-2007, 02:51:30
Hola,


De antemano le anticipo que si este hilo no va aqui lo muevan al debido lugar donde debe de ir.


Hombre, digo yo, que, antes de publicar el hilo debes mirar en qué subforo cae mejor, apróximadamente. Yo creo que este hilo no va en "Conexión con bases de datos". Tal vez vaya en MySQL, Orable, o la base de datos que uses, pero, como tampoco lo dices... a ver quién ata el cascabel al gato.

De momento quédese el hilo donde está, hasta más ver. Lo que sí he hecho ha sido editar el título del hilo, porque "Búsqueda" sólo quedaba un poco abstracto, por decirlo así. Piensa que en los títulos de los hilos se basan luego las búsquedas que se pueden llevar a cabo en los foros, de ahí la importancia de que tengan un título descriptivo.

Neftali [Germán.Estévez]
07-11-2007, 11:36:45
Puedes usar un simple Locate para posicionarte en el registro que necesites.
El problema de las búsquedas incremetales es la velocidad y los recursos que consumen.
Si es una tabla pequeña, puedes utilizar un ClientDataSet para cargarla en memoria y a partir de ahí realizar la búsqueda.
El problema es si no puedes cargar toda la tabla en memoria (esto no siempre es posible) o es muy grande, porque posiblemente tendrás problemas de velocidad.

Coloca un Edit dobde escribes el texto y una tabla apuntando a la tabla employee de DBDemos ordenada por FirstName; Algo así:


Select * from employee order by FirstName, LastName


Con este código en el OnChange debería valer.


// Busqueda incremental
ClientDataSet1.Locate('FirstName', Edit1.Text, [loCaseInsensitive, loPartialKey]);


Acabo de subir un ejemplo completo a la sección de ejemplos de mi web (http://neftali.clubdelphi.com/). Puedes descargarlo y ver el código fuente.

loquillo3
08-11-2007, 03:51:37
Hola,
Neftali probe tu ejemplo y es lo que quiero hacer, intente hacerlo por mi mismo pero no pude.
POr cierto mi base de datos esta hecha en access no se si me puedes dar una manito en eso.

Saludos.

tefots
08-11-2007, 11:06:27
para busquedas incrementales yo uso like

conforme el usuario va escribiendo en un textbox
en el onkeypres del textbox
hago lo siguiente.

if textbox1.text<>'' then begin
dbbrid1.beginupdate
query1.close
query1.sql.add('select from tabla1 where tabla1.campo like '%dato%')
query1.open
dbgrid.endupdate
end;

con esto , el dbgrid se va posicionando localizando el registro correspondiente conforme vamos escribiendo o borrando.
en acces el like creo que no hay que ponerle % , el codigo es solo como funciona , hay que adaptarlo un poco.

nota : para optimizar ,tambien se puede poner un temporizador (y meter el codigo en el temporizador) , y en el onkeypress dehabilitar y habilitar el temporizador , de unos 200/300ms. asi cuando escriba , no se posiciona cada vez que apretemos una tecla sino que lo hace cuando pase x tiempo despues de apretar la ultima tecla.

saludos.

Neftali [Germán.Estévez]
08-11-2007, 11:48:33
...intente hacerlo por mi mismo pero no pude.

¿Exactamente qué pasó?
¿Error?
En principio la Base de Datos no tiene nada que ver, si te fijas en el ejemplo, la búsqueda se hace sobre los datos que ya hay cargados en el DataSet (vía TClientDataSet), por lo tanto es independiente de cómo se carguen los datos.

De todas formas he modificado el ejemplo para permitir cargar los datos desde un XML o desde un MDB.

Lepe
08-11-2007, 13:41:00
izar ,tambien se puede poner un temporizador (y meter el codigo en el temporizador) , y en el onkeypress dehabilitar y habilitar el temporizador , de unos 200/300ms. asi cuando escriba , no se posiciona cada vez que apretemos una tecla sino que lo hace cuando pase x tiempo despues de apretar la ultima tecla.

saludos.

Yo prefiero al presionar intro en el edit de búsqueda:


procedure TForm1.Edit1keyDown(...);
begin
if key = vk_return then
begin
// abrir y cerrar la consulta
end;


Saludos

Neftali [Germán.Estévez]
08-11-2007, 16:34:55
Yo prefiero al presionar intro en el edit de búsqueda...

Eso siempre!!! En eso estoy con Lepe.

Aunque te he dado la solución, tengo que decir que si vas a acabar buscando por Manolo, yo también encuentro una tontería buscar por: m, ma, man, mano, manol y finalmente manolo.
Lo que pasa que queda muy bonito y a los clientes les gusta mucho;:p
Básicamente a ellos les da igual que para hacerlo así debas generar más tráfico de red de la cuenta o traerte muchos más registros de los necesarios,... Eso sí luego que funcione, que vaya muy rápido y que consuma poco...:D:D:D

loquillo3
08-11-2007, 16:41:29
Estaba viendo este codigo que genero marcsc:


interface

TBuscador = class(TObject)
private
FIndiceCampo: Integer;
FDataSet: TDataSet;
public
constructor Create(DS: TDataSet = nil);
property DataSet: TDataSet read FDataSet write FDataSet; //Sobre el que se hace la búsqueda
function Buscar(Texto: String; BuscarBOF: Boolean = True): Boolean;
end;

implementation

//Como el valor por omisión del parámetro DS es nil, puedes llamar al constructor
//sin parámetros y asignarle posteriormente el DataSet
constructor TBuscador.Create(DS: TDataSet = nil);
begin
inherited Create;
FDataSet:= DS;
FIndiceCampo:= 0;
end;

//El parámetro BuscarEOF, por defecto True, busca el texto desde el inicio del
//DataSet. En caso que se especifique el valor False, buscará incrementalmente
function TBuscador.Buscar(Texto: String; BuscarBOF: Boolean = True): Boolean;
begin
Result:= False;
with FDataSet do
begin
if BuscarBOF then
begin
First;
FIndiceCampo:= 0;
end;

while (not EOF) and (not Result) do
begin
while (FIndiceCampo < Fields.Count) and (not Result) do
begin
//Esto seria una busqueda absoluta, si quieres opciones de búsqueda
//parcial, con opciones de mayúsculas etc te lo dejo como mejora ;)
Result:= Fields[FIndiceCampo].Text = Texto;
Inc(FIndiceCampo);
end;
FIndiceCampo:= 0;
Next;
end;
end;
end;


Neftali si tu pudieras poner un pequeño ejemplo hecho en access podria guiarme de ahi, ya que vi en el tuyo que usabas un archivo xml.

Saludos

Neftali [Germán.Estévez]
08-11-2007, 18:07:02
Neftali si tu pudieras poner un pequeño ejemplo hecho en access podria guiarme de ahi, ya que vi en el tuyo que usabas un archivo xml.

Ya te lo había comentado antes.

De todas formas he modificado el ejemplo para permitir cargar los datos desde un XML o desde un MDB.

Es el mismo sitio donde estaba el otro; Link (http://neftali.clubdelphi.com/ejemplos_files/busqueda_incremental_clientdataset.zip).