Working With Grids - Basic Concepts

Applies to TestComplete 15.47, last modified on January 20, 2023

Working with supported grid controls

When you are recording a test or explore your tested application by using the Object Browser or Object Spy, TestComplete automatically detects the type of a grid control in your tested application. If the grid is supported, TestComplete automatically associates it with a scripting object. You can use properties and methods of that object to access your grid data and simulate user actions over your grid. For example, click cells. You call those methods and properties the same way you call any object’s property or methods, that is, object.spec_method. No specific notation is needed.

The image below shows the application hierarchy exposed by using the Object Browser and the object that TestComplete has associated with a grid control in the application:

Object that TestComplete associates with a control

Click the image to enlarge it.

The code snippet below demonstrates how you can click a grid cell and change its value:

JavaScript

function ClickGridCell()
{
  var p, w;
  // Obtain the grid object
  p = Sys.Process("DataGridViewSample");
  w = p.WinFormsObject("Form1").WinFormsObject("dataGridView1");
  // Call a control-specific method
  w.ClickCell(0, "Customer Name");
  // Assign value to a control-specific property
  w.$set("wValue", 0, "Customer Name", "Samuel Clemens");
}

JScript

function ClickGridCell()
{
  var p, w;
  // Obtain the grid object
  p = Sys.Process("DataGridViewSample");
  w = p.WinFormsObject("Form1").WinFormsObject("dataGridView1");
  // Call a control-specific method
  w.ClickCell(0, "Customer Name");
  // Assign value to a control-specific property
  w.wValue(0, "Customer Name") = "Samuel Clemens";
}

Python

def ClickGridCell():
  # Obtain the grid object
  p = Sys.Process("DataGridViewSample")
  w = p.WinFormsObject("Form1").WinFormsObject("dataGridView1")
  # Call a control-specific method
  w.ClickCell(0, "Customer Name")
  # Assign value to a control-specific property
  w.wValue[0, "Customer Name"] = "Samuel Clemens"

VBScript

Sub ClickGridCell
  Dim p, w
  ' Obtain the grid object
  Set p = Sys.Process("DataGridViewSample")
  Set w = p.WinFormsObject("Form1").WinFormsObject("dataGridView1")
  ' Call a control-specific method
  Call w.ClickCell(0, "Customer Name")
  ' Assign value to a control-specific property
  w.wValue(0, "Customer Name") = "Samuel Clemens"
End Sub

DelphiScript

procedure ClickGridCell;
var p, w : OleVariant;
begin
  // Obtain the grid object
  p := Sys.Process('DataGridViewSample');
  w := p.WinFormsObject('Form1').WinFormsObject('dataGridView1');
  // Call a control-specific method
  w.ClickCell(0, 'Customer Name');
  // Assign value to a control-specific property
  w.wValue[0, 'Customer Name'] := 'Samuel Clemens';
end;

C++Script, C#Script

function ClickGridCell()
{
  var p, w;
  // Obtain the grid object
  p = Sys["Process"]("DataGridViewSample");
  w = p["WinFormsObject"]("Form1")["WinFormsObject"]("dataGridView1");
  // Call a control-specific method
  w["ClickCell"](0, "Customer Name");
  // Assign value to a control-specific property
  w["wValue"](0, "Customer Name") = "Samuel Clemens";
}

In addition, you can verify that your grid control contains the expected data. You do it by using special table checkpoint operation that compares the actual grid control contents with the stored baseline value. To learn more about table checkpoints, see About Table Checkpoints.

Supported grid controls

Currently, TestComplete provides extended support for the following grid controls (and their descendants):

Show list

Note: For TestComplete to recognize the grid controls that are inherited from the listed controls, specify the derived control class name in the appropriate group of the project’s Object Mapping options.
For example, to map a Microsoft DataGridView descendant to the DataGridView object, add the control’s class name (including the namespace) to the Microsoft Controls > WinForms > DataGridView group. TestComplete will recognize the descendant control in the application as the DataGridView object, and you will be able to call the DataGridView object’s properties and methods to simulate user actions over the control. For more information on this technique, see Object Mapping.

Basic principles

The objects listed above use the same principles for simulating user actions over controls:

  • For each method that simulates a click or double-click on a grid cell, you can specify the grid column using its index or caption.

    Indexes are zero-based and correspond to the column’s position in the grid’s internal columns collection. So, the column index does not necessarily correspond to its visible position in the grid.

    When specifying a caption, you can use wildcards (* and ?) or regular expressions. The asterisk (*) corresponds to a string of any length (including an empty string), the wildcard question mark corresponds to any single character (including none). To specify more complicated parts of a caption, use regular expressions.

    The methods and properties can treat the captions as case-sensitive or case-insensitive depending on the Use case-sensitive parameters project settings (you can change it in the Properties page of your project’s editor).

  • All methods that simulate user actions (ClickCell, ClickRowIndicator, ClickColumnHeader, Keys, etc.) activate the window, where they should simulate the actions. The only exception is Sys.Keys; it sends keystrokes to the currently focused window.

  • All methods that simulate user actions automatically scroll the grid so that the desired element becomes visible. Also, if the ClickCell action is applied to the cell which is hidden under a collapsed group, the group is automatically expanded.

