delphi TClientDataSet[9]: 计算字段和 State  
官方Delphi 学习QQ群: 682628230(三千人)
频道

delphi TClientDataSet[9]: 计算字段和 State


TClientDataSet[9]: 计算字段和 State

20200814113733983.png

TClientDataSet 中计算字段有两种: Calculated(计算字段)、InternalCalc(内部计算字段).


两者区别是: Calculated 在每次需要时都要重新计算; InternalCalc 只需要计算一次.

Calculated 需要计算的时间, InternalCalc 需要存取的时间; 当然后者快.


计算字段不会被保存到文件.


下面的例子先定义了两个整数字段: sum1、sum2;

又定义了两个计算字段: SUM(求和)、MUL(求积), 分别指定了 Calculated、InternalCalc.


计算是在 TClientDataSet 的 OnCalcFields 事件中完成的, 每当需要计算结果时事件会被自动激活.

除了 OnCalcFields 事件中的代码外, 其他都可以在设计时完成; 这里是动态完成的.


//准备: 窗体放置 ClientDataSet1、DataSource1、DBGrid1(关联一下)、Button1

//程序运行后, 可用 Tab 和 ↑ ↓ → ← 键配合着输入测试数据.


{ 建立数据集, 包括计算字段 }

procedure TForm1.Button1Click(Sender: TObject);

begin

  with TIntegerField.Create(Self) do

  begin

    FieldName := 'num1';       { FieldKind 的默认值是 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;  { 指定为计算字段 }

    DataSet := ClientDataSet1;

  end;


  with TIntegerField.Create(Self) do

  begin

    FieldName := 'MUL';

    FieldKind := fkInternalCalc; { 指定为内部计算字段 }

    DataSet := ClientDataSet1;

  end;


  ClientDataSet1.CreateDataSet;

  Button1.Enabled := False;

end;


{ OnCalcFields 事件 }

procedure TForm1.ClientDataSet1CalcFields(DataSet: TDataSet);

begin

  { 获取计算字段的值 }

  DataSet['SUM'] := DataSet['num1'] + DataSet['num2'];


  { 获取内部计算字段的值; 一般要先判断一下以避免重复运算 }

  if DataSet.State = dsInternalCalc then

    DataSet['MUL'] := DataSet['num1'] * DataSet['num2'];

end;



在上面程序的基础上再添加一个 Timer1, 为详细测试 Calculated 和 InternalCalc 的区别, 代码修改如下:

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; { 指定为内部计算字段 }

    DataSet := ClientDataSet1;

  end;

  ClientDataSet1.CreateDataSet;


  { 添加测试数据 }

  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;



测试图:




TDataSetState.State: TDataSetState;

TDataSetState = (

dsInactive,     { 数据集被关闭 }

dsBrowse,       { 浏览模式 }

dsEdit,         { 编辑模式, 意味着 Edit 方法已被调用, 而编辑后的数据尚未被提交 }

dsInsert,       { 插入模式, 即 insert 被调用, 但变化还没有提交 }

dsSetKey,       { 设置键值模式, 意味着 SetKey 被调用, 而 GotoKey 尚未被调用 }

dsCalcFields,   { OnCalcFields 事件已发生, 对记录值的计算正在进行中 }

dsFilter,       { 数据集正在处理一个记录过滤器、查找字段或其他需要用到过滤器的操作 }

dsNewValue,     { 数据集处于 NewValue 属性被访问的临时状态 }

dsOldValue,     { 数据集处于 OldValue 属性被访问的临时状态 }

dsCurValue,     { 数据集处于 CurValue 属性被访问的临时状态 }

dsBlockRead,    { 数据正被写入缓冲区, 此时数据库表中指针的移动并不触发数据感知组件的更新和事件的发生 }

dsInternalCalc, { 一个字段值正在被计算, 以供一个有 fkInterternalCalc 类型的 Fieldkind 属性的字段使用 }

dsOpening       { 数据集处于正在打开状态但是还没有结束, 这种状态发生在数据集被异步打开时 }

);



推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 DelphiW.com 开发 源码 文档 技巧 All Rights Reserved
晋ICP备14006235号-8 晋公网安备 14108102000087号

执行时间: 0.037824869155884 seconds