Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Valor en celda de DBGrid según código en base de datos (https://www.clubdelphi.com/foros/showthread.php?t=48489)

Gabo 26-09-2007 11:49:29

Valor en celda de DBGrid según código en base de datos
 
Tengo un DBGrid donde despliego los pagos que ha hecho un cliente. Allí muestro datos como la fecha del pago, el monto y la forma de pago.

Para desplegarlo utilizo un TIBQuery con la siguiente consulta:

Código SQL [-]
SELECT PAGO_CODIGO, PAGO_FECHA, PAGO_MONTO, PAGO_FORMAPAGO, 
FROM PAGO WHERE CLIENTE_CODIGO=:cliente

El tema es que en el campo PAGO_FORMAPAGO almaceno un caracter que me indica la forma de pago, donde:

0 indica un pago en efectivo
1 indica un pago por transferencia
y así sucesivamente...

Debido a lo ya explicado, en el DBGrid me aparece el caracter respectivo, pero yo quiero que me aparezca lo que representa.

Tengo entendido que los DBGrid no proveen de ningún recurso para cambiar el valor en el momento de desplegarlo y por lo tanto todo cambio debe ser en la consulta. ¿O me equivoco?

¿Es posible hacer el cambio en el DataSource o más bien debo cambiar la consulta SQL?

Sabría hacer la consulta si el significado de PAGO_FORMAPAGO está en otra tabla, y podría solucionarlo con algo así:

Código SQL [-]
SELECT PAGO.PAGO_CODIGO, PAGO.PAGO_FECHA, PAGO.PAGO_MONTO, FORMAPAGO.FORMAPAGO
FROM PAGO, FORMAPAGO WHERE PAGO.CLIENTE_CODIGO=:cliente AND PAGO.COD_FORMAPAGO=FORMAPAGO.COD_FORMAPAGO

Pero, ¿cómo podría cambiar esa primera consulta SQL sin crear una tabla nueva?

Nota: Utilizo Interbase 6.0

Gracias a todos de antemano.... ;)

gluglu 26-09-2007 12:00:42

Una de las maneras para hacer lo que quieres es utilizar el evento OnGetText del campo FORMA_PAGO del DataSet en el cual vas a hacer la consulta.

No sé si tienes un DataSet para dicha consulta ? Pero si es así, puedes utilizar dicho evento que sería algo así como :

Código Delphi [-]
procedure TForm1.IBDataSet1FORMA_PAGOGetText(Sender: TField;
  var Text: string; DisplayText: Boolean);
begin
  case IBDataSet1FORMA_PAGO.AsInteger of
    0 : Text := 'Efectivo';
    1 : Text := 'Transferencia';
  end;
end;

De esta manera en el DBGrid que utilizas sale el texto que defines ewn esta función. (En tiempo de diseño, no. Pero en tiempo de ejecución, si).

Espero haberte ayudado. ;)

Neftali [Germán.Estévez] 26-09-2007 12:10:40

Creo que sí puedes conseguirlo directamente. Añade los campos al DataSet (Tabla/Query) y una vez añadidos revisa los eventos OnGetText y OnSetText del campo Forma de Pago.

Si no quieres hacerlo así puedes modificar la consulta hacer la JOIN y conseguir el campo que necesitas. Si lo llamas igual que el anterior (y el anterior lo quitas) seguramente no tendrás que modificar el dbGrid, ya que los campos serán los mismos.

Por último, se me ocurre que puedes crear una vista. Para conseguir lo mismo que con la respuesta anterior. Que los campos de salida sean los mismos y así no tendrás que modificar el Grid.

NOTA: Veo que se me adelantaron.

Gabo 26-09-2007 12:16:41

Cita:

Empezado por gluglu (Mensaje 233920)
Una de las maneras para hacer lo que quieres es utilizar el evento OnGetText del campo FORMA_PAGO del DataSet en el cual vas a hacer la consulta.

No sé si tienes un DataSet para dicha consulta ? Pero si es así, puedes utilizar dicho evento que sería algo así como :


Código Delphi [-]procedure TForm1.IBDataSet1FORMA_PAGOGetText(Sender: TField;
var Text: string; DisplayText: Boolean);
begin
case IBDataSet1FORMA_PAGO.AsInteger of
0 : Text := 'Efectivo';
1 : Text := 'Transferencia';
end;
end;




De esta manera en el DBGrid que utilizas sale el texto que defines ewn esta función. (En tiempo de diseño, no. Pero en tiempo de ejecución, si).

Espero haberte ayudado. ;)

No, no tengo ningún control TIBDataset, de hecho jamás lo he ocupado. Sólo un TIBQuery y un TDataSource. ¿Sabes si hay alguna correspondencia entre el evento OnGetText del TIBDataset y alguno de los eventos del Dataset del DataSource, o me estoy liando?

