简体   繁体   中英

How to make percentage from calculation record divided with summary DBGRID Delphi

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM