Get Text Blocks by Custom Conditions

Applies to TestComplete 15.31, last modified on March 17, 2022

In your tests, you may need to access a portion of optically recognized text to simulate user actions on it.

Usually, you do this by using the OCR.Recognize.BlockByText(Text, SelectionPreference) method. The method returns a text block specified by its text and (optionally) by its location in the search area (for example, at the bottom or to the right). You can find a detailed description of using the method in Get Text Block by Position.

However, there can be situations where it is not enough to get the needed text block. For example, if the specified search area contains multiple text blocks with the same text, or the position of the needed text block changes from one test run to another. In this case, you can implement your own search algorithm:

  1. Use the OCR.Recognize method to recognize all the text in the specified area.

  2. Use the OCR.Recognize.Block and OCR.Recognize.BlockCount properties to iterate through all text blocks.

  3. Check each block against expected conditions until you find the block you need. For example, you can check whether a block’s text matches a string pattern. You can also check a block’s size and location.

    To get a block’s text, use the TextBlock.Text property. To get a block’s size and location, use the TextBlock.Bounds property.

  4. When you get the block you need, you can simulate user actions on it.

In scripts

The code below contains the GetTextBlockCustom routine that gets an onscreen object and a regular expression and returns a text block whose text matches the expression. If there is no text block whose text matches the expression, the routine returns null (null in JavaScript, JScript, C#Script and C++Script, None in Python, Nothing in VBScript, nil in DelphiScript).

The Main routine shows how to call the GetTextBlockCustom routine to get the needed text block and simulate user actions on it.

JavaScript, JScript

function GetTextBlockCustom(anObject, aPattern)
{
  // Recognize the text the specified onscreen object shows
  var obj = OCR.Recognize(anObject);
  if (obj.FullText != "" && obj.BlockCount > 0)
  {
    // Iterate through text blocks
    // until the one that matches the regular expression is found is found
    for (var i = 0; i < obj.BlockCount; i ++)
    {
      var re = new RegExp(aPattern, "ig");
      Matches = obj.Block(i).Text.match(re);
      if (Matches != null)
      {
        // Return the first block that matches the regular expression
        return obj.Block(i);
      }

    }
  // If no text block matches the specified regular expression,
  // return null
  return null;
  }
  else
    return null;

}

function Main()
{
  // The search condition (a regular expression)
  var searchPattern = "\w*[-]\w*";

  // Get an onscreen object
  var obj = Sys.WaitProcess("MyApp").WaitWindow("Window", "*", -1, 1000);

  // Get the text block that matches the search condition
  var b = GetTextBlockCustom(obj, searchPattern);
  if (b != null)
  {
    // Simulate user actions on the text block
    b.Click();
    …
  }
  …

}

Python

import re

def GetTextBlockCustom(anObject, aPattern):
  # Recognize the text the specified onscreen object shows
  obj = OCR.Recognize(anObject)
  if (obj.FullText != "" and obj.BlockCount > 0):
   # Iterate through text blocks
   # until the one that matches the regular expression is found
   for i in range (0, obj.BlockCount - 1):
     m = re.search(aPattern, obj.Block[i].Text)
     if m is not None:
       # Return the first block that matches the regular expression
       return obj.Block[i]
       
   # If no text block matches the specified regular expression,
   # Return None
   return None
  else:
    return None
    

def Main():
  # The search condition (a regular expression)
  searchPattern = "\w*-\w*"
  
  # Get an onscreen object
  obj = Sys.WaitProcess("MyApp").WaitWindow("Window", "*", -1, 1000)
  
  # Get the text block that matches the search condition
  b = GetTextBlockCustom(obj, searchPattern)
  if b != None:
    # Simulate user actions on the text block 
    b.Click()
    #...
  # ...

VBScript

Function GetTextBlockCustom(anObject, aPattern)

  ' If no text block matches the specified regular expression,
  ' return Nothing
  Set GetTextBlockCustom = Nothing

  ' Recognize the text the specified onscreen object shows
  Set obj = OCR.Recognize(anObject)
  If obj.FullText <> "" And obj.BlockCount > 0 Then
    ' Iterate through text blocks
    ' until the one that matches the regular expression is found
    For i = 0 To obj.BlockCount - 1
      Set regExpr = New RegExp
      regExpr.Pattern = aPattern
      regExpr.IgnoreCase = True
      regExpr.Global = True

      If regExpr.Test(obj.Block(i).Text) Then
        ' Return the first block that matches the regular expression
        Set GetTextBlockCustom = obj.Block(i)
        Exit For
      End If
    Next
  End If

End Function

Sub Main()
  ' The search condition (a regular expression)
  searchPattern = "\w*-\w*"

  ' Get an onscreen object
  Set obj = Sys.WaitProcess("MyApp").WaitWindow("Window", "*", -1, 1000)

  ' Get the text block that matches the search condition
  Set b = GetTextBlockCustom(obj, searchPattern)
  If Not b Is Nothing Then
    ' Simulate user actions on the text block
    b.Click
    …
  End If
  …

End Sub

DelphiScript

function GetTextBlockCustom(anObject, aPattern);
var obj, i, regExpr;
begin

  // If no text block matches the specified regular expression,
  // return nil
  result := nil;

  // Recognize the text the specified onscreen object shows
  obj := OCR.Recognize(anObject);
  if ((obj.FullText <> '') and (obj.BlockCount > 0)) then
  begin
    // Iterate through text blocks
    // until the one that matches the regular expression is found
    for i := 0 to obj.BlockCount - 1 do
    begin
      regExpr := HISUtils.RegExpr;
      regExpr.Expression := aPattern;
      regExpr.InputString : = obj.Block[i].Text;
      if regExpr.ExecPos then
      begin
        // Return the first block that matches the regular expression
        result := obj.Block[i];
        break;
      end;
    end;
  end;

end;

procedure Main();
var searchPattern, obj, b;
begin
  // The search condition (a regular expression)
  searchPattern := '\w*-\w*';

  // Get an onscreen object
  obj := Sys.WaitProcess('MyApp').WaitWindow('Window', '*', -1, 1000);

  // Get the text block that matches the search condition
  b := GetTextBlockCustom(obj, searchPattern);
  if b <> nil then
  begin
    // Simulate user actions on the text block
    b.Click();
    …
  end;
  …

end;

C++Script, C#Script

function GetTextBlockCustom(anObject, aPattern)
{
  // Recognize the text the specified onscreen object shows
  var obj = OCR["Recognize"](anObject);
  if (obj["FullText"] != "" && obj["BlockCount"] > 0)
  {
    // Iterate through text blocks
    // until the one that matches the regular expression is found
    for (var i = 0; i < obj["BlockCount"]; i ++)
    {
      var re = new RegExp(aPattern, "ig");
      Matches = obj["Block"](i)["Text"]["match"](re);
      if (Matches != null)
      {
        // Return the first block that matches the regular expression
        return obj["Block"](i);
      }

    }
  // If no text block matches the specified regular expression,
  // return null
  return null;
  }
  else
    return null;

}

function Main()
{
  // The search condition (a regular expression)
  var searchPattern = "\w*[-]\w*";

  // Get an onscreen object
  var obj = Sys["WaitProcess"]("MyApp")["WaitWindow"]("Window", "*", -1, 1000);

  // Get the text block that matches the search condition
  var b = GetTextBlockCustom(obj, searchPattern);
  if (b != null)
  {
    // Simulate user actions on the text block
    b["Click"]();
    …
  }
  …

}

In keyword tests

Option 1

To iterate through text blocks, you can use the For Loop or While Loop operation. To check the block properties, you can use the If Then operation:

Iterate through text blocks until you find a needed one

Option 2

  1. Copy the GetTextBlockCustom function code from the example above to a script unit in your project in TestComplete.

  2. Call the function from your keyword test by using the Run Code Snippet or Run Script Routine operation.

  3. Save the text block the function returns to a variable.

    To learn how to get the results of a routine called from a keyword test, see Checking Operation Result. To learn how to set a variable value in a keyword test, see Keyword Test Variables.

  4. Simulate the needed user actions on the returned text block in a way you find suitable. For example, by using the Run Code Snippet operation.

Get a needed text block and simulate user actions on it

Option 3

  1. Copy the Main routine from the example above to a script unit in your project in TestComplete.

  2. Modify the routine to work with your tested objects and to use the search conditions you need.

  3. Call the routine from your keyword test by using the Run Code Snippet or the Run Script Routine operation.

Call a script routine that gets a needed text block and simulate user actions on it

See Also

Optical Character Recognition
Regular Expressions Syntax
Checking Operation Result
Checking Conditions
Organizing Loops
Get Controls With No Text Contents

Highlight search results