Searching for Records in Borland TDBGrid

Applies to TestComplete 14.50, last modified on April 22, 2021

To simulate user actions over the TDBGrid control or to obtain the data of the grid cells, you will have to locate the row that contains the data that you are going to work with. This topic describes several approaches that can be used to locate records in the TDBGrid control.

You can locate the desired record using any of the approaches described below in this topic. At the end of the topic we will also compare these approaches.

To perform these actions, TestComplete must have access to internal methods and properties of the TDBGrid control. This requires the following conditions be met:

When testing Borland TDBGrid controls, use specific methods and properties of the corresponding BorlandTDBGrid object. You can call these methods and properties from your keyword tests, as well as from scripts. This topic describes how to work with an object’s properties and methods from your scripts. However, when testing a TDBGrid control from your keyword test, you can use the same methods and properties calling them from keyword test operations. For more information, see Keyword Tests Basic Operations.

Searching in the Underlying Dataset

A TDBGrid control displays data stored in the dataset (TDataset object), to which the control is connected. When the tested application activates another record in the dataset, the TDBGrid control activates the appropriate row. To choose a row in the grid, you can use the methods of the dataset object that search for the appropriate record. When you activate a record in the dataset, the grid control will highlight the appropriate row.

To find a record in the dataset, you can use methods of the TDataset object. Most often you will use the Locate method. This method locates a record, in which fields contain the specified values. The method has the following syntax:

DatasetObj.Locate(Fields, Values, Options)

The method parameters specify the following information:

  • Fields - The name of the dataset field (or fields), in which the method will search. Multiple field names should be separated with semicolons.
  • Values - One or several sought-for values. If you search in several fields, the parameter should specify the array holding the search values.
  • Options - A combination of the two constants: DB.loCaseInsensitive and DB.loPartialKey. These constants defines the search options. If DB.loCaseInsensitive is specified, the method ignores the case when comparing string values. If DB.loPartialKey is specified, the search value can include only part of the matching field, for instance, New will match both Newfoundland and New York. The DB.loCaseInsensitive and DB.loPartialKey constants are analogues to the loCaseInsensitive and loPartialKey constants defined by the VCL library.

If the method finds the record, it returns True, else - False. For complete information on the Locate method, see Delphi or C++Builder documentation.

Note: The first parameter of the method should specify the dataset’s field name (or names) and these names may differ from the column names. So, you have to write script code that obtains the field name by column name (see sample below).

Also, since the Locate method searches in dataset fields, the data type of the search values must match the data type of dataset fields. Else, an error will occur during the method execution. For instance, if you search in a text field and specify an integer value for the search, you will get an error message informing you about incompatible data types.

The Locate method can also search for a record by using several field values. Below is the code that demonstrates this.

Example

View description

JavaScript

function Main ()
{
  var p, Grid, Values, ConvertedValues;

  // Obtain the grid object
  p = Sys.Process("csdemos");
  p.VCLObject("FrmLauncher").VCLObject("BtnViews").ClickButton();
  Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1");

  // Create the array of sought-for values
  Values = new Array ("Papadopoulos", "Chris", 887);
  // Convert the array
  ConvertedValues = ConvertArray(Values);

  // Locate a record
  if (SearchByLocateEx (Grid, "LastName;FirstName;PhoneExt", ConvertedValues) )
    Log.Message ("Record was found and selected.")
  else
    Log.Message ("Record was not found.");
}

// Search using the Locate method
function SearchByLocateEx(GridObj, ColCaptions, SearchValues)
{
  // Obtain the field names
  let FldNames = GetFieldNameEx (GridObj, ColCaptions);
  // Prepare the search options (DB.loCaseInsensitive and DB.loPartialKey constants
  // are analogues to VCL's loCaseInsensitive loPartialKey constants)
  let SearchOptions = MkSet (DB.loCaseInsensitive, DB.loPartialKey);
  // Call the Locate method
  return GridObj.DataSource.DataSet.Locate(FldNames, SearchValues, SearchOptions);
}

// Get columns' field names
function GetFieldNameEx (GridObj, ColCaptions)
{
  // Get an array of column captions
  let ColCaptionsArr = ColCaptions.split(";");
  // Create an array that will store field names
  let FldNamesArr = new Array (ColCaptionsArr.length);
  // Get the columns' field names
  for (let i=0; i<ColCaptionsArr.length; i++)
    FldNamesArr[i] = GetFieldName (GridObj, ColCaptionsArr[i]);

  // Return a semicolon-delimited string holding field names
  return FldNamesArr.join(";");
}

