你想要的是直截了当的,但你需要小心如何做到这一点.
暂时离开gui方面,您要做的是将计算列添加到TAdoDataSet并在其OnCalcFields事件中初始化它.不过,你不要想做的是计算TotalQuantity在该事件中.因为a)OnCalcFields将为数据集中的每一行调用OnCalcFields事件,并且b)在事件内部执行任何移动数据集光标的操作 - 就像在另一个答案中建议的那样遍历数据集 - 将以递归方式调用OnCalcFields事件.
避免这种递归问题的方法,以及避免做任何必要的工作,只是在第一次打开表时以及任何时候它的值可以改变时,即在编辑,插入或删除行时计算TotalQuantity ,然后将结果保存在表单或数据模块的字段中.有两种主要方法可以进行此计算:1)使用TAdoQuery执行Sql,如"SELECT SUM(Quantity)FROM MyTable"或2)使用
在表上打开的第二个 TAdoDataSet 实例.优选地,该第二实例不应具有与其连接的任何gui控件,因此可以尽可能快地遍历它而不必使用DisableControls和EnableControls.
要将百分比字段添加到AdoDataSet,请双击它以弹出字段编辑器,右键单击它并选择New field.确保将其设置Type为Calculated.
一旦你有你GetTotalQuantity的程序设置,您需要设置事件处理程序,从您的AdoDataSet的BeforeOpen,BeforeInsert,BeforeEdit和AfterDelete事件调用它.
然后在您的OnCalcFields事件中,计算并分配计算到的百分比值.
完成所有这些操作所需的代码非常简单,例如
procedure TForm1.GetTotalQuantity;
begin
// AdoQuery1 contains Sql to obtain the sum of the AdoDataSet's
if AdoQuery1.Active then
AdoQuery1.Close;
AdoQuery1.Open;
try
TotalQuantity := AdoQuery1.Fields[0].AsFloat; // TotalQuantity is a field of your for, (or datamodule)
finally
AdoQuery1.Close;
end;
end;
Run Code Online (Sandbox Code Playgroud)
要么
procedure TForm1.GetTotalQuantity;
begin
// Note: AdoDataSet2 is a second instance of TAdoDataSet set up to access the same
// db table as the one connected to the OP's DBGrid
if AdoDataSet2.Active then
AdoDataSet2.Close;
AdoDataSet2.Open;
try
TotalQuantity := 0;
while not AdoDataSet2.Eof do begin
TotalQuantity := TotalQuantity + AdoDataSet2Quantity.AsFloat; // AdoDataSet2.Quantity.AsFloat;
AdoDataSet2.Next;
end;
finally
AdoDataSet2.Close;
end;
end;
Run Code Online (Sandbox Code Playgroud)
OnCalcFields事件:
procedure TForm1.AdoDataSet1CalcFields(DataSet : TDataSet);
begin
if TotalQuantity > 0 then
AdoDataSet1Percentage.AsFloat := AdoDataSet1Quantity.AsFloat / Total Quantity * 100;
end;
Run Code Online (Sandbox Code Playgroud)
将百分比计算字段添加到AdoDataSet并为数据集设置OnCalcFields事件后,DBGrid将很乐意显示它,就像数据集的任何其他字段一样.