Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Tablas planas (https://www.clubdelphi.com/foros/forumdisplay.php?f=20)
-   -   Problemas con FORMAT y SUM (https://www.clubdelphi.com/foros/showthread.php?t=94706)

Dexter182 31-05-2020 20:51:40

Problemas con FORMAT y SUM
 
Estoy intentando hacer algo simple como mostrar en un DBGrid una columna como Currency.
Si bien lo he logrado exitosamente en otras oportunidades, esta vez es un campo calculado y no lo puedo hacer andar.
La consulta es esta:
Código Delphi [-]
      Modulo.Consulta.Active := FALSE;
      Modulo.Consulta.SQL.Clear;
      Modulo.Consulta.SQL.Add('SELECT Month(Fecha)as Mes, SUM(Total) as Total FROM Ventas');
      Modulo.Consulta.SQL.Add('WHERE Year(Fecha) = :pFecha');
      Modulo.Consulta.SQL.Add('GROUP BY Month(Fecha)');
      Modulo.Consulta.Parameters.ParamByName('pFecha').Value := Edit_Anio.Text;
      Modulo.Consulta.Active := TRUE;
He probado las siguientes opciones:


Opción 1:
Código Delphi [-]
Modulo.Consulta.SQL.Add('SELECT Month(Fecha)as Mes, FORMAT(SUM(Total),"Currency") as Total FROM Ventas');
Resultado: El DBGrid no muestra nada en esa columna

Opción 2:
Código Delphi [-]
Modulo.Consulta.SQL.Add('SELECT Month(Fecha)as Mes, CCur(SUM(Total)) as Total FROM Ventas');
Resultado: El DBGrid muestra los resultados igual que en la consulta original

Opción 3: Varios intentos en el evento DrawCell con cosas del siguiente estilo
Código Delphi [-]
DBGrid_Ventas.Fields[1].SetFieldType(ftCurrency);
Resultado: Idem anterior.

Estoy trabajando en Delphi 7, con ADO y base de datos en Access.

¿En que le puedo estar errando?.

Gracias de antemano!

duilioisola 01-06-2020 12:54:22

¿Has probado modificando la propiedad DisplayFormat del campo?
Esto evita que tengas que hacer cosas raras en el SQL.

No tengo Delphi a mano en este momento, pero esta es la idea:
Código Delphi [-]
  FieldByName('TOTAL').DisplayFormat := '0.00';
  // o como lo muestras en tu código
  DBGrid_Ventas.Fields[1].DisplayFormat := '0.00';

Dexter182 01-06-2020 14:04:10

Antes que nada, ¡gracias por contestar!


Recuerdo haber probado la propiedad DisplayFormat y estoy casi seguro que lo hice también en el evento DrawCell.
Por las dudas lo voy a probar de nuevo en la tarde, que de tantas cosas que leí y probé tengo un lío importante en la cabeza. :D

kuan-yiu 01-06-2020 14:55:32

Creo que tienes que definir los campos de forma persistente en la query (también sirve en un ClientDataSet) y ahí puedes indicar que es tipo Currency. Lo hice hace tiempo pero no lo encuentro y lo estoy diciendo de memoria por lo que no recuerdo si deberás tocar también DisplayFormat para que se representen como desees.
Si el campo es calculado después de la consulta (cualquier cosa distinta de fkData) es cuando no es posible definirlo como Currency pero en tu caso es una de las columnas de la query por lo que debería funcionar.

duilioisola 02-06-2020 09:17:35

Este es un ejemplo real que tengo en mi código:
No son campos persistentes, por lo que tengo que explicitamente decirle que tipo de campo es.
Lo que busco es que las fechas no muestren la hora y los valores numéricos se muestren con dos decimales y separador de miles.
Código Delphi [-]
procedure TDMEmpleado.xEmpleadoAfterOpen(DataSet: TDataSet);
begin
  // Formato de campos
  with xEmpleado do
  begin
     TDateField(FieldByName('FECHA_NACIMIENTO')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_ANTIGUEDAD')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_INICIO_CONTRATO')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_FIN_CONTRATO')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_VENCIMIENTO_EPI')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_VALIDEZ_CURSO')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_ENTREGA_MATERIAL_PRESTADO')).DisplayFormat := 'dd/mm/yyyy';
     TDateField(FieldByName('FECHA_REVISION_MEDICA')).DisplayFormat := 'dd/mm/yyyy';

     TNumericField(FieldByName('PORC_JORNADA')).DisplayFormat := ',0.00';
     TNumericField(FieldByName('HORAS_ANUALES')).DisplayFormat := ',0.00';
  end;

  // Tablas unidas mediante DataSource
  xEpi.Open;
  xCurso.Open;
  xMaterialPrestado.Open;
  xDocumento.Open;
  xRevisionMedica.Open;

[...]

Este código lo he puesto en el AfterOpen porque los campos son dinámicos.
En el caso de tener campos estáticos, pongo el código de formato en el OnCreate del DataModule.
He visto que para DataSets grandes es mucho más rápido tener los formatos puestos antes de abrirlos.

duilioisola 02-06-2020 09:23:35

Este es otro código que encontré.
En este caso no conozco los campos que saldrán, pues el SQL lo proporciona el usuario.
Es parte de una extracción de datos.

Código Delphi [-]
procedure TDMExtraccionDatos.Ejecutar;
var
  i : integer;