// Get the field name
function GetFieldName (GridObj, ColCaption)
{
  // Iterate through the columns collection
  for (let i = 0; i < GridObj.Columns.Count; i++)
    // Check the column caption
    if (equal(GridObj.Columns.Items(i).Field.DisplayName, ColCaption))
      return GridObj.Columns.Items(i).FieldName; // Column is found

  return ""; // Column is not found
}

// Convert the array
function ConvertArray(JavaScriptArray)
{
  // Use the Dictionary object to convert JavaScript array
  let objDict = getActiveXObject("Scripting.Dictionary");
  objDict.RemoveAll();
  for (i in JavaScriptArray)
    objDict.Add(i, JavaScriptArray[i]);
  return objDict.Items();
}

JScript

function Main ()
{
  var p, Grid, Values, ConvertedValues;

  // Obtain the grid object
  p = Sys.Process("csdemos");
  p.VCLObject("FrmLauncher").VCLObject("BtnViews").ClickButton();
  Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1");

  // Create the array of sought-for values
  Values = new Array ("Papadopoulos", "Chris", 887);
  // Convert the array
  ConvertedValues = ConvertArray(Values);

  // Locate a record
  if (SearchByLocateEx (Grid, "LastName;FirstName;PhoneExt", ConvertedValues) )
    Log.Message ("Record was found and selected.")
  else
    Log.Message ("Record was not found.");
}

// Search using the Locate method
function SearchByLocateEx(GridObj, ColCaptions, SearchValues)
{
  // Obtain the field names
  var FldNames = GetFieldNameEx (GridObj, ColCaptions);
  // Prepare the search options (DB.loCaseInsensitive and DB.loPartialKey constants
  // are analogues to VCL's loCaseInsensitive loPartialKey constants)
  var SearchOptions = MkSet (DB.loCaseInsensitive, DB.loPartialKey);
  // Call the Locate method
  return GridObj.DataSource.DataSet.Locate(FldNames, SearchValues, SearchOptions);
}

// Get columns' field names
function GetFieldNameEx (GridObj, ColCaptions)
{
  // Get an array of column captions
  var ColCaptionsArr = ColCaptions.split(";");
  // Create an array that will store field names
  var FldNamesArr = new Array (ColCaptionsArr.length);
  // Get the columns' field names
  for (var i=0; i<ColCaptionsArr.length; i++)
    FldNamesArr[i] = GetFieldName (GridObj, ColCaptionsArr[i]);

  // Return a semicolon-delimited string holding field names
  return FldNamesArr.join(";");
}

// Get the field name
function GetFieldName (GridObj, ColCaption)
{
  // Iterate through the columns collection
  for (var i = 0; i < GridObj.Columns.Count; i++)
    // Check the column caption
    if (GridObj.Columns.Items(i).Field.DisplayName == ColCaption)
      return GridObj.Columns.Items(i).FieldName; // Column is found

  return ""; // Column is not found
}

// Convert the array
function ConvertArray(JScriptArray)
{
  // Use the Dictionary object to convert JScript array
  var objDict = new ActiveXObject("Scripting.Dictionary");
  objDict.RemoveAll();
  for (var i in JScriptArray)
    objDict.Add(i, JScriptArray[i]);
  return objDict.Items();
}

Python

def Main ():
  
  # Obtain the grid object
  p = Sys.Process("csdemos")
  p.VCLObject("FrmLauncher").VCLObject("BtnViews").ClickButton()
  Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1")

  # Create the array of sought-for values
  Values = list("Papadopoulos", "Chris", 887)

  # Locate a record
  if(SearchByLocateEx (Grid, "LastNameFirstNamePhoneExt", Values)):
    Log.Message ("Record was found and selected.")
  else:
    Log.Message ("Record was not found.")

# Search using the Locate method
def SearchByLocateEx(GridObj, ColCaptions, SearchValues):
  # Obtain the field names
  FldNames = GetFieldNameEx (GridObj, ColCaptions)
  # Prepare the search options (DB.loCaseInsensitive and DB.loPartialKey constants
  # are analogues to VCL's loCaseInsensitive loPartialKey constants)
  SearchOptions = MkSet (DB.loCaseInsensitive, DB.loPartialKey)
  # Call the Locate method
  return GridObj.DataSource.DataSet.Locate(FldNames, SearchValues, SearchOptions)

