Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Currency desde DBGrid a StringGrid sin perder precisión (https://www.clubdelphi.com/foros/showthread.php?t=90666)

Dexter182 07-08-2016 21:26:11

Currency desde DBGrid a StringGrid sin perder precisión
 
Estoy convencido que esto que voy a preguntar debe estar en algún lugar del foro, pero no lo he podido encontrar.

Resulta que tengo una aplicación típica de punto de venta, en la que muestro los resultados de la búsqueda de artículos en un DBGrid y luego desde este elijo que artículo se agregará a la venta (armada en un StringGrid).
Lo que va sucediendo es que desde el número original, al que se muestra en pantalla en la búsqueda en formato moneda, al que posteriormente se agrega al StringGrid se va perdiendo precisión con los redondeos.
Los problemas son con los artículos cuyo precio es muy pequeño y cuando se venden mucho de ellos. Por ejemplo: en 200 artículos de $0.13 hay una diferencia de $0.8 (80 centavos).
Si bien no es mucho, me gustaría saber si es factible acomodar eso y quizás lo más importante ¿tiene sentido hacerlo?.

La consulta SQL es la siguiente:
Código Delphi [-]
Modulo.Consulta.Active := FALSE;
Modulo.Consulta.SQL.Clear;
Modulo.Consulta.SQL.Add('SELECT Cod_Producto as Código, Desc_Producto as Descripción,');
Modulo.Consulta.SQL.Add('FORMAT((Precio+(Precio*(Porcentaje_Ganancia/100))+(Precio+(Precio*(Porcentaje_Ganancia/100)))*0.21), "Currency") as Precio,');
Modulo.Consulta.SQL.Add('Cant_Existente as Stock FROM Productos');
Modulo.Consulta.SQL.Add(Filtro);
Modulo.Consulta.Active := TRUE;

Saludos y gracias de antemano!

Casimiro Notevi 07-08-2016 22:57:36

En eso no tiene absolutamente nada que ver los dbgrids, stringgrinds, etc.
¿Qué tipo de dato usas en los campos de la tabla para almacenar importes?

Dexter182 07-08-2016 23:05:55

Hola Casimiro.
Muchas gracias por responder.

El campo Precio es del tipo Moneda (uso una base de datos de Access XP).

Saludos!

ecfisa 08-08-2016 18:09:58

Hola.

¿ Con que función pasas el valor moneda a las celdas del StringGrid ?

Saludos :)

Dexter182 09-08-2016 20:16:58

Hola ecfisa!.

Muchas gracias a vos también por responder.

Al importe lo tomo desde el DBGrid de la siguiente forma:
Código Delphi [-]
StringGrid.Cells[3,i] := DBGrid_Resultado.Fields[2].Text

Por lo que me estás preguntando, intuyo que no es la manera más correcta. :o

Saludos!

ecfisa 09-08-2016 20:48:29

Hola Dexter182.

No, no digo que no sea correcta... pero por las dudas proba de este modo:

Código Delphi [-]
...
uses Math;

...
  StringGrid.Cells[3, i] := FloatToStr( RoundTo(DBGrid_Resultado.Fields[2].AsCurrency, -2) );
Y también recorda que es mejor usar la función FieldByName que la propiedad vectorial Fields, ya que si algún día cambias el órden de las columnas podrías tener problemas.

Saludos :)

Dexter182 10-08-2016 05:35:08

Ecfisa: ¡Nuevamente gracias por tu tiempo!

Probé de la manera que me recomiendas y me salta una excepción EConverterError '$ 38,54' is not a valid floating point value.
Por las dudas cambié el FloatToStr por CurrToStr, pero obtuve los mismo resultados.
Cita:

Empezado por ecfisa (Mensaje 507527)
Y también recorda que es mejor usar la función FieldByName que la propiedad vectorial Fields, ya que si algún día cambias el orden de las columnas podrías tener problemas.

OK!. La verdad que no he tenido en cuenta ese detalle.
Además mejora la legibilidad del código.
¡Gracias por el consejo!

Saludos!

AgustinOrtu 10-08-2016 05:54:57

Crea un registro TFormatSettings e indica los parámetros de conversión acorde a la configuración regional de tu sistema. Ese registro lo envías como parámetro a las versiones sobrecargadas de cualquier función de conversión

Dexter182 13-08-2016 05:32:36

Gracias Agustín por brindar otra sugerencia!

Yo creo que debo tener un gigante error de concepto en como usar los DBGrids, más que nada por esto que me dice Casimiro:
Cita:

Empezado por Casimiro Notevi
En eso no tiene absolutamente nada que ver los dbgrids, stringgrinds, etc.

He leído en otros hilos parecidos al mío comentarios similares de Casimiro y nunca entendí muy bien a que se refiere.
Tampoco logro sacarle provecho a lo que sugiere Agustín y estoy convencido de que es parte del mismo error de concepto.

Cita:

Empezado por ecfisa
Y también recorda que es mejor usar la función FieldByName que la propiedad vectorial Fields

