简体   繁体   English

如何通过计算记录除以汇总DBGRID Delphi来得出百分比

[英]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% ? 我有显示列小计和列百分比的dbgrid,如何从此公式显示列百分比:(小计/总计)* 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? 我无法修改我的SQL,因为我的SQL非常复杂,所以我认为解决方案可能使用计算字段,不是吗? 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. 以下假设您的数据集实际上不包含显示的最后一行,而是包含“ 111077,100”的行-如果包含,那么下面显示的用于计算GrandTotal的步骤是不必要的,您只需要填充琐碎的Percent计算字段。

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. 如果您的数据集是TClientDataSet ,则可以使用TAggregateField代表GrandTotal和计算字段代表每个数据行对GrandTotal的贡献,很容易地实现Percent值。 See code below. 请参见下面的代码。

If you are not using a TClientDataSet already then you have several options, including 如果尚未使用TClientDataSet,则有几种选择,包括

  • If your DataSet is of a type which supports aggregate fields then you can do the equivalent of the code below. 如果您的数据集是支持aggregate fields的类型,则可以执行以下代码的等效操作。

  • 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. 使用现有的DataSet作为TDataSetProvider的数据集源,并使用TDataSetProvider作为TClientDataSetProvider ,并使用TClientDataSet将数据提供给网格。

  • 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. 不要使用TClientDataSet和/或TAggregateField ,而是使用现有的DataSet进行以下显示,但是如果您的DataSet类型支持,请将Percent字段设置为fkInternalCalc字段,否则将其设置为fkCalculated ,请省略GrantTotal TAggregateField字段并在代码中计算GrandTotal。 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. 一种方法是打开数据集后,通过一次遍历数据集( while not DataSet.Eof ... )来计算它。

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. 在下面的代码中,我已经在代码中创建了所有字段,而不是使用对象检查器的字段编辑器,因此您可以轻松地确切地看到使TAggregateField起作用所需的最小设置是什么。

Note: I could be wrong but don't think you could get a standard TDBGrid to display the final, 100%, row of your screenshot. 注意:我可能是错的,但是您认为您无法获得标准的TDBGrid来显示屏幕快照的最后100%。 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. 使用Developer Express TcxGrid等可以进行类似的操作,但是如果您需要TDBGrid来执行此操作,则应询问如何提出新问题。

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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