Delphi DBGrid 中的计算百分比
Calculated percentage in Delphi DBGrid
几天前我一直在维护一个 Delphi 应用程序。
客户想要向 DBGrid 添加百分比列,现在显示 "Quantity" 列。当然,百分比将是
行数 / 总数量 * 100
我无法修改基础 TADOTable,因为它在代码的其他地方使用,但我尝试将计算字段添加到 TADOTable - 但似乎计算字段不能具有基于聚合值的值(即总和数量)。
我成功地向 DBGrid 添加了一个空列,但是有什么方法可以填充每一行中的 % 值吗?
您是否尝试过在 OnCalcFields 事件中计算百分比?不能 100% 确定以下内容,但此示例可能对您有所帮助:
procedure TClass.DataSetCalcFields(DataSet: TDataSet);
var
Bookmark: String;
TotalQuantity: Double;
begin
// Save current position
Bookmark := Dataset.Bookmark;
// Calculate the total quantity in a while loop through the dataset:
Dataset.First;
while not Dataset.Eof do
begin
TotalQuantity := TotalQuantity + Dataset.FieldByName('QUANTITY').AsFloat;
Dataset.Next;
end;
// Load current position
Dataset.Bookmark := Bookmark;
// Calculate the percentage:
if TotalQuantity > 0 then
begin
Dataset.FieldByName('PERCENTAGE').AsFloat := Dataset.FieldByName('QUANTITY').AsFloat / TotalQuantity * 100;
end
else
begin
Dataset.FieldByName('PERCENTAGE').AsFloat := 0;
end;
end;
end;
你想做的事很简单,但你需要小心做事的方式。
暂且把gui方面放在一边,你要做的是添加一个计算好的
列到您的 TAdoDataSet 并在其 OnCalcFields
事件中对其进行初始化。然而,
您不要 想要做的是计算该事件中的 TotalQuantity
。
因为 a) 将为数据集中的每一行调用 OnCalcFields
事件
AND b) 在 OnCalcFields
事件中做任何移动数据集光标的事情
- 就像另一个答案中建议的那样遍历数据集 - 将递归
调用 OnCalcFields
事件。
避免此递归问题并避免做不必要的工作的方法是仅在以下情况下计算 TotalQuantity
table 是第一次打开,任何时候它的值都可能改变,也就是说,当一行
被编辑、插入或删除,然后将结果保存在表单的一个字段中
或数据模块。您可以通过两种主要方式进行此计算:1) 使用 TAdoQuery
像 "SELECT SUM(Quantity) FROM MyTable" 一样执行 Sql 或 2) 使用 第二个实例
在您的 table 上打开的 TAdoDataSet。最好这第二个实例不应该有任何 gui
连接到它的控件,因此可以尽可能快地遍历它而无需
必须使用 DisableControls
和 EnableControls
.
要将百分比字段添加到您的 AdoDataSet,请双击它以弹出字段编辑器,右键单击它并 select 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;
或
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;
OnCalcFields 事件:
procedure TForm1.AdoDataSet1CalcFields(DataSet : TDataSet);
begin
if TotalQuantity > 0 then
AdoDataSet1Percentage.AsFloat := AdoDataSet1Quantity.AsFloat / Total Quantity * 100;
end;
将百分比计算字段添加到 AdoDataSet 并为数据集设置 OnCalcFields 事件后,DBGrid 将很乐意显示它,就像数据集的任何其他字段一样。
几天前我一直在维护一个 Delphi 应用程序。 客户想要向 DBGrid 添加百分比列,现在显示 "Quantity" 列。当然,百分比将是 行数 / 总数量 * 100
我无法修改基础 TADOTable,因为它在代码的其他地方使用,但我尝试将计算字段添加到 TADOTable - 但似乎计算字段不能具有基于聚合值的值(即总和数量)。
我成功地向 DBGrid 添加了一个空列,但是有什么方法可以填充每一行中的 % 值吗?
您是否尝试过在 OnCalcFields 事件中计算百分比?不能 100% 确定以下内容,但此示例可能对您有所帮助:
procedure TClass.DataSetCalcFields(DataSet: TDataSet);
var
Bookmark: String;
TotalQuantity: Double;
begin
// Save current position
Bookmark := Dataset.Bookmark;
// Calculate the total quantity in a while loop through the dataset:
Dataset.First;
while not Dataset.Eof do
begin
TotalQuantity := TotalQuantity + Dataset.FieldByName('QUANTITY').AsFloat;
Dataset.Next;
end;
// Load current position
Dataset.Bookmark := Bookmark;
// Calculate the percentage:
if TotalQuantity > 0 then
begin
Dataset.FieldByName('PERCENTAGE').AsFloat := Dataset.FieldByName('QUANTITY').AsFloat / TotalQuantity * 100;
end
else
begin
Dataset.FieldByName('PERCENTAGE').AsFloat := 0;
end;
end;
end;
你想做的事很简单,但你需要小心做事的方式。
暂且把gui方面放在一边,你要做的是添加一个计算好的
列到您的 TAdoDataSet 并在其 OnCalcFields
事件中对其进行初始化。然而,
您不要 想要做的是计算该事件中的 TotalQuantity
。
因为 a) 将为数据集中的每一行调用 OnCalcFields
事件
AND b) 在 OnCalcFields
事件中做任何移动数据集光标的事情
- 就像另一个答案中建议的那样遍历数据集 - 将递归
调用 OnCalcFields
事件。
避免此递归问题并避免做不必要的工作的方法是仅在以下情况下计算 TotalQuantity
table 是第一次打开,任何时候它的值都可能改变,也就是说,当一行
被编辑、插入或删除,然后将结果保存在表单的一个字段中
或数据模块。您可以通过两种主要方式进行此计算:1) 使用 TAdoQuery
像 "SELECT SUM(Quantity) FROM MyTable" 一样执行 Sql 或 2) 使用 第二个实例
在您的 table 上打开的 TAdoDataSet。最好这第二个实例不应该有任何 gui
连接到它的控件,因此可以尽可能快地遍历它而无需
必须使用 DisableControls
和 EnableControls
.
要将百分比字段添加到您的 AdoDataSet,请双击它以弹出字段编辑器,右键单击它并 select 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;
或
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;
OnCalcFields 事件:
procedure TForm1.AdoDataSet1CalcFields(DataSet : TDataSet);
begin
if TotalQuantity > 0 then
AdoDataSet1Percentage.AsFloat := AdoDataSet1Quantity.AsFloat / Total Quantity * 100;
end;
将百分比计算字段添加到 AdoDataSet 并为数据集设置 OnCalcFields 事件后,DBGrid 将很乐意显示它,就像数据集的任何其他字段一样。