PDA

Ver la Versión Completa : DBgrid calcular en campo


CrazySoft
17-08-2012, 02:46:07
Hola, estimados tengo una duda como hacer que en un campo de tipo numerico de un DBGrid pueda realizar una operacion aritmetica por ejemplo al editar el campo, introducir una operacion aritmerica por ejemplo ((10*5)-3)/2 y al salir que al salir solo que de el valor calculado.

Lo que hice fue añadir un componente Tedit al DBGrid sobreponiendo la casilla y recuperando el valor del campo y posteriormente puedo ingresar la formula pero tengo problemas al salir del edit no me asigna el valor calculado o al ingresar al modo de edicion.

incorpore la unidad CalcExpress que le permite calcular de la expresion

o que componente puedo usar


adjunto lo que hice o quitare los componentes que no estoy estan usando para temer una mejor vision para ver donde esta el problema

http://terawiki.clubdelphi.com/Test/DBGrid con funciones.rar (http://terawiki.clubdelphi.com/Test/?download=DBGrid+con+funciones.rar)

muchas gracias por su colaboracion

ecfisa
17-08-2012, 03:26:15
Hola CrazySoft.

Usa el evento OnGetText del TField correspondiente.

En tu caso sería algo parecido a esto:

procedure TForm1.DataSetCampoGetText(Sender: TField; var Text: String;
DisplayText: Boolean);
begin
Text := FloatToStr(Tu_Funcion_CalcularExpresion(TField(Sender).Value));
end;

Presupuse que la función Tu_Funcion_CalcularExpresion devuelve un valor tipo flotante, de retornar una cadena, es innecesario usar la función FloatToStr.

Saludos.

CrazySoft
17-08-2012, 06:42:14
Gracias ecfisa

hice lo que me dijiste pero aun tengo problemas, puse el valor de 2+2-1 y da error "2+2-1 no es valor de coma flotante ..."

y tampoco me permite ingresar / o * en el campo

el campo que estoy usando es de tipo real

hice la prueba con un campo de tipo texto y me funciono bien, pero mi problemas es que lo necesito que sea numerico

asi esta mi codigo, que podria hacer????



Uses CalcExpress;

function TForm1.CalcularExpresion(Expre: string): Real;
var
CalcExpress1: TCalcExpress;
args: array[0..100] of extended;
begin

CalcExpress1 := TCalcExpress.Create(self);
CalcExpress1.Formula := Expre;
result := CalcExpress1.calc(args);
CalcExpress1.free;

end;

procedure TForm1.ADOTable1ValorGetText(Sender: TField; var Text: string;
DisplayText: Boolean);

begin

Text := floattostr(CalcularExpresion(TField(Sender).Value));

end;


Gracias

ecfisa
17-08-2012, 13:12:52
Hola CrazySoft.

Acabo de hacer esta prueba

function CalcularExpresion(Expre: string): Double;
begin
Result := StrToFloat(Expre)*2;
end;

procedure TForm1.IBDataSetFloatGetText(Sender: TField; var Text: String; DisplayText: Boolean);
begin
Text := FloatToStr(CalcularExpresion(TField(Sender).Value));
end;

sobre un campo numérico (DOUBLE PRECISION de Firebird), y tál como pensaba funciona bién.

El tratamiento dentro de la función CalcularExpresion no tiene importancia ya que ambas (la tuya y la mía de prueba) reciben una cadena de caracteres y devuelven un número real.

Desconozco que DBMS estes usando pero proba cambiando el modo de enviar el argumento a CalcularExpresion por:
TField(Sender).AsString
o por:
FloatToStr(TField(Sender).AsFloat)

Saludos.

CrazySoft
17-08-2012, 16:59:35
hola ecfisa, mira sigo con el problema el error me sale antes del GetText, y no pe permite ingresar * o / en el DBGrid,

estoy usando D6 y Access para el ejemplo y tambien probe con FB , y me sa el mismo error



// Tedit añadido para el calculo en la expresion en el campo expresio que es de tipo numerico no funciona muy bien

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
IsChecked: array[Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or
DFCS_CHECKED);
var
DrawState: Integer;
DrawRect: TRect;
begin
if (gdFocused in State) then
begin

