如何在delphi中迭代像矩阵一样的DBGrid

时间:2014-12-09 10:39:45

标签: delphi

我有一个填充Access数据库的DBGrid。我想要的只是像矩阵一样迭代那些数据,例如单元格00,01,02,10,11,12,

2 个答案:

答案 0 :(得分:5)

DBGrid只是数据的直观表示。本机方式是迭代数据集和字段 如果您的数据集确实支持RecNo,您可以使用RecNo和字段索引访问这些值。(*)
确保不要访问RecordCount -1以上的行和FieldCount -1以上的字段

var
  i: Integer;
begin
  Dataset.DisableControls;
  try
    Dataset.First;
    While not Dataset.EOF do
    begin
      for i := 0 to Dataset.FieldCount - 1 do
      begin
        //Access your Field of the current row by depending of your intention by Value/String whatever you need
        //DoSomeThingWith(Dataset.Fields[i].Value); // make sure to handle NULL values
        DoSomeThingWith(Dataset.Fields[i].asString);
      end;
      Dataset.Next;
    end;
  finally
    Dataset.EnableControls;
  end;
end;

//(*)
Function GetFieldValue(Dataset:TDataset;Row:Integer;FieldIndex:Integer):Variant;
begin
  Dataset.RecNo :=  Row;
  Result := Dataset.Fields[FieldIndex].Value;
end;

答案 1 :(得分:1)

你已经拥有并接受了一个很好的答案(我已经+ 1d,顺便说一句)给你的q,但是当我差不多完成这个时,我想 我不妨发布它,如果只是填写一些关于如何访问[Row,Column]中的数据集的细节 如果你真的必须的话。当然,这并不是说这样做是个好主意。

所以,以下内容纯粹是作为对另一个答案的补充,而不是"完成"有了它并受到类似的警告:

  • 并非所有TDataSet后代都有意义地实现RecNo

  • Ditto with DataSet.RecordCount(特别是Sql服务器)

  • 对于任何非平凡大小的数据集,性能将是可怕的a)b)如果您尝试通过列访问它,那么绝对可怕,然后行"对于"循环(因为DataSet必须遍布整个地方!)。

它使用TDataArray类来包装(和隐藏)数据集,但允许访问其字段数据,如下所示:

    {Something which can receive a variant} := DataArray[Row, Column];
不过,它是"默认"在类的DataProperty中,您可以避免编写

    {Something ...} := DataArray.Data[Row, Column];

你问过以矩阵样式访问DBGrid的原因并不是一个好主意,原因如前所述。你也可以"切断中间人"并访问填充网格的数据集。

代码

  TForm1 = class(TForm)
    CDS1: TClientDataSet;
    procedure FormCreate(Sender: TObject);
  private
    procedure SetUp;
  end;

  TDataArray = class
  private
    FDataSet : TDataSet;
    function GetData(Row, Column: Integer): Variant;
  public
    constructor Create(ADataSet : TDataSet);
    function RowCount : Integer;
    function ColumnCount : Integer;
    property Data[Row, Column : Integer] : Variant read GetData; default;   //NB 1-based
  end;
[...]

function TDataArray.ColumnCount: Integer;
begin
  Result := FDataSet.FieldCount;
end;

function TDataArray.RowCount: Integer;
begin
  Result := FDataSet.RecordCount;
end;

constructor TDataArray.Create(ADataSet: TDataSet);
begin
  inherited Create;
  FDataSet := ADataSet;
end;

function TDataArray.GetData(Row, Column: Integer): Variant;
var
  MoveBy : Integer;
begin
  Assert((Row > 0) and (Row <= FDataSet.RecordCount));  // check Column, too, if you want
  MoveBy := Row - FDataSet.RecNo;
  if MoveBy <> 0 then begin
    FDataSet.DisableControls;
    try
      FDataSet.MoveBy(MoveBy);
    finally
      FDataSet.EnableControls;
    end;
  end;
  Result := FDataSet.Fields[Column - 1].Value;
end;

procedure TForm1.SetUp;
var
  DataArray : TDataArray;
  Row,
  Column : Integer;
  AValue : Variant;
begin
  CDS1.FieldDefs.Add('ID', ftInteger);
  CDS1.FieldDefs.Add('Name', ftString, 20);
  CDS1.FieldDefs.Add('Value', ftString, 80);
  CDS1.CreateDataSet;

  CDS1.InsertRecord([1, 'A', 'A Value']);
  CDS1.InsertRecord([2, 'B', 'B Value']);
  CDS1.InsertRecord([3, 'C', 'C Value']);

  DataArray := TDataArray.Create(CDS1);
  try
    for Row := 1 to DataArray.RowCount do begin
      for Column := 1 to DataArray.ColumnCount do begin
        AValue := DataArray[Row, Column];
      end;
    end;
  finally
    DataArray.Free;
  end;
end;