3

I want to make something like that. I have a list in my StringGrid and i want to delete one row by selecting cell and then clicking the button. Then this list should show again in StringGrid without this row. The biggest problem i have with deleting row, i tried whis one procedure but it only deleted row in StringGrid, not in list, i think.

    procedure DeleteRow(Grid: TStringGrid; ARow: Integer);
var
  i: Integer;
begin
  for i := ARow to Grid.RowCount - 2 do
    Grid.Rows[i].Assign(Grid.Rows[i + 1]);
  Grid.RowCount := Grid.RowCount - 1;
end;

Please someone for help. :)

Vekka
  • 141
  • 1
  • 1
  • 12
  • I´m not sure I understand correctly, but it seems to me that you have two structures, a list and a grid. The code you presented removes one row from the grid. What prevents you to remove the corresponding item from the list? – AlexSC Dec 06 '13 at 13:47
  • So i should just remove in one time item from the list and Grid? I didn't think about that... – Vekka Dec 06 '13 at 13:55
  • If you use live bindings to display the list in the grid, you could just delete the item from the list. – Marcus Adams Dec 06 '13 at 14:23

2 Answers2

3

If you're using a standard VCL TStringGrid (without using the live bindings made available in recent versions), you can use an interposer class to access the protected TCustomGrid.DeleteRow method.

The following code has been tested in Delphi 2007. It uses a simple TStringGrid dropped on a form, with the default columns and cells, and a standard TButton.

The TForm.OnCreate event handler simply populates the grid with some data to make it easier to see the deleted row. The button click event deletes row 1 from the stringgrid every time it's clicked.

Note: The code does no error checking to make sure that there are enough rows. This is a demo application and not an example of production code. Your actual code should check the number of rows available before attempting to delete one.

// Interposer class, named to indicate it's use
type
  THackGrid=class(TCustomGrid);

// Populates stringgrid with test data for clarity    
procedure TForm1.FormCreate(Sender: TObject);
var
  i, j: Integer;
begin
  for i := 1 to StringGrid1.ColCount - 1 do
    StringGrid1.Cells[i, 0] := Format('Col %d', [i]);
  for j := 1 to StringGrid1.RowCount - 1 do
  begin
    StringGrid1.Cells[0, j] := Format('Row #d', [j]);
    for i := 1 to StringGrid1.ColCount - 1 do
    begin
      StringGrid1.Cells[i, j] := Format('C: %d R: %d', [i, j]);
    end;
  end;
end;

// Deletes row 1 from the stringgrid every time it's clicked
// See note above for info about lack of error checking code.
procedure TForm1.Button1Click(Sender: TObject);
begin
  THackGrid(StringGrid1).DeleteRow(1);
end;

If you're using a more recent version, and have attached the data to the grid using live bindings, you can just delete the row from the underlying data and let the live bindings handle removing the row.

Ken White
  • 123,280
  • 14
  • 225
  • 444
2

The selected row can be retrieved StringGrid1.selected and the you can call the following procedure.

procedure TUtils.DeleteRow(ARowIndex: Integer; AGrid: TStringGrid);
var
  i, j: Integer;
begin
  with AGrid do
  begin
    if (ARowIndex = RowCount) then
      RowCount := RowCount - 1
    else
    begin
      for i := ARowIndex to RowCount do
        for j := 0 to ColumnCount do
          Cells[j, i] := Cells[j, i + 1];

      RowCount := RowCount - 1;
    end;
  end;
end;
mghazal
  • 48
  • 7
  • 1
    Alternatively, call the `TStringGrid.DeleteRow()` method. It is declared as `protected`, but you can use an accessor class to reach it: `type TStringGridAccess = class(TStringGrid) end; TStringGridAccess(AGrid).DeleteRow(ARowIndex);` – Remy Lebeau Jan 08 '16 at 03:05
  • Just to note that the ARowIndex cannot be RowCount as indices start from 0, and everywhere RowCount and ColumnCount should be minus 1. Anyway.. – Peter MP Mar 21 '23 at 13:37