[DUG] StringGrid/DBGrid
John Bird
johnkbird at paradise.net.nz
Wed Sep 7 15:54:38 NZST 2005
I have been using the D5 vanilla StringGrid for displaying data.
The data I am reading is from non database data files - I am reading it in
myself using TFileStream.
>From now on I want to be inputting and editing data in grids, but the
standard StringGrid does not have many embedded cell editors - the one it
supplies seems pretty simple - it does not do even the things the standard
editbox one does (move through a string one word at a time etc with Ctrl/W
etc).
Can anyone who has an opinion on the options below kindly give a
recommendation!
(see below for a tiny reward)
As I see it my options are:
Option 1 - Add a few extra features to the standard stringgrid and use that
for my stuff.
____________________________________________________________________________
______________
I would need:
-a enter cell event (to store the current contents of the cell to check
for changes)
-a exit cell event (so I can call code to verify any cell changes)
-someway to know the position on the screen of the current cell in case
I want to pop up a lookup window
If I could do all of these I would have all I need. Best way to get these?
I could use the onDrawCell event?
Option 2 - DBGrid
_________________
I note the DBGrid seems to have a lot more data verification and cell events
onColEnter and onColExit (are these meant to be called onCellEnter and
onCellExit?) The help says these are when a cell is entered and exited. If
it is a colenter and not a cell enter, what happens if the user arrows from
one cell to the one below it - does it fire?
I notice there is a LoadFromFile and a SavetoFile which looks like I could
use to get the data into the grid.
To use the TDBGrid I could use these methods or a TClientDataSet.
Option 3 - use a third party grid control.
__________________________________________
So far I haven't needed to do this, but have been wondering about some of
the 3rd party components like XStringGrid and AliGrid. I like having
everything vanilla and not having upgrade issues, but also don't wish to
reinvent the wheel all the time!
Option 4 - TClientDataSet and upgrade
_____________________________________
Now TClientDataSet is not in D5, and some friends (namely Gary B) have been
long telling me this is the simplest way to display, edit and manipulate
data (using DBGrid), so it might be time to upgrade, hence look at D7 or
D2005. I think the stuff I have done so far is unlikely to break D2005, so
happy to look at either. Best sources of an upgrade?
Reward
______
For reading this far here is a tiny reward: a little bit of code I wrote to
sort a standard stringgrid. Very fast. Note it only does (case insensitive)
alpha compares, but could easily be modified to do other orderings. As I
already put in numbers right justified into grids it also works for numbers
for me.
It makes a tag stringlist which is sorted in one step, then copies the
original data into a temporary array and then puts it back in the new order
to the original stringgrid. While a bit more work, it is a lot faster than
using a two record at a time exchange or a bubblesort. It also allows
sorting by two columns.
If there is anything I have done you would like to improve kindly tell me!
procedure xcSortGrid(var
PGrid:TStringGrid;SortColumn1:Integer;SortColumn2:integer;AscDesc:char;CaseI
nSensitive:Boolean);
var
UnsortedList:TStringList;
olddefrow,newdefrow:integer; //keep same data row as default
oldrow,datalhs,ptr,colptr,rowptr:integer;
tempstr:string;
lAscDesc:char;
tempcells:array of array of string;
begin
if PGrid.rowcount < 2 then exit; //nothing to sort
UnsortedList:=TStringList.Create;
UnsortedList.sorted:=false;
olddefrow:=-1;
NewDefRow:=-1;
if PGrid.row>0 then oldDefRow:=PGrid.row;
for ptr:=0 to PGrid.rowcount-1 do
begin
//put sort col plus orig pointer into stringlist
tempstr:=PGrid.cells[SortColumn1,ptr]+PGrid.cells[SortColumn2,ptr];
if CaseInsensitive=true then uppercase(tempstr);
xcstrpad(tempstr,60); //make the string 60 chars long
tempstr:=tempstr+inttostr(ptr);
UnSortedList.Add(tempstr);
end;
//sort it
UnSortedList.sorted:=true;
//now copy original cells to tempcells dynamic array
setlength(tempcells,PGrid.colcount,PGrid.rowcount);
for rowptr:=0 to PGrid.rowcount-1 do
begin
for colptr:=0 to PGrid.colcount-1 do
begin
tempcells[colptr,rowptr]:=PGrid.cells[colptr,rowptr];
end;
end;
//now write back to grid
lAscDesc:=upcase(AscDesc);
if lAscDesc='A' then
begin
for ptr:=0 to PGrid.rowCount-1 do
begin
tempstr:=copy(UnSortedList[ptr],61,10);
oldrow:=strtoint(tempstr);
if oldrow=oldDefRow then NewDefRow:=ptr;
//oldptr is orig row number, ptr is new row number
for colptr:=0 to PGrid.colcount-1 do
begin
PGrid.cells[colptr,ptr]:=tempcells[colptr,oldrow];
end;
end;
end
else
begin
for ptr:=PGrid.rowcount-1 downto 0 do
begin
tempstr:=copy(UnSortedList[ptr],61,10);
oldrow:=strtoint(tempstr);
if oldrow=oldDefRow then NewDefRow:=ptr;
//oldptr is orig row number, ptr is new row number
for colptr:=0 to PGrid.colcount-1 do
begin
PGrid.cells[colptr,ptr]:=tempcells[colptr,oldrow];
end;
end;
end;
UnsortedList.free;
tempcells:=nil;
if (OldDefRow>0) and (NewDefRow >=0) then PGrid.row:=NewDefRow;
//note this means if the current row was 0 (the top) the new default row
after sorting is still the top,
//which is generally the best sense.
end;
John B
More information about the Delphi
mailing list