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.
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.