¡Y claro que eres una ayuda! Aunque no me contestes la pregunta directamente, me sirve para seguir familiarizándome con el resto de los controles y sus eventos. ;)

Gabo 26-09-2007 12:24:21

Hola Neftalí, gracias por tu respuesta. :)

Cita:

Empezado por Neftali (Mensaje 233921)
Creo que sí puedes conseguirlo directamente. Añade los campos al DataSet (Tabla/Query) y una vez añadidos revisa los eventos OnGetText y OnSetText del campo Forma de Pago.

Lo mismo, no ocupo un Dataset... :(

Cita:

Empezado por Neftali (Mensaje 233921)
Si no quieres hacerlo así puedes modificar la consulta hacer la JOIN y conseguir el campo que necesitas. Si lo llamas igual que el anterior (y el anterior lo quitas) seguramente no tendrás que modificar el dbGrid, ya que los campos serán los mismos.

Vale, pero esta solución sería creando una nueva tabla, ¿no? Eso si podría hacerlo, pero lo que me gustaría saber es como hacerlo sin crear la tabla...

gluglu 26-09-2007 12:26:17

Perdón .... lo mismo es prácticamente utilizar el TIBDataSet que el TIBQuery.

No había sabido expresarme correctamente, y no me fijé detalladamente en tu exposición.

Pues bien. El DBGrid lo tendrás asociado al TDataSource, y a su vez el DataSource lo tendrás asociado al TQuery. Correcto. hasta aquí.

Lo que necesitas ahora es hacer doble click encima del elemento TQuery y ahí te aparecerá (en principio) una lista en blanco. De nuevo click derecho y añades todos los campos que te aparecen, que serán aquellos que has definido en tu consulta SQL.

Siguiente paso. Sobre el campo FORMA_PAGO haz click, y en Object Inspector selecciona los eventos. Tendrás el evento OnGetText y ahí pones el código que te puse anteriormente.

Y ya está. Con esto en tiempo de ejecución obtendrás el resultado esperado.

;)

gluglu 26-09-2007 12:28:23

Tampoco ví la respuesta de Neftalí. Pero creo que lo más fácil e inmediato es lo que he detallado en mi respuesta anterior.

Yo al menos lo utilizo en innumerables ocasiones de dicha manera. :p

Gabo 26-09-2007 13:06:30

Funciona muy bien con ese sistema, no lo conocía. :)

Gracias gluglu!!! Gracias Neftalí!!!

Lepe 26-09-2007 14:06:29

Alguien lo ha comentado ya, pero aquí va más detallado:

Crea una tabla Formapago con los campos idformapago autoincrement y Formapago de tipo varchar(20).

Crea una vista (View) que una la tabla Cliente y formapago.
Usa un TIBQuery para consultar esa vista enlazado a un TIBUpdateSql.

El query se usa para seleccionar un registro de la vista, (que ya incluye los campos idFormaPago y FormaPago) y el UpdateSql, se encarga de modificar la tabla cliente estableciendo el idformapago que se haya elegido de un DBLookUpComboBox.

La tabla formapago, puedes dejarla oculta para el usuario (o crear un simple Form que permita añadir formas de pago ... ya esto depende del tiempo que tengas). La forma de pago puede cambiar: cheque, efectivo, pagaré, por internet, etc, y solo tendrás que añadir un registro a esa tabla para que todo funcione sin problemas.

Si usas un carácter, después tienes que interpretar ese número en el código delphi y/o en consultas sqls, tendrás que modificar el código fuente y las sqls para añadir una nueva forma de pago.

Ten en cuenta que la tabla Formapago tendrá 4 o 5 registros como mucho, no supone mucha carga extra, pero simplifica muchisimo actualizaciones, borrados, etc, estableciendo la integridad referencial.

Por otra parte haces un correcto diseño de la Base de Datos, en cuanto a Normalización (por ejemplo).

Saludos

Saludos

gluglu 26-09-2007 14:28:26

Y como dijo Gabo que sabía hacer, no sería mejor que en vez de complicarnos la vida con un Vista adicional y tal, hacer directamente un Join en la consulta SQL y obtener los textos correspodientes según los valores del campo FORMA_PAGO.

Pero entiendo una vez más que esa no era la pregunta de Gabo, sino saber si se podía hacer sin crear precisamente esa tabla y sin el Join.

Pongo un caso articular mío que viene a cuento de mi hilo 'paralelo' que anda ahora mismo por aquí en el foro SQL.

