Skip to main content

Example: TcxDataSummary.OnAfterSummary, TcxCustomDataController.Groups

  • 4 minutes to read

In this example, a summary value is calculated based on the results of other two summaries. The TcxDataSummary.OnAfterSummary event, which occurs when all summaries are already calculated, is used to calculate a new summary.

Let us examine a table that represents information from the pricelist containing three columns: VendorNo, Description, and ListPrice. We want to group data by vendor and calculate three summaries: the summary that displays a sum of the ListPrice column values, the summary representing the number of goods supplied by a specific vendor and the summary that displays the average value of the ListPrice column values. Though it is possible to create an average summary by specifying its skAverage type, we will calculate it based on two other summary values and format it in a specific manner.

The Initialize procedure groups data by vendor and creates three summaries. The third summary is of the skNone type. It is substituted for the average summary in the MyAfterSummary procedure (a TcxDataSummary.OnAfterSummary event handler).

procedure TForm1.Initialize;
var
  ASummaryItem: TcxDataSummaryItem;
begin
  //group by vendor
  DBTableView1VendorNo.GroupIndex := 0;
  DBTableView1VendorNo.Visible := False;
  with DBTableView1.DataController.Summary do
  begin
    BeginUpdate;
    try
      //set prefix and postfix for a group capion
      DefaultGroupSummaryItems.BeginText := '{';
      DefaultGroupSummaryItems.EndText := '}';
      //summary on ListPrice
      ASummaryItem := DefaultGroupSummaryItems.Add;
      ASummaryItem.Kind := skSum;
      ASummaryItem.ItemLink := DBTableView1ListPrice;
      ASummaryItem.Position := spFooter;
      //summary on Description
      ASummaryItem := DefaultGroupSummaryItems.Add;
      ASummaryItem.Kind := skCount;
      ASummaryItem.ItemLink := DBTableView1Description;
      ASummaryItem.Position := spFooter;
      //dummy summary on Description
      ASummaryItem := DefaultGroupSummaryItems.Add;
      ASummaryItem.Kind := skNone;
      ASummaryItem.ItemLink := DBTableView1Description;
      //subscribe to the OnAfterSummary event
      OnAfterSummary := MyAfterSummary;
    finally
      EndUpdate;
    end;
  end;
end;

The MyAfterSummary procedure is a TcxDataSummary.OnAfterSummary event handler. As data is only grouped by one column, we need to iterate the data groups only at level 0. The TcxCustomDataController.Groups property allows you to determine data group indexes which are required by the TcxDataSummary.GroupSummaryValues property. The CalculateGroupAverage procedure evaluates the average price for every data group. The output string for the average summary is constructed by the Format function.

procedure TForm1.MyAfterSummary(ASender: TcxDataSummary);
var
  AChildDataGroupsCount: Integer;
  AChildDataGroupIndex, AParentDataGroupIndex: TcxDataGroupIndex;
  AChildPosition: Integer;
begin
  //iterate through data groups at the level 0
  AParentDataGroupIndex := -1;
  with DBTableView1.DataController.Groups do
  begin
    AChildDataGroupsCount := ChildCount[AParentDataGroupIndex];
    for AChildPosition := 0 to AChildDataGroupsCount - 1 do
    begin
      //data group index of a child
      AChildDataGroupIndex := ChildDataGroupIndex[AParentDataGroupIndex, AChildPosition];
      CalculateGroupAverage(AChildDataGroupIndex);
    end;
  end;
end;
procedure TForm1.CalculateGroupAverage(ADataGroupIndex: TcxDataGroupIndex);
var
  AVarSum, AVarCount, AVarAverage: Variant;
begin
  with DBTableView1.DataController.Summary do
  begin
    //get sum of prices for a specific data group
    //the second argument identifies a summary index in the
    //TcxDataSummary.DefaultGroupSummaryItems collection
    AVarSum := GroupSummaryValues[ADataGroupIndex, 0];
    //get records count in a group
    AVarCount := GroupSummaryValues[ADataGroupIndex, 1];
    if not (VarIsNull(AVarSum) or VarIsNull(AVarCount)) then
    begin
      AVarAverage := AVarSum / AVarCount;
      GroupSummaryValues[ADataGroupIndex, 2] := Format('%m / %d = %m', [Double(AVarSum), Integer(AVarCount), Double(AVarAverage)]);
    end;
  end;
end;

The following image demonstrates a grid control after executing the Initialize procedure.