Search code examples
delphidevexpresstcxgrid

Loop through records on a cxgrid and update a field/column


I have a cxGrid where I apply a filter to select certain records. When that is done I want to be able to update a field/column in the grid to mark each record that is to be used for the next operation. I haven't been able to figure this out

Maybe I haven't been specific enough when describing my problem. I have the cxGrid where I have applied a filter selecting some records. What I then need to do is to click a columnheader and then have a field called fldselected set to True for these records.


Solution

  • What your updated q is asking for is straightforward and as usual with Devex stuff, it's all in the OLH as long as you can find your way into it.

    A way to find which rows currently match the filter is to use the

    cxGrid1DBTableView1.DataController.FilteredRecordIndex[]
    

    property. You can then find that record in the dataset to process it in some way using

    cxGrid1DBTableView1.DataController.LocateByKey().
    

    Update: The original version of this answer assumed that the dataset had an integer ID field. As the OP has said he uses GUIDs instead, I've upddated it accordingly.

    Assuming the TClientDataSet CDS1 has fields Guid : TGuidField, Name : TStringfield, size 32 and Selected : TBooleanField and is connected to a cxDBTableView, with filtering enabled, of a TcxGrid.

    • Make sure the cxGrid1DBTableView1.DataController.KeyFieldNames is set to 'Guid'.

    • Add a regular TDBGrid to the form and point it at the same datasource as the TcxGrid. The point of this is to make it easy to verify that the code is working as required.

    • Add the code below to the unit, and point cxDBTableView1's OnColumnHeaderClick at the handler cxGrid1DBTableView1ColumnHeaderClick, and the form's OnCreate at the FormCreate.

    Compiler & run

    Code:

    procedure TForm1.cxGrid1DBTableView1ColumnHeaderClick(Sender: TcxGridTableView;
        AColumn: TcxGridColumn);
    begin
      if AColumn = cxGrid1DBTableView1Name then
        ProcessFilteredRecords;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      AGuid : TGuid;
      i : Integer;
      lResult : Longint;
    begin
      CDS1.IndexFieldNames := 'Name';
      CDS1.CreateDataSet;
    
      for i:= 0 to 6 do begin
        lResult := SysUtils.CreateGUID(AGuid);
        CDS1.Insert;
        CDS1.FieldByName('Name').AsString := Chr(Ord('A') + i);
        CDS1.FieldByName('Guid').AsString := GuidToString(AGuid);
        CDS1.FieldByName('Selected').AsBoolean := False;
        CDS1.Post;
      end;
    
      CDS1.First;
    end;
    
    procedure TForm1.ProcessFilteredRecords;
    var
      V : Variant;
      i,
      Index: Integer;
      BM : TBookMark;
    begin
    
      BM := CDS1.GetBookMark;
      CDS1.DisableControls;
      try
        for i := 0 to cxGrid1DBTableView1.DataController.FilteredRecordCount - 1 do begin
          Index := cxGrid1DBTableView1.DataController.FilteredRecordIndex[i];
          // Next, get the GUID value of the row
          V := cxGrid1DBTableView1.DataController.Values[Index, 0];
          if cxGrid1DBTableView1.DataController.LocateByKey(V) then begin
            CDS1.Edit;
            CDS1.FieldByName('Selected').AsBoolean := True;
            CDS1.Post;
          end;
        end;
      finally
        CDS1.EnableControls;
        CDS1.GotoBookmark(BM);
        CDS1.FreeBookmark(BM);
      end;
    end;