Yo obtengo 3 campos de mi consulta SQL, Apellido1, Apellido2 y Nombre, y los quiero mostrar en una UNICA columna de un DBGrid, y en el 'formato' Apellido1 Apellido2, Nombre es decir los dos apellidos separados por un espacio y con una , del nombre. Pero condicionando a si existe o no el 2º Apellido, y a si existe o no también el Nombre obtenido en la consulta SQL.

Para ello me viene ideal la función OnGetText de un campo del DBGrid.

Código Delphi [-]
procedure TForm.IBDataSet1NOMBREGetText(Sender: TField;
  var Text: string; DisplayText: Boolean);
begin
  if IBDataSet1HABITAC.IsNull then
    Text := 'Todas las Habitaciones'
  else begin
    Text := IBDataSet1APELLIDO1.AsString;
    if not IBDataSet1APELLIDO2.IsNull then
      Text := Text + ' '  + IBDataSet1APELLIDO2.AsString;
    if not IBDataSet1NOMBRE.IsNull then
      Text := Text + ', ' + IBDataSet1NOMBRE.AsString;
  end;
end;

En cualquier caso, Gabo sabrá usar la que a él mejor le interese con las diferentes opciones que le estamos dando. ;)

Gabo 26-09-2007 14:58:48

Cita:

Empezado por gluglu (Mensaje 233944)
Y como dijo Gabo que sabía hacer, no sería mejor que en vez de complicarnos la vida con un Vista adicional y tal, hacer directamente un Join en la consulta SQL y obtener los textos correspodientes según los valores del campo FORMA_PAGO.

Pero entiendo una vez más que esa no era la pregunta de Gabo, sino saber si se podía hacer sin crear precisamente esa tabla y sin el Join.

Como decía "El Chavo": "Eso, eso, eso, eso..."

Es que a veces hay ciertos campos para los que no veo claro crear una tabla aparte (un campo ESTADO_CIVIL, por ejemplo), pero tampoco me gusta crearlos de una anchura tal que pueda contener un string, sino un valor que represente a dicho string.

Siguiendo con el ejemplo del estado_civil, no lo creo como un varchar(15) donde tenga que poner cada vez "Soltero", "Casado", etc., sino como un varchar(1) que contiene valores como 0, 1, etc. (o letras si alguien lo prefiere). Pero claro al desplegarlo en el DBGrid no quiero que aparezca el código sino lo que representa.

Cita:

Empezado por gluglu (Mensaje 233944)
Pongo un caso articular mío que viene a cuento de mi hilo 'paralelo' que anda ahora mismo por aquí en el foro SQL.

Yo obtengo 3 campos de mi consulta SQL, Apellido1, Apellido2 y Nombre, y los quiero mostrar en una UNICA columna de un DBGrid, y en el 'formato' Apellido1 Apellido2, Nombre es decir los dos apellidos separados por un espacio y con una , del nombre. Pero condicionando a si existe o no el 2º Apellido, y a si existe o no también el Nombre obtenido en la consulta SQL.

Para ello me viene ideal la función OnGetText de un campo del DBGrid.


Código Delphi [-]procedure TForm.IBDataSet1NOMBREGetText(Sender: TField;
var Text: string; DisplayText: Boolean);
begin
if IBDataSet1HABITAC.IsNull then
Text := 'Todas las Habitaciones'
else begin
Text := IBDataSet1APELLIDO1.AsString;
if not IBDataSet1APELLIDO2.IsNull then
Text := Text + ' ' + IBDataSet1APELLIDO2.AsString;
if not IBDataSet1NOMBRE.IsNull then
Text := Text + ', ' + IBDataSet1NOMBRE.AsString;
end;

end;

Pero para eso, ¿no te convendría más concatenar los campos en la consulta? Algo así como:

Código SQL [-]
SELECT CLIENTE_CODIGO, (CLIENTE_APELLIDOS ||' ' ||CLIENTE_NOMBRE) AS NOMBRE, 
           CLIENTE_NOMBRE, CLIENTE_APELLIDOS, etc...
FROM CLIENTE

Cita:

Empezado por gluglu (Mensaje 233944)


En cualquier caso, Gabo sabrá usar la que a él mejor le interese con las diferentes opciones que le estamos dando. ;)

Eso, eso, eso, eso...:D

Por cierto, gracias a ti también Lepe por tu respuesta.

gluglu 26-09-2007 15:07:28

La entonación a mi comentario anterior está en el 'If' :p

Devuélmeme tu en una misma consulta los siguientes valores (hacer hincapie especial en la separación de la coma (,) y en la utilización de espacios o no).

Sánchez Gómez, Juan
Pérez, José
Smith, Robert
Rodriguez López

Con la concatenación, en primer lugar, no podría poner la condición de mostrar la , si existe o no el nombre. Y lo mismo pasaría con la concatenación en el caso de tener o no dos apellidos.

