TClientDataSet 中計(jì)算字段有兩種: Calculated(計(jì)算字段)、InternalCalc(內(nèi)部計(jì)算字段).
兩者區(qū)別是: Calculated 在每次需要時(shí)都要重新計(jì)算; InternalCalc 只需要計(jì)算一次.
Calculated 需要計(jì)算的時(shí)間, InternalCalc 需要存取的時(shí)間; 當(dāng)然后者快.
計(jì)算字段不會(huì)被保存到文件. 
下面的例子先定義了兩個(gè)整數(shù)字段: sum1、sum2;
又定義了兩個(gè)計(jì)算字段: SUM(求和)、MUL(求積), 分別指定了 Calculated、InternalCalc.
計(jì)算是在 TClientDataSet 的 OnCalcFields 事件中完成的, 每當(dāng)需要計(jì)算結(jié)果時(shí)事件會(huì)被自動(dòng)激活.
除了 OnCalcFields 事件中的代碼外, 其他都可以在設(shè)計(jì)時(shí)完成; 這里是動(dòng)態(tài)完成的. 
//準(zhǔn)備: 窗體放置 ClientDataSet1、DataSource1、DBGrid1(關(guān)聯(lián)一下)、Button1
//程序運(yùn)行后, 可用 Tab 和 ↑ ↓ → ← 鍵配合著輸入測(cè)試數(shù)據(jù).
{ 建立數(shù)據(jù)集, 包括計(jì)算字段 }
procedure TForm1.Button1Click(Sender: TObject);
begin
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'num1';       { FieldKind 的默認(rèn)值是 fkData }
    DataSet := ClientDataSet1;
  end;
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'num2';
    DataSet := ClientDataSet1;
  end;
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'SUM';
    FieldKind := fkCalculated;  { 指定為計(jì)算字段 }
    DataSet := ClientDataSet1;
  end;
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'MUL';
    FieldKind := fkInternalCalc; { 指定為內(nèi)部計(jì)算字段 }
    DataSet := ClientDataSet1;
  end;
  ClientDataSet1.CreateDataSet;
  Button1.Enabled := False;
end;
{ OnCalcFields 事件 }
procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);
begin
  { 獲取計(jì)算字段的值 }
  DataSet['SUM'] := DataSet['num1'] + DataSet['num2'];
  { 獲取內(nèi)部計(jì)算字段的值; 一般要先判斷一下以避免重復(fù)運(yùn)算 }
  if DataSet.State = dsInternalCalc then
    DataSet['MUL'] := DataSet['num1'] * DataSet['num2'];
end;
在上面程序的基礎(chǔ)上再添加一個(gè) Timer1, 為詳細(xì)測(cè)試 Calculated 和 InternalCalc 的區(qū)別, 代碼修改如下: 
var
  Calc, InternalCalc: Integer;
procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'num1';
    DataSet := ClientDataSet1;
  end;
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'num2';
    DataSet := ClientDataSet1;
  end;
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'SUM';
    FieldKind := fkCalculated;
    DataSet := ClientDataSet1;
  end;
  with TIntegerField.Create(Self) do
  begin
    FieldName := 'MUL';
    FieldKind := fkInternalCalc; { 指定為內(nèi)部計(jì)算字段 }
    DataSet := ClientDataSet1;
  end;
  ClientDataSet1.CreateDataSet;
  { 添加測(cè)試數(shù)據(jù) }
  ClientDataSet1.DisableControls;
  for i := 0 to 999 do ClientDataSet1.AppendRecord([i, i]);
  ClientDataSet1.EnableControls;
  Button1.Enabled := False;
end;
procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);
begin
  Inc(Calc);
  DataSet['SUM'] := DataSet['num1'] + DataSet['num2'];
  if DataSet.State = dsInternalCalc then
  begin
    Inc(InternalCalc);
    DataSet['MUL'] := DataSet['num1'] * DataSet['num2'];
  end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Text := Format('Calc: %d; InternalCalc: %d', [Calc, InternalCalc]);
end;
測(cè)試圖:
 
 
TDataSetState.State: TDataSetState; 
TDataSetState = (
dsInactive,     { 數(shù)據(jù)集被關(guān)閉 }
dsBrowse,       { 瀏覽模式 }
dsEdit,         { 編輯模式, 意味著 Edit 方法已被調(diào)用, 而編輯后的數(shù)據(jù)尚未被提交 }
dsInsert,       { 插入模式, 即 insert 被調(diào)用, 但變化還沒有提交 }
dsSetKey,       { 設(shè)置鍵值模式, 意味著 SetKey 被調(diào)用, 而 GotoKey 尚未被調(diào)用 }
dsCalcFields,   { OnCalcFields 事件已發(fā)生, 對(duì)記錄值的計(jì)算正在進(jìn)行中 }
dsFilter,       { 數(shù)據(jù)集正在處理一個(gè)記錄過濾器、查找字段或其他需要用到過濾器的操作 }
dsNewValue,     { 數(shù)據(jù)集處于 NewValue 屬性被訪問的臨時(shí)狀態(tài) }
dsOldValue,     { 數(shù)據(jù)集處于 OldValue 屬性被訪問的臨時(shí)狀態(tài) }
dsCurValue,     { 數(shù)據(jù)集處于 CurValue 屬性被訪問的臨時(shí)狀態(tài) }
dsBlockRead,    { 數(shù)據(jù)正被寫入緩沖區(qū), 此時(shí)數(shù)據(jù)庫表中指針的移動(dòng)并不觸發(fā)數(shù)據(jù)感知組件的更新和事件的發(fā)生 }
dsInternalCalc, { 一個(gè)字段值正在被計(jì)算, 以供一個(gè)有 fkInterternalCalc 類型的 Fieldkind 屬性的字段使用 }
dsOpening       { 數(shù)據(jù)集處于正在打開狀態(tài)但是還沒有結(jié)束, 這種狀態(tài)發(fā)生在數(shù)據(jù)集被異步打開時(shí) }
);