I have dbgrid which display column subtotal and column percentage, how to display column percentage from this formula : (subtotal / grandtotal) * 100% ? for detail information please see below picture
I couldnt modify my SQL, because my SQL is very complicated, so i think solution maybe use calculated field, doesnt it? Could someone help me to solve this problem. Thanks in advanced.
The following assumes that your dataset doesn't actually contain the last row you've shown, the one that contains "111077, 100" - if it does, then the steps I show below to calculate the GrandTotal are unnecessary, and you only need to populate the Percent
calculated field, which is trivial.
If your DataSet is a TClientDataSet
, you can implement the Percent values quite easily using the combination of a TAggregateField
to represent the GrandTotal and a calculated field to represent each data row's contribution towards the GrandTotal. See code below.
If you are not using a TClientDataSet already then you have several options, including
If your DataSet is of a type which supports aggregate fields
then you can do the equivalent of the code below.
Use your existing DataSet as the dataset source of a TDataSetProvider
, and use the TDataSetProvider
as the Provider
of a TClientDataSet
and use the TClientDataSet
to supply the data to your grid.
Don't use a TClientDataSet
and/or TAggregateField
and instead do similar to what is shown below with your existing DataSet, but make the Percent field an fkInternalCalc
field if your DataSet type supports it, or an fkCalculated
one if not, omit the GrantTotal TAggregateField
field and calculate the GrandTotal in code. One way to do this would be to calculate it by a once-only traversal of the dataset ( while not DataSet.Eof ...
) after you open it.
In the code below, I've created all the fields in code, rather than using the Object Inspector's Fields editor, so you can easily see exactly what are the minimum settings necessary to get a TAggregateField
to work.
Note: I could be wrong but don't think you could get a standard TDBGrid
to display the final, 100%, row of your screenshot. Somthething similar could be done using the Developer Express TcxGrid
, amongst others, but if you need a TDBGrid to do this, you should ask how to in a new question.
Code
TForm1 = class(TForm)
CDS: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
procedure CDSCalcFields(DataSet: TDataSet);
procedure FormCreate(Sender: TObject);
private
CDSID : TIntegerField;
CDSTotal : TCurrencyField;
CDSPercent : TFloatField;
CDSGrandTotal : TAggregateField;
public
procedure SetUp;
end;
[...]
procedure TForm1.SetUp;
var
i : Integer;
begin
CDSID := TIntegerField.Create(Self);
CDSID.FieldName := 'ID';
CDSID.FieldKind := fkData;
CDSID.DataSet := CDS;
CDSTotal := TCurrencyField.Create(Self);
CDSTotal.FieldName := 'Total';
CDSTotal.FieldKind := fkData;
CDSTotal.DataSet := CDS;
CDSPercent := TFloatField.Create(Self);
CDSPercent.FieldName := 'Percent';
CDSPercent.FieldKind := fkInternalCalc;
CDSPercent.DataSet := CDS;
CDSGrandTotal := TAggregateField.Create(Self);
CDSGrandTotal.FieldName := 'GrandTotal';
CDSGrandTotal.FieldKind := fkAggregate;
CDSGrandTotal.Expression := 'Sum(Total)';
CDSGrandTotal.DataSet := CDS;
CDSGrandTotal.Active := True;
CDS.OnCalcFields := CDSCalcFields;
CDS.IndexFieldNames := 'ID';
CDS.CreateDataSet;
for i := 1 to 2 do begin
CDS.InsertRecord([i, i]);
end;
CDS.First;
end;
procedure TForm1.CDSCalcFields(DataSet: TDataSet);
var
Value : Double;
V : Variant;
begin
V := CDSGrandTotal.Value;
if not VarIsNull(V) then begin
Value := CDSTotal.AsFloat;
Value := Value * 100 / V;
CDSPercent.Value := Value;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetUp;
end;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.