Y adicionalmente, por ejemplo en el caso que expuse arriba, si los tres campos son null, devolver un texto determinado a representar en el DBGrid. Todo esto creo que es imposible con una simple concatenación en la consulta SQL. Es para ello que utilizo frecuentemente la función OnGetText.

Gabo 26-09-2007 15:21:11

Ya entiendo :), eso me pasa por no haber revisado bien tu código y entender lo que hacía en primer lugar... :o:p:D

Neftali [Germán.Estévez] 26-09-2007 16:02:38

Cita:

Empezado por Gabo (Mensaje 233925)
Lo mismo, no ocupo un Dataset...

El Query o la Tabla derivan del TDataSet, por lo tanto sirven también. Actílvalos y haz un Click derecho para acceder a los Fields (FieldEditor); Desde ahí hay una opción para añadirlos todos.

Cita:

Empezado por Gabo (Mensaje 233925)
...pero esta solución sería creando una nueva tabla, ¿no? Eso si podría hacerlo, pero lo que me gustaría saber es como hacerlo sin crear la tabla...

¿Pero el angun lado deberás guardar los valores correspondientes a los enteros?
O el una tabla o como hemos comentado antes, en el DataSet.
La otra opción sería usar CASE o IF en la consulta si los valores son pocos.

De todas ellas me inclino por la de la tabla nueva (si es posible).

Gabo 26-09-2007 16:11:03

Cita:

Empezado por Neftali (Mensaje 233962)
El Query o la Tabla derivan del TDataSet, por lo tanto sirven también. Actílvalos y haz un Click derecho para acceder a los Fields (FieldEditor); Desde ahí hay una opción para añadirlos todos.

Sí, de hecho lo he solucionado así. Desconocía esas opciones, gracias. :)

Cita:

Empezado por Neftali (Mensaje 233962)
¿Pero el angun lado deberás guardar los valores correspondientes a los enteros?
O el una tabla o como hemos comentado antes, en el DataSet.
La otra opción sería usar CASE o IF en la consulta si los valores son pocos.

De todas ellas me inclino por la de la tabla nueva (si es posible).

Por ahora lo estoy guardando en el Dataset. El argumento de porqué no lo guardo en una tabla está aquí.

juanelo 26-09-2007 16:41:43

Hola Gabo,
Para mi lo mas sensato es utilizar un ClientDataSet que contenga todos los campos de tu query y ademas le adiciono un campo internalCalc que sea el que se calcule en tiempo de ejecucion en se evento OnCalcFields ... asi vuelves independiente tus datos de la forma en la que los visualizas (Siempre existe la de crear una tabla con los correspondientes valores y hacer un join).
Saludos

Gabo 26-09-2007 16:58:17

Cita:

Empezado por juanelo (Mensaje 233978)
Hola Gabo,
Para mi lo mas sensato es utilizar un ClientDataSet que contenga todos los campos de tu query y ademas le adiciono un campo internalCalc que sea el que se calcule en tiempo de ejecucion en se evento OnCalcFields ... asi vuelves independiente tus datos de la forma en la que los visualizas (Siempre existe la de crear una tabla con los correspondientes valores y hacer un join).
Saludos

¡Y seguimos con la tablita y su join! :D:D:D

Gracias por la sugerencia, aunque me sigue pareciendo mejor la idea de gluglu. No me implica agregar ningún otro componente y la encuentro más simple... ;)

Lepe 27-09-2007 01:44:58

Cuando te toque modificar un programa entero buscando el 0,1,2 etc.. modifcar fuentes,sqls, compilar, probar, rehacer instalador y llevar al cliente.... después nos contarás lo pesados que fuimos con la tablita :D:p:p

Saludos

juanelo 27-09-2007 17:01:01

Cita:

Empezado por Lepe (Mensaje 234216)
Cuando te toque modificar un programa entero buscando el 0,1,2 etc.. modifcar fuentes,sqls, compilar, probar, rehacer instalador y llevar al cliente.... después nos contarás lo pesados que fuimos con la tablita :D:p:p

Saludos

Estoy 1000% de acuerdo con Lepe. Recordaras .... si tan solo hubiera un tabla con ... pero en fin esperemos que este tu proyecto no vaya para alla y que te salga lo mejor posible.
Saludos

Gabo 01-10-2007 09:08:00

Hola!!

Perdón por la demora pero hemos estado con festivos por acá :D:D

En general, prefiero usar tablas para esos menesteres, pero insisto en que hay casos en que no lo veo necesario, como el ejemplo mencionado del "Estado_civil". Aunque pase el tiempo no se va a crear ningún nuevo estado civil, por lo que aunque me toque recompilar mi código muchas veces más por n motivos, nunca haré una modificación en cuanto a eso.


La franja horaria es GMT +2. Ahora son las 17:34:36.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi