PDA

Ver la Versión Completa : Suma de una columna de un DBGRID


Pollo2004
20-10-2008, 20:00:48
Hola, nuevamente quisiera q alguien me corrija esto, xq me esta volviendo loco y no logro q haga lo q yo pretendo.
Quiero q al ingresar un producto y se calcule el precio de ese item, lo vaya a acumulando en y sumando en otro campo calculado de mi tabla para luego sacar el total a pagar.

1º codigo es este:

tengo un campo calculado para sacar el precio a pagar por item, entonces lo q hago es acumularlo y lo muestro (cre q el error esta q la acumulacion la hago en el procedimiento oncaculated de la tabla, en el mismo q calculo el precio del item entonces no me lo acumula.)
el codigo seria asi:
var
acum: currency;

procedure TForm4.Table4CalcFields(DataSet: TDataSet);
begin
table4Total.ascurrency:= table4Cantidad.AsInteger * Table4Precio.asCurrency;
acum:= acum + table4Total.ascurrency;
end;

2º creo q esta debe ser la correcta pero no se como hacerlo.
ah medida q se ingreso una fila acumularlo a una varible y mostrar eso.
No se como moverme fila por fila y ingresar al dato ese.
Mi idea es asi lo escribo es pseudocodigo:

cuando pasa a la siguiente fila
acumulador:= dbgrid1.columns[n] + acumulador;

Gracias!!!

Caral
20-10-2008, 20:44:07
Hola
No estoy muy seguro, lo hice hace algun tiempo y no me acuerdo bien, pero creo que el tutorial de facturación (http://www.terawiki.clubdelphi.com/archivos/Delphi-Win32/Tutoriales/Tutorial%20Facturacion.zip) hace lo que necesitas, revisalo, tal vez te sirva.
Saludos

enecumene
20-10-2008, 20:50:38
Hola, colocar esto en los eventos AfterDelete y AfterPost de tu dataset, debes adaptarlo a tu manera:

procedure TFReposicion.cdDetallesAfterDelete(DataSet: TDataSet);
Var
Suma: Double;
Campo: TField;
Begin
Suma:=0;
Try
With cdDetalles Do Begin
DisableControls;
Campo := FieldByName('valor');
First;
While Not EoF Do Begin
Suma := Suma + Campo.AsFloat;
Next;
End;
End;
Finally
cdDetalles.EnableControls;
End;
dsCaja.DataSet.FieldByName('total').AsFloat := Suma;
end;

Saludos.

Pollo2004
21-10-2008, 11:16:17
hola enecumene, a ver si entiendo ...
campo: tfield; --->esto es la declarion de un acum de tipo tfield?
Campo := FieldByName('valor');---> le asigno a campo el valor q tengo en ese campo..(mi caso total?), y porq pusiste entre literales 'valor'
y donde pusiste cdDetalles y cdCaja te estas refiriendo al nombre de las tablas?
Perdon por todas las preguntas, pero prefiero preguntar y sacarme las dudas antes de decir q si como los locos!

enecumene
21-10-2008, 14:03:53
Hola Pollo2004, TField es una clase tipo campo, Campo := FieldByName('valor'); donde "Valor" es el campo de la columna que vas a sumar y restar, cdDetalles es un dataset (Puede ser TTable o TQuery) y dsCaja es un datasource donde muestro el total (Pero eso es en mi caso, en tu caso puede ser un TTable o TQuery en el mismo Form), recordad colocarlos en los eventos mencionados anteriormente en el dataset asociado al DBGrid.

Saludos.

enecumene
22-10-2008, 21:00:22
Hola, ¿te resultó? ¿Conseguiste otro código? :confused: :confused:

Saludos.

Pollo2004
23-10-2008, 03:54:03
hola enecumene, no he logrado compilarlo, te paso como lo deje a tu codigo y te indico donde me sale el error
procedure TForm5.TDetaAfterDelete(DataSet: TDataSet);
var
Suma: Double;
Campo: TField;
Begin
Suma:=0;
Try
With DsDeta Do Begin
TDeta.DisableControls;
Campo := TDetaTotal;
TDeta.First;
While Not EoF Do Begin
Suma := Suma + Campo.AsFloat;
Next;
End;
End;
Finally
TDeta.EnableControls;
End;
TDeta.TDetaSinIva.AsCurrency := Suma; (aca tengo el error al compilar,TDetaSinIva es un campo calculado)
end;


Me larga un error diciendo q no esta declarado el identidicador TDetaSinIva.

mañana lo voy a ver con un poco mas tiempo, para ver si le encuentro la solucion, cualquier sugerencia es bienvenida!
saludos! Nos vemos!

enecumene
23-10-2008, 13:54:45
Hola, Amigo no puedes mostrar un resultado en un campo calculado debes mostrarlo en un campo normal o en un edits, cuando tengas más tiempo estúdialo y verás que es un código muy sencillo ;).

Saludos.

jhonny
23-10-2008, 14:12:23
debes mostrarlo en un campo normal o en un edits...


O en un TAggregateField ;)

Pollo2004
28-10-2008, 01:07:20
Hola nuevamente, perdon por la demora....enecumene he logrado compilar tu idea, pero no me funciona, la verdad no se xq...
corregi mi error de esta manera, puse un label.caption:= currtostr(suma);

Bueno aca no me muestra nada.

Yo lo q me gustaria es recorrer el dbgrid y controlar desde ahi las filas q ingreso, pero no se como moverme x fila, si alguien lo sabe soy todo oido..

Por las dudas te paso mi form para q le hechen una miradita
unit Factura;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, StdCtrls, DBTables, Mask, DBCtrls, Grids, DBGrids, ExtCtrls,
Buttons;
type
TForm5 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;
DBGrid1: TDBGrid;
DBText1: TDBText;
DBText2: TDBText;
DBText3: TDBText;
DBText4: TDBText;
DBLookupComboBox1: TDBLookupComboBox;
DBText5: TDBText;
DBEdit1: TDBEdit;
DBText6: TDBText;
DSCliente: TDataSource;
TCliente: TTable;
DSProd: TDataSource;
TProd: TTable;
DSFact: TDataSource;
TFact: TTable;
DSDeta: TDataSource;
TDeta: TTable;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
TClienteIdCliente: TStringField;
TClienteRazonSocial: TStringField;
TClienteDireccion: TStringField;
TClienteLocalidad: TStringField;
TClienteCodigoPostal: TFloatField;
TClienteTelefono: TFloatField;
TClienteCuitCuil: TFloatField;
TProdCodProducto: TStringField;
TProdDetalle: TStringField;
TProdCosto: TCurrencyField;
TProdPrecioLista: TCurrencyField;
TProdStock: TFloatField;
TProdStockMin: TFloatField;
TFactNumFact: TFloatField;
TFactTipo: TStringField;
TFactFecha: TDateField;
TFactTotal: TCurrencyField;
TFactIdCliente: TStringField;
TDetaIditem: TAutoIncField;
TDetaCodProducto: TStringField;
TDetaCantidad: TFloatField;
TDetaNumFactura: TFloatField;
TDetaPrecioLista: TCurrencyField;
TDetaDetalle: TStringField;
TDetaTotal: TCurrencyField;
SpeedButton1: TSpeedButton;
BitBtn1: TBitBtn;
TDetaPrecio: TCurrencyField;
Label4: TLabel;
Label5: TLabel;
TFactSubTot: TCurrencyField;
TDetaSinIva: TCurrencyField;
Label6: TLabel;
procedure FormActivate(Sender: TObject);
procedure TDetaCalcFields(DataSet: TDataSet);
procedure DBGrid1Enter(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure TDetaCantidadValidate(Sender: TField);
procedure BitBtn1Click(Sender: TObject);
procedure TDetaAfterDelete(DataSet: TDataSet);



private
{ Private declarations }
public
{ Public declarations }
end;
var
Form5: TForm5;
NFact: integer;
implementation
{$R *.dfm}
procedure TForm5.FormActivate(Sender: TObject);
begin

TFact.last;
Tfact.edit;
NFact:= TFactNumFact.asinteger;
NFact:= NFact + 1;
TFact.append;
TFactFecha.AsDateTime:= now;
TfactNumFact.AsInteger:= NFact;
end;

procedure TForm5.TDetaCalcFields(DataSet: TDataSet);
begin
TDetaTotal.ascurrency:= TDetaCantidad.asinteger * TDetaPrecio.ascurrency;
end;
procedure TForm5.DBGrid1Enter(Sender: TObject);
begin
if TFact.state in dseditmodes then
TFact.post;
TDeta.append;
end;
procedure TForm5.SpeedButton1Click(Sender: TObject);
begin
TDeta.Append;
TDeta.Post;
if messagedlg ('LA FACTUA FUE CREADA CON EXITO', mtInformation, mbokCancel,0) = mrok
then
form5.close;
end;

procedure TForm5.TDetaCantidadValidate(Sender: TField);
begin
if TDetaCantidad.asinteger > TProdStock.asinteger then
showmessage ('NO HAY SUFICIENTE STOCK PARA ESTE PEDIDO')
else
TProd.edit;
TProdStock.AsInteger:= TProdStock.AsInteger - TDetaCantidad.asinteger;
TProd.post;
end;
procedure TForm5.BitBtn1Click(Sender: TObject);
begin
TFact.Cancel;
TDeta.edit;
TDeta.Prior;
TDeta.Delete;
Form5.Close;
end;
procedure TForm5.TDetaAfterDelete(DataSet: TDataSet);
var
Suma: Double;
Campo: TField;
Begin
Suma:=0;
Try
With DsDeta Do Begin
TDeta.DisableControls;
Campo := TDetaTotal;
TDeta.First;
While Not EoF Do Begin
Suma := Suma + Campo.AsFloat;
Next;
End;
End;
Finally
TDeta.EnableControls;
End;
label6.caption := currtostr(Suma);
end;


end.

Gracias otra vez por el aguante y las pilas q le ponen!!!

Caral
28-10-2008, 01:13:15
Hola
La verdad es que he seguido el hilo y cada vez entiendo menos.
No se exactamente lo que se pretende, me da la impresión de que se quiere sumar los datos que hay en un campo que presenta un dbgrid, pero no entiendo por que el uso de un campo calculado.
Me pongo a pensar: Que pasa si no se quiere calcular todos los campos del dbgrid o si hay algún error y se quiere corregir?.
No se, no lo capto.
Saludos

Pollo2004
28-10-2008, 02:30:56
Hola
La verdad es que he seguido el hilo y cada vez entiendo menos.
No se exactamente lo que se pretende, me da la impresión de que se quiere sumar los datos que hay en un campo que presenta un dbgrid, pero no entiendo por que el uso de un campo calculado.
Me pongo a pensar: Que pasa si no se quiere calcular todos los campos del dbgrid o si hay algún error y se quiere corregir?.
No se, no lo capto.
Saludos

Mira lo q yo pretendo hacer es una factura y a medida q ingreso un producto, calculo precio * cantidad y me da el resultado de ese producto, ok? hasta ahi todo claro, el tema es cuando ingreso otro producto tengo q hacer lo mismo, pero a su vez tengo q acumular un total general de la factura, q viene a ser todos los resultados de precio * cantidad de todos los productos q vendi.

Espero aclarar tu panorama y q puedas aportar tus ideas. gracias caral!

enecumene
28-10-2008, 02:40:35
Hola, el código que te propuse hace exactamente eso que quieres hacer, lo uso y me funciona perfecto, te aconsejo revises bien donde está fallando.

Saludos.

Pollo2004
29-10-2008, 02:06:35
Hola, el código que te propuse hace exactamente eso que quieres hacer, lo uso y me funciona perfecto, te aconsejo revises bien donde está fallando.

Saludos.

Estoy trantando de seguir paso a paso el codigo y me entro una duda con respecto a la sentencia WITH, funciona como un IF? o es de la ecepcion?
el disablecontrols coloca la tabla en q estado? despues el resto lo entiendo.

otra duda q me entro mirando detenidamente el codigo es el soguiente!
Table1.first, lo coloca en el inicio de la tabla, esto es correcto?
Entonces me pregunto, me sumaria todos los registros, viejos, nuevos de otras facturas completamentes todos?, o al existir una integridad referencial fijo un dominio q solamente me sume los q cargo en ultimo para ese num de factura?

Caral
29-10-2008, 02:11:38
Hola
Es el problema con los maestros, hacen códigos y luego a nosotros los novatos nos toca tratar de entender de que se trata.
Estos Maestros, cuando aprenderán.:D:D
A ver Maestro enecumene, ilustranos:D;)
Saludos

enecumene
29-10-2008, 02:15:03
Hola, el with sirve para trabajar con un objeto específico es útil para reducir el código, ejemplo:

With Tabla1 do
begin
Close;
SQL.Clear;
SQL.Text := 'sentencia....';
Open;
end;

Aquí sin el with...do:

Tabla1.Close;
Tabla1.SQL.Clear;
Tabla1.SQL.Text := 'sentencia....';
Tabla1.Open;

¿Ves la diferencia?, con el First se coloca desde el primer registro de la tabla, como estás tratando de realizar facturas es lógico que deberías estar usando tablas de memorias o una tabla temporal, porque si no, te sumará todos los registros viejos, por eso se recomienda usar tablas de memorias o temporales donde puedes trabajar solamente con esos registros de manera individual a los registros viejos. Espero que se te claro sino me avisas.

Saludos.

enecumene
29-10-2008, 02:16:20
Hola
Es el problema con los maestros, hacen códigos y luego a nosotros los novatos nos toca tratar de entender de que se trata.
Estos Maestros, cuando aprenderán.:D:D
A ver Maestro enecumene, ilustranos:D;)
Saludos

Ya ilustré algo a ver si se entiende :D:D

Caro
29-10-2008, 02:21:57
Hola Pollo2004, también lo puedes lograr creandote un campo Agregado en su propiedad Expression haces un sum de tu campo calculado SUM(CampoCalculado), activas el campo agregado y también AgregatesActive de tu DataSet.

Saluditos

Caral
29-10-2008, 02:24:06
Hola
........
¿Ves la diferencia?, con el First se coloca desde el primer registro de la tabla, como estás tratando de realizar facturas es lógico que deberías estar usando tablas de memorias o una tabla temporal, porque si no, te sumará todos los registros viejos, por eso se recomienda usar tablas de memorias o temporales donde puedes trabajar solamente con esos registros de manera individual a los registros viejos. Espero que se te claro sino me avisas.

Saludos.
Bueno en este caso tengo que diferir un poco del maestro.:D
Tener una tabla temporal es tener mas cosas de la cuenta, a veces es bueno, pero en este caso no lo veo necesario.
Se habla de facturas, estas siempre tienen un numero consecutivo y unico, se puede hacer referencia a este numero sin necesidad de otra cosa.
En mi primera intervención sugerí que se revisara el tutorial de facturacion, ahi se hacen los calculos sin usar tablas temporales ni otras cosas.
Lo siento enecumene, pero algo he aprendido de ti.:D
Saludos

enecumene
29-10-2008, 02:33:47
Lo digo porque no se sabe si los detalles de las facturas lo esta registrando directamente a la tabla o en un stringgrid, en este caso es directo a la tabla entonces está involucrando los demás registros anteriores, digo yo no sé, hay muchas formas de realizar una factura, en mi caso la numeración la asigno luego de grabar y utilizo tablas de memorias, así cuando hago la suma, sumo lo que registro y no todos luego le asigno la numeración de la factura. :), pero bueno, dejemos que otro maestro nos ilumine con este asunto :D

Pollo2004
29-10-2008, 16:58:33
hola quisiera saber q componente es este 'stringgrid', ya q lo nombran aca y lo he visto por ahi.
Lo de la tabla virtual me intereso bastante, pero no se como seria, me imagine algo as¡, crear una tabla mientras se ejecuta el form factura, al aceptar la factura volcarla a la tabla original y luego eliminar la q usamos, tambien seria muy util para controlar el stock de la tabla producto, no es asi?