Ir al contenido


Foto

Filtrar DBGrid por una DBLookupComboBox


  • Por favor identifícate para responder
13 respuestas en este tema

#1 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 mensajes

Escrito 24 abril 2012 - 11:18

Hola soy yo de nuevo, como ayer con una duda que me ocupó toda la tarde.
Tengo un DBGrid que tengo enlazado con un DataSourceTodasFichas ese DataSource está enlazado con un QueryTodasFichas donde sencillamente importo todos los registros de la tabla Fichas.
El tema es que quiero hacer un filtro sobre esa misma query utilizando un DBLookupComboBox.
Ese Combo enseña el campo NOMBRE de una otra consulta hecha por QueryTodosClientes, pero yo trabajo con el campo ID_CLIENTE de esa query utilizando:


delphi
  1. IBQueryCarga_Clientes.FieldByName('ID_CLIENTE').Value;


Eso funciona sin problema y me devuelve bien la referia ID.

Mi tema es como hago para pillar eso y crear un filtro en la QueryTodasFichas ?
Estuve probando cosas que topé por internet, pero la verdad no les pillé la idea. Basicamente tengo ahora mismo el código:


delphi
  1. procedure TFormPrincipal.DataClientesDataChange(Sender: TObject;
  2.   Field: TField);
  3. begin
  4.   IBQueryTodasFichas.Filter:='Cliente like '+VarToStr(IBQueryCarga_Clientes.FieldByName('ID_CLIENTE').Value);
  5.   IBQueryTodasFichas.Filtered:=True;
  6. end;



Donde estoy yo fallando ?
  • 0

#2 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 24 abril 2012 - 11:25

Hola
La verdad es que para algo tan sencillo yo usaria un combobox ya que tiene el evento onchange que sirve mucho para hacer el filtro.
Saludos
  • 0

#3 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 mensajes

Escrito 24 abril 2012 - 11:31

Hola Caral, gracias por la ayuda.

No tengo problema por hacerlo en um combobox, lo cargaria de la base de datos de clientes y ya está.
El tema es que no sé como crear, aplicar el filtro y que la dbgrid se actualize con los cambios.
Tampoco tengo problemas por poner un botón , que se seleccione los filtros que se quiere aplicar y hacerlo, no tengo problema por el evento, el tema que se me escapa como hacer ese filtrado.
Tienes algún ejemplo para un novato de uso de um combobox para hacer filtrados sobre un dbgrid ?
Te lo agradecería inmensamente, pq lo que encuentro por internet la verdad me deja más confuso que me clarifica algo
  • 0

#4 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 24 abril 2012 - 11:37

Hola
Claro amigo:
Digamos que tienes un combobox y quieres filtrar el dbgrid que esta ligado a un query:
En el evento OnChage del combobox pones esto:



delphi
  1. var
  2.   Filtro : String;
  3. begin
  4.   If (Combobox1.Text <> '') then
  5.   begin
  6.       IBQueryTodasFichas.Filtered := False;
  7.       Filtro := 'Cliente Like '''+ Combobox1.Text + '%''';
  8.       IBQueryTodasFichas.Filter := Filtro;
  9.       IBQueryTodasFichas.Filtered := True
  10.   end
  11.   else IBQueryTodasFichas.Filtered := False;


Lo mismo puedes hacer usando el dbluckCombobox, pero usando un boton.
Saludos
  • 0

#5 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 24 abril 2012 - 12:08

Otra opción es usar condiciones en el mismo query y evitamos usar los filtros...  *-)

Usando el botón que te propone Caral:



delphi
  1. {Declaramos una constante global para almacenar el SQLOriginal}
  2. const
  3.       SQLOriginal  = 'select campos from FICHAS';  // Aquí el query que te recupera todos los registros de la tabla fichas



Y después en el evento OnClick del botón...



delphi
  1.     begin     
  2.       If (Combobox1.Text <> '') then
  3.       begin
  4.           IBQueryTodasFichas.Close;
  5.           IBQueryTodasFichas.SQL.Text := SQLOriginal +  ' where Cliente Like '''+ Combobox1.Text + '%''';;  //Ingresamos el query original y el filtro
  6.           IBQueryTodasFichas.Open;
  7.       end;



Es otra manera de hacerlo y en lo personal me gusta más que manejar filtros en los querys  (y)

Saludox ! :)


  • 0

#6 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 24 abril 2012 - 12:23

Creo que el problema es que tu elección de cliente te devuelve un entero, y con un entero usar like no es lo correcto, like es para textos, por si por ejemplo al elegir se toma el nombre del cliente en lugar de una id numérica.

Para un id tipo entero, usa mejor esto:



delphi
  1. procedure TFormPrincipal.DataClientesDataChange(Sender: TObject;
  2.   Field: TField);
  3. begin
  4.   IBQueryTodasFichas.Filter:='Cliente='+IBQueryCarga_Clientes.FieldByName('ID_CLIENTE').AsString;
  5.   IBQueryTodasFichas.Filtered:=True;
  6. end;



Fíjate también que no es necesario acceder el campo como un variant y luego convertirlo a string, puedes pedirle el valor al campo AsString, AsInteger o AsFloat, de hecho es lo más recomendable ya que tu sabes de antemano el tipo de valor que contiene el campo y en que variable quieres colocarlo, y firebird -o delphi, lo mismo da- que haga el trabajo "internamente" y te devuelva tu valor ya preparadito.
  • 0

#7 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.301 mensajes
  • LocationArgentina

Escrito 24 abril 2012 - 12:27

Hola,
En lo posible como recomienda Fenareth hay que traer las consultas ya filtradas empleando WHERE.
Ahora bien, si desde el conjunto de datos devuelto hay que aplicar un "2do filtro" allí si es una buena alternativa el uso del Filter.

Téngase en cuenta que el uso de Filter es Local, por lo que es más lento que pedirle al motor que nos de el conjunto ya filtrado. Y además, el uso de Filter es limitado debido a que las posibles condiciones y primitivas que puede aceptar son reducidas a comparación del potente WHERE de un verdadero motor.

La lección es: "Cuanto más filtrado puedas traer los datos a la aplicación mejor."

Saludos,
  • 0

#8 Fenareth

Fenareth

    Advanced Member

  • Administrador
  • 3.486 mensajes
  • LocationMexico City

Escrito 24 abril 2012 - 12:38

Hola,
En lo posible como recomienda Fenareth hay que traer las consultas ya filtradas empleando WHERE.
Ahora bien, si desde el conjunto de datos devuelto hay que aplicar un "2do filtro" allí si es una buena alternativa el uso del Filter.
...


Y aún cuando hay más de un filtro es posible modificar el SQL para ingresar los nuevos filtros  (y)

Lo que pasa es que mi lema va más allá... siempre que sea posible poner a trabajar al motor de la base de datos y no a Delphi, que para eso está hecho  *-)

Además corríjanme si me equivoco, los filtros son un tanto limitados en su uso, no ???  ^o|

Saludox ! :)
  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.301 mensajes
  • LocationArgentina

Escrito 24 abril 2012 - 02:24

Y aún cuando hay más de un filtro es posible modificar el SQL para ingresar los nuevos filtros  (y)

Depende.
Siempre que esa consulta sea dinámica, y creada/armada en tiempo de ejecución, si. En otro caso no es posible modificarla.

Aquí es bueno hacer mencionar una buena práctica que al menos yo la consideraba implícita: en lo posible hay que llevar las consultas al lado del servidor, aprovechando las vistas y los procedimientos almacenados. De este modo en la aplicación solo tiene lugar una llamada a dichas vistas y SPs. O en todo caso, aprovechar una combinación de consultas dinámicas sobre una vista o procedimiento seleccionable.

Muchas veces uno llena de consultas en los componentes TXXQuery; consultas que son estáticas, fijas... que no se van a modificar nunca en la aplicación; siempre es la misma. En un ambiente cliente/servidor con muchos puestos esto se traduce a que el aplicativo arme y prepare las consultas, las mande a ejecutar y reciba... esto multiplicado por N puestos y M veces al día no es muy bueno. Podría mejorarse si uno usa .Prepare() pero sigue siendo un desperdicio.

Puede mejorarse mucho más si directamente dejamos a estas consultas estáticas como lo son: verdaderamente estáticas en el lado servidor y que directamente la aplicación las use. Nada de preparar, etc.


Lo que pasa es que mi lema va más allá... siempre que sea posible poner a trabajar al motor de la base de datos y no a Delphi, que para eso está hecho  *-)

Por supuesto. Se supone, que en teoría, el motor es lo suficientemente inteligente y bien preparado. Sabe hacer su trabajo de una manera mucho más efectiva que lo que se puede conseguir de forma local... sobre todo en lo que hace a Filtros; que no cuenta con un amplio soporte de todo lo que puede hacer un motor.

