Dbgrid计算

时间:2011-01-24 22:26:30

标签: delphi dbgrid

我有一个DBGrid,我正在尝试进行结算表,但有时它不会进行计算。我该怎么避免?

procedure TOrcamentos.DBGridEh1ColExit(Sender: TObject);
var
  percent: double;
  Unid: double;
  tot: currency;
  vaz: string;
begin
  if Dorcamen_SUB.DataSet.State in [dsEdit, dsInsert] then
    try  
      Dorcamen_SUB.DataSet.Post;
    finally
      vaz := DBGridEh1.Columns[3].Field.text;
      if (vaz<> '') then
        try
          Torcamen_SUB.Edit;
          Unid := (Torcamen_SUB.FieldByName('QT').AsFloat);
          tot := (Torcamen_SUB.FieldByName('Precovenda').AsFloat);
          percent := (Torcamen_SUB.FieldByName('Desconto').AsFloat);
          try
            tot := tot+(tot * percent)/ 100;
          finally
            Torcamen_SUB.FieldByName('Total').AsFloat := unid*tot;
            Torcamen_SUB.Post;
            Orcamentos.TotalExecute(self);
          end;
        except
        end;
    end;
end;

2 个答案:

答案 0 :(得分:2)

实现计算的更好方法实际上是将计算移动到网格链接到的TTable组件。 Total字段实际上不应该是数据库中的字段,而是基于来自其他字段的值的计算字段。只需使用表的字段编辑器添加一个额外字段,键入字段名称Total,选择正确的数据类型,然后选择字段类型为Calculated。单击Ok,然后为表的OnCalcField事件添加与此类似的代码:

Torcamen_SUB.FieldByName('Total')。AsFloat:= Torcamen_SUB.FieldByName('QT')。AsFloat *( Torcamen_SUB.FieldByName('Precovenda')。AsFloat +(Torcamen_SUB.FieldByName('Precovenda')。AsFloat * Torcamen_SUB.FieldByName('Desconto')。AsFloat)/ 100);

一般的经验法则是,除非确实需要,否则不应将计算值保存到数据库中。最好将它们作为计算字段添加到数据集中,然后将网格链接到数据集。然后,所有计算字段将显示在网格中,每行将根据该行的值显示正确的计算值。

答案 1 :(得分:1)

我认为您将业务逻辑(如计算总计)与用户交互逻辑(如某些网格列丢失焦点的事件)混合在一起,这是应用程序不稳定行为的来源。

看起来甚至不知道它发生在哪里以及它不会发生的地方。

考虑使用Field的事件(例如,OnChange事件)来执行这种计算。

如果您正在使用具有聚合功能的数据集(如TClientDataSet),那就太幸运了,因为您只能declare what you want in a TAggregateField而忘记“手动”进行计算。

不是你的问题但是......要小心你使用try / finally的方式......例如,在这段代码中:

try
  tot := tot+(tot * percent)/ 100;
finally
  Torcamen_SUB.FieldByName('Total').AsFloat := unid*tot;
  //other things
end;

请注意,如果由于某种原因在try和finally子句之间的行上发生异常,则变量tot将具有未定义的值(在这种情况下,是前一个赋值的结果),因此赋值给Torcamen_SUB毕竟,.total字段会出错。我不确定它是不是你想要的。