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)用, 但變化還沒(méi)有提交 } dsSetKey, { 設(shè)置鍵值模式, 意味著 SetKey 被調(diào)用, 而 GotoKey 尚未被調(diào)用 } dsCalcFields, { OnCalcFields 事件已發(fā)生, 對(duì)記錄值的計(jì)算正在進(jìn)行中 } dsFilter, { 數(shù)據(jù)集正在處理一個(gè)記錄過(guò)濾器、查找字段或其他需要用到過(guò)濾器的操作 } dsNewValue, { 數(shù)據(jù)集處于 NewValue 屬性被訪問(wèn)的臨時(shí)狀態(tài) } dsOldValue, { 數(shù)據(jù)集處于 OldValue 屬性被訪問(wèn)的臨時(shí)狀態(tài) } dsCurValue, { 數(shù)據(jù)集處于 CurValue 屬性被訪問(wèn)的臨時(shí)狀態(tài) } dsBlockRead, { 數(shù)據(jù)正被寫(xiě)入緩沖區(qū), 此時(shí)數(shù)據(jù)庫(kù)表中指針的移動(dòng)并不觸發(fā)數(shù)據(jù)感知組件的更新和事件的發(fā)生 } dsInternalCalc, { 一個(gè)字段值正在被計(jì)算, 以供一個(gè)有 fkInterternalCalc 類型的 Fieldkind 屬性的字段使用 } dsOpening { 數(shù)據(jù)集處于正在打開(kāi)狀態(tài)但是還沒(méi)有結(jié)束, 這種狀態(tài)發(fā)生在數(shù)據(jù)集被異步打開(kāi)時(shí) } ); |
|
來(lái)自: 獨(dú)孤求財(cái) > 《DELPHI》