- - * - WhiteUnicorn - * - -




* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >


2849:Determining Record Number In A dBASE Table

KEYWORDS: record number dBASE DBIGETRECORD BDE IDAPI AREA: Database Programmin

dBASE tables employ a fairly static record numbering system. The record
number for a given record reflects its physical position in the table
file. These record number are not subject to change dependent on the
filtering of data or index ordering. For instance, a record that is the
first record stored in the .DBF file would be record number 1. It is
possible that, through the ordering of an index, this record may be
displayed as the last of 100 records. In such a case, its record would
remain the same -- one -- and would not be changed to 100 to reflect its
position in the index ordered data set. This is in contrast with Paradox
tables, where there is a sequence number. The Paradox sequence number is
like the dBASE record number except that it is much more fluid and the
number for a given record will reflect its position relative to the data
set. That is, a record may not always have the same sequence number given
filtering of the data set to reduce the number of records or when an index
is active that may change the displayed order of the record.

In database applications created with Delphi and the Borland Database
Engine (BDE), there is no provision built into the stock data components
for extracting or determining the record for dBASE tables. Such an opera-
tion is, however, possible by making a call from the application a BDE
function.

There are a number of BDE functions that will return information about the
current dBASE record, such as the record number. Basically, any function
that fills a BDE pRECProps structure would suffice. Such BDE functions
include DbiGetRecord, DbiGetNextRecord, and DbiGetPriorRecord. Of course,
only the first of these functions really applies to retrieving information
about the current record. The other two move the record pointer when in-
voked, similar in effect to the Next and Prior methods of the TTable or
TQuery components.

The pRECProps structure consists of the fields:

  iSeqNum: type LongInt; specifies the sequence number of the record
    (relative to the data set, including filtering and index ordering);
    applicable if the table type supports sequence numbers (Paradox only).

  iPhyRecNum: type LongInt; specifies the record number for the record;
    applicable only when the table type supports physical record numbers
    (dBASE only).

  bRecChanged: type Boolean; not currently used.

  bSeqNumChanged: type Boolean; not currently used.

  bDeleteFlag: type Boolean; indicates whether the record is deleted;
    applicable only for table types that support soft-deletes (dBASE
    only).

One of these BDE functions may be invoked in a Delphi application to fill
this structure, from which the physical record number may be retrieved.
Below is an example of the DbiGetRecord function used for this purpose.

  function RecNo(ATable: TTable): LongInt;
  var
    R: RECProps;
    rslt: DbiResult;
    Error: array [0..255] of Char;
  begin
    ATable.UpdateCursorPos;
    rslt := DbiGetRecord(ATable.Handle, dbiNoLock, nil, @R);
    if rslt = DBIERR_NONE then
      Result := R.iPhyRecNum
    else begin
      DbiGetErrorString(rslt, Error);
      ShowMessage(StrPas(Error));
      Result := -1;
    end;
  end;

As with invoking any BDE function in a Delphi application, the BDE wrapper
units DbiTypes, and DbiErrs, DbiProcs must be included in the Uses section
of the unit in which the BDE function will be invoked (the Uses section
not shown here). To make this function more transportable, it does not
reference the subject TTable component directly, but a reference to the
TTable is passed as a parameter. If this function is used in a unit that
does not reference the Delphi units DB and DBTables, they must be added so
that references to the TTable component will be valid.

The UpdateCursorPos method of the TTable is called to ensure that the
record number current in the TTable component is synchronized with that
of the underlying table.

BDE functions do not in themselves cause an exception if they fail.
Rather, they return a value of BDE type DbiResult that indicates the succ-
ess or failure of the intended operation. This return value must then be
retrieved and evaluated by the front-end application, and the appropriate
action taken. A result other than DBIERR_NONE indicates an unsuccessful
execution of the function. An extra step may be taken (as in the example
above) to query the BDE to translate an error code into a readable mess-
age with the BDE function DbiGetErrorString. In this example, the return
value from the invoking of DbiGetRecord is stored in the variable rslt,
and then compared against DBIERR_NONE to determine the success of the
function call.

If the call to DbiGetRecord succeeds, the physical record number from the
iPhyRecNum field of the pRECProps structure is stored to the variable
Result, which is the function's return value. To indicate when the
function has failed (i.e., the involing of the DbiGetRecord function
failed), a value of negative one is returned instead of the record
number. This value is purely arbitrary, and any value of a compatible
type may be used at the discretion of the programmer.

        TI



* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >



- - * - Anastasija aka WhiteUnicorn - * - - LJLiveJournal
PFPhotoFile