¿Puede ser que la propiedad FieldByName no esté disponible directamente desde el DBGrid?.
Puedo usarla directamente desde un ADOQuery, pero para usarla desde un DBGrid tengo que hacer algo como esto:
Código Delphi [-]
StringGrid.Cells[3, i] := DBGrid_Resultado.DataSource.DataSet.FieldbyName('Precio').AsString;
Agradezco a todos su ayuda y les pido perdón por mi ignorancia. :o

Saludos!

AgustinOrtu 13-08-2016 05:39:29

Casimiro intenta decirte que los controles visuales simplemente se limitan a mostrar datos

Los datos propiamente dichos estan en un TDataSet (ni siquiera un ADOQuery, que es una implementacion; TDataSet es abstracto)

Cuanto mas abstractas sean las clases que usas, mas facil es de realizar mantenimientos mas adelante a tu codigo
Cuanto mas concretas sean las clases que usas, es mas dificil porque al "atarte" a una implementacion particular, si luego tenes que cambiar a otra, podes perder algunas caracteristicas o te obliga a cambiar la forma de hacer las cosas

En el DBGrid no tenes la propiedad FieldByName porque es de un DataSet

Osea, en algun momento conectaste tu DBGrid a un DataSet usando de intermediario un DataSource. Tenes que tener muy presente que haya un DataSource en el medio, el DataSet que conoce el Grid es uno solo. En alguna parte de tu codigo estas creando esa relacion

Código Delphi [-]
  AlgunDataSource.DataSet := TuDataSet/Query/etc;
  DBGrid.DataSource := AlgunDataSource;

Si haces la prueba de cerrar "TuDataSet/Query/etc" o modificar un campo, o lo que fuera, el Grid se "actualiza"

Por lo tanto para acceder a los datos del Grid, la forma correcta es usando el DataSet.

Casimiro Notevi 13-08-2016 10:35:06

Cita:

Empezado por AgustinOrtu (Mensaje 507653)
Casimiro intenta decirte que los controles visuales simplemente se limitan a mostrar datos...

^\||/^\||/^\||/
AgustinOrtu lo ha dejado claro, un dbgrid es solamente una "ventana" a los datos, un lugar por donde mostrar, repito, mostrar, mostrar los datos del dataset. Es en el dataset donde debes hacer todo el trabajo. La ventana mostrará lo que hagas en el dataset. La ventana es el dbgrid. Si pintas tu habitación de color azul, desde la calle la gente verá a través de tu ventana la habitación azul. Si la pintas de verde, la gente verá a través de la ventana que la has pintado verde. Pero tú no haces nada con la ventana, salvo cambiarle el tamaño, ponerle unas cortinas para que no te vean o cerrarla y luego abrir la ventana en otra habitación para que la gente vea otros datos/muebles. Piensa siempre en dbgrid = ventana.

ecfisa 13-08-2016 23:30:29

Hola Dexter182
Cita:

Empezado por Dexter182 (Mensaje 507652)
...
¿Puede ser que la propiedad FieldByName no esté disponible directamente desde el DBGrid?.
Puedo usarla directamente desde un ADOQuery, pero para usarla desde un DBGrid tengo que hacer algo como esto:
Código Delphi [-]
StringGrid.Cells[3, i] := DBGrid_Resultado.DataSource.DataSet.FieldbyName('Precio').AsString;
Agradezco a todos su ayuda y les pido perdón por mi ignorancia. :o

El método FieldByName existe en la clase TDataSet, de modo que no tendrías que tener ningún problema en invocarlo como mostras arriba.

Desde el componente DBGrid podes acceder al DataSet asociado y al campo mismo, ejemplo:
Código Delphi [-]
...
var
  dts: TDataSet;
  fld: TField;
begin
  dts := DBGrid_Resultado.DataSource.DataSet;
  fld := dts.FieldByName('Precio');
  ShowMessageFmt('%s%s%s%s%s',
    [DBGrid_Resultado.DataSource.DataSet.FieldByName('Precio').AsString, #10,  // [1]
    dts.FieldByName('Precio').AsString, #10,  // [2]
    fld.AsString]);  // [3]
Mostrará tres veces el valor correspondiente al registro actual. Es decir que [1], [2] y [3] son diferentes modos de hacer referencia al mismo registro (o valor).

Saludos :)

Dexter182 14-08-2016 02:25:26

¡¡¡Muchísimas gracias a los tres!!!!
Han sido realmente muy claros.

Nunca me percaté de esto que tan claramente me explicaron y siempre accedí a los datos desde el mismo DBGrid (es decir, siempre convirtiendo de texto a lo que fuese necesario).
Tengo varias cosas para corregir en mi programa. :o

Muchas gracias de verdad!!!! ^\||/

PD: Si bien no me dedico a la programación, mi trabajo se ha facilitado mucho con un programa que hice en Delphi y al que siempre le voy agregando, modificando y arreglando cosas y este foro es mi fuente habitual de consulta para intentar desasnarme.


La franja horaria es GMT +2. Ahora son las 16:52:53.

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