if (Column.Field.FieldName = 'Expresion') then
with Expresion do
begin
text := FloattoStr(Column.Field.asfloat);

Left := Rect.Left + DBGrid1.Left + 1;
Top := Rect.Top + DBGrid1.Top + 1;
Width := Rect.Right - Rect.Left + 2;
Height := Rect.Bottom - Rect.Top + 2;
Visible := True;

end;
end
else {in this else area draw any "stay behind" bitmaps}
begin
end; //if focused
end;

procedure TForm1.FormCreate(Sender: TObject);
var
i, j: Integer;
begin
AdoTable1.Active := True;

with DBGrid1.DataSource.DataSet do
for i := 0 to DBGrid1.FieldCount - 1 do
for j := 0 to FieldCount - 1 do
if Fields[j].FieldName = DBGrid1.Fields[i].FieldName then
DBGrid1.Columns[i].Title.Alignment := Fields[j].Alignment;

DBGrid1.Align := alClient;


Expresion.Visible := False;

end;

procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin

if (DBGrid1.SelectedField.FieldName = 'Expresion') then
Expresion.Visible := False;
end;

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
if (key = Chr(9)) then Exit;

if (DBGrid1.SelectedField.FieldName = 'Expresion') then
begin
Expresion.SetFocus;
SendMessage(Expresion.Handle, WM_Char, word(Key), 0);
end;

end;

procedure TForm1.ExpresionKeyPress(Sender: TObject; var Key: Char);
begin
if key=#13 then
Begin
DBGrid1.DataSource.Edit;
ExpresionExit(self);
end;
end;

procedure TForm1.ExpresionExit(Sender: TObject);
begin
if DBGrid1.DataSource.State in [dsEdit, dsInsert] then
Begin
ADOTable1Expresion.Value := CalcularExpresion(Expresion.text);
Expresion.text :=ADOTable1Expresion.text;
end;
end;

function TForm1.CalcularExpresion(Expre: string): Real;
var
CalcExpress1: TCalcExpress;
args: array[0..100] of extended;
begin

CalcExpress1 := TCalcExpress.Create(self);
CalcExpress1.Formula := Expre;
result := CalcExpress1.calc(args);
CalcExpress1.free;

end;

function CalcularExpresionX(Expre: string): Double;
begin
Result := StrToFloat(Expre)*2;
end;


// este es un campo de tipo numerico, me da error antes de llegar a este punto me da error 5-2 no es valor de punto flotantes y no me permite ingresar 6/4

procedure TForm1.ADOTable1DebeGetText(Sender: TField; var Text: string;
DisplayText: Boolean);

begin

Text := floattostr(CalcularExpresion(TField(Sender).AsString));
// Text := floattostr(CalcularExpresion(FloatToStr(TField(Sender).AsFloat)));
// Text := floattostr(CalcularExpresion(TField(Sender).Value));

end;


// este es un campo de tipo texto, y funciona todo correctamente pero necesito que sea numerico

procedure TForm1.ADOTable1TitleGetText(Sender: TField; var Text: String;
DisplayText: Boolean);
begin
Text := floattostr(CalcularExpresion(TField(Sender).asstring));

end;




adjunto el ejemplo que estoy hacendo

Gracias, por la ayuda

ecfisa
17-08-2012, 17:18:17
y no pe permite ingresar * o / en el DBGrid
Hola CrazySoft.

No me había percatado que podías ingresar caracteres como: *,/,+,-,^, etc. Entonces no creo que puedas hacerlo en un campo numérico, me parece que vas a tener que usar uno alfanumérico (ftString).

Algo como:

function CalcularExpresion(Expre: string): string;
begin
...
Result := FloatToStr(CalcExpress1.calc(args));
end;


procedure TForm1.IBDataSetCampoGetText(Sender: TField;
var Text: String; DisplayText: Boolean);
begin
Text := CalcularExpresion(TField(Sender).AsString);
end;


Saludos.

CrazySoft
18-08-2012, 01:32:01
gracias ecfisa, por la colaboracion seguire intentando solucionar el problema que tengo, ya esta casi pero no me gusta algunos asunto de funcionalidad