Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force a Client DataSet to recalculate calculated and internal calculated fields?

I have a ClientDatSet with a few fkInternalCalc fields. The CDS is not linked to any provider; instead it's filled on the fly. How can I force CDS to recalculate all the "calculable" fields? I can not call Refresh() because there is no provider to refresh data from. The only way I have come with so far has been to navigate through all records, which is not the best way.

PS: I have read this question and this post, but I'm hoping for a more elegant way.

like image 303
iMan Biglari Avatar asked Jul 28 '13 10:07

iMan Biglari


1 Answers

I achieve that with a helper (stripped here to the necessary), which allows to call the protected methods without any hack. Make sure to check for DataSet.State = dsInternalCalc inside OnCalcFields for fkInternalCalc fields.

type
  TClientDataSetHelper = class helper for TClientDataSet
  public
    function AssureEditing: Boolean;
    procedure InternalCalc;
  end;

function TClientDataSetHelper.AssureEditing: Boolean;
begin
  result := not (State in [dsEdit, dsInsert]);
  if result then
    Edit;
end;

procedure TClientDataSetHelper.InternalCalc;
var
  needsPost: Boolean;
  saveState: TDataSetState;
begin
  needsPost := AssureEditing;
  saveState := setTempState(dsInternalCalc);
  try
    RefreshInternalCalcFields(ActiveBuffer);
  finally
    RestoreState(saveState);
  end;
  if needsPost then
    Post;
end;

This can easily be expanded for normal calculated fields using CalculateFields. Although this shouldn't be necessary as calculated fields are recalculated whenever any other data field changes.

like image 182
Uwe Raabe Avatar answered Sep 27 '22 18:09

Uwe Raabe