Jump to content
PrimeMinister

How do I check for empty rows in a string grid?

Recommended Posts

Hey guys, so for this program I'm writing I want to check a string grid for empty rows/rows with just spaces in them and then subsequently deleting them to clean the grids up a bit.

I made a procedure that reads the fields from a specific table in a DB and into a corresponding string grid. While 13 of the 14 grids I have, read the records like they're supposed to from the DB, one single table doesn't read correctly, it reads the same amount of records again as empty rows when displayed on the grid.

For example, let's say I have 3 records in the table in the DB and I read it into the grid, the records display properly but then they add 3 more rows with just spaces in them.

 

My code for this so far:

procedure TfrmPuntehou.IncreaseRowCount(grid: TStringGrid);
begin
  //increases rows in grid
  grid.RowCount:= grid.RowCount+1;
end;

procedure TfrmPuntehou.WriteToList(tbl: TADOTable;grid:TStringGrid);
var
  Row: Integer;
  i: Integer;
begin

  tbl.Active:= True;

  Row := 1;

  // Populate cells
  Tbl.First;
  while not (Tbl.Eof) do
  begin
    grid.Cells[0,Row]:= IntToStr(Row);
    grid.Cells[1,Row]:= tbl.fields[0].AsString;
    grid.Cells[2,Row]:= tbl.fields[1].AsString;
    grid.Cells[3,Row]:= tbl.fields[2].AsString;
    Inc(Row);
    IncreaseRowCount(grid);
    Tbl.Next;
  end;
  tbl.Active:=false;

  //what I'm planning to do to alleviate this but I'm not sure to use in the conditions of the if
  // because if I say grid.Rows[i] = ''/grid.Rows[i] = ' ' then I get an error
//  for i := 1 to grid.RowCount - 1 do
//  begin
//    if () OR () then
//    begin
//      grid.Rows[i].Delete;
//    end;
//  end;
end;

Illustration of what I'm talking about:

 

What is supposed to happen:

success.thumb.PNG.eb70ee95b49d239252fac34dbcc048ab.PNG

 

What's happening (the records are inserted correctly, but there are unnecessary rows here for only 3 records. When exported to a CSV the empty rows are filled with spaces"):

fail.thumb.PNG.3976edbbc8be86db9bc306d70323f38c.PNG

 

Thanks in advance for any help on this!

 

Kind Regards

PrimeMinister

 

Share this post


Link to post
Guest
4 hours ago, PrimeMinister said:

one single table doesn't read correctly

So fix the actual problem before asking/looking for a workaround.

Asking us to help you by-pass problem that you created it not constructive.

 

Oh, ah! Just realized i wrote an "heffernandic" post!

Share this post


Link to post
3 hours ago, Vandrovnik said:

In your code, I cannot see initial setting of grid.RowCount.

I set RowCount to 2

Share this post


Link to post
1 hour ago, Dany Marmur said:

So fix the actual problem before asking/looking for a workaround.

Asking us to help you by-pass problem that you created it not constructive.

 

Oh, ah! Just realized i wrote an "heffernandic" post!

oh ok

Share this post


Link to post

For what it's worth, if you "delete" rows by reducing the RowCount, I'd recommend clearing the cell contents first. I found many situations where I'd reduce the RowCount, then increase it later and the cell contents were still there. This may have been fixed in later versions of Delphi as I've not checked it in a while.

 

Share this post


Link to post

I use wrappers that fill my grids, and I clear the grid and set up the grid size before I start loading data.

Share this post


Link to post

it would can be some like this:  It's never too late... then

implementation

{$R *.dfm}

type
  TMyHack = class(TStringGrid); // to access "DeleteRow()"

function MyHowManyRowsToDelete(const AStringGrid: TStringGrid): TArray<integer>;
var
  LRowText: string;
begin
  result := [];
  //
  for var i: integer := 0 to (AStringGrid.RowCount - 1) do
    begin
      LRowText := '';
      //
      for var j: integer := 0 to (AStringGrid.ColCount - 1) do
        begin
          LRowText := LRowText + AStringGrid.Cells[j, i].Trim;
          //
          if (LRowText <> '') then // to avoid still...
            break;
        end;
      //
      if LRowText.Trim = '' then // all columns is empty = row empty
        result := result + [i];
    end;
end;

procedure TForm1.BtnNormalizeRowsClick(Sender: TObject); // the main idea
var
  LRowsToDelete : TArray<integer>;
  LCurrentRowPos: integer;
begin
  // in StringGrid/Grid all cells is a string, normally!
  //
  // VisibleRowCount or RowCount = ??? = you decide!
  // StringGrid1.FixedRows = what to do with it?
  //
  LCurrentRowPos := StringGrid1.Row;
  //
  LRowsToDelete := MyHowManyRowsToDelete(StringGrid1);
  //
  if (Length(LRowsToDelete) = StringGrid1.RowCount) then // all rows empty
    begin
      StringGrid1.RowCount := 0;
      exit;
    end;
  //
  for var i: integer := high(LRowsToDelete) downto 0 do // last to first...
    TMyHack(StringGrid1).DeleteRow(LRowsToDelete[i]);   // remove it
  //
  if (LCurrentRowPos > (StringGrid1.RowCount - 1)) then
    StringGrid1.Row := StringGrid1.RowCount - 1
  else
    StringGrid1.Row := LCurrentRowPos;
end;

 

image.thumb.png.d236a6d094c303b4d8211d676a6a1381.png

 

Edited by programmerdelphi2k

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×