begin
  with xResultado do
  begin
     DisableControls;
     try
        Close;
        Open;

        // Agrego DisplayFormat segun el tipo de campo
        for i := 0 to FieldCount - 1 do
        begin
           with Fields[i] do
           begin
              if DataType in [ftSmallint, ftInteger, ftWord] then
                 TIntegerField(Fields[i]).DisplayFormat := '0'
              else
              if DataType in [ftFloat, ftCurrency] then
                 TFloatField(Fields[i]).DisplayFormat := ',0.000'
              else
              if DataType in [ftDateTime, ftDate, ftTime] then
                 TDateTimeField(Fields[i]).DisplayFormat := 'dd/mm/yyyy hh:nn:ss';
           end;
        end;
     finally
        EnableControls;
     end;
  end;
end;

Dexter182 02-06-2020 13:37:27

¡Muchísimas gracias por las respuestas! ||-||

Ayer no tuve tiempo de probar nada.
Espero hoy poder hacerlo, así les comento como me fue.

Consulta: ¿en que evento llamás al procedimiento TDMExtraccionDatos?


Saludos y nuevamente gracias!

duilioisola 02-06-2020 14:09:33

Tengo un formulario que muestra las diferentes extracciones de datos personalizadas.
Cada extracción de datos es un SQL (SELECT ... FROM ... WHERE ...)
El SQL se asigno al DataSet xResultado.SelectSQL.
En un panel se crean tantos componentes TEdit como parámetros haya en el WHERE. La propiedad Tag del TEdit es el indice del parámetro.
Hay un botón para ejecutar la consulta pasándole los parámetros. Este es el evento que llama a TDMExtraccionDatos.Ejecutar.
Te dejo el código por si te sirve de algo...

Código Delphi [-]
procedure TFMExtraccionDatos.BEjecutaClick(Sender: TObject);
var
  i : integer;
begin
  inherited;
  if (PCMain.ActivePage = TSFicha) then
  begin
     // Recorro los componetes de panel de parameros
     for i := 0 to PNLFicha.ComponentCount - 1 do
     begin
        // Si el componente es un TEdit
        if (PNLFicha.Components[i] is TEdit) then
        begin
           // Con el parámetro asociado al TEdit...
           with DMExtraccionDatos.xResultado.Params[TEdit(PNLFicha.Components[i]).Tag] do
           begin
              if (DataType in [ftString, ftWideString]) then
                 AsString := TEdit(PNLFicha.Components[i]).Text;

              if (DataType = ftFloat) then
                 AsFloat := StrToFloatDef(TEdit(PNLFicha.Components[i]).Text, 0);

              if (DataType in [ftInteger, ftSmallint]) then
                 AsInteger := StrToIntDef(TEdit(PNLFicha.Components[i]).Text, 0);

              if (DataType = ftDateTime) then
                 AsDateTime := StrToDateTime(TEdit(PNLFicha.Components[i]).Text);
           end;
        end;
     end;

     // Ejecuto el SQL
     DMExtraccionDatos.Ejecutar;
  end
  else
  begin
     PCMain.ActivePage := TSFicha;
     PCMainChange(Sender);
     CreaParametros;
  end;
end;

Dexter182 02-06-2020 14:53:21

OK. ¡¡¡Muchísimas gracias por la pronta respuesta!!!

Dexter182 02-06-2020 23:11:02

¡Lo hice andar! ¡Mil gracias! ||-||


El código que me funcionó fue este:
Código Delphi [-]
TFloatField(Modulo.Consulta.FieldByName('Total')).DisplayFormat := '$ ,0.00; $-,0.00';
"Consulta" es un ADOQuery


Este código no logré hacerlo andar:
Código Delphi [-]
DBGrid_Ventas.Fields[1].DisplayFormat := '0.00';
Me saltaba el siguiente error: [Error] Informe_Ventas.pas(63): Undeclared identifier: 'DisplayFormat'


Cita:

Empezado por duilioisola
En este caso no conozco los campos que saldrán, pues el SQL lo proporciona el usuario.

Cita:

Empezado por duilioisola
El SQL se asigno al DataSet xResultado.SelectSQL.

Seré curioso en tu manera de trabajar.
Lo que yo hago es usar un AdoQuery para consultas y un ADOCommand para Altas, Bajas y Modificaciones, siempre asignando las sentencias SQL desde mi código fuente.
O sea, reutilizo los mismos componentes para todas las consultas, etc.
¿Como es eso de que el SQL lo proporciona el usuario?



Agradezco muchísimo la ayuda y la buena predisposición!!! ^\||/^\||/^\||/

duilioisola 03-06-2020 09:10:41

Cita:

Me saltaba el siguiente error: [Error] Informe_Ventas.pas(63): Undeclared identifier: 'DisplayFormat'
Fields[1] se refiere a un campo de un dataset (Consulta).
El DBGrid tiene campos tipo TField. Este tipo de campo es genérico y tiene las propiedades y métodos básicos de ese objeto.
TFloatField es un descendiente de TField y agrega alguna funcionalidad extra. Por ejemplo, la propiedad para dar formato al dato(número) que contiene.
Para poder asignar esta propiedad deberás hacer un cast para decirque el el objeto es de tipo TFloatField.
Código Delphi [-]
TFloatField(DBGrid_Ventas.Fields[1]).DisplayFormat := '0.00';

Dexter182 04-06-2020 01:46:43

Perfecto!
Ahora así lo pude hacer andar también de esa manera.
¡Muchas gracias! ||-||


La franja horaria es GMT +2. Ahora son las 16:32:31.

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