# Get columns' field names
def GetFieldNameEx (GridObj, ColCaptions):
  # Get an array of column captions
  ColCaptionsArr = ColCaptions.split("")
  # Create an array that will store field names
  FldNamesArr = list(ColCaptionsArr.length)
  # Get the columns' field names
  for i in range(0, ColCaptionsArr.length-1):
    FldNamesArr[i] = GetFieldName (GridObj, ColCaptionsArr[i])

  # Return a semicolon-delimited string holding field names
  return FldNamesArr.join("")

# Get the field name
def GetFieldName (GridObj, ColCaption):
  # Iterate through the columns collection
  for i in range(0, GridObj.Columns.Count-1):
    # Check the column caption
    if (GridObj.Columns.Items[i].Field.DisplayName == ColCaption):
      return GridObj.Columns.Items[i].FieldName # Column is found

  return "" # Column is not found

VBScript

Sub Main
  Dim p, Grid, Values

  ' Obtain the grid object
  Set p = Sys.Process("csdemos")
  p.VCLObject("FrmLauncher").VCLObject("BtnViews").ClickButton
  Set Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1")

  ' Create the array of sought-for values
  Values = Array ("Papadopoulos", "Chris", 887)

  ' Locate a record
  If SearchByLocateEx (Grid, "LastName;FirstName;PhoneExt", Values) Then
    Log.Message ("Record was found and selected.")
  Else
    Log.Message ("Record was not found.")
  End If
End Sub

' Search using the Locate method
Function SearchByLocateEx (GridObj, ColCaptions, SearchValues)
  Dim FldNames, SearchOptions
  ' Obtain the field names
  FldNames = GetFieldNameEx(GridObj, ColCaptions)
  ' Prepare the search options (DB.loCaseInsensitive and DB.loPartialKey constants
  ' are analogues to VCL's loCaseInsensitive loPartialKey constants)
  SearchOptions = MkSet(DB.loCaseInsensitive, DB.loPartialKey)
  ' Call the Locate method
  SearchByLocateEx = GridObj.DataSource.DataSet.Locate (FldNames, SearchValues, SearchOptions)
End Function

' Get the columns' field names
Function GetFieldNameEx (GridObj, ColCaptions)
  Dim ColCaptionsArr, FldNamesArr, i

  ' Get an array of column captions
  ColCaptionsArr = Split (ColCaptions, ";")
  ' Create an array that will store field names
  FldNamesArr = CreateVariantArray (0, UBound(ColCaptionsArr))
  ' Get the columns' field names
  For i=0 To UBound(ColCaptionsArr)
    FldNamesArr(i) = GetFieldName (GridObj, ColCaptionsArr(i))
  Next

  ' Return a semicolon-delimited string holding field names
  GetFieldNameEx = Join (FldNamesArr, ";")
End Function

' Get the field name
Function GetFieldName (GridObj, ColCaption)
  ' Iterate through columns collection
  For i = 0 To GridObj.Columns.Count
    ' Check the column caption
    If GridObj.Columns.Items(i).Field.DisplayName = ColCaption Then
      GetFieldName = GridObj.Columns.Items(i).FieldName ' Column is found
      Exit Function
    End If
  Next

  GetFieldName = "" ' Column is not found
End Function

DelphiScript

function GetFieldNameEx(GridObj, ColCaptions); forward;
function GetFieldName (GridObj, ColCaption); forward;
function SearchByLocateEx (GridObj, ColCaptions, SearchValues); forward;

procedure Main;
var p, Grid, Values : OleVariant;
begin
  // Obtain the grid object
  p := Sys.Process('csdemos');
  p.VCLObject('FrmLauncher').VCLObject('BtnViews').ClickButton;
  Grid := p.VCLObject('FrmViewDemo').VCLObject('Panel2').VCLObject('DBGrid1');

  // Create the array of sought-for values
  Values := CreateVariantArray (0, 2);
  Values[0] := 'Papadopoulos';
  Values[1] := 'Chris';
  Values[2] := 887;

  // Locate a record
  if SearchByLocateEx (Grid, 'LastName;FirstName;PhoneExt', Values) then
    Log.Message ('Record was found and selected.')
  else
    Log.Message ('Record was not found.');
end;

// Search using the Locate method
function SearchByLocateEx (GridObj, ColCaptions, SearchValues);
var FldNames, SearchOptions : OleVariant;
begin
  // Obtain the field names
  FldNames := GetFieldNameEx(GridObj, ColCaptions);
  // Prepare the search options (DB.loCaseInsensitive and DB.loPartialKey constants
  // are analogues to VCL's loCaseInsensitive loPartialKey constants)
  SearchOptions := MkSet(DB.loCaseInsensitive, DB.loPartialKey);
  // Call the Locate method
  Result := GridObj.DataSource.DataSet.Locate (FldNames, SearchValues, SearchOptions);
end;

// Get columns' field names
function GetFieldNameEx(GridObj, ColCaptions);
var FldNames, n, i : OleVariant;
begin
  FldNames := '';
  // Process the string of column names
  aqString.ListSeparator := ';';
  n := aqString.GetListLength (ColCaptions);
  for i := 0 to n-2 do
    // Get the field name for the current column and add it to the resulting string
    FldNames := FldNames + GetFieldName (GridObj, aqString.GetListItem(ColCaptions, i)) + ';' ;
  FldNames := FldNames + GetFieldName (GridObj, aqString.GetListItem(ColCaptions, n-1));

  Result := FldNames;
end;

// Get the field name
function GetFieldName (GridObj, ColCaption);
var i : OleVariant;
begin
  // Iterate through the columns collection
  for i := 0 to GridObj.Columns.Count-1 do
    // Check the column caption
    if GridObj.Columns.Items[i].Field.DisplayName = ColCaption then
    begin
      Result := GridObj.Columns.Items[i].FieldName; // Column is found
      Exit;
    end;

  Result := ''; // Column is not found
end;

C++Script, C#Script

function Main ()
{
  var p, Grid, Values, ConvertedValues;

  // Obtain the grid object
  p = Sys["Process"]("csdemos");
  p["VCLObject"]("FrmLauncher")["VCLObject"]("BtnViews")["ClickButton"]();
  Grid = p["VCLObject"]("FrmViewDemo")["VCLObject"]("Panel2")["VCLObject"]("DBGrid1");

  // Create the array of sought-for values
  Values = new Array ("Papadopoulos", "Chris", 887);
  // Convert the array
  ConvertedValues = ConvertArray(Values);

  // Locate a record
  if (SearchByLocateEx (Grid, "LastName;FirstName;PhoneExt", ConvertedValues) )
    Log["Message"]("Record was found and selected.")
  else
    Log["Message"]("Record was not found.");
}

// Search using the Locate method
function SearchByLocateEx(GridObj, ColCaptions, SearchValues)
{
  // Obtain the field names
  var FldNames = GetFieldNameEx (GridObj, ColCaptions);
  // Prepare the search options (DB.loCaseInsensitive and DB.loPartialKey constants
  // are analogues to VCL's loCaseInsensitive loPartialKey constants)
  var SearchOptions = MkSet (DB["loCaseInsensitive"], DB["loPartialKey"]);
  // Call the Locate method
  return GridObj["DataSource"]["DataSet"]["Locate"](FldNames, SearchValues, SearchOptions);
}

// Get columns' field names
function GetFieldNameEx (GridObj, ColCaptions)
{
  // Get an array of column captions
  var ColCaptionsArr = ColCaptions["split"](";");
  // Create an array that will store field names
  var FldNamesArr = new Array (ColCaptionsArr["length"]);
  // Get the columns' field names
  for (var i=0; i<ColCaptionsArr["length"]; i++)
    FldNamesArr[i] = GetFieldName (GridObj, ColCaptionsArr[i]);

  // Return a semicolon-delimited string holding field names
  return FldNamesArr["join"](";");
}

// Get the field name
function GetFieldName (GridObj, ColCaption)
{
  // Iterate through the columns collection
  for (var i = 0; i < GridObj["Columns"]["Count"]; i++)
    // Check the column caption
    if (GridObj["Columns"]["Items"](i)["Field"]["DisplayName"] == ColCaption)
      return GridObj["Columns"]["Items"](i)["FieldName"]; // Column is found

  return ""; // Column is not found
}

// Convert the array
function ConvertArray (JScriptArray)
{
  // Use the Dictionary object to convert JScript array
  var objDict = new ActiveXObject ("Scripting.Dictionary");
  objDict["RemoveAll"]();
  for (var i in JScriptArray)
    objDict["Add"](i, JScriptArray[i]);
  return objDict["Items"]();
}

Searching by Iterating Through Grid Rows

Quite often, users search for records by iterating through grid records and examining cell values. You can create a script that will emulate these user actions. Below is a sample script that demonstrates this approach.

Example

View description

JavaScript

// Activate a row by its index (zero-based)
function ActivateRow(GridObject, RowIndex)
{
  GridObject.DataSource.DataSet.First();
  GridObject.DataSource.DataSet.MoveBy(RowIndex);
}

// Get the cell by its row and column indexes (zero-based)
function GetCell(GridObject, Row, Col)
{
  var FldName, Fld;
  
  // Get the field name
  FldName = GridObject.Columns.Items(Col).FieldName;
  // Activate the row
  ActivateRow(GridObject, Row);
  // Get the field text
  Fld = GridObject.DataSource.DataSet.FieldByName(FldName);
  return Fld.AsString;
}

// Search for a row by cell value
function SearchCell(GridObject, ColIndex, Value)
{

  let r = -1;
  // Iterate through grid records
  for(let i = 0; i < GridObject.DataSource.DataSet.RecordCount; i++)
  {
    // Get cell value and comparing it with the sought-for value
    if (equal(GetCell(GridObject, i, ColIndex), Value))
    {
      r = i;
      break;
    }
  }
  return r;
}

function Main()
{
  var p, Grid;
  
  // Obtain the grid object
  p = Sys.Process("csdemos");
  Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1");
  
  // Search
  if(!equal(SearchCell(Grid, 1, "Papadopoulos"), - 1))
    Log.Message("Found");
  else
    Log.Message("Not Found");
}

JScript

// Activate a row by its index (zero-based)
function ActivateRow(GridObject, RowIndex)
{
  GridObject.DataSource.DataSet.First();
  GridObject.DataSource.DataSet.MoveBy(RowIndex);
}

// Get the cell by its row and column indexes (zero-based)
function GetCell(GridObject, Row, Col)
{
  var FldName, Fld;
  
  // Get the field name
  FldName = GridObject.Columns.Items(Col).FieldName;
  // Activate the row
  ActivateRow(GridObject, Row);
  // Get the field text
  Fld = GridObject.DataSource.DataSet.FieldByName(FldName);
  return Fld.AsString;
}

// Search for a row by cell value
function SearchCell(GridObject, ColIndex, Value)
{
  var i, r;
  
  r = -1;
  // Iterate through grid records
  for(i = 0; i < GridObject.DataSource.DataSet.RecordCount; i++)
  {
    // Get cell value and comparing it with the sought-for value
    if (GetCell(GridObject, i, ColIndex) == Value)
    {
      r = i;
      break;
    }
  }
  return r;
}

function Main()
{
  var p, Grid;
  
  // Obtain the grid object
  p = Sys.Process("csdemos");
  Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1");
  
  // Search
  if( SearchCell(Grid, 1, "Papadopoulos") != - 1)
    Log.Message("Found");
  else
    Log.Message("Not Found");
}

Python

# Activate a row by its index (zero-based)
def ActivateRow(GridObject, RowIndex):
  GridObject.DataSource.DataSet.First()
  GridObject.DataSource.DataSet.MoveBy(RowIndex)

# Get the cell by its row and column indexes (zero-based) 
def GetCell(GridObject, Row, Col):
  
  # Get the field name
  FldName = GridObject.Columns.Items(Col).FieldName
  # Activate the row
  ActivateRow(GridObject, Row)
  # Get the field text 
  Fld = GridObject.DataSource.DataSet.FieldByName(FldName)
  return Fld.AsString

# Search for a row by cell value 
def SearchCell(GridObject, ColIndex, Value):
  
  r = -1
  # Iterate through grid records
  for i in range(0, GridObject.DataSource.DataSet.RecordCount): 
    # Get cell value and comparing it with the sought-for value
    if (GetCell(GridObject, i, ColIndex) == Value):
      r = i
      break
  return r

def Main1():

  # Obtain the grid object
  p = Sys.Process("csdemos")
  Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1")
  
  # Search
  if( SearchCell(Grid, 1, "Papadopoulos") != - 1):
    Log.Message("Found")
  else:
    Log.Message("Not Found")

VBScript

' Activates a row by its index (zero-based)
Sub ActivateRow(GridObject, RowIndex)
  Call GridObject.DataSource.DataSet.First()
  Call GridObject.DataSource.DataSet.MoveBy(RowIndex)
End Sub

' Getting the cell by its row and column indexes (zero-based)
Function GetCell(GridObject, Row, Col)
  ' Getting the field name
  FldName = GridObject.Columns.Items(Col).FieldName
  ' Activating the row
  Call ActivateRow(GridObject, Row)
  ' Getting the field text
  Set Fld = GridObject.DataSource.DataSet.FieldByName(FldName)
  GetCell = Fld.AsString
End Function

' Searching for a row by cell value
Function SearchCell(GridObject, ColIndex, Value)
  SearchCell = -1
  ' Iterating through grid records
  For i = 0 To GridObject.DataSource.DataSet.RecordCount - 1
    ' Getting cell value and comparing it with the sought-for value
    If GetCell(GridObject, i, ColIndex) = Value Then
      SearchCell = i
      Exit For
    End If
  Next 
End Function

Sub Main
  ' Obtaining the grid object
  Set p = Sys.Process("csdemos")
  Set Grid = p.VCLObject("FrmViewDemo").VCLObject("Panel2").VCLObject("DBGrid1")
  
  ' Searching
  If SearchCell(Grid, 1, "Papadopoulos") <> -1 Then
    Log.Message("Found")
  Else
    Log.Message("Not found")
  End If
End Sub

DelphiScript

// Activate a row by its index (zero-based)
procedure ActivateRow(GridObject, RowIndex);
begin
  GridObject.DataSource.DataSet.First();
  GridObject.DataSource.DataSet.MoveBy(RowIndex);
end;

// Get the cell by its row and column indexes (zero-based)
function GetCell(GridObject, Row, Col);
var
  FldName, Fld : OleVariant;
begin
  // Get the field name
  FldName := GridObject.Columns.Items[Col].FieldName;
  // Activate the row
  ActivateRow(GridObject, Row);
  // Get the field text
  Fld := GridObject.DataSource.DataSet.FieldByName[FldName];
  Result := Fld.AsString;
end;

// Search for a row by cell value
function SearchCell(GridObject, ColIndex, Value);
var 
  i : OleVariant;
begin
  Result := -1;

  // Iterate through grid records
  for i := 0 to GridObject.DataSource.DataSet.RecordCount - 1 do 
  begin 
    // Get cell value and comparing it with the sought-for value
    if GetCell(GridObject, i, ColIndex) = Value then
    begin
      Result := i;
      Exit;
    end;
  end;
end;

procedure Main;
var
  p, Grid : OleVariant;
begin
  // Obtain the grid object
  p := Sys.Process('csdemos');
  Grid := p.VCLObject('FrmViewDemo').VCLObject('Panel2').VCLObject('DBGrid1');
  
  // Search
  if SearchCell(Grid, 1, 'Papadopoulos') <> -1 then
    Log.Message('Found')
  else
    Log.Message('Not Found');
end;

C++Script, C#Script

// Activate a row by its index (zero-based)
function ActivateRow(GridObject, RowIndex)
{
  GridObject["DataSource"]["DataSet"]["First"]();
  GridObject["DataSource"]["DataSet"]["MoveBy"](RowIndex);
}

// Get the cell by its row and column indexes (zero-based)
function GetCell(GridObject, Row, Col)
{
  var FldName, Fld;
  
  // Get the field name
  FldName = GridObject["Columns"]["Items"](Col)["FieldName"];
  // Activate the row
  ActivateRow(GridObject, Row);
  // Get the field text
  Fld = GridObject["DataSource"]["DataSet"]["FieldByName"](FldName);
  return Fld["AsString"];
}

// Search for a row by cell value
function SearchCell(GridObject, ColIndex, Value)
{
  var i, r;
  
  r = -1;
  // Iterate through grid records
  for(i = 0; i < GridObject["DataSource"]["DataSet"]["RecordCount"]; i++)
  {
    // Get cell value and comparing it with the sought-for value
    if (GetCell(GridObject, i, ColIndex) == Value)
    {
      r = i;
      break;
    }
  }
  return r;
}

function Main()
{
  var p, Grid;
  
  // Obtain the grid object
  p = Sys["Process"]("csdemos");
  Grid = p["VCLObject"]("FrmViewDemo")["VCLObject"]("Panel2")["VCLObject"]("DBGrid1");
  
  // Search
  if( SearchCell(Grid, 1, "Papadopoulos") != -1)
    Log["Message"]("Found");
  else
    Log["Message"]("Not Found");
}

As you can see, to activate a row, we called two methods of the grid’s dataset: First and MoveBy. That is, locating a record requires two steps: we choose the first record and then move the selection to the specified distance. Using this technique guarantees that the selection procedure will work in both filtered and non-filtered datasets.

If the dataset is not filtered, you can activate grid rows by using the grid’s vertical scroll bar. When displaying the data stored in a non-filtered dataset, the TDBGrid control sets the minimum position of the vertical scroll bar to 1 and the maximum position to the number of dataset records. By specifying the scroll box position you can activate the desired row by its index.

To get a scripting interface to the grid’s vertical scroll bar, use the VScroll property of the scripting object that corresponds to the TDBGrid control. This property is provided by TestComplete. It returns the ScrollBar object corresponding to the vertical scroll bar of the control. To set the scroll bar’s position, use the Pos property of the ScrollBar object. The following code demonstrates how you can use this property:

JavaScript, JScript

// Activate a row by its index (zero-based)
function ActivateRowByScrollBar (GridObj, RowIndex)
{
  GridObj.VScroll.Pos = RowIndex + 1;
}

Python

# Activate a row by its index (zero-based)
def ActivateRowByScrollBar (GridObj, RowIndex):
  GridObj.VScroll.Pos = RowIndex + 1

VBScript

' Activate a row by its index (zero-based)
Sub ActivateRowByScrollBar (GridObj, RowIndex)
  GridObj.VScroll.Pos = RowIndex + 1
End Sub

DelphiScript

// Activate a row by its index (zero-based)
procedure ActivateRowByScrollBar (GridObj, RowIndex);
begin
  GridObj.VScroll.Pos := RowIndex + 1;
end;

C++Script, C#Script

// Activate a row by its index (zero-based)
function ActivateRowByScrollBar (GridObj, RowIndex)
{
  GridObj["VScroll"]["Pos"] = RowIndex + 1;
}

Note: Since the minimum scroll bar position is 0 and the row index is zero-based, we increased the RowIndex parameter by 1 when assigning it to the Pos property.

We would like to note once again that this approach only works if the TDBGrid displays data of a non-filtered dataset.

Which Approach to Choose

We described two variants of the searching procedure. One of these variants uses the Locate method and another one iterates through the rows of the grid to find the desired row.

In general, the approach that uses the Locate method provides a faster search. If the dataset has indexes, the Locate method will search using these indexes. However, the method analyzes data stored in the database fields and this may cause problems, which can affect your decision on using the method.

Since the Locate method checks data stored in the database fields, you have to be aware of the field data type and specify the appropriate data as a search value. Else, an error will occur. For instance, if the field holds an integer value and you specify a string, you will get an error message during the script execution.

Note that the fields’s data may differ from the data you see in the grid cells: VCL includes special events, which let programmers change the field text to be displayed in visual controls. So, the TDBGrid control may display the modified text rather than the data stored in the field. For instance, a field may store an integer value (say, 3), but the grid may display the string other than “3”, because the event handler can change the displayed text to something like “3 book(s)” or “3 user(s)”. Please remember this when specifying the sought-for values for the Locate method.

The second variant of the search procedure iterates through the grid records and analyzes the field’s text, so it does not depend on the field type and on the TField object’s events that change the displayed text. However, the iteration approach functions a lot slower than the Locate method. So, you can use it when you need to search for data within the field’s text.

Note that developers change the cell text using events of the TField and TDBGrid objects. The iteration approach does not depend on the TField event handlers. However, it will not help if developers modify the cell values using events of the TDBGrid control. To search for records in this case, you will have to use the Locate method of the TDataset object.

See Also

Working With Borland TDBGrid
Iterating Through Rows in Borland TDBGrid
Obtaining and Setting Cell Values in Borland TDBGrid

Highlight search results