簡體   English   中英

FDQuery和OnCalcFields,獲取上一行

[英]FDQuery and OnCalcFields, get the previous line

Delphi 10.3.3 FireDAC:DBGrid / FDQuery / MySQL VCL

大家好,

我有一個包含這些字段的表

----------------------
|  id  |    data      |
----------------------
|  1   | 0=A;1=B;2=C  |
|  2   | 2=Z          |
|  3   |              |
|  4   | 0=Y;1=X      |
|  5   |              |
|  6   |              |

每一行數據只代表表中的變化

我希望它顯示在 DBGRID 中:

-----------------------
|  id  | C0 | C1 | C2 |
-----------------------
|  1   | A  | B  | C  |
|  2   | A  | B  | Z  |
|  3   | A  | B  | Z  |
|  4   | Y  | X  | Z  |
|  5   | Y  | X  | Z  |
|  6   | Y  | X  | Z  |

我現在能做的只有下表:

-----------------------
|  id  | C0 | C1 | C2 |
-----------------------
|  1   | A  | B  | C  |
|  2   |    |    | Z  |
|  3   |    |    |    |
|  4   | Y  | X  |    |
|  5   |    |    |    |
|  6   |    |    |    |

為了獲得這個結果,我在事件 FDQuery1.BeforeOpen 中創建了額外的列,在事件 OnCreateFields 中,我填充了每一列,但我不知道前一行的內容

那么,我該如何填寫 DBgrid 中缺少的字段呢? 謝謝弗蘭克

我認為您的意思是OnCalcFields ,而不是OnCreateFields

您需要的當然是可能的,無論是服務器端使用例如 SQL 子查詢從前一行派生必要的值,還是使用計算字段的客戶端。 這個答案是關於在客戶端做的。

進行涉及另一個數據集行的客戶端計算的問題是,要做到這一點,您需要能夠在 OnCalcFields 事件期間移動數據集 cursor。 但是,當時,DataSet 將位於 dsCalcFields 或 dsInternalCalc state 中,盡管如此,但您不能輕易移動到數據集中的另一行。 可以這樣做,但需要聲明一個后代數據集 class (TMyFDQuery) 以便您可以訪問必要的SetTempState以在您從“其他”行中獲取必要的信息后恢復到之前的 state,如果您需要的不僅僅是一個字段,您需要在某個地方臨時存儲這些值。 所以這樣做會很混亂。

更簡潔的方法涉及使用 FireDAC 的數據集和 TClientDataSets 之間的功能相似性。 TClientDatasSets 的優點之一是您可以輕松地在兩個 CDS 之間移動數據集內容,只需執行以下操作

CDS2.Data := CDS1.Data;

FireDAC 數據集可以做同樣的事情,但在任何 FD 數據集類型之間。 所以這是我在你的情況下會做的:

  1. 將 FDMemTable 添加到您的表單/數據模塊並在 FDQuery 的 AfterOpen 事件中將查詢數據復制到其中,如下所示:
procedure TForm2.FDQuery1AfterOpen(DataSet: TDataSet);
begin
  FDQuery1.DisableControls;
  try
    FDMemTable1.Data := FDQuery1.Data;
    FDMemTable1.Open;
  finally
    FDQuery1.First;
    FDQuery1.EnableControls;
  end;
end;

FDQuery1.First 是在 FDMemTable 數據可用時強制它重新計算字段(在初始 FDQuery1.Open 期間,當然不能)。

  1. 在 FDQuery 的 OnCalcFields 事件中,使用這樣的代碼將計算字段的值基於從前一行獲取的值(當然,如果有一個,第一行不能有“前”行):
procedure TForm2.FDQuery1CalcFields(DataSet: TDataSet);
begin
  if FDMemTable1.Active then begin
    if FDMemTable1.Locate('ContactID', FDQuery1.FieldByName('ContactID').AsInteger, []) then begin
      FDMemTable1.Prior;
      if not FDMemTable1.Bof then begin
        //  Set FDQuery1's calculated fields that depend on prior row
        FDQuery1.FieldByName('PriorRowID').AsInteger := FDMemTable1.FieldByName('ContactID').AsInteger;
      end;
    end;
  end;
end;

在這個例子中,我查詢的數據集有一個ContactID主鍵,計算的值就是前一行的 ContactID 值。 當然,在現實生活中,使用持久字段變量比繼續調用FieldByName更有效。

我想另一種可能性可能是使用 CloneCursor 方法來獲取查找 cursor 以訪問“先前”行,但是我自己沒有嘗試過,而且無論如何可能都不可能(CloneCuror 副本中的計算字段會發生什么情況?)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM