ADO Database Delphi

Title: Row number in a DBGrid
Question: Implementing a different method of getting the line number of a selected row in a DBGrid. Using dataset.RecNo is not the best practice with a master-detail relationships.
Answer:
This is a different method for getting the line number of a selected row in a DBGrid and the total number of lines using master-detail relationships. The table.recno doesn't respect the order of the items in the detail dataset.
So in the AfterScroll event of the master dataset you load a TStringList with the recno property of all the items. Then you can use the index property of that TStringList to search the exact rownumber.
The source uses two dataset (master-detail), a dbgrid and two label to put the selected row number and the total row number.
...
Database: TDatabase;
Details: TTable;
Master: TTable;
...
nRowLbl: TLabel;
totRowsLbl: TLabel;
...
procedure LoadRowList();
function getRowNum: integer;
function getTotRowsNum: integer;
...
var
Form1: TForm1;
rowList: TStringList;
inserting: Boolean;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Master.Open;
end;
procedure TForm1.MasterBeforeOpen(DataSet: TDataSet);
begin
rowList:=TStringList.Create;
Details.Open;
end;
procedure TForm1.MasterNewRecord(DataSet: TDataSet);
begin
rowList.Clear;
end;
procedure TForm1.DetailsAfterDelete(DataSet: TDataSet);
begin
//re-load the list
LoadRowList;
end;
procedure TForm1.DetailsAfterPost(DataSet: TDataSet);
begin
if inserting then
rowList.Add(inttostr(Details.RecNo));
inserting:= false;
nRowLbl.Caption:=IntToStr(getRowNum);
end;
function TForm1.getRowNum: integer;
var
nRiga: integer;
begin
if (Details.RecordCount=0) then
getRowNum:=1
else
begin
nRiga:=Details.RecNo;
if nRiga-1 then
getRowNum:=rowList.IndexOf(inttostr(nRiga)) + 1
else
getRowNum:=Details.RecordCount + 1;
end;
end;
procedure TForm1.DetailsNewRecord(DataSet: TDataSet);
begin
DetailsRIG_CODICE.Value := MasterDOC_CODICE.Value;
inserting:=true;
end;
procedure TForm1.DetailsBeforeCancel(DataSet: TDataSet);
begin
inserting:=false;
end;
function TForm1.getTotRowsNum: integer;
begin
if (Details.RecordCount=0) then
getTotRowsNum:=1
else
if Details.RecNo-1 then
getTotRowsNum:=Details.RecordCount
else
getTotRowsNum:=Details.RecordCount + 1;
end;
procedure TForm1.MasterAfterScroll(DataSet: TDataSet);
begin
LoadRowList;
nRowLbl.Caption:=IntToStr(getRowNum);
totRowsLbl.Caption:=IntToStr(getTotRowsNum);
end;
procedure TForm1.DetailsAfterScroll(DataSet: TDataSet);
begin
if not Details.ControlsDisabled then
begin
nRowLbl.Caption:=IntToStr(getRowNum);
totRowsLbl.Caption:=IntToStr(getTotRowsNum);
end;
end;
procedure TForm1.LoadRowList;
begin
rowList.Clear;
Details.DisableControls; //for better performance
Details.First;
while not Details.Eof do
begin
rowList.Add(inttostr(Details.RecNo));
Details.Next;
end;
Details.EnableControls;
end;