FDQuery和OnCalcFields,获取上一行

时间:2020-04-29 10:38:43

标签: mysql delphi firedac

德尔福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中缺少的字段? 谢谢 法兰克

1 个答案:

答案 0 :(得分:1)

我认为您的意思是OnCalcFields,而不是OnCreateFields

您需要什么 在服务器端,通过从先前 使用例如使用计算字段的SQL子查询或客户端。这个答案是关于做到这一点 客户端。

进行涉及另一数据集行的客户端计算的问题是 为此,您需要能够在OnCalcFields事件期间移动数据集光标。但是,此时,数据集将处于dsCalcFields或dsInternalCalc状态 而且,尽管如此,您仍无法轻松移动到数据集中的另一行。这是可能,但是 需要声明一个后代数据集类(TMyFDQuery),以便您可以访问SetTempState 从“其他”获取必要的信息后,有必要还原为先前的状态 行,并且,如果您需要涉及多个字段,则需要在某个地方临时存储值。 因此,这样做会变得混乱。

更简洁的方法涉及在FireDAC的数据集和TClientDataSet之间使用功能相似性。 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。首先是在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方法来获取查找游标 来访问“先前”行,但是我还没有尝试过自己,可能仍然无法实现 (CloneCuror副本中的计算字段会发生什么?)。