DelphiScript - Working With Strings

Applies to TestComplete 14.30, last modified on November 21, 2019

This topic contains information about handling strings in DelphiScript and provides examples of operations that deal with strings. It contains the following sections:

Basics

A string is a sequence of symbols or digits. Strings are among the most frequently used data types. Like any other data type, strings in TestComplete are represented as OLE-compatible variants.

In DelphiScript, a sequence of literal characters enclosed in single quotation marks (') is recognized as a string. Double quotation marks (") are allowed within a string. To insert a single quotation mark into a string, it should be duplicated. The following is an example of string:

DelphiScript

str1 := 'The brig was heading to Liverpool, when the captain noticed a ship.';
str2 := '"Ahoy! Is there anyone?" - the captain cried.';
str3 := '''Nobody.'' - was the answer.';

To deal with strings, TestComplete has a special aqString scripting object. The object is available for all supported scripting languages, so that you can use it to operate with string values regardless of the chosen language.

Method, Property Description
aqString.AddListItem Adds a new item to a string list.
aqString.ChangeListItem Changes the value of the string list item with the given index.
aqString.Compare Compares two specified strings.
aqString.Concat Concatenates two specified strings.
aqString.DeleteListItem Removes an item with the given index from a string list.
aqString.Find Searches for a substring within the given string. Use this method instead of the obsolete aqString.Contains.
aqString.Format Generates a formatted string.
aqString.GetChar Retrieves a single character from the input string.
aqString.GetLength Returns the number of characters in a string.
aqString.GetListItem Returns an individual item from the list passed through the input string.
aqString.GetListLength Returns the number of items in the string list.
aqString.Insert Inserts one string to another at the specified position.
aqString.ListSeparator Specifies a character used to separate individual values in a list.
aqString.Quote Encloses the specified string in quotes.
aqString.QuoteSymbol Specifies a symbol used as a quotation mark.
aqString.Remove Removes a number of characters from the input string.
aqString.Replace Replaces all the occurrences of one substring with another substring.
aqString.SubString Retrieves a substring from the input string.
aqString.ToLower Converts the specified string to lower case.
aqString.ToUpper Converts the specified string to upper case.
aqString.Trim Removes spaces and control characters from the specified string.
aqString.Unquote Converts a quoted string to an unquoted string.

Another scripting object that is useful for string manipulation is aqConvert. This object has several methods that convert values of different types to a string representation and vice versa.

Method Description
aqConvert.CurrencyToFormatStr Converts a currency value to a string using the specified format settings.
aqConvert.CurrencyToStr Converts a currency value to a string.
aqConvert.DateTimeToFormatStr Converts the given date value to a string using the specified format.
aqConvert.DateTimeToStr Converts the given date value to a string.
aqConvert.FloatToStr Converts a floating-point value to a string.
aqConvert.IntToStr Converts the given number into a string.
aqConvert.StrToCurrency Converts the specified string to a currency value.
aqConvert.StrToDate Converts the specified string to a date value.
aqConvert.StrToDateTime Converts the specified string to a date/time value.
aqConvert.StrToFloat Converts the specified string to a floating-point value.
aqConvert.StrToInt Converts the specified string to an integer value.
aqConvert.StrToInt64 Converts the specified string to a long integer value.
aqConvert.StrToTime Converts the specified string to a time value.
aqConvert.VarToStr Converts the specified variant value to a string.

Furthermore, you can use native DelphiScript functions that operate with strings. The table below lists these functions:

Property, Method Description
Chr(Value) Returns a character with the specified ASCII code.
Copy(Str, Index, Count) Returns a substring of Str running from position Index (starting at 1), with the Count length. Never exceeds the actual contents of Str, and will return an empty string when Index is beyond the length of Str.
Delete(Str, Index, Count) Deletes a substring of Str running from position Index (starting at 1), with the Count length. Never exceeds the actual contents of Str, and will delete nothing when Index is beyond the length of Str.
Insert(S, Str, Index) Inserts S into the string Str at the Index (starting at 1) position.
Length(Str) Returns the number of characters in the specified string.
Pos(SubStr, Str) Returns the position of the first match (case significant) for SubStr inside Str. Positions beginning at 1. If SubStr is not found in Str, the function returns 0.
SetLength(Str, NewLength) Sets the length of Str to NewLength. This always creates a new string object, fills it from the old Str object and points Str to it. If NewLength is smaller than Length(Str), then the extra characters are lost. If NewLength is greater, then the new object has extra space to use before it will need reallocation from the string manager.

Special characters

In DelphiScript you can emulate any character by using the Chr function with the appropriate ASCII code. Another way to emulate a character is to prefix its ASCII code with # symbol. This also applies to special characters that are used to format string values. The table below lists the most frequently used special characters.

Description Character sequence
Carriage return. Chr(13) -- or -- #13
Line feed.
On Unix platforms it is interpreted as new line.
Chr(10) -- or -- #10
A combination of carriage return and line feed.
On Windows platforms it is interpreted as new line.
Chr(13)+Chr(10) -- or -- #13#10
Form feed. Chr(12) -- or -- #12
Horizontal tab. Chr(9) -- or -- #9
Vertical tab. Chr(11) -- or -- #11

Characters returned by Chr function should be joined to the string by concatenation:

DelphiScript

Str := 'A string.' + Chr(13) + Chr(10) + 'Another one string.';

The # symbol notation can be used both in concatenation with a string and within the string text (when enclosed in single quotation marks):

DelphiScript

Str1 := 'A string.' + #13#10 + 'Another one string.';
Str2 := 'A string.'#13#10'Another one string.';

Getting the string length

To obtain the total number of characters in a string you can either call the aqString.GetLength method, or call DelphiScript's Length function. The character position in DelphiScript is not zero-based, so the maximum position number in a string is equal to the string length. The following code demonstrates both ways of obtaining the string length:

DelphiScript

procedure StringLengthDemo;
var aString;
begin
  aString:='Some text';
  Log.Message('The string is ' + IntToStr(aqString.GetLength(aString)) + ' character(s) long.');
  Log.Message('The string is ' + IntToStr(Length(aString)) + ' character(s) long.');
end;

Using TestComplete, you can limit the length of string parameters returned by functions of the tested application. For this purpose, use the Maximum string length of [out] parameters project property. If the length of the string returned from the application via one of its out parameters exceeds the property’s value, TestComplete treats the returned string as a null one.

Concatenating strings

The operation that forms a string out of several others is called concatenation. The aqString object has the aqString.Concat method that performs this operation.

However, it is much more convenient to use the addition operator (+) for this purpose. If one of the addition operands is a string, then the performed operation is considered to be string concatenation rather than number addition.

This sample code shows how to make a string out of several substrings:

DelphiScript

procedure ConcatenationDemo;
var Str1;
begin
  Str1:='String No 1 ';
  Log.Message(aqString.Concat(Str1, 'String No 2'));
  Log.Message(Str1 + 'String No 2 ' + 'String No ' + IntToStr(3) + ' ');
end;

Comparing strings

The comparison of two strings is widely used during testing. Generally a test procedure obtains textual data (user input, file contents, property value and so on) and then compares it with the expected data. The TestComplete aqString object has a specific method aqString.Compare that compares one string value to another. The aqString.Compare method has three parameters: two of them - String 1 and String2 specify the strings to be compared, while the last parameter defines whether the comparison should be case-sensitive or not.

You can also use the equality operator of DelphiScript to perform case-sensitive comparison.

Both of the methods can compare strings holding specific national symbols, for example characters with diacritical marks ( , , and others).

The code below demonstrates the specifics of the above-mentioned methods.

DelphiScript

procedure StringComparison;
begin

  // Comparing the string in different letter cases
  Log.Message('aqString.Compare(''ABRA'', ''abra'', true): ' + aqConvert.VarToStr(aqString.Compare('ABRA', 'abra', true)));
  Log.Message('aqString.Compare(''ABRA'', ''abra'', false): ' + aqConvert.VarToStr(aqString.Compare('ABRA', 'abra', false)));

  // Applying the equality operator of DelphiScript
  Log.Message('''abra'' = ''abra'': ' + aqConvert.VarToStr('abra' = 'abra'));
  Log.Message('''abra'' = ''ABRA'': ' + aqConvert.VarToStr('abra' = 'ABRA'));


  // Dealing with native-language characters
  // The following code assumes that French layout is installed on computer
  // 040C - is the identifier of the French layout
  if (aqEnvironment.IsLanguageSupported($040C) and aqEnvironment.SetKeyboardLayout(Sys.Process('TestComplete').Id, $040C)) then

    begin
      // Comparing the string in different letter cases
      Log.Message('aqString.Compare(''Français'', ''français'', true): '+aqConvert.VarToStr(aqString.Compare('Français', 'français', true)));
      Log.Message('aqString.Compare(''Français'', ''français'', false): '+aqConvert.VarToStr(aqString.Compare('Français', 'français', false)));

      // Applying the equality operator of DelphiScript
      Log.Message('''Français'' = ''français'': ' + aqConvert.VarToStr('Français' = 'français'));
      Log.Message('''Français'' = ''Français'': ' + aqConvert.VarToStr('Français' = 'Français'));
    end;
end;

Accessing individual character of a string

The string data type can hold as series of characters as well as individual characters. In DelphiScript strings are implemented as one-dimensional arrays. This allows you to extract a single character out of the string. Besides, you can perform the same action using the aqString.GetChar method. Note however, that the index within DelphiScript arrays is one-based, whereas the index for the GetChar method is zero-based.

The sample routine below illustrates both approaches, it posts the given text to the TestComplete log in two different ways: as a whole string and by a single letter.

DelphiScript

procedure StringByLetter;
var aString, i;
begin
  aString := 'Per aspera ad astra';
  Log.Message('The string is : ' + aString);
  Log.Message('And now this text letter by letter using aqString.GetChar:');
    for i := 0 to aqString.GetLength(aString)-1 do Log.Message(aqString.GetChar(aString, i));
  Log.Message('And now this text letter by letter using indexed access:');
    for i := 1 to Length(aString) do Log.Message(aString[i]);
end;

Searching for characters and substrings

One of the most common tasks that one has to perform when working with string values is determining whether specific text is part of a string. To perform such tasks, the aqString object has the Find method. If the specified substring was found, the method returns the number of the first occurrence of the substring within the source string. If the specified substring was not found, the method returns -1:

DelphiScript

procedure StringOccurrenceDemo;
var aString, aSubString, Res;
begin
  aString := 'Per aspera ad astra';
  aSubString := 'astra';
  Res := aqString.Find(aString, aSubString);
  if Res <> -1 then
    Log.Message('A substring "' + aSubString + '" was found in string "' + aString+'"' + 'at position ' + aqConvert.IntToStr(Res))
  else
    Log.Message('There are no occurrences of "' + aSubString + '" in "' + aString + '".');
end;

You can also get the position where the specified substring occurs using the native DelphiScript function Pos. If the substring was found, the function returns the initial position (from 1) of the first substring match. If no occurrences were found, then it returns 0. The code below demonstrates how to use it:

DelphiScript

procedure TextPosDemo;
var aString, aSubString, findpos;
begin
  aString:='Per aspera ad astra';
  aSubString := 'astra';
  findpos := Pos(aSubString, aString);
  if findpos <> 0
  then
   Log.Message('A substring "' + aSubString + '" was found at position ' + IntToStr(findpos))
  else
   Log.Message('There are no occurrences of ''' + aSubString + ''' in ''' + aString + '''.');
end;

Getting a substring

DelphiScript has a special routine named Copy that allows you to extract a substring out of a string. The function returns a text fragment that starts at a given position and has a specified length. Negative and zero values for positions are interpreted as the first character in a string. If the specified length is greater than the string length, then the substring lasts until the end of the initial string. If length parameter is negative or zero then the empty string is returned.

The aqString object also has a similar method - SubString that returns a substring starting from the specified position and having the given length. However, this method cannot accept negative values, and the position numbers are zero-based.

The sample code below demonstrates how to use both of the routines:

DelphiScript

procedure GetStringDemo;
var Str;
begin
  Str := '123456789';

  Log.Message(Copy(Str, 2, 5)); // Posts "23456"
  Log.Message(Copy(Str, 2, 20)); // Posts "23456789"
  Log.Message(Copy(Str, -2, 3)); // Posts "123"
  Log.Message(Copy(Str, 2, 0)); // Posts ""

  Log.Message(aqString.SubString(Str, 1, 5)); // Posts "23456"
  Log.Message(aqString.SubString(Str, 1, 20)); // Posts "23456789"
  Log.Message(aqString.SubString(Str, 2, 0)); // Posts ""
end;

Splitting strings

Sometimes it is required to make several strings out of a single string. This operation splits a string into substrings. In DelphiScript this operation can be performed by the aqString.GetListItem. It extracts a substring with the specified index out of the input string. It was designed to read the items from a string lists (see Working with string lists for more information). However it allows to redefine the delimiter characters and be used to get sentences, separate words and so forth.

DelphiScript

procedure SplitDemo;
var s, ss, prevSep;
begin
    s := 'Better late than never but better never late.';
    // Assign list separator to space character
    prevSep := aqString.ListSeparator;
    aqString.ListSeparator := ' ';
    // Split by spaces
    Log.Message('There are ' + aqConvert.IntToStr(aqString.GetListLength(s)) + ' words in a string');
    Log.Message('The first word is: ' + aqString.GetListItem(s, 0));
    // Restore previous separator
    aqString.ListSeparator := prevSep;
end;

Removing extra spaces from a string

The aqString object has a special routine aqString.Trim that excludes the leading, trailing spaces, or both, from a string. Generally this method is applied to remove the "useless" spaces in the beginning or end of the strings obtained from the user input.

DelphiScript

procedure TrimDemo;
var str;
begin
  str := '    Hallo    ';
  Log.Message('"' + aqString.Trim(str, aqString.stLeading) + '"'); //Posts "Hallo    "
  Log.Message('"' + aqString.Trim(str, aqString.stTrailing) + '"'); //Posts "    Hallo"
  Log.Message('"' + aqString.Trim(str, aqString.stAll) + '"'); // Posts "Hallo"
end;

Another function that can be useful when handling user input strings is excluding extra inner spaces out of the string. This function seems to be similar to Trim, but the latter only removes spaces at the beginning or end of the string and does not affect the spaces within the string. The general idea of the function is for the string to be parsed into separate words and then a new string is constructed. The new string consists of the same words but is separated with a single space between words.

DelphiScript

function TrimInner(Str);
var aWord, prevSep, i;
begin
    Result := '';
    prevSep := aqString.ListSeparator;
    // Split at each space character.
    aqString.ListSeparator := ' ';
    for i := 0 to aqString.GetListLength(Str)-1 do
        begin
         aWord := aqString.GetListItem(Str,i);
         if aWord <> '' then Result := Result + aWord + ' ';
        end;
    // Restore previous separator
    aqString.ListSeparator := prevSep;
    Result := aqString.Trim(Result);
end;

// An example of how to use this function
procedure TrimInnerDemo;
begin
  Log.Message(TrimInner('Follow the    white rabbit'));
end;

Replacing characters and substrings

Quite often we need to find and replace a character or substring within a string. There are two ways to do this: by using the aqString.Replace method or using the RegExpr.Replace method provided by the HISUtils plugin.

The aqString object method is much easier to use and can be applied when you need to change a definite character or string. It allows you to set whether the search should be case-sensitive or not. Here is an example of how to use this method:

DelphiScript

procedure StringReplaceDemo;
var str;
begin
  str := 'Hi, Bob. Have you seen Bob Robbinson?';
  str := aqString.Replace(str, 'Bob', 'Jack', true);
  Log.Message(str);
end;

The RegExp object method is a little more complicated, but it offers more flexibility. You can change not only a definite character or string, but all fragments matching the specified regular expression pattern. However, you have to create an instance of RegExp object and set the pattern before replacing. The regular expression pattern is defined via the RegExpr.Expression property. Besides, there are certain flags that are set by the RegExpr.ModifierStr property, which affect the search procedure. The most frequently used modifiers are: i - search ignoring the letter case, m - perform multiline search and s - treats a string as a single line. Read the Regular Expressions Syntax topic to learn how to compose regular expressions. The first sample demonstrates how to change a definite string using the Replace method.

DelphiScript

procedure RegExpReplaceDemo1;
var str, re;
begin
  str := 'Hi, Bob. Have you seen Bob Robbinson?';
  // Create a RegExpr instance
  re := HISUtils.RegExpr;
  // Define regular expression pattern.
  re.Expression := 'Bob';
  // Perform replace operation
  str := re.Replace(str, 'Jack');
  Log.Message(str);
end;

The second example shows how to replace a substring with alternative parts. The patterns of alternative parts are separated by pipe characters (" | "). For instance, in the sample below the /ht(ml|m)/ pattern matches both html and htm:

DelphiScript

procedure RegExpReplaceDemo2;
var str, re;
begin
  str := 'The html is widely used in Internet. The HTM file is a text file with tags.';
  // Create a RegExpr instance
  re := HISUtils.RegExpr;
  // Define regular expression pattern.
  re.Expression := 'ht(ml|m)';
  // Set ignore letter case modifier
  re.ModifierStr := 'i';
  // Perform replace operation
  str := re.Replace(str, 'hypertext markup language');
  Log.Message(str);
end;

Furthermore, using regular expressions you can search for the text fragments that match the specified format. In the next sample, all dates written in the DD/MM/YYYY format are substituted with the Some Date string. This operation can be useful, for example, when comparing two reports that contain the generation date.

DelphiScript

procedure RegExpReplaceDemo3;
var str, re;
begin
  str := 'Date of report: 30/04/2005.';
  // Create a RegExpr instance
  re := HISUtils.RegExpr;
  // Define regular expression pattern.
  re.Expression := '\d{1,2}.\d{1,2}.\d{2,4}';
  // Perform replace operation
  str := re.Replace(str,'Some Date');
  Log.Message(str);
end;

Changing the letter case

Capital and lower case letters can be included in a string. The TestComplete aqString object has special methods that convert uppercased letters to lower case and vice versa. They are: aqString.ToLower and aqString.ToUpper.

The code below demonstrates how these methods are applied.

DelphiScript

procedure LetterCaseDemo;
var str;
begin
  str := 'The word "Champagne" is of French origin';
  // Converting to lower case
  Log.Message(aqString.ToLower(str));
  // Converting to upper case
  Log.Message(aqString.ToUpper(str));
end;

Working with string lists

Some scripting objects, generally, controls like ListBoxes, ComboBoxes, Memos, return data about their state or contents as string lists. The individual data elements (or items) in this list are separated by commas, line breaks, carriage returns or some other delimiter characters.

The aqString object has a number of specific methods (AddListItem, ChangeListItem, DeleteListItem, GetListItem and GetListLength) that are intended to deal with such lists of textual data. The AddListItem and DeleteListItem, respectively, append the item to the list, or remove the item from the list. The GetListItem method retrieves the item with the given index, and ChangeListItem assigns a new value to the given item. The GetListLength method returns the total number of items in the string list.

The symbol that is used as the separator of list items is defined by the ListSeparator property. By default the list separator is a pipe character "|", but it can be reassigned to comma, column, line break, carriage return, tabulation, and any other printable and non-printable character, or even to several characters.

Here is the sample code that shows how to operate with the string lists returned by scripting objects.

DelphiScript

procedure ListDialogOptions;
var OptStr, prevSep, i;
begin
    // Get a string with dialog options
    OptStr := UserForms.UserForm1.SaveDialog1.Options;
    // Assign list separator to comma
    prevSep := aqString.ListSeparator;
    aqString.ListSeparator := ',';
    // Get the number of dialog options
    Log.Message('The dialog has ' + aqConvert.IntToStr(aqString.GetListLength(OptStr)) + ' option(s) enabled:');
    // Iterate through the options list
    for i := 0 to aqString.GetListLength(OptStr)-1 do
      //Get the option and post it to log
      Log.Message('Option No ' + aqConvert.IntToStr(i+1) + ' is: ' + aqString.GetListItem(OptStr, i));
    // Restore previous separator
    aqString.ListSeparator := prevSep;
end;

procedure ManageMemoText;
var StrList, prevSep;
begin
    // Get a string with memo lines
    StrList := UserForms.UserForm1.cxMemo1.Lines.Text;
    // Post the memo contents to log
    Log.Message(UserForms.UserForm1.cxMemo1.Lines.Text);
    // Assign list separator to newline character
    prevSep := aqString.ListSeparator;
    aqString.ListSeparator := #13#10;
    // Append one more line
    StrList := aqString.AddListItem(StrList, 'Last Line');
    Log.Message(StrList);
    // Change the value of the first line
    StrList := aqString.ChangeListItem(StrList, 'New First Line', 0);
    // Set the memo contents to a new list
    UserForms.UserForm1.cxMemo1.Lines.Text := StrList;
    // Post the memo contents to log
    Log.Message(UserForms.UserForm1.cxMemo1.Lines.Text);
    // Restore previous separator
    aqString.ListSeparator := prevSep;
end;

See Also

DelphiScript Reference
aqString Object
aqConvert Object

Highlight search results