Además corríjanme si me equivoco, los filtros son un tanto limitados en su uso, no ???  ^o|

Saludox ! :)

Es justo lo que dije yo:

Y además, el uso de Filter es limitado debido a que las posibles condiciones y primitivas que puede aceptar son reducidas a comparación del potente WHERE de un verdadero motor.


No te equivocas. Efectivamente, los filtros que soporta los datasets tiene las primitivas más básicas del lenguaje SQL. No son válidas cosas más complejas como un COALESCE() por dar un ejemplo. Es más creo recordar, no tengo Delphi a mano para comprobarlo, que solo permite LIKE, %, #, *, <, >, <=, >=, '' y se acabó.

Saludos,
  • 0

#10 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 02:56


Además corríjanme si me equivoco, los filtros son un tanto limitados en su uso, no ???  ^o|

Saludox ! :)


No solo son limitados, sino terriblemente ineficientes. Su uso debería estar restringido a datasets de pocas filas....

Es mejor dejarle a la base de datos el procedimiento de filtrado...


saludos
  • 0

#11 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 24 abril 2012 - 03:09

Hola
Sois demasiado perfeccionistas. :p
La pregunta fue sencilla:

......... que se seleccione los filtros que se quiere aplicar y hacerlo,.......... se me escapa como hacer ese filtrado.
Tienes algún ejemplo para un novato .....

Evidentemente es mejor una sentencia sql pero si ya se trajo la información con una entonces aplica el filtro con facilidad.
Me estáis enredando al novato. :D :p
Saludos
  • 0

#12 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4.945 mensajes
  • LocationMéxico

Escrito 24 abril 2012 - 03:18

Hola
Sois demasiado perfeccionistas. :p
Evidentemente es mejor una sentencia sql pero si ya se trajo la información con una entonces aplica el filtro con facilidad.
Me estáis enredando al novato. :D :p

(b)  (y)  :D  :D cierto... :p
  • 0

#13 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.301 mensajes
  • LocationArgentina

Escrito 24 abril 2012 - 09:37

Como diría el Chavo: bueno pero no te enojes  :D

Espero que coruxito no se sienta intimidado, ni decepcionado de la idea de los filtros. Es una herramienta más que está a disposición y si uno la sabe combinar con otras tantas herramientas y técnicas le puede sacar buen uso.

Lo lamento si te estropeé al novato Caral. Después nos los agradecerás... ¡tu mismo sabes que novato es marca registrada!  :D

Saludos,
  • 0

#14 coruxito

coruxito

    Advanced Member

  • Miembros
  • PipPipPip
  • 55 mensajes

Escrito 25 abril 2012 - 01:48

Hola amigos. sois unos cracks. Gracias a todos. La verdad que Delphius tiene razón sobre lo que dice, lo que pasa es que al empezar, principalmente tirando al fin del dia, pues el cerebro no le dan las mejores ideas del dia.
No lo lograría sin vuestra ayuda, leí todo lo que habéis me pasado y al final lo hize de la siguiente manera:


delphi
  1. procedure TFormPrincipal.BAplicaFiltrosClick(Sender: TObject);
  2. begin
  3.   IBQueryTodasFichas.Close;
  4.   IBQueryTodasFichas.SQL.Text:='select * from Fichas';
  5.   IBQueryTodasFichas.SQL.Text := IBQueryTodasFichas.SQL.Text+' where Cliente='+VarToStr(IBQueryCarga_Clientes.FieldByName('ID_CLIENTE').Value);
  6.   IBQueryTodasFichas.Open;
  7. end;



Opté por montar un botón de aplicar filtros, así la persona puede optar por los que quiera (va tener por lo menos 9-10 por lo que estoy mirando) y le dando al botón pues le viene los datos actualizados.

Como miráis acabé optando por la solución de Fenareth, porque la verdad entiendo mejor el hacer un select que aplicar los filtros. Sólo cambié el usar una variable global no por nada pq la verdad me parece elegante, pero como no recomiendan las globales ni para C, ni para Java por motivos de seguridad... Pues no sé si en Pascal/Delphi tendría el mismo tipo de implicación, pues sí hago algo MUY ligado a formulário, no trabajo elegantemente con clases, pero bueno va funcionando, que por lo que voy pillando de ese curro quieren las cosas rápido, les dá igual como las hagas !!!  :D
  • 0




IP.Board spam blocked by CleanTalk.