【问题标题】:FDQuery and OnCalcFields, get the previous lineFDQuery和OnCalcFields,获取上一行
【发布时间】:2020-04-29 10:38:43
【问题描述】:

德尔福 10.3.3 FireDAC:DBGrid / FDQuery / MySQL 视频控制器

大家好,

我有一个包含这些字段的表格

----------------------
|  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 中缺失的字段? 谢谢 弗兰克

【问题讨论】:

  • 您可以改用TStringGrid
  • 第一行是否总是包含所有状态?您需要编辑或添加行吗?
  • Olivier:我尝试过使用 TStringGrid,但更新需要更多时间(5 次)
  • sddk:第一行并不总是包含所有状态。我不需要编辑或添加行,只需显示即可。
  • “更多时间更新”是什么意思?显示网格?它不应该。你有多少行?

标签: mysql delphi firedac


【解决方案1】:

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

你需要什么 当然是可能的,无论是在服务器端,通过从先验派生出必要的值 行使用例如使用计算字段的 SQL 子查询或客户端。这个答案是关于做的 客户端。

进行涉及另一个数据集行的客户端计算的问题在于 为此,您需要能够在 OnCalcFields 事件期间移动数据集光标。但是,此时,DataSet 将处于 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.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 方法来获取查找光标 访问“先前”行,但我自己没有尝试过,无论如何可能都不可能 (CloneCuror 副本中的计算字段会发生什么情况?)。

【讨论】:

  • 非常感谢您非常完整的回复。我已经使用 FDmemTable 进行了一些测试,这似乎是解决方案。我现在需要将它集成到我的应用程序中。再次感谢!
  • 很高兴为您提供帮助。完成集成后,如果您能接受这个答案(通过单击其 LHS 上的勾号图标),那就太好了。
猜你喜欢
  • 2017-10-18
  • 2023-03-07
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多