You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi 10.3.3 FireDAC:如何在DBGrid中继承上一行值填充缺失字段

解决Delphi FireDAC DBGrid继承上一行字段值的问题

嗨,Franck,针对你遇到的问题,核心思路是维护一个全局缓存来记录各列的最新值,每次加载行数据时先更新缓存,再用缓存填充当前行的空字段。下面是具体的实现步骤和代码示例:

1. 定义缓存变量

首先在窗体类中添加一个私有数组,用来保存C0、C1、C2的最新值,作为后续行的继承来源:

type
  TForm1 = class(TForm)
    FDConnection1: TFDConnection;
    FDQuery1: TFDQuery;
    DBGrid1: TDBGrid;
    DataSource1: TDataSource;
    procedure FDQuery1BeforeOpen(DataSet: TDataSet);
    procedure FDQuery1CalcFields(DataSet: TDataSet);
  private
    FCachedValues: array[0..2] of string; // 对应C0、C1、C2的缓存值
    procedure ParseData(const DataStr: string); // 解析data字段的辅助函数
  public
    { Public declarations }
  end;

2. 在BeforeOpen事件初始化缓存并创建计算字段

在FDQuery打开前,初始化缓存为空,并动态创建C0、C1、C2三个计算字段:

procedure TForm1.FDQuery1BeforeOpen(DataSet: TDataSet);
var
  i: Integer;
begin
  // 初始化缓存为空白
  FillChar(FCachedValues, SizeOf(FCachedValues), 0);

  // 动态添加C0-C2计算字段
  for i := 0 to 2 do
  begin
    with TStringField.Create(DataSet) do
    begin
      FieldName := 'C' + IntToStr(i);
      Size := 20;
      Calculated := True;
      DataSet.FieldDefs.Add(FieldName, ftString, 20);
      DataSet.Fields.Add(Self);
    end;
  end;
end;

3. 实现data字段解析函数

写一个辅助函数,解析当前行的data字段内容,更新缓存中对应索引的值:

procedure TForm1.ParseData(const DataStr: string);
var
  Parts, KeyValue: TStringList;
  i, Index: Integer;
begin
  if Trim(DataStr) = '' then Exit; // 空data字段直接跳过

  Parts := TStringList.Create;
  KeyValue := TStringList.Create;
  try
    Parts.Delimiter := ';';
    Parts.StrictDelimiter := True;
    Parts.DelimitedText := DataStr;

    KeyValue.Delimiter := '=';
    for i := 0 to Parts.Count - 1 do
    begin
      KeyValue.DelimitedText := Parts[i];
      if (KeyValue.Count = 2) and TryStrToInt(KeyValue[0], Index) then
      begin
        // 仅更新有效索引(0-2)的缓存值
        if (Index >= 0) and (Index <= 2) then
          FCachedValues[Index] := KeyValue[1];
      end;
    end;
  finally
    KeyValue.Free;
    Parts.Free;
  end;
end;

4. 在CalcFields事件填充字段值

利用OnCalcFields事件(每行数据加载后触发),先解析当前行的data更新缓存,再将缓存值赋值给对应的计算字段:

procedure TForm1.FDQuery1CalcFields(DataSet: TDataSet);
var
  i: Integer;
  DataStr: string;
begin
  // 获取当前行的data字段内容
  DataStr := DataSet.FieldByName('data').AsString;

  // 解析data,更新全局缓存
  ParseData(DataStr);

  // 将缓存值赋值给C0-C2字段
  for i := 0 to 2 do
  begin
    DataSet.FieldByName('C' + IntToStr(i)).AsString := FCachedValues[i];
  end;
end;

关键说明

  • 为什么不用OnCreateFields?这个事件仅在字段创建时触发一次,无法针对每行数据做处理,也就拿不到上一行的内容。而OnCalcFields是每行数据加载后都会触发,刚好适合维护行与行之间的状态缓存。
  • 缓存是全局的,会随着行的遍历持续更新,确保后续行能继承最新的字段值。
  • 如果你的列数更多,可以把数组改成动态列表(比如TStringList),方便扩展。

内容的提问来源于stack exchange,提问作者franckcl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:42:34