When recording actions with the listed grid controls, the following principles are used:

  • In all methods that simulate user actions with grid cells and column headers, columns are recorded using their captions.

  • If a grid cell uses a specific in-place editor (for example, an editor with embedded buttons), clicks on grid cells are recorded with coordinates, that is, as ClickCellXY actions. The same concerns recording clicks on column headers that include custom elements -- they are recorded as ClickColumnHeaderXY actions.

  • Clicks on rows’ expand buttons are recorded as Expand and Collapse actions.

Working with unsupported grid controls

If your tested grid control is not supported (you can view the list of supported grid controls above), TestComplete does not associate it with a special scripting object. To test it, you can use the following approaches:

Use grid control native methods and properties

If your tested application is Open, that is, if TestComplete can access the internal properties and methods of your application’s objects (those are the same methods and properties that are available to the application developers from the source code), you can use them to simulate user actions over your grid control and access its data.

The code below shows how to use the native CurrentCell property of the DataGridView control to specify whether a grid cell is selected:

View description

JavaScript

function Main ()
{
  var p, Grid;

  // Obtain the grid object
  p = Sys.Process ("DataGridViewSample");
  Grid = p.WinFormsObject("Form1").WinFormsObject("dataGridView1");

  // Click some cells
  SelectCell (Grid, 2, "Customer Name");
  SelectCell (Grid, 2, "Product");
  SelectCell (Grid, 2, "Quantity");
}

// Selects the specified cell
function SelectCell (Grid, RowIndex, ColumnId)
{
  // Get the cell's column index
  let ColIndex = GetColIndexById (Grid, ColumnId);
  // Select the cell
  Grid.CurrentCell = Grid.Item(ColIndex, RowIndex);
}

// Returns the column index by its identifier
function GetColIndexById (Grid, ColumnId)
{
  // Check if the column is specified by caption or index
  if (equal(aqObject.GetVarType(ColumnId), varOleStr))
  {
    // Search for the column by its caption
    for (let i=0; i<Grid.ColumnCount; i++)
      if (equal(Grid.Columns.Item(i).HeaderText.OleValue, ColumnId))
        return i; // Column is found

    return -1;    // Column is not found
  }
  else
    // The column is specified by index; return this index
    return ColumnId;
}

JScript

function Main ()
{
  var p, Grid;

  // Obtain the grid object
  p = Sys.Process ("DataGridViewSample");
  Grid = p.WinFormsObject("Form1").WinFormsObject("dataGridView1");

  // Click some cells
  SelectCell (Grid, 2, "Customer Name");
  SelectCell (Grid, 2, "Product");
  SelectCell (Grid, 2, "Quantity");
}

// Selects the specified cell
function SelectCell (Grid, RowIndex, ColumnId)
{
  // Get the cell's column index
  var ColIndex = GetColIndexById (Grid, ColumnId);
  // Select the cell
  Grid.CurrentCell = Grid.Item(ColIndex, RowIndex);
}

// Returns the column index by its identifier
function GetColIndexById (Grid, ColumnId)
{
  // Check if the column is specified by caption or index
  if (aqObject.GetVarType(ColumnId) == varOleStr)
  {
    // Search for the column by its caption
    for (i=0; i<Grid.ColumnCount; i++)
      if (Grid.Columns.Item(i).HeaderText.OleValue == ColumnId)
        return i; // Column is found

    return -1;    // Column is not found
  }
  else
    // The column is specified by index; return this index
    return ColumnId;
}

Python

def Main ():

  # Obtain the grid object
  p = Sys.Process ("DataGridViewSample")
  Grid = p.WinFormsObject("Form1").WinFormsObject("dataGridView1")

  # Click some cells
  SelectCell (Grid, 2, "Customer Name")
  SelectCell (Grid, 2, "Product")
  SelectCell (Grid, 2, "Quantity")

# Selects the specified cell
def SelectCell (Grid, RowIndex, ColumnId):
  # Get the cell's column index
  ColIndex = GetColIndexById (Grid, ColumnId)
  # Select the cell
  Grid.CurrentCell = Grid.Item(ColIndex, RowIndex)

# Returns the column index by its identifier
def GetColIndexById (Grid, ColumnId):
  # Check if the column is specified by caption or index
  if (aqObject.GetVarType(ColumnId) == varOleStr):
    # Search for the column by its caption
    for i in range(0, Grid.ColumnCount-1):
      if (Grid.Columns.Item[i].HeaderText.OleValue == ColumnId):
        return i # Column is found

    return -1    # Column is not found
  else:
    # The column is specified by index return this index
    return ColumnId

VBScript

Function Main ()
  Dim p, Grid

  ' Obtain the grid object
  Set p = Sys.Process ("DataGridViewSample")
  Set Grid = p.WinFormsObject("Form1").WinFormsObject("dataGridView1")

  ' Click some cells
  Call SelectCell (Grid, 2, "Customer Name")
  Call SelectCell (Grid, 2, "Product")
  Call SelectCell (Grid, 2, "Quantity")
End Function

' Selects the specified cell
Function SelectCell (Grid, RowIndex, ColumnId)
  ' Get the cell's column index
  Dim ColIndex
  ColIndex = GetColIndexById (Grid, ColumnId)
  ' Select the cell
  Set Grid.CurrentCell = Grid.Item(ColIndex, RowIndex)
End Function

' Returns the column index by its identifier
Function GetColIndexById (Grid, ColumnId)
  ' Check if the column is specified by caption or index
  If aqObject.GetVarType(ColumnId) = varOleStr Then
  
    ' Search for the column by its caption
    For i=0 To Grid.ColumnCount-1
      If Grid.Columns.Item(i).HeaderText.OleValue = ColumnId Then
        GetColIndexById = i ' Column is found
        Exit Function
      End If
    Next
    GetColIndexById = -1    ' Column is not found
  Else
    ' The column is specified by index return this index
    GetColIndexById = ColumnId
  End If
End Function

DelphiScript

procedure SelectCell (Grid, RowIndex, ColumnId); forward;
function GetColIndexById (Grid, ColumnId); forward;

procedure Main_SelectCell;
var p, Grid : OleVariant;
begin
  // Obtain the grid object
  p := Sys.Process ('DataGridViewSample');
  Grid := p.WinFormsObject('Form1').WinFormsObject('dataGridView1');

  // Click some cells
  SelectCell (Grid, 2, 'Customer Name');
  SelectCell (Grid, 2, 'Product');
  SelectCell (Grid, 2, 'Quantity');
end;

// Selects the specified cell
procedure SelectCell (Grid, RowIndex, ColumnId);
var ColIndex : OleVariant;
begin
  // Get the cell's column index
  ColIndex := GetColIndexById (Grid, ColumnId);
  // Select the cell
  Grid.CurrentCell := Grid.Item[ColIndex, RowIndex];
end;

// Returns the column index by its identifier
function GetColIndexById (Grid, ColumnId);
var i: OleVariant;
begin
  // Check if the column is specified by caption or index
  if aqObject.GetVarType(ColumnId) = varOleStr then
  begin
    // Search for the column by its caption
    for i:=0 to Grid.ColumnCount-1 do
      if Grid.Columns.Item[i].HeaderText.OleValue = ColumnId then
      begin
        Result := i; // Column is found
        Exit;
      end;

    Result := -1;    // Column is not found
  end
  else
    // The column is specified by index; return this index
    Result := ColumnId;
end;

C++Script, C#Script

function Main ()
{
  var p, Grid;

  // Obtain the grid object
  p = Sys["Process"]("DataGridViewSample");
  Grid = p["WinFormsObject"]("Form1")["WinFormsObject"]("dataGridView1");

  // Click some cells
  SelectCell (Grid, 2, "Customer Name");
  SelectCell (Grid, 2, "Product");
  SelectCell (Grid, 2, "Quantity");
}

// Selects the specified cell
function SelectCell (Grid, RowIndex, ColumnId)
{
  // Get the cell's column index
  var ColIndex = GetColIndexById (Grid, ColumnId);
  // Select the cell
  Grid["CurrentCell"] = Grid["Item"](ColIndex, RowIndex);
}

// Returns the column index by its identifier
function GetColIndexById (Grid, ColumnId)
{
  // Check if the column is specified by caption or index
  if (aqObject["GetVarType"](ColumnId) == varOleStr)
  {
    // Search for the column by its caption
    for (i=0; i<Grid["ColumnCount"]; i++)
      if (Grid["Columns"]["Item"](i)["HeaderText"]["OleValue"] == ColumnId)
        return i; // Column is found

    return -1;    // Column is not found
  }
  else
    // The column is specified by index; return this index
    return ColumnId;
}

Use coordinate-based actions

You can simulate user actions over your grid control by using coordinate-based methods that TestComplete provides for all visual objects, like Click, DblClick, Keys, and so on. By default, when you record a test over a grid control that TestComplete does not support, it will use those methods.

Use optical character recognition

If simulating user actions over your grid control by coordinates is not reliable enough, or if your grid control is a graphical element rendered on the screen (for example, it is a part of a chart), you can use optical character recognition (OCR) to test your grid control. You can capture the text content of your grid control, access individual text blocks, and simulate basic user actions (like mouse clicks) over them. For example, you can simulate user actions over individual cells or column headers. To work with the captured text content of a grid control, TestComplete provides the following methods and properties:

  • OCR.Recognize.AsTable and OCR.Recognize.DetectTable - Recognize a grid control on the screen. The former property recognizes and returns the entire text content of the specified recognition area as a grid. The latter property returns a grid that resides in the specified area within the recognition area (can be helpful if your recognition area contains several grids).

  • RowCount and ColumnCount - Return the number of rows and columns of your tested grid control.

  • Cell - Allows getting the content of an individual cell and simulating user actions over the cell.

  • Column - Allows getting the content of an individual grid header and simulating user actions over the header.

The code below shows how you can use these objects to click a grid cell:

JavaScript

function Main()
{
  let url = "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_tbody";

  Browsers.Item(btChrome).Run(url);
  let page = Sys.Browser("chrome").Page("*tryit*");

  let frame = page.FindChildEx("idStr", "iframeResult", 10);
  // Use OCR to get the grid
  let ocrTable = OCR.Recognize(frame).AsTable(true);

  // Post the contents of the top-left cell to the test log
  Log.Message("Cell contains: " + ocrTable.Cell(0, 0).Text);

  // Click the top-left cell of the grid
  ocrTable.Cell(0, 0).Click();
  }
}

JScript

function Main()
{
  var url = "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_tbody";

  Browsers.Item(btChrome).Run(url);
  var page = Sys.Browser("chrome").Page("*tryit*");

  var frame = page.FindChildEx("idStr", "iframeResult", 10);
  // Use OCR to get the grid
  var ocrTable = OCR.Recognize(frame).AsTable(true);

  // Post the contents of the top-left cell to the test log
  Log.Message("Cell contains: " + ocrTable.Cell(0, 0).Text);

  // Click the top-left cell of the grid
  ocrTable.Cell(0, 0).Click();

}

Python

def Main():
  url = "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_tbody"
  
  Browsers.Item[btChrome].Run(url)
  page = Sys.Browser("chrome").Page("*tryit*")
  
  frame = page.FindChild("idStr", "iframeResult", 10)
  # Use OCR to get the grid control
  ocrTable = OCR.Recognize(frame).AsTable[True]
    
  # Post the contents of the top-left cell to the test log
  Log.Message("Cell contains: " + ocrTable.Cell[0, 0].Text)
      
  # Click the top-left cell of the grid
  ocrTable.Cell[0, 0].Click();

VBScript

Sub Main()
  url = "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_tbody"

  Browsers.Item(btChrome).Run(url)
  Set page = Sys.Browser("chrome").Page("*tryit*")

  Set frame = page.FindChildEx("idStr", "iframeResult", 10)
  ' Use OCR to get the grid
  Set ocrTable = OCR.Recognize(frame).AsTable(True)

  ' Post the contents of the top-left cell to the test log
  Log.Message("Cell contains: " & ocrTable.Cell(0, 0).Text)

  ' Click the top-left cell of the grid
  ocrTable.Cell(0, 0).Click

End Sub

DelphiScript

procedure Main();
var url, page, frame, ocrTable;
begin
  url := 'https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_tbody';

  Browsers.Item(btChrome).Run(url);
  page := Sys.Browser['chrome'].Page('*tryit*');

  frame := page.FindChildEx('idStr', 'iframeResult', 10);
  // Use OCR to get the grid
  ocrTable := OCR.Recognize(frame).AsTable(true);
  // Post the contents of the top-left cell to the test log
  Log.Message('Cell contains: ' + ocrTable.Cell[0, 0].Text);

  // Click the top-left cell of the grid
  ocrTable.Cell[0, 0].Click();
end;

C++Script, C#Script

function Main()
{
  var url = "https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_tbody";

  Browsers["Item"](btChrome)["Run"](url);
  var page = Sys["Browser"]("chrome")["Page"]("*tryit*");

  var frame = page["FindChildEx"]("idStr", "iframeResult", 10);
  // Use OCR to get the grid
  var ocrTable = OCR["Recognize"](frame)["AsTable"](true);

  // Post the contents of the top-left cell to the test log
  Log["Message"]("Cell contains: " + ocrTable["Cell"](0, 0)["Text"]);

  // Click the top-left cell of the grid
  ocrTable["Cell"](0, 0)["Click"]();
}

In addition, you can verify that your tested grid control contains the expected data. You can do it by using special table checkpoints operations. These table checkpoints capture the actual text content of your tested grid control and compare them with the baseline content stored in your TestComplete project. To learn more about the checkpoints, see About Table Checkpoints.

See Also

Working With Grids
Object-Specific Tasks
Simulating User Actions
Supported Controls
Optical Character Recognition

Highlight search results