Corel WordPerfect Office - X5 User Guide for PerfectScript

?
s
;
W
0
g
6
t
=
9
}
3
*
&
m
7
A
#
%
!
@
92
2
5
+
User Guide for PerfectScript™
Contents
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
Understanding macro concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3
Understanding macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Understanding macro statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Understanding macro syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Understanding macro structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Using expressions in macro statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Understanding variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Understanding constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Understanding operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Understanding expression types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Using command statements in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Understanding command names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Understanding parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Understanding return values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Using assignment statements in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Using conditional statements in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Using loop statements in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Using calling statements in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Understanding labels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Understanding functions and procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Understanding callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Creating calling statements from subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Using comment statements in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Accessing external applications in macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Understanding OLE Automation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Understanding Dynamic Data Exchange (DDE) . . . . . . . . . . . . . . . . . . . . . . . . 80
Learning more about macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Using the WordPerfect Office Software Development Kit (SDK) . . . . . . . . . . . 81
Using the Corel Web site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Contents i
Getting started with macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .83
Using the PerfectScript utility. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Specifying PerfectScript settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Creating macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .89
Migrating legacy macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Recording macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Writing and editing macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Compiling macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Playing macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Making macros user-friendly. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Creating dialog boxes for macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .101
Understanding dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Setting up dialog boxes for macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
Setting up controls for dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Setting up callbacks for dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Testing dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Displaying dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
Debugging macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .135
Getting started with the PerfectScript Debugger . . . . . . . . . . . . . . . . . . . . . . . . . 135
Using the Debugger to debug macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Getting more information while debugging macros . . . . . . . . . . . . . . . . . . . . . . . 143
Working with breakpoints while debugging macros . . . . . . . . . . . . . . . . . . . . . . . 150
Working with variables while debugging macros . . . . . . . . . . . . . . . . . . . . . . . . . 156
Navigating the code while debugging macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Troubleshooting the Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .167
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .175
ii Contents

Introduction

Welcome to the Corel® WordPerfect® Office User Guide for PerfectScript™!
PerfectScript™ is a command-based macro-programming language that you can use to automate tasks in Corel® WordPerfect®, Corel® Quattro Pro®, and Corel® Presentations™. This documentation contains basic information about creating simple PerfectScript macros, as well as detailed, technical information about creating more complex PerfectScript macros.
This documentation contains the following sections:
• “Understanding macro concepts” on page 3 explains the concepts that are
associated with macros, and shows how these concepts apply to PerfectScript macros
• “Getting started with macros” on page 83 introduces you to the PerfectScript
utility, which you can use to create macros quickly and easily
• “Creating macros” on page 89 examines how to create macros, either by migrating
ones that already exist or by recording or writing new ones
• “Creating dialog boxes for macros” on page 101 describes how to use a dialog box
to create an interface between the application and the user
• “Debugging macros” on page 135 demonstrates how to find and correct any errors
in your macros
This documentation also contains a glossary.
Introduction 1
Please see the PerfectScript Help file (psh.chm) for the following additional sections:
• “PerfectScript Command Reference” documents the syntax elements and macro commands for PerfectScript
• “WordPerfect Command Reference” documents the system variables and macro commands for WordPerfect
• “Quattro Pro Command Reference” documents the syntax elements and macro commands for Quattro Pro, for both PerfectScript and the native Quattro Pro macro-programming language
• “Presentations Command Reference” documents the macro commands for Presentations
• “Gallery of sample macros” provides sample macros for PerfectScript and WordPerfect
2Introduction

Understanding macro concepts

When performing repetitive or complex tasks in WordPerfect Office, you can save time by using PerfectScript macros. In this section, you’ll learn the concepts that are associated with macros, and you’ll learn how these concepts apply to PerfectScript macros.
This section contains the following topics:
• Understanding macros
• Using expressions in macro statements
• Using command statements in macros
• Using assignment statements in macros
• Using conditional statements in macros
• Using loop statements in macros
• Using calling statements in macros
• Using comment statements in macros
• Accessing external applications in macros
• Learning more about macros

Understanding macros

A macro specifies a sequence of actions that you can quickly repeat later. For example, a macro can automate a WordPerfect task such as setting the margins, selecting a font, or creating a merge file.
To create macros for WordPerfect Office, you can use the PerfectScript macro­programming language. PerfectScript is called a “command-based language” because it uses macro commands to store the results of an action rather than storing the individual steps that are used to carry out that action.
You can also create macros for Quattro Pro by using the native macro­programming language for the application. For information, please see “Understanding the native Quattro Pro macro language” in the Quattro Pro Command Reference section of the PerfectScript Help file (psh.chm).
Understanding macro concepts 3
You can also use Microsoft® Visual Basic® for Applications (VBA) to create macros for WordPerfect Office. For detailed information about VBA and VBA macros, please see the Corel WordPerfect Office User Guide for VBA (vba_ug.pdf).
A macro consists of a set of instructions or statements. By using the various types of macro statements, you can create PerfectScript macros that automate anything from a basic task to a complex procedure. For more information about macro statements, see “Understanding macro statements” on page 4.
Through the use of macro statements, PerfectScript lets you create macros that access applications outside of WordPerfect Office. For more information, see “Accessing external applications in macros” on page 77.
For even more information about macros, you can consult additional resources for WordPerfect Office. For information, see “Learning more about macros” on page 81.
The proper form of macro components is governed by a set of rules, or syntax. For more information about macro syntax, see “Understanding macro syntax” on page 5.
If you structure your macros well, they will function well — and be much easier to edit. For more information about macro structure, see “Understanding macro structure” on page 5.

Understanding macro statements

If a macro represents a set of instructions, then a macro statement represents a single step in those instructions. The simplest macro consists of only one statement, while the most complex macro consists of multiple statements that are performed in sequence.
A group of related statements is called a “statement block.”
Some statements require an expression, which is a formula that represents a value. For more information about expressions, see “Using expressions in macro statements” on page 8.
By combining expressions with other macro components, you can create any of the following types of statements:
command statements — consist of a macro command, which represents a single instruction (typically, an action). For more information, see “Using command statements in macros” on page 47.
4 Understanding macro concepts
assignment statements — assign a value to an expression. For more information, see “Using assignment statements in macros” on page 54.
conditional statements — execute a statement (or a group of statements) when a specified condition is met. For more information, see “Using conditional statements in macros” on page 54.
loop statements — execute a statement (or a group of statements) a specified number of times until (or while) an expression is true. For more information, see “Using loop statements in macros” on page 57.
calling statements — call a statement (or a group of statements). For more information, see “Using calling statements in macros” on page 59.
comment statements — contain notes that explain the purpose of a macro without affecting its play. For more information, see “Using comment statements in macros” on page 77.

Understanding macro syntax

The proper form of macro components is governed by a set of rules, or syntax. For a macro to work properly, its code must use the correct syntax — that is, the code must be “syntactically correct.”
For each macro component that is described in this documentation, details on proper macro syntax are included.
Some macro statements are too lengthy to fit into a single line of macro code. If your macro editor automatically inserts a hard return at the end of every line, you must insert an underscore character (
_ ) at the end of each line that wraps.
For information on specifying a macro editor, see “To specify settings for editing macros” on page 86.

Understanding macro structure

If you structure your macros well, they will function well — and be much easier to edit.
You can structure a macro in several ways. The basic function of a macro is to accomplish a task by following a series of steps, so the ideal structure for a macro depends on the task involved — and on the amount of code that is required to carry out that task. For example, if a macro involves multiple tasks that require large amounts of
Understanding macro concepts 5
code, you can make the macro more manageable by breaking it into smaller pieces (called subroutines — see “Understanding subroutines” on page 59).
From a structural standpoint, the two main types of macros are as follows:
sequential macros — progress in steps from start to finish. For more information, see “Understanding sequential macros” on page 6.
procedural macros — progress in steps based on user intervention. For more information, see “Understanding procedural macros” on page 7.
Understanding sequential macros
A sequential macro progresses in steps from start to finish. All steps are taken in the required order, and the code is written to suit that purpose.
An example of a sequential macro follows:
HardReturn () HardReturn () GetString( var1; "Enter Name"; "Data Entry"; 100 ) Type (Text: var1) HardReturn () GetString( var2; "Enter Address"; "Data Entry"; 100 ) Type( var2 ) HardReturn () HardReturn () Type (Text: "Dear " + var1 + ":") HardReturn () HardReturn () Type (Text: "Yaddah Yaddah Yaddah") HardReturn () HardReturn () HardReturn () Type (Text: "Sincerely,") HardReturn () HardReturn () HardReturn () HardReturn ()
6 Understanding macro concepts
Type (Text: "Paul McRussell") HardReturn () Type (Text: "Manager, Eat-a-Chicken Burger, Anywhere, USA")
Understanding procedural macros
A procedural macro progresses in steps based on user intervention, through the use of functions and procedures (see “Understanding functions and procedures” on page 61). Using functions and procedures in a macro lets the programmer compartmentalize code so it can be called from anywhere in the macro. Compartmentalization breaks logical pieces of code into smaller segments, and these segments can be separated by use of the
Label, Function, and Procedure commands (see “Understanding subroutines” on
page 59). Smaller pieces of code are easier to work with, and they are also easier to debug.
An example of a procedural macro follows:
HardReturn () HardReturn () //Call the function to get the name sName = GetName() Type (Text: sName) HardReturn () //Call the function to get the address sAddress = GetAddress() Type (sAddress ) HardReturn () HardReturn () Type (Text: "Dear " + sName + ":") HardReturn () HardReturn () Type (Text: "Yaddah Yaddah Yaddah") HardReturn () HardReturn () HardReturn () Type (Text: "Sincerely,") HardReturn ()
Understanding macro concepts 7
HardReturn () HardReturn () HardReturn () Type (Text: "Paul Russell") HardReturn () Type (Text: "Manager, Eat-a-Burger, Anywhere, USA") Function GetName() GetString( sName; "Type in the name of the addressee"; _ "Enter Name"; 100 ) RETURN( sName ) EndFunction Function GetAddress() GetString( sAddress; "Type in the address of the addressee"; _ "Enter Address"; 100 ) RETURN( sAddress ) EndFunction

Using expressions in macro statements

Macros consist of statements. Some macro statements involve an action that must be captured as an expression. An expression is a formula that represents a value.
To create expressions, you use the following macro components:
variables — store a single value at a time, but this value can change during macro play. For more information, see “Understanding variables” on page 10.
constants — store a single value at a time, and this value cannot change during macro play. For more information, see “Understanding constants” on page 25.
operators — are symbols (such as
+, -, *, and %) that combine variables and
constants to determine a value. For more information, see “Understanding operators” on page 25.
Understanding expressions
Expressions are created by combining variables or constants (or both) with operators — or by combining other expressions with operators.
The following examples contain expressions that involve variables and operators.
8 Understanding macro concepts
Example Result
x := "John Doe"
vLeftMargin := 5i
ResultOfOperation := 3 + 4
z := z + 1
x := y > 1
If (y>1) Beep EndIf
The variable x equals the character string
John Doe.
The variable vLeftMargin equals the measurement
5i.
The variable ResultOfOperation equals
7 (that is, the result of the numeric
expression
3 + 4).
The variable z equals the value of z + 1. However, a variable can contain only one value at a time, so the original value of
z is
lost unless previously assigned to another variable.
The variable x equals the result of the relational expression
True if y contains a value greater than 1, or
it equals
False if y contains a value less
than or equal to
y > 1 (that is, x equals
1).
The result of y>1 is evaluated without assigning the result to a variable. The computer beeps if the value of
1 (that is, if the result of the expression
than
y>1 equals True). The beep is skipped if the
value of
y is less than or equal to 1 (that is, if
the result of the expression equals
y is greater
False).
The following example contains expressions that involve variables, constants, and operators. The value as constants. The operators
vCount - 1, vCount = 0, and vCount = 4. Function BeepBeep(vCount) Repeat Beep Wait(3) vCount := vCount - 1
Understanding macro concepts 9
vCount is used as a variable, while the values 0, 4, and -1 are used
- and = are used to create expressions from these values:
Until(vCount = 0) Return EndFunc ForEach(vCount; {1; 2; 3; 4; 5}) If(vCount = 4) Break EndIf BeepBeep(vCount) Wait(5) EndFor
MessageBox(x; "BREAK"; "Variable vCount equals 4"; IconInformation!)
Quit
For more information about the types of expressions that you can create, see “Understanding expression types” on page 40.

Understanding variables

A variable stores a single value at a time, but this value can change during macro play.
Variables must be “declared” before they can be used. Declaring a variable instructs PerfectScript to set aside memory for the variable.
Assigning a value to — or “initializing” — a variable involves pointing that variable to the memory cell where its desired value is stored. If desired, variables can be initialized with a value at the time of declaration. Although the value of a variable can belong to any data type, the most common data types for variables are numbers and character strings.
For more information about declaring and initializing variables, see “Declaring and initializing variables” on page 12.
Unlike other programming languages, PerfectScript does not force the programmer to specify the type of data to be stored in a variable.
10 Understanding macro concepts
When a variable is declared, it is assigned to one of four types:
local variables — pertain only to the current macro. By default, variables are automatically declared local if no variable type is specified. For more information, see “Working with local variables” on page 13.
global variables — pertain to the current macro and to macros that are called by the
Run and Chain commands. For more information, see “Working with global
variables” on page 15.
persistent variables — pertain to any PerfectScript macro, for as long as PerfectScript is running. For more information, see “Working with persistent variables” on page 16.
constant variables — represent a value that cannot change during macro play. For more information, see “Working with constant variables” on page 18.
Two additional kinds of variables require special attention:
•A system variable is a type of macro command that contains current system information such as the current chart type or the default directory. For example, the PerfectScript system variable contains the error value of a
Cancel, Error, or Not Found condition
ErrorNumber
(as illustrated in line 44 of the annotated macro sample ASSERT.WCM in the PerfectScript Help file [psh.chm]). Similarly, the WordPerfect system variable folder for WordPerfect macros to a variable named
?PathMacros assigns the path and name of the default
vMacroPath, which
is updated to reflect any changes to the directory. For more information about system variables, see “Understanding macro commands” on page 47.
•An implicit variable is a variable that is defined by PerfectScript. For example the
MacroDialogResult variable contains the control value
of the button that releases a dialog box (see “Releasing dialog boxes by using PerfectScript code” on page 132).
The type of a variable determines its visibility (or scope) and its duration in memory, so it’s important to understand when to use each variable type. If you try to access a variable from a line of code in which that variable is not visible, an “out-of-scope” error is generated.
Understanding macro concepts 11
In addition to variable type, the following factors determine the scope of a variable:
• where the variable is declared — for example, in the main body, in a function, in a procedure, in another macro, or in a separate program altogether
• which line of code is currently executing
You can check whether a variable exists. For more information, see “Determining whether variables exist” on page 18.
When a variable is no longer required, you can discard it. For more information, see “Discarding variables” on page 19.
If you want to assign a collection of data to a single variable name, you can use an array. The rules for using arrays are the same as for using variables. For more information, see “Working with arrays” on page 20.
Declaring and initializing variables
When you declare a macro, you specify a name for it.
For best results, it is highly recommended that you give your variables a descriptive name. Variable names have the following standards:
• They must begin with a letter.
• They can include any other combination of letters or numbers.
• They must be 50 characters or fewer in length.
• They are not case-sensitive.
Optionally, you can initialize a variable at its time of declaration by using an assignment operator (
:= or =) to specify a value.
By following a few simple conventions for naming variables, you can make your macro code easier to understand. For instance, variables that have a string value should have a name that begins with a lowercase
sFirstName := "Dave" sAddress := "1625 East Nowhere St." sBirthday := "6/12/69"
s, as in the following examples:
Similarly, variables that have a numeric value should have a name that begins with a lowercase
nAge := 25 nTotal := 145.97
12 Understanding macro concepts
n, as in the following examples:
In the preceding examples, all declared variables are local, by default, because no variable type is specified.
Working with local variables
Local variables pertain only to the current macro. Local variables are the default variable type and, as such, should be used in most situations. You can use the PerfectScript programming commands
Declare or Local to create local variables.
Variables that are declared in user-defined functions and user-defined procedures are local to those subroutines. For more information about subroutines, functions, and procedures, see “Understanding subroutines” on page 59.
Local variables can be declared in the following way:
Declare ( sQReport )
or
Local ( sQReport )
Local variables can be declared and intitialized in the following way:
sQReport := "Q4" Declare ( sQReport := "Q4" )
or
sQReport := "Q4" Local ( sQReport := "Q4" )
If you want, you can use the Declare command or the Local command to declare and initialize more than one local variable at a time. Variables are separated by a semicolon (
;), as in the following example:
Declare (sFilename := "c:\test.wpd"; sTemp; nCount; cMainCount:=10)
When a local variable is declared, it is assigned to the local-variable table. Variables in the local-variable table are visible only until the end of the level of code in which they are declared. The level of code usually refers to the main body or a subroutine (that is, a function or procedure). Consider the following sample code:
FileNew /* Declare sName as a local variable and initialize to the string
value "Dave" */ vName := "Dave"
Understanding macro concepts 13
/* Call the procedure */ TypeName ( ) Quit Procedure TypeName ( ) /* This variable is out of scope. It has not been declared in the
procedure TypeName */ Type ( vName ) HardReturn EndProcedure
The preceding code assigns the string "Dave" to the variable. It then calls the procedure which tries to type the contents of the variable. Because the variable is out of scope within this procedure, the following error occurs when playing the macro:
Undefined variable ‘VNAME’ has been referenced. Check line 9 of macro file ‘test.wcm.’
Consider the following sample code:
... /* Variables declared in the main body are visible in the main body */ vNameMain := "Dave" NewScope ( ) /* When processing this Procedure vNameMain is not visible */ NewScope2 ( ) /* When processing this Function vNameMain is not visible */ ... Quit // Subroutines . . . Procedure NewScope ( ) /* Local variables declared in a procedure are visible only i n that
procedure */ NameNewScope := "Fred" ... EndProcedure Function NewScope2 ( )
14 Understanding macro concepts
/* Local variables declared in a function are visible only in that function */
vNameNewScope2 := "John" ... EndFunction
In the preceding code, all three variables (VNameMain, NameNewScope, and
VNameNewScope2) are named differently. However, these variables could have been
named the same and still have been completely unique variables — each one holding different data — because they are each declared at a different level of the macro and therefore each have their own scope.
Working with global variables
Global variables pertain to the current macro and to macros that are called by the Run
Chain commands. Although a necessity in some cases, global variables should be
and used with care. You can use the PerfectScript programming command
Global to create
global variables.
Global variables can be declared in the following way:
Global ( nCount )
Global variables can be declared and initialized in the following way:
Global ( sFilename := "c:\Expense.wpd" )
If you create two variables with the same name (for example, Declare x and
Global x), the following statement specifies that the global variable x is assigned the
5:
value
Global x:=5
If you want, you can use the Global command to declare and initialize more than global variable at a time by separating variables with a semicolon (
;).
When a variable is declared global, it is assigned to the global-variable table. Variables assigned to the global-variable table are in scope anytime after they are declared, and they exist until the end of the macro in which they are declared. If a global variable is declared on the very first line of a macro, it is accessible in the main body, in subroutines, and in other macros that are started with the commands
Run or Chain. The following
is an example of a global variable in use:
... /* The global variable is not yet declared and not yet accessible */
Understanding macro concepts 15
Global ( sGlobalName := "Fred" ) /* Any reference after this to the variable sGlobalName accesses the
global variable */ ... /* Call the function */ DoSomething ( ) Type ( sGlobalName ) ... /* sGlobalName ceases to exist when the macro ends */ Quit Procedure DoSomething ( ) /* Change the value of the global variable to "Dave" */ sGlobalName := "Dave" ... EndProcedure
In the preceding example, the procedure is called after the global variable
sGlobalName is declared and initialized. Inside this procedure, the contents of the
variable are changed from
Procedure DoSomething allow you to start another macro from within the current
"Fred" to "Dave". The commands DoSomething and
macro and, therefore, to access and change any variables that are declared global in the current macro.
Working with persistent variables
Persistent variables pertain to any PerfectScript macro, for as long as PerfectScript is running. Although a necessity in some cases, persistent variables should be used with care. You can use the PerfectScript programming command persistent variables — in much the same way as you can use the
Persist to create
Global command to
create global variables.
Persistent variables can be declared in the following way:
Persist ( VariableName )
Persistent variables can be declared and initialized in the following way:
Persist ( VariableName := Value ) PersistAll ( On! ) ...
16 Understanding macro concepts
/* All variables declared in the default manner are now persistent instead of local*/
VariableName := Value ... PersistAll ( Off! )
The preceding example uses the PersistAll command to change the default variable­declaration method from local to persistent and back again. All variables between
PersistAll ( On! ) and PersistAll ( Off! ) are declared as Persistent
variables. This technique is useful when you want an entire block of variables to be persistent.
If you want, you can use the than persistent variable at a time by separating variables with a semicolon (
Persist command to declare and initialize more
;).
When a variable is declared persistent, it is assigned to the persistent-variable table. Variables in the persistent table remain in scope and exist until PerfectScript shuts down.
PerfectScript does not shut down until all the applications that use PerfectScript (WordPerfect, Quattro Pro, and Presentations) have shut down.
Persistent variables are visible during merges and, as such, provide an effective method for passing values between macros and merges. If you need to use data during a merge, use persistent variables. For best results, give persistent variables a descriptive name, and denote their data type.
The following example of a persistent variable requires the use of two macros and includes a test that determines whether the variable has been initialized.
The first macro in this example is as follows:
Persist ( sAppName := "WordPerfect Suite 8" ) MessageBox( retVal; sAppName; "Left margin equals: " + ?Marg inLeft ) Run ( "Macro2.wcm" )
The second macro in this example is as follows:
MessageBox(retVal; sAppName; "Right margin equals: " + ?MarginRight)
The following example illustrates scope by using local and persistent variables:
Persist ( x := "This is persistent variable x" ) CreateOutline()
Understanding macro concepts 17
// Original variable value remains unchanged. MessageBox ( retVal ; "Information"; "The variable x = " + x ) Quit Procedure CreateOutline ( ) /* PerfectScript will look first at the local variable table. If a
variable exists in that table, that variable will be used before the persistent variable. By creating a local variable inside the function, we will force PerfectScript to find the local variable. This local variable x will be destroyed when execution returns from this subroutine. */
Local ( x := 0 ) ForNext ( x; 1; 10 ) // for loop creates a basic outline vCharacter := NTOC(96) + x Tab() Type ( "(" + vCharacter + ")" ) Indent() HardReturn() EndFor EndProcedure
Working with constant variables
Constant variables — also called “constants” — represent a value that cannot change during macro play. As such, constants must be initialized upon declaration, and their assigned value cannot change. Constants should be used sparingly, if at all.
Expressions are formed by using operators (see “Understanding operators” on page 25) to combine constants with other types of variables. For more information about constants, see “Understanding constants” on page 25.
Determining whether variables exist
You can use the Exists command to determine whether a variable exists — that is, whether it has been declared and initialized. The following sample code shows how to use the
// Declare and initialize a variable’s Name := "Fred" // Use Exists to see if the variable still exists as a local variable If ( Exists ( sName; Local! ) )
18 Understanding macro concepts
Exists command:
... EndIf ... Quit
The Exists command returns a value after checking the specified variable against the variable tables. The variable tables are checked in the following order: local, then global, then persistent.
If you specify a variable-table parameter for the
Exists command, a value of True is
returned if that variable is found in the specified variable table. If the variable is not found in the specified variable table, a value of
False is returned. The following
example illustrates this scenario:
If( Exists ( x ; Global!) = TRUE ) x := 147 Else Global ( x := 147 ) EndIf
If you do not specify a variable-table parameter for the Exists command, one of the following values is returned:
NotFound! or 0 — indicates that the variable does not exist in any variable table
Local! or 1 — indicates that the variable exists in the local-variable table
Global! or 2 — indicates that the variable exists in the global-variable table
Persistent! or 3 — indicates that the variable exists in the persistent-variable
table
The following example illustrates this scenario:
Persist( x := 3 ) If ( Exists( x ) = Exists.Persistent!) MessageBox ( retVar; "Variable"; "This variable Exists in the _ Persist variable pool (" + Exists ( x ) + ")" ) EndIf
Discarding variables
You can use the Discard command to remove a variable from memory by deleting it from its associated variable table. The following sample code shows how to use the
Discard command:
Understanding macro concepts 19
// Declare and initialize a variable sName := "Fred" ... // Free the memory used by vName Discard ( sName ) // sName no longer exists and cannot be accessed ... Quit
The Discard command searches the variable tables in the following order: local, then global, then persistent. If variables with the same name exis t in d ifferent variable tables, you may need to use the
Discard command multiple times, as in the following sample
code:
While(Exists(VariableName)) Discard(VariableName) EndWhile
Working with arrays
If you want, you can assign a collection of data to a single variable name by creating an “array.” The elements in a PerfectScript array can be declared and initialized in the same ways as variables. Unlike other programming languages, however, PerfectScript lets you assign the elements in an array to different data types. PerfectScript arrays therefore provide a powerful way to control large amounts of data on one or more dimensions.
To use an array, you must first declare it and initialize its elements. When a macro is played, a run-time error is incurred for each array element that is not both declared and initialized.
The commands for declaring arrays are the same as for declaring variables:
Local, Global and Persist. At declaration, an array requires the following items:
Declare,
• an alphanumeric (case-insensitive) name that begins with a letter and is limited to 50 characters
• a subscript, marked in brackets (
[]), that specifies how many array elements to
create
The following commands declare a one-dimensional array that contains five elements:
Declare(aMyArray[5]) — declares a one-dimensional, five-element local array
Local(aMyArray[5]) — declares a one-dimensional, five-element local array
20 Understanding macro concepts
Global(aGlobalArray[5]) — declares a one-dimensional, five-element global
array
Persist(aPersistArray[5]) — declares a one-dimensional, five-element
• persistent array
Every array contains a hidden element called
0. This element stores the total
number of elements in the array (not including itself), and an attempt to assign any other value to this element generates an error message. In the previous examples, the declared array actually includes six elements if you include element
0.
The preceding examples declare an array but do not initialize its elements. Before you can use an array, you must individually initialize each array element. To initialize an array element, you must specify the array name; the subscript (or index) number of the array element, enclosed in brackets (
[]); and the desired value for the array element.
The following example illustrates how to initialize each element in an array after declaring the array.
// Declare a 5-element array Declare ( aMyArray[5] ) // Initialize each of the five elements aMyArray[1] := "One" aMyArray[2] := "Two" aMyArray[3] := "Three" aMyArray[4] := "Four" aMyArray[5] := "Five"
You can simplify the process of initializing array elements after declaring an array by using the following syntax:
Declare ( aMyArray[5]; nCount := 0 ) ForEach (x; {"One"; "Two"; "Three"; "Four"; "Five"}) nCount := nCount +1 aMyArray[ nCount ] := x EndFor
Understanding macro concepts 21
If you want, you can initialize an array upon its declaration (in which case, the number of elements need not be specified). The following commands declare and initialize a one­dimensional array that contains five elements:
Declare(aMyArray[]:={"One";"Two";"Three";"Four";"Five"})
declares and initiatlizes a one-dimensional, five-element local array
Local(aMyArray[]:={"One";"Two";"Three";"Four";"Five"}) — declares
• and initiatlizes a one-dimensional, five-element local array
aMyArray[]:={"One";"Two";"Three";"Four";"Five"} — declares and
• initiatlizes a one-dimensional, five-element local array
Global(aGlobalArray[]:={"One";"Two";"Three";"Four";"Five"})
declares and initiatlizes a one-dimensional, five-element global array
Persist(aPersistArray[]:={"One";"Two";"Three";"Four";"Five"})
• declares and initiatlizes a one-dimensional, five-element persistent array
PerfectScript arrays can have up to ten dimensions. A two-dimensional array is like a table with rows and columns: Each cell in the table is an individual element.
For declaring a multi-dimensional array, the syntax of the subscript operator ( as follows: The number of dimensions is followed by a semicolon (
;), which is followed
[]) is
by the number elements within each dimension. The following example shows how to declare a three-dimensional array in which each dimension has five elements:
Declare ( aMyArray[3;5] )
Each dimension can have up to 32,767 elements (depending on available memory), and each element can be individually accessed and initialized. For accessing and initializing an element in a multi-dimensional array, the syntax of the subscript operator ( as follows: The dimension number of the element is followed by a semicolon (
[]) is
;), which
is followed by the subscript (or index) number of the element within that dimension.
The following syntax specifies the first element in the first dimension:
aMyArray[1;1] := "1-1"
The following syntax specifies the third element in the second dimension:
aMyArray[2;3] := "2-3"
The following stynax specifies the fifth element in the third dimension:
aMyArray[3;5] := "3-5"
Multi-dimensional arrays, like one-dimensional arrays, can be initialized at their time of declaration. In this scenario, the number of elements in each dimension does not need to be explicitly stated because it is implied by the actual initialization of those elements.
22 Understanding macro concepts
In addition, the dimensions are separated by a semicolon (;). The following example illustrates this syntax:
aMyArray[] := {{"1-1"; "1-2"; "1-3"; "1-4"; "1-5"}; // First row {"2-1"; "2-2"; "2-3"; "2-4"; "2-5"}; // Second row {"3-1"; "3-2"; "3-3"; "3-4"; "3-5"} } // Third row
PerfectScript provides a special form of initialization for multi-dimensional arrays. This form, called a slice (
...), lets you initialize the elements on a single dimension by
repeating the last-initialized element throughout that dimension. When initializing with a slice, you must fully initialize at least one row in each dimension to define the extent of the slice. The following example illustrates the syntax for using a slice:
// Declares a three-dimensional array (3x3x6) initializing all elements with a slice
aMyArray[] := { { {1;1;1;1;1;1}; // First dimension, first row {1; ... }; // First dimension, second row, replicated with value 1 {1; ... } }; // First dimension, third row {{2;2;2;2;2;2}; // Second dimension, first row {2; ... }; // Second dimension, second row {2; ... } }; // Second dimension, third row {{3;3;3;3;3;3}; // Third dimension, first row {3; 4, ... }; // Third dimension, second row, replicated with value 4 {3; 1; ... } } } // Third dimension, third r ow, r eplicate d wit h _
value 1
You can use the Dimensions command to return the following information about an array:
• total number of dimensions in the array
• total number of elements in the array
• number of elements in each dimension
• index range
In some cases, you must declare an array dynamically and therefore cannot be sure how many dimensions are contained in the array. The
Dimensions command allows a macro
to act dynamically by querying the size of an array:
Understanding macro concepts 23
aFiles[] := GetFileList() // returns an array of random size ForNext (x; 1; Dimensions( aFiles[]; 0 ) ) // Dimensions queries the array for the size FileOpen ( aFiles[x] ) FooterA(Create!) Type ( "McRae's Eat-a-Burger ") SubStructureExit() FileSave ( aFiles[x]; WordPerfect_60! ) Close() EndFor Function GetFileList() ... // statement block that creates an array (sized) dynamically Return ( ArrayOfFiles[] ) EndFunction
Please note that MacroArgs[] is a special PerfectScript array that contains values that are passed to the macro by the commands illustrates the
// Macro: MAIN.WCM // Include full path if macro not // in default macros directory Run("TSTMACRO"; {"x"; "y"; "z"})
MacroArgs[] array.
Chain, Nest, or Run. The following example
// Macro: TSTMACRO.WCM // Compile, then play MAIN.WCM vElements = Dimensions (MacroArgs[]; 0) If (vElements != 0) ForNext (x; 1; vElements; 1) MessageBox (z; "Element Values"; "MacroArgs[" + x + "] = " + _ MacroArgs[x]) EndFor Else Beep
24 Understanding macro concepts
MessageBox (z; "Error"; "No values passed"; IconExclamation!) EndIf // Result: x y z

Understanding constants

A constant — also called a constant variable — represents a value that cannot change during macro play.
By contrast, most variables represent a value that can change during macro play. For more information, see “Understanding variables” on page 10.
Constants must be initialized upon declaration, and their assigned value cannot change. You can declare and initiatlize a constant in the following way:
Constant ( WPCLASSNAME := "WordPerfect.8.32" )
A compile-time error occurs if a constant is misused in one of the following ways:
• if the constant is not initialized upon declaration — for example, if the declaration statement is missing an assignment operator (
• if an attempt is made to assign a different value to a constant after it has been declared and initialized
You can set constants apart from other variables by giving them a name that appears entirely in capital letters. This naming convention is the generally accepted practice in C/C++ and other programming languages.
:=) or an assigned value (or both)

Understanding operators

Operators are used to combine variables (see “Understanding variables” on page 10) and constants (see “Understanding constants” on page 25) into expressions — and even to combine expressions into other expressions. In PerfectScript, operators can be either “unary” or “binary.”
Unary operators are symbols or words that represent an operation on only one operand or expression. The following table lists the unary operators that are available in PerfectScript.
Understanding macro concepts 25
Operator Action Example and result
+
-
NOT
~
Multiplies an operand by +1
Multiplies an operand by -1
Inverts the result of relational and logical expressions
Toggles a binary value (that is, converts
1 to 0, and 0 to 1)
+5
Result: +5 (that is, 5 * +1)
-10
Result: -10 (that is, 10 * -1)
See “Understanding logical operators” on page 31.
See “Understanding bitwise operators” on page 35.
Binary operators are symbols or words that represent an operation on two operands or expressions. In the following example, the binary plus operator (
4, and the assignment operator (:=) assigns the result of the arithmetic expression
and
3 + 4 to variable x. x := 3 + 4
+) adds the operands 3
All PerfectScript operators can be classified into the following functional categories:
assignment operators — symbols that assign the value of a right-operand expression to a left-operand variable. For more information, see “Understanding assignment operators” on page 27.
arithmetic operators — symbols or words that represent a mathematical operation on two operands. For more information, see “Understanding arithmetic operators” on page 27.
relational operators — symbols that represent a relational operation on two operands, such that the operation result equals either true or false. For more information, see “Understanding relational operators” on page 28.
logical operators — words that represent a logical relationship between conditions, or that invert a condition. For more information, see “Understanding logical operators” on page 31.
bitwise operators — symbols that represent a bitwise operation on two integer operands. For more information, see “Understanding bitwise operators” on page 35.
When used together to form an expression, operators are evaulated by PerfectScript based on precedence level. For more information about operator precedence, see “Understanding operator precedence” on page 38.
26 Understanding macro concepts
For detailed information on each operator, please see the “Operators” topic in the PerfectScript Command Reference section of the PerfectScript Help file (psh.chm).
Understanding assignment operators
Assignment operators are symbols that assign the value of a right-operand expression to a left-operand variable.
The following table lists the assignment operators that are available in PerfectScript.
Operator Action Example and result
:= or = Assignment of a value to a
variable
Understanding arithmetic operators
x := "John Doe"
Result: The variable x equals the character string
John Doe.
Arithmetic operators are symbols or words that represent a mathematical operation on two operands.
All arithmetic operators are binary operators.
The following table lists the arithmetic operators that are available in PerfectScript.
Operator Action Example and result
*
/
-
+
Multiplication
Division
Subtraction of numbers and reduction of strings
Addition of numbers and concatenation of strings
vStr := "abcdefg" - "efg"
Result: vStr equals "abcd" (by reduction of strings)
vStr := "abcd" + "efg"
Result: vStr equals
"abcdefg" (by concatenation
of strings)
Understanding macro concepts 27
Operator Action Example and result
%
MOD
DIV
**
Floating point modulus division — returns remainder of floating­point division
Integer modulus division — returns remainder of integer division
Integer division — returns integer portion of integer division
Exponentiation — raises a number to a power
x:=10.1 % 3
Result: x equals 1.1
x := 9 % 3
Result: x equals 0
x := 10 MOD 3
Result: x equals 1
x := 10.1 MOD 3
Result: error (because MOD cannot be used on real numbers)
x := 10 DIV 3
Result: x equals 3
x := 9 DIV 3
Result: x equals 3
x := 9.1 DIV 3.5
Result: error (because DIV cannot be used on real numbers)
vResult = 2**3
Result: vResult = 8 (that is,
2 to the power of 3) vResult = 4**2
Result: vResult = 16 ( that
4 to the power of 2)
is,
Understanding relational operators
Relational operators are symbols that represent a relational operation on two operands. The operation result equals
True or False.
All relational operators are binary operators.
The following table lists the relational operators that are available in PerfectScript.
28 Understanding macro concepts
Operator Action Example and result
>
>=
<
Greater than
Greater than or equal to
Less than
x := 10 z := (x>5)
Result: z equals True (because
x is greater than 5)
x := 10 If (x>=10) Beep Else Quit EndIf
Result: The computer beeps because the result of expression
>= 10
equals True (that is, x
10). The Else statement
equals is skipped, so the
Quit
x
command does not end the macro.
x := 10 z := (x<5)
Result: z equals False (becuase
x is not less than 5)
Understanding macro concepts 29
Operator Action Example and result
<=
=
Less than or equal to
Equal to Note: Whereas
LIKE is True
regardless of whether the compared strings are identical in
= is case-sensitive.
case,
x := 20 If (x<=10) Beep Else Quit EndIf
Result: The computer does not beep because the result of expression
False (that is, x is greater than
10). The Else statement is
played, so the
x <= 10 equals
Quit command
ends the macro.
x := 10 z := (x=5)
Result: z equals False (because
x is not equal to 5) x := 10 z := (x = 10)
Result: z equals True (becuase
x is equal to 10) x := "Abc" z := (x = "Abc")
Result: z equals True ( because
x is equal to "Abc") x := "Abc" z := (x = "abc")
Result: z equals False (because
x must be the same as "Abc",
including case)
<>
Not equal to
30 Understanding macro concepts
Operator Action Example and result
!=
IN
LIKE
Not equal to
Membership
Case-insensitive string equality Note: Whereas
= is True only if
the compared strings are identical in case,
LIKE disregards
case altogether.
x := 10 z := (x!=5)
Result: z equals True (because
x is not equal to 5) x := 12 z := (x !=12)
Result: z equals False (because
x is equal to 12)
z := 3 IN {1; 2; 3}
Result: z equals True
z := 3 IN (1; 2; 4}
Result: z equals False
z := {1; 2; 3} IN {1; 2; 3}
Result: z equals True
z := {1; 2} IN {1; 2; 3}
Result: z equals True
z := {1; 2; 3} IN {1; 2; 4}
Result: z equals False
z := ("abc" LIKE "Abc")
Result: z equals True
Understanding logical operators
Logical operators are words that either invert one condition or represent a logical relationship between conditions. A condition is the result of a relational expression (see “Understanding relational expressions” on page 45).
Most logical operators are binary operators. The exception is
NOT.
The following table lists the logical operators that are available in PerfectScript.
Understanding macro concepts 31
Operator Action Example and result
NOT
AND
Inverts the result of a relational expression
Combines two relational expressions. Each expression must be expression to be
True for the logical
True.
See also the detailed NOT examples that follow this table.
x := 8 If ((x<10) AND NOT (x=5)) Beep EndIf
Result: The result of the logical expression equals
x is less than 10, AND NOT x is
equal to
x := 1 y := 2 z := ((x = 1) AND (y = 2))
5, or x is not equal to 5).
True ( because
Result: z equals True. The
AND expression is True
logical because both the relational expressions
True.
are
x = 1 and y = 2
32 Understanding macro concepts
Operator Action Example and result
XOR
OR
Combines two relational expressions. Only one expression
True for the logical
can be expression to be are true or both are logical expression is
True. If both
False, the
False. The
XOR function is also called “exclusive OR.”
Combines two relational expressions. Only one expression needs to be expression to be
True for the logical
True. The OR
function is also called “inclusive OR.”
See also the detailed XOR example that follows this table.
x := 1 y := 2 z := ((x = 0) XOR (y = 2))
Result: z equals True (because only one relational expression is
True) z := ((x = 1) XOR (y = 2))
Result: z equals False (because both relational expressions are
True) z := ((x = 0) XOR (y = 1))
Result: z equals False (because both relational expressions are
False)
x := 1 y := 2 z := ((x = 1) OR (y = 5))
Result: z equals True. The
OR expression is True
logical because the relational expression
x = 1 is True.
Here are some more detailed examples of NOT.
NOT Example Result
x := 5 y := (x<10) z := NOT(x<10)
Understanding macro concepts 33
If x is less than 10, True is assigned to y
False (that is, the inverted result of the
and expression
x<10) to z.
NOT Example Result
x := 5 z := (x<10) If (NOT(z)) Beep Else Quit EndIf
x := 5 If (NOT(x<10)) Beep Else Quit EndIf
x := 5 If (x>10) Beep Else Quit EndIf
The result of the expression x<10 is assigned to variable
z. The Beep command causes
the computer to beep if the inverted value of
z equals True. However, the inverted value
z equals False, so there is no beep; the
of
Else statement is played, and the Quit
command ends the macro. NOTE: For more information about
If
conditions, see “Understanding If conditions” on page 55.
In this shorthand notation, the computer is instructed to beep if the inverted result of the expression the result of there is no beep; the played, and the
x<10 equals True. However,
NOT(x<10) equals False, so
Else statement is
Quit command ends the
macro.
This example represents an alternative to using the expression beeps. However, the result equals (because the value of the
NOT operator. If the result of the
x>10 equals True, the computer
False
x is less than 10), so
Else statement is played and the Quit
command ends the macro.
Here is a more detailed example of XOR.
XOR Example Result
x := 1 y := 2 If ((x = 0) XOR (y = 2)) Beep EndIf
34 Understanding macro concepts
In this shorthand notation, the result of the
XOR expression equals True because
logical the relational expression and the relational expression
x = 0 is False
y = 2 is True.
Understanding bitwise operators
Bitwise operators are symbols that represent a bitwise operation on two-integer operands.
Most bitwise operators are binary operators. The exception is bitwise NOT (
The following table lists the bitwise operators that are available in PerfectScript.
Operator Action Example and result
~
Toggles a binary value (that is, converts
1 to 0, and 0 to 1). Also
called “bitwise unary NOT” — “unary” because it has a single complement.
&
Results in 1 if both operand bits
1, 0 if one of the operand bits
are
1, or 0 if both operands are
is not
0. Also called “bitwise AND.”
~-15
Note: The binary equivalent of
-15 is 1111111111110001.
Result:
0000000000001110)
x:=1000&31
14 (binary
Note: The binary equivalent of
1000 is 1111101000 and of 31
0000011111.
is Result:
0000001000) x:=65535&535
x equals 8 (binary
Note: The binary equivalent of
65535 is 1111111111111111
535 is
and of
0000001000010111.
Result:
0000001000010111)
x equals 535 (binary
~).
Understanding macro concepts 35
Operator Action Example and result
|
Results in 1 if either operand is 1. Also called “bitwise inclusive OR.”
x:=1000|27
Note: The binary equivalent of
1000 is 1111101000 and of 27
0000011011.
is Result:
1111111011) x:=65535|535
x equals 1019 (binary
Note: The binary equivalent of
65535 is 1111111111111111
535 is
and of
0000001000010111.
Result:
1111111111111111)
^
Results in 0 if operands match, 1 otherwise. Also called “bitwise exclusive OR (XOR)”.
x:=1000^40
Note: The binary equivalent of
1000 is 1111101000 and of 40
is Result:
1111000000) x:=65535^535
x equals 65535 (binary
0000101000. x equals 960 (binary
Note: The binary equivalent of
65535 is 1111111111111111
535 is
and of
0000001000010111.
Result:
1111110111101000)
x equals 65000 (binary
36 Understanding macro concepts
Operator Action Example and result
<<
>>
<<<
Shifts bits left by the specified number of places. For example, specifying
1 place shifts all bits
one place to the left (and inserts a
0 at the right end of the binary
number, effectively multiplying the value by 2.
Shifts bits right by the specified number of places. For example, specifying
1 place shifts all bits
one place to the right (and inserts
0 at the left end of the binary
a number, effectively dividing the value by 2.
Rotates bits left by the specified number of places. For example, specifying
1 rotates all bits one
place to the left.
x:=500<<1
Note: The binary equivalent of
500 is 0111110100.
Result:
1111101000) x:=65535<<1
x equals 1000 (binary
Note: The binary equivalent of
65535 is 1111111111111111.
Result:
1111111111111110)
x:=1000>>1
x equals 131070 (binary
Note: The binary equivalent of
1000 is 1111101000.
Result:
0111110100) x:=65535>>1
x equals 500 (binary
Note: The binary equivalent of
65535 is 111111111111111.
Result:
0111111111111111)
x:=-2147450881<<<1
x equals 32767 (binary
Note: The binary equivalent of
-2147450881 is 10000000000000000111111
111111111.
Result:
00000000000000001111111 111111111
x equals 65535 (binary
)
Understanding macro concepts 37
Operator Action Example and result
>>>
Rotates bits right by the specified number of places. For example, specifying
1 rotates all bits one
place to the right.
x:=65535>>>1
Note: The binary equivalent of
65535 is 00000000000000001111111 111111111
Result:
.
x equals -2147450881
(binary
10000000000000000111111
111111111)
Understanding operator precedence
The following table explains operator precedence, which is used by PerfectScript to evaluate expressions.
Precedence level Operators
1 •parentheses [
•unary minus (
•unary plus (
•bitwise not (
•logical not (
2 •exponentiation (
3 •multiplication (
•division (
•modulus division (
•integer division (
()]
-)
+)
~)
NOT)
**)
*)
/)
% or MOD)
DIV)
4 •addition (
•subtraction (
5•left shift (
•right shift (
•left rotation (
•right rotation (
+)
-)
<)
>)
<)
>)
38 Understanding macro concepts
Precedence level Operators
6•equality (=)
•inequality (
•“less than” state (
•“less than” state or equality (
•“greater than” state (
•“greater than” state or equality (
•membership (
•case-insensitive string equality (
!=)
<)
<=)
>)
>=)
IN)
LIKE)
7•bitwise and (
•bitwise or (
•bitwise XOR (
8•logical and (
9•logical or (
•logical xor (
10 •assignment (
&)
|)
^)
AND)
OR)
XOR)
:= or =)
The following rules apply to operator precedence:
• Operators with the same precedence are evaluated from left to right.
• Operators inside parentheses are evaluated before operators outside parentheses.
• Operators inside nested parentheses are evaluated from the innermost parentheses out.
Here are some examples that illustrate operator precedence.
Example Result
x := ((50 * 5 + 50) * 3 + 100)
x
equals 1000:
•50 * 5 = 250
•250 + 50 = 300
•300 * 3 = 900
•900 + 100 = 1000
x := ((50 * (5 + 50)) * 3 + 100)
x
equals 8350:
•5 + 50 = 55
•55 * 50 = 2750
•2750 * 3 = 8250
•8250 + 100 = 8350
Understanding macro concepts 39
Example Result
x := ((50 * 5 + 50) * (3 + 100))
x
equals 30900:
•50 * 5 = 250
•250 + 50 = 300
•3 + 100 = 103
•300 * 103 = 30900

Understanding expression types

By combining variables (see “Understanding variables” on page 10) and constants (see “Understanding constants” on page 25) with operators (see “Understanding operators” on page 25), you can form expressions for use in macro statements.
PerfectScript macros support the following expression types:
numeric expressions — numeric variables or numeric constants, or a combination of the two as joined by a numeric operator. For more information, see “Understanding numeric expressions” on page 41.
measurement expressions — variables or constants that contain a measurement value, or a combination of the two as joined by a numeric operator. For more information, see “Understanding measurement expressions” on page 41.
radix expressions — values that combine a number with a character that identifies the “radix” for that number (that is, the base of its number system). For more information, see “Understanding radix expressions” on page 42.
character expressions — variables or character constants (such as letters, digits, or keyboard symbols), or a combination of the two as joined by the plus operator ( the minus operator (
-), or a relational operator. For more information, see
“Understanding character expressions” on page 43.
arithmetic expressions — statements that represent arithmetic operations, or statements that contain two operands that are joined by an arithmetic operator. For more information, see “Understanding arithmetic expressions” on page 45.
relational expressions — statements that represent a relational operation, or statements that contain two operands that are joined by a relational operator. For more information, see “Understanding relational expressions” on page 45.
logical expressions — statements that represent logical operations, or statements that contain two relational expressions that are joined by a logical operator. For more information, see “Understanding logical expressions” on page 46.
+),
40 Understanding macro concepts
bitwise expressions — statements that represent bitwise operations, or statements that contain two operands that are joined by a bitwise operator. For more information, see “Understanding bitwise expressions” on page 46.
Command calls and function calls can be used in an expression if they return a value. For more information, see “Using calling statements in macros” on page 59.
Understanding numeric expressions
Numeric expressions are numeric variables or numeric constants — or a combination of the two as joined by a numeric operator.
Given that
Example Explanation
x
5
x * 5
+5
-(x + 10)
Understanding measurement expressions
x equals 3, the following examples are valid numeric expressions.
Variable that contains a numeric value
Numeric constant
Expression that multiplies x by 5 Note: This expression is also an arithmetic expression.
Unary plus constant
Unary minus expression, which negates the result of
x plus 10
Measurement expressions are variables or constants that contain a measurement value — or a combination of the two as joined by a numeric operator. A measurement value is created by combining a number (which represents the desired number of units) with a character (which identifies the desired unit of measurement).
The available units of measurement, and their associated identifiers, are as follows.
Unit of measurement Identifier
Inches
Centimeters
Millimeters
Understanding macro concepts 41
" or i
c
m
Unit of measurement Identifier
Points (72 per inch)
WP units (1200 per inch)
p
w
You can add and subtract measurement expressions as you do numeric expressions (see “Understanding numeric expressions” on page 41). When an operation is performed on measurement expressions that have different units of measure, the right operand is converted to the type of the left-measurement operand.
Combining numeric expressions with measurement expressions can produce unexpected results.
You do not need to specify a unit of measure for command-measurement expressions that follow
DefaultUnits.
If you do not specify a unit of measure for a measurement expression, and
DefaultUnits has not been encountered, the default unit of measurement
WP units (1200 per inch) is used.
Given that
z equals 4i (that is, 4 inches), the following examples are valid measurement
expressions.
Example Explanation
5c
Constant (5 centimeters)
z
z * 10i
-z
Understanding radix expressions
Variable that contains a measurement value of 4 inches
Expression that multiplies z by 10i (that is, 10 inches)
Unary minus, which yields -4i (that is, negative 4 inches)
The radix is the base of a number system. Radix expressions contain a radix value, which is created by combining a number (which represents the number value) with a character (which identifies the radix).
A radix value must begin with a number. For this reason, you must place a zero before any hexadecimal numbers that begin with the letters
42 Understanding macro concepts
A through F.
The available radix choices, and their associated identifiers, are as follows.
Radix Identifier
16 (hexadecimal system)
8 (octal system)
2 (binary system)
x or h
o
b
The following examples are valid radix expressions.
Example Result
x := 1Ah
x := 0Ah
x
equals the hexidecimal value of 26
x
equals the hexidecimal value of 10
Note: A numeric value of
Ah is not valid
because it does not begin with a number.
0Ah.
x := 1111b
x := 44o
Understanding character expressions
Instead, you must use
x
equals the binary value of 15
x
equals the octal value of 36
Character expressions are character variables or character constants (such as letters, digits, or keyboard symbols) — or a combination of the two as concatenated by the plus operator ( (such as
+), separated by the minus operator (-), or compared by a relational operator
>).
A character constant that is enclosed in single quotation marks specifies an ASCII numeric value, as in the following examples.
Example Result
x := ‘A’
x := ‘A’ + ‘B’
x
equals 65
equals 131 (that is, 65 + 66)
x
A character string must be enclosed in double quotation marks. If the string already contains double quotation marks, it must use a second set of double quotation marks, as in the following examples.
Understanding macro concepts 43
Example Result
x := "His name is "John"" Doe"
x := """John Doe"""
x
equals His name is "John" Doe
x equals "John Doe"
The following examples are valid character expressions.
Example Explanation
"John Doe"
z := "Joe " + "Doe"
x := z + ", Jr."
Character string
Expression that is assigned to variable z (such that
z equals Joe Doe)
Expression that is assigned to variable x (such that
x equals Joe Doe, Jr.)
If you concatenate a character string and a number, the number is converted to a character string. If you concatenate a numeric character and a number, the numeric character is converted to a number and the two are added. For examples, see the table that follows.
Example Result
x := "A" + 1
x := "1" + 1
x
equals A1 (which is a character string)
x
equals 2 (which is a number)
x := ("A" + (1 + 3))
x
equals A4 (which is the result of a
mathematical operation [1+3=4] being converted to a character string before being concatenated to A)
x := ("A" + 1 + 3)
x equals A13 (which is a character string
because the numbers converted and not added, due to operator precedence)
x := (1 + 3 + "A")
x
equals 4A (which is a character string
because the numbers are added and then converted to a character string, due to operator precedence)
44 Understanding macro concepts
Understanding arithmetic expressions
Arithmetic expressions are statements that represent arithmetic operations, or statements that contain two operands that are joined by an arithmetic operator. The result of an arithmetic operation is a numeric value.
Example Result
x := 1 + 2
x := 3 * 3
x := "2" * 3 * 4
x
equals 3
x equals 9
x equals 24 (because 2 is converted to a
number then multiplied)
x := "A" * 2
Error (becuase letters and numbers cannot be multiplied by each other)
Understanding relational expressions
Relational expressions are statements that represent a relational operation, or statements that contain two operands that are joined by a relational operator. The result of a relational operation is either
Given that
Example Result
z := (x = 6)
z := (x = 5)
z := ("Ab" > "Bb")
z := ("Ab" != "Bb")
x equals 5, the following examples yield the described results.
True or False.
z
equals False (because 5 is less than 6)
z
equals True (because 5 equals 5)
z
equals False (becuase Ab is less than, or
comes before,
z
equals True (because Ab is not equal to
Bb)
Bb)
Given that return
x equals "A", y equals "B", and z equals "a", the following expressions
True or False in variable w.
Example Result
w := (x < y)
w equals False (becuase uppercase A is less
than, or comes before, uppercase B)
Understanding macro concepts 45
Example Result
w := (x > z)
w
equals True (uppercase A is greater than,
or comes after, lowercase a).
Understanding logical expressions
Logical expressions are statements that represent logical operations, or statements that contain two relational expressions that are joined by a logical operator. The result of a logical operation equals
Given that
True or False in variable w.
Example Result
w := ((x <= y) AND (y <= z))
w := ((x = y) AND (y <= z))
w := NOT(y > z)
w := ((x != 5) AND (y != 20) _ AND (z = 20))
w := (((x = 5) AND (y = 20)) _ OR (z = 20))
x equals 10, y equals 5, and z equals 20, the following expressions return
True or False.
w
equals True (because both relational
expressions are true)
w
equals False (because the first relational
expression is false)
w
equals True (because 5 is not greater than
20)
w
equals True (becuase all relational
expressions are true)
w
equals True (because the expression z =
20
is true)
w := (((x = 5) AND (y = 20)) _ OR _NOT (z = 20))
Understanding bitwise expressions
w
equals False (because all relational
expressions are false)
Bitwise expressions are statements that represent bitwise operations, or statements that contain two operands that are joined by a bitwise operator. The result of a bitwise operation is a numeric value.
Consider the following examples of bitwise expressions.
46 Understanding macro concepts
Bitwise operator Example and result
Bitwise NOT (
Bitwise AND (
~)
&)
Bitwise inclusive OR (|)
Bitwise XOR (^)
Bitwise shift left (<<)
Bitwise shift right (>>)
Bitwise rotate left (<<<)
Bitwise rotate right (>>>)
x := ~(-15)
Result: x equals 14 (complement of 1)
x := ~(-15) + 1
Result: x equals 15 (complement of 2)
x := 65535 & 535
Result: x equals 535
x := 65535 | 535
Result: x equals 65535
x := 65535 ^ 535
Result: x equals 65000
x := 65535 << 1
Result: x equals 131070
x := 65535 >> 1
Result: x equals 32767
x := -2147450881 <<< 1
Result: x equals 65535
x := 65535 >>> 1
Result: x equals -2147450881

Using command statements in macros

A command statement consists of a macro command, which represents a single instruction (typically, an action) in a macro.
Understanding macro commands
PerfectScript provides access to two main types of macro commands: product commands and programming commands.
OLE object commands represent a third type of PerfectScript macro commands. Also called “a method,” an OLE object command performs a task on an OLE
Understanding macro concepts 47
object in a specific OLE Automation server. For more information, see “Understanding OLE Automation” on page 77.
Product commands perform functions that let you use WordPerfect Office features in your macros. Product commands can be specific to one WordPerfect Office application or common to all of them. Many product commands require you to specify parameters that determine settings for dialog boxes or other application features (such as the ruler).
Product commands that report information (that is, return a value) about the state of an application or feature are sometimes called system variables. In WordPerfect, system variables begin with a leading question mark (as in
?ColumnWidth). In Presentations, system variables begin with a leading Env
EnvPaths).
(as in
Programming commands perform functions that let you direct the function of a macro by controlling how application features act and interact. For example, you can use programming commands to specify macro conditions (see “Using conditional statements in macros” on page 54), specify that part of a macro run several times (see “Using loop statements in macros” on page 57), invoke or jump to a specified subroutine (see “Using calling statements in macros” on page 59), and so on.
You can use a product command by itself to create a basic macro that performs a simple task within a WordPerfect Office application. For example, the following product command displays the fourth slide in the current slideshow in Presentations:
ShowSlide(Slide: 4)
However, you must use product commands and programming commands together if you want to create a more complex macro. For example, the following code uses the product commands commands
If, Else, and Endif to determine which dialog box to display in
WordPerfect. (The Line Height dialog box is displayed if the Line Spacing dialog box is displayed if
If (x = "A") LineHeightDlg Else LineSpacingDlg Endif
48 Understanding macro concepts
LineHeightDlg and LineSpacingDlg with the programming
x equals the value "A", while
x has any other value.)
Understanding macro-command components
All macro commands have a name, and most macro commands have one or more parameters (which are marked by separators). For a PerfectScript macro to work properly,
its macro commands must be spelled correctly and must include all required parameters (and the necessary separators) in the correct order.
When you create a macro by recording it (see “Recording macros” on page 92), the correct syntax is automtically applied to all macro commands. However, when you create a macro by typing code (see “Writing and editing macros” on page 93), you must manually apply the correct syntax to all macro commands.
In addition, some macro commands can be used to return data from various sources. Such commands are said to have return values.
As previously mentioned, product commands that return a value about the state of an application or feature are sometimes called system variables.
For more information about the components of a macro command, see the following topics:
• Understanding command names
• Understanding parameters
• Understanding return values

Understanding command names

The name of a macro command (that is, the “command name”) indicates which feature is activated by that command.
Sometimes, a name is all that is necessary to perform the complete action of a macro command. For example, name itself contains enough information to complete the task of displaying the Open File dialog box in WordPerfect.
Understanding command-name syntax
Command names are not case-sensitive. Although many commands appear in mixed case, you can type them entirely in uppercase or lowercase if desired.
Most command names do not contain spaces. Exceptions include programming commands that call a subroutine, such as
Understanding macro concepts 49
FileOpenDlg is a complete macro command because the
Case Call or OnCancel Call.
For information about calling statements, see “Using calling statements in macros” on page 59.

Understanding parameters

While a command name (see “Understanding command names” on page 49) specifies a feature, some tasks require more information than this feature name alone can provide. To capture the settings for a feature, some macro commands provide one or more parameters, which are passed to the macro compiler (or between statement blocks) to carry out the desired task. For example, the WordPerfect product command
Backup() is associated with the Automatic Document Backup feature, which can be
toggled by specifying a parameter, as in
The type of information that is required by a parameter is represented by a data type. Each parameter accepts a specific data type. The most common data type for programming commands is Va r i a b l e (see “Understanding variables” on page 10), while the most common data types for a product command are String (which specifies sequence of characters), Numeric (which specifies a numeric value), and Enumeration (which specifies one fixed value from a list of possible values).
In the macro-command syntax, data types are displayed in italicized text.
Backup(State:On!).
Parameters of data type choose. These enumerations are identified by a trailing exclamation point ( example, the WordPerfect command
Rotation, which provides the following enumerations: Degrees90!, Degrees 180!, Degrees 270!, and None!.
In the following example of a WordPerfect macro command,
Where is a parameter of data type Enumeration, and it is assigned the enumeration
name.
AdvanceDown!. Amount is a parameter of type Numeric, and it is assigned a numeric
value of
1.0". The resulting macro command instructs WordPerfect to advance the
Enumeration provide a set list of enumerations from which to
!). For
BoxCaptionRotation provides the parameter
Advance is the command
insertion point down by one inch.
Advance (Where: AdvanceDown!; Amount: 1.0")
Understanding parameter syntax
The parameters for a macro command must be enclosed in a set of parentheses [ ()]. Inserting a space between the command name and the left parenthesis is optional. However, using both a left parenthesis and a right parenthesis is mandatory; omitting either parenthesis is a common error than can prevent a macro from compiling.
50 Understanding macro concepts
Some programming commands and system variables have no parameters. Their syntax is the command name alone. Examples include the PerfectScript command
Pause and the WordPerfect command ?FeatureBar.
Some product commands have no parameters. Their syntax is usually written with empty parentheses. An example is the WordPerfect command
PosScreenUp ().
Using parentheses is mandatory for user-defined functions and procedures. For more information about functions and procedures, see “Understanding subroutines” on page 59.
A parameter is separated from its value by a colon (
:). Inserting a space between colon
and value is optional.
Each parameter ends with a semicolon (
;). When a macro command requires several
parameters, they must be placed in the order shown (and separated by their trailing semicolons). Inserting a space after a semicolon is optional.
For macro commands that have a single parameter, using the trailing semicolon is optional.
If you omit an optional parameter, you must include its semicolon in the syntax to keep the parameters that follow in their correct positions. Consider the following WordPerfect command:
AbbreviationExpand (AbbreviationName:; Template: PersonalLibrary!)
This command can be shortened as follows:
AbbreviationExpand (; PersonalLibrary!)
If a macro command accepts repeating parameters, the series must be enclosed in a set of braces (
Let’s consider an example of parameter syntax in action. The WordPerfect has two parameters: enclosed in a set of parentheses and separated by a semicolon. parameter, so its instances must be separated by a semicolon, and this series of
{}).
MakeItFit command for
TargetPage and Adjust. These parameters must be
Adjust is a repeating
Adjust
parameters must be enclosed in a set of braces. Here is an example of the proper syntax for this macro command:
MakeItFit (TargetPage: 1; {Adjust: FitTopMargin!; _ Adjust: FitFontSize!;})
Understanding macro concepts 51
Some macro statements are too lengthy to fit into a single line of macro code. If your macro editor automatically inserts a hard return at the end of every line, you must insert an underscore character (
_ ) at the end of each line that wraps.
For information on specifying a macro editor, see “To specify settings for editing macros” on page 86.
One way to reduce the length of a macro command is to omit parameter names. For example, the WordPerfect command as
InhibitInput (Off!). Similarly, consider the WordPerfect command
GraphicsLineLength (Length: Numeric), which can be written as follows: GraphicsLineLength (Length: 2I)
InhibitInput (State: Off!) works the same
or
GraphicsLineLength (2I)

Understanding return values

Some macro commands let you retrieve data from various sources. For example, such commands can get the current date from the system, the current page number or document filename from an application, or a specific value from the Windows® registry. This information is usually returned as a return value. Many programming commands provide return values, as do some product commands.
WordPerfect returns this type of information primarily with system variables.
Handling return values
To h andl e a re turn valu e, you mus t ass ign it to a variable (see “Understanding variables” on page 10) or use it in an expression (see “Understanding expressions” on page 8). For example, the expression
vVariable := ?Name assigns the return value of ?Name
(which represents the filename of the current WordPerfect document) to the variable
vVariable.
The return value of a system variable is handled in the same manner as the return value of a macro command.
To ignore a return value, don’t handle it. For instance, some macro commands both change the state of an option and return the previous state of that option. If you want to change the state of an option without returning its previous state, you can ignore the return value.
52 Understanding macro concepts
Evaluating to return values
Macro commands that return values (and system variables) are said to “evaluate to” their return value. For example, because expression rather that using
?Name evaluates to the filename of the current document, you can use ?Name in an
4. Similarly, because the WordPerfect system variable
(2+2) evaluates to 4, you can use (2+2) in an
expression rather than using the filename of the current document.
Consider a macro that opens a file, writes text to it, and then closes it. To close the file, you can use the PerfectScript command returns
True if the file closes successfully (and False otherwise). Because CloseFile
CloseFile; however, this command also
evaluates to its return value, you can use the following syntax to both close the file (where
If (CloseFile (FileID: xxxx)) ...(statements to execute if the file was successfully closed)... Else ...(statements to execute if the file was not successfully closed)... EndIf
xxxx is the ID number of the file) and check whether it closes successfully:
Return values can be handled outside of the context of a command. However, for return values of data type Enumeration, the returned enumeration has no meaning unless it is associated with a command. For example, the enumeration
On! has no meaning by
itself, but when used in the context of a command parameter, it indicates that that parameter is turned on. For this reason, PerfectScript evaluates return values of type Enumeration to the name of the command, followed by a period, followed by the enumeration (that is,
command name.enumeration!).
For example, the syntax for the programming command
enumeration := Cancel (State: Enumeration)
Cancel is as follows:
The Cancel command determines how a macro responds to a Cancel condition. It also returns the previous
Cancel state to On!, stores the current state of the Cancel command in the variable vVariable, and types Correct in the current WordPerfect document:
Cancel (State: On!) vVariable := Cancel () If (vVariable = Cancel.On!) Type ("Correct") EndIf
Understanding macro concepts 53
Cancel state (On! or Off!). The following example sets the
If (vVariable = "Cancel.Off!") Type ("Not Correct") EndIf
If the optional parameter is omitted, the Cancel state can be returned without changing it. In this scenario, the in the second
If statement assumes that the enumeration returned by the Cancel
Type command is not executed because the expression
command is a string. (Although enumerations look like strings, they are not.)
Enumerations have numeric equivalents. In the preceding example, equal to command
1. If you were to follow the above example with the WordPerfect product Type(vVariable), the number 1 would be typed in the current document.
vVariable is also
The numeric equivalents of enumerations can change, so as previously mentioned, you must use the syntax
command name.enumeration! to evaluate to return values.

Using assignment statements in macros

Assignment statements assign the value of an expression (see “Understanding expressions” on page 8) to a variable (see “Understanding variables” on page 10). The assignment operator ( operand variable.
For more information about assignment operators, see “Understanding assignment operators” on page 27.
For example, the result of the following assignment statement is that
:
Doe x := "John Doe"
The result of the following assignment statement is that y equals 5:
y := 5
:= or =) assigns the value of a right-operand expression to a left-
x equals John
The result of the following assignment statement is that z equals the result of 3 + 4:
z := 3 + 4

Using conditional statements in macros

Conditional statements execute a statement (or statement block) when a specified condition is met — that is, when an expression is true, or when a variable matches a
54 Understanding macro concepts
constant.
You can use a conditional statement to present the user with a list of options.
Conditional statements include
Case, If, and Switch. For more information about
these conditions, see the following topics:
• Understanding Case conditions
• Understanding If conditions
• Understanding Switch conditions
Understanding Case conditions
A Case condition executes a Label statement when Test (that is, a user-defined variable) matches a constant value.
In the following example,
2, then Label (Next) is called. If there is no match, then Label (Other) is called. Case (Test; {1; Start; 2; Next}; Other) ...(other statements)... Label (Start) ...statement block... Label (Next) ...statement block... Label (Other) ...statement block...
Case Call Return after a Label statement.
Label (Start) is called if Test matches 1. If Test matches
is a similar condition to Case. A Case Call statement expects a
Understanding If conditions
An If condition uses an If-Else-Endif construction to execute a statement (or statement block) when an expression is true.
In the following example, the first statement block is executed if the expression is true (that is, if block is executed.
If (x = 5) ...statement block... Else
Understanding macro concepts 55
x equals 5). If the expression x = 5 is not true, the second statement
Else is optional.
x = 5
...statement block... Endif
In the following example, the statement block is executed if Expression is true. If
Expression is not true, the first statement after Endif is executed. (Note, then, that
for this example to work,
If (Expression) ...statement block... Endif
Understanding Switch conditions
Expression must evaluate to either true or false.)
A Switch condition uses a Switch-EndSwitch construction to execute a statement (or statement block) when
<Test> matches <Selector>.
In the following example, the statement block after if
<Test> matches <Selector>. Switch (<Test>) Caseof <Selector>: ...statement block... Caseof <Selector>: ...statement block... Caseof <Selector>: ...statement block... Default: ...statement block... EndSwitch
Caseof <Selector> is executed
The statement block for a Switch conditon can call a subroutine (see “Understanding subroutines” on page 59). If
Continue follows a statement
block, the next statement block is automatically executed.
By using a
Switch condition, you can alter the sequential play of macro commands. For
example, if the following pair of commands is used in a macro, the second command overrides the first (because the Paint Brush width is set to 25 pixels and subsequently changed to 75 pixels):
SetBrushWidth(BrushWidth: 25) SetBrushWidth(BrushWidth: 75)
56 Understanding macro concepts
If you want the macro to choose between these SetBrushWidth commands, you can
Switch condition. In the following example, a Paint Brush width of 25 pixels is
use a set if variable Finally, if (The value of or
GetNumber.) Switch (Test) Caseof 1: SetBrushWidth(BrushWidth: 25) Caseof 2: SetBrushWidth(BrushWidth: 75) Default: SetBrushWidth(BrushWidth: 50) Endswitch
Test equals 1. If Test equals 2, a Paint Brush width of 75 pixels is set.
Test equals any value except 1 or 2, a Paint Brush width of 50 pixels is set.
Test can be determined by using a programming command such as Menu
The following example contains two CaseOf statements. If variable x equals 1, a subroutine named
Switch (x) CaseOf 1: CALL (Start) CaseOf 2: CALL (Stop) EndSwitch
Start is called. If x equals 2, a subroutine named Stop is called.

Using loop statements in macros

Loop statements execute a statement (or statement block) a specified number of times until (or while) an expression is true. When the loop ends, the macro continues to the next statement.
You can indent lines to show levels of loop statements.
Loop statements include
For, Repeat, and While. For more information about loop
statements, see the following sections:
• Understanding For loops
• Understanding Repeat loops
• Understanding While loops
Understanding For loops
A For loop uses a For-EndFor construction to execute a statement (or statement block) a specified number of times.
Understanding macro concepts 57
In the following example, <InitialValue> initializes <ControlVariable>.
<TerminateExp> tests the value of <ControlVariable>. <IncrementExp>
increases the value of loop ends. (If
<TerminateExp> is initially false, then the statements do not execute
<ControlVariable> until <TerminateExp> is false and the
because the test is checked at the start of the loop.)
For (<ControlVariable>; <InitialValue>; <TerminateExp>; <IncrementExp>)
...statement block....
EndFor
In the following example, x is initialized to 1. The statement block executes while x is less than
For(x; 1; x < 5; x + 1) ...statement block... EndFor
5, and x is incremented by 1 at the end of each loop.
Similar loop statements to For are ForEach and ForNext.
Understanding Repeat loops
A Repeat loo p uses a Repeat-Until construction to execute a statement (or statement block) until an expression is true. All
Repeat statements execute at least once because
the expression is checked at the end of the loop.
In the following example, the statement block is executed until the expression is true (that is, until
Repeat ...statement block... Until (x >= 10)
x is greater than or equal to 10).
x = 10
However, the loop in the previous example does not end until the value of x changes to make the expression true. In the following example, the expression to increment or equal to
Repeat ...statement block... x := x + 1 Until (x >= 10)
58 Understanding macro concepts
x by 1 at the end of each loop so that the loop ends when x is greater than
10.
x := x + 1 is used
Understanding While loops
A While loop uses a While-EndWhile construction to execute a statement (or statement block) while an expression is true. A
While statement cannot execute unless
the expression is true because the expression is checked at the start of the loop.
In the following example, the statement block is executed while the expression is true (that is, while
x is less than or equal to 10). If x is greater than 10, the loop does
x<= 10
not execute.
While (x <= 10) ...statement block... EndWhile
However, the loop in the previous example does not end until the value of x changes to make the expression true. In the following example, the expression to increment or equal to
While (x<=10) ...statement block... x := x + 1 EndWhile
x by 1 at the end of each loop so that the loop executes while x is less than
10.
x := x + 1 is used

Using calling statements in macros

Calling statements involve a subroutine, which is one or more statements that are grouped as one item.
The larger a macro becomes, the more likely the need to create subroutines. Creating subroutines makes it easier to reuse code, and makes the macro easier to read and understand.
Understanding subroutines
A subroutine consists of a statement or a statement block that is played when called by a macro. Subroutines are useful because their statements are accessible to any part of a macro and can be called any number of times during play.
Consider the following example:
Call (SubExample) ...(other statements)...
Understanding macro concepts 59
Label (SubExample) ...statement block... Return
In the preceding example, the calling statement Call (SubExample) calls (that is, directs macro play to) the subroutine directs macro play to the statement that follows
Label (SubExample). The Return command
Call (SubExample).
PerfectScript macros support the following types of subroutines:
labels — act as a place holder, or marker, in a macro. For more information, see “Understanding labels” on page 60.
functions and procedures — contain one or more statements that execute when called. Functions can be used to return a value, but procedures cannot. For more information, see “Understanding functions and procedures” on page 61.
callbacks — enable a macro to respond immediately, and in specific ways, to events. For more information, see “Understanding callbacks” on page 74.
You can use subroutines to create calling statements. For more information, see “Creating calling statements from subroutines” on page 75.

Understanding labels

A label is a subroutine that acts as a place holder, or marker, in a macro. A macro can call the label when a certain function needs to be performed. After that function is performed, the immediately follows the call to the label.
Return command redirects execution to the command that
Labels in the main body of a macro can execute without being called.
Labels cannot hide macro code or macro variables.
In general, macro labels are not used in structured programming unless they are needed within a function or procedure.
Creating labels
A label is created by using the Label command, which has one parameter: the name of the subroutine. The
Label command takes no optional parameters.
Label names have the following conventions:
• They must begin with a character.
• They must consist of one or more letters or numbers.
60 Understanding macro concepts
• They are limited to 30 characters. (If a label name is longer than 30 characters, only the first 30 characters are recognized.)
• They have an optional trailing
@ sign.
Labels generally include one or more statements and are followed by the commands
Return or Quit.
Calling labels
Label statements execute in the same way as other macro statements and do not need to be called. However, if desired, you can call a label by using any of the following PerfectScript commands:
• Call
•Go
• Case
• Case Call
• OnCancel
• OnCancel Call
• OnError
• OnError Call
• OnNotFound
• OnNotFound Call
• OnDdeAdvise Call
• DdeExecuteExt
Structuring labels
The following is an example of a label:
Call( MyLabel@ ) Quit Label( MyLabel@ ) MessageBox (nVar; ""; "The Label was called.") Return

Understanding functions and procedures

Functions and procedures are subroutines that contain one or more statements that execute when called. Most functions and procedures have parameters that receive values from a calling statement. However, some functions and procedures have zero parameters, in which case, they perform like a labels” on page 60) except that they cannot execute unless called by the macro.
Understanding macro concepts 61
Label statement (see “Understanding
The difference between functions and procedures is that functions can return a value whereas procedures cannot.
Creating functions and procedures
Functions and procedures can be placed anywhere in a macro, or in a macro-library file (see “Storing functions and procedures in macro libraries” on page 71). Functions begin with the word
PROCEDURE and end with ENDPROC.
FUNCTION and end with ENDFUNC, while procedures begin with the word
A function or procedure cannot be defined inside another subroutine.
When you create a function or a procedure, you must name it. Function names and procedure names have the following conventions:
• They must begin with a character.
• They must consist of one or more letters or numbers.
• They are limited to 30 characters. (If a function name is longer than 30 characters, only the first 30 characters are recognized.)
• They can (optionally) have a trailing
@ sign.
Functions accept any of the following:
Return statement that has no parameters (return 0)
•a
• a value contained in a variable that is the result of a function
• an enumerated type that asserts a
Cancel, Error, or Not Found condition
• a value contained in a variable that is the result of a function operation
Procedures accept any of the following:
•a
Return statement that has no parameters (which direct macro execution to the
statement that follows the caller of a procedure)
Return statement that has one parameter (which is an enumerated type that
•a asserts a
Cancel, Error, or Not Found condition)
Functions and procedures can include outside the function. However, a
Label statement inside a function must not
Label statements that are not visible
have the same name as a function or procedure.
Using variables in functions and procedures
Function variables and procedure variables are local (or “private”) to the function or procedure. A variable with the same name as a function variable or procedure variable can be used elsewhere in the macro without conflict.
62 Understanding macro concepts
Variables are discussed, in general, in the section “Understanding variables” on page 10. However, the following details apply to using variables in funtions and procedures:
• By default, variables are created as local variables. Local variables are not visible to subroutines unless declared as part of the subroutine. (In other words, local variables created outside of a subroutine cannot be used by that subroutine.) The reverse is also true: If a variable is declared inside a subroutine, that variable cannot be used or accessed outside of that subroutine. (The exception to this rule occurs when a local variable created inside a function is returned to the calling statement by using the
Return command, or when a parameter is passed by reference.)
• Global variables can be accessed anywhere in the macro for the life of the macro. These variables can be accessed and modified within any function or procedure. They are also visible to and can be modified by a macro that is started by the macro that declared the global variable.
• Persistent variables, like global variables, can be accessed and modified at any time during macro execution. The major difference between persistent variables and global variables is that a persistent variable exists after the macro that declared it finishes execution. For example, if macro A declares a persistent variable named
nTestVar and sets its initial value to 3, this variable is not discarded when macro A
completes execution; if you run macro B, and macro B attempts to use the value of
nTestVar is still 3.
nTestVar,
To destroy a persistent variable, you must either use the
Discard command or
close the Macro Facility. Merge variables are persistent variables, so they can be used during macro execution and merge execution.
The scope of a variable refers to the portion of a macro in which a variable is accessible. According to scope rules, variables can be created with the same name if they do not hold the same scope. If the scope of same-named variables is the same, the contents of the original variable are modified by the next instance of that variable.
To understand how scope affects a macro, examine the following code:
nHardReturn := NTOC(0f90ah) Global sVariable1 := "I’m the first" sVariable2 := "I’m the second" sVariable3 := "" sVariable4 :="I’m the fourth" sVariable5 := CreateVariable( sVariable2; &sVariable3; sVariable4 ) MessageBox ( nretVal; "Variable Values";
Understanding macro concepts 63
"sVariable1: " + sVariable1 + nHardReturn + "sVariable2: " + sVariable2 + nHardReturn + "sVariable3: " + sVariable3 + nHardReturn + "sVariable4: " + sVariable4 + nHardReturn + "sVariable5: " + sVariable5) Quit Function CreateVariable( sVariable2; &sVariable3; sVariable4 ) sVariable1 := "I'm Global, I changed" sVariable2 := "I’m not going to change" sVariable3 := "I finally got initialized" sVariable4 := "I am not really the Fourth" Return ( sVariable4 ) EndFunc
In the preceding example, the only modified values are sVariable1 and sVariable3.
sVariable1 is global and sVariable3 is passed to the function by address; they are
the only values that the function can “see.” The other variables were not modified because they were not within the scope of the function.
In the preceding example, the variable
sVariable4 may be in question. When
this variable is passed to the function, a copy of the variable is made inside the function. This variable contains the same content and the same name as the original
sVariable4, but it can be seen only by the function. The content of
this second variable is modified and returned, and assigned, to a new variable called
sVariable5.
Now consider the following example:
Global ( X ) X = "My name is John Doe" DoCount() MessageBox ( retVal; "Variable"; X ) Quit Procedure DoCount() x = 1 ForNext ( y; 1; 5 )
64 Understanding macro concepts
x = x * 10 EndFor EndProc
In the preceding example, variable X would be equal to "My name is John Doe." if not declared global. The variable
x declared inside the DoCount procedure would have
been local to that procedure and would not have modified the contents of the original variable. Such problems become very apparent in large macros that include many variables. (This example also illustrates the need to give variables names that are meaningful.)
Use global or persistent variables only when necessary. When variables are declared as global or persistent and are visible to all sections of a macro, they may be changed or altered in ways that lead to unexpected behavior in your macros.
Passing variables to functions and procedures
Sometimes, you must pass parameters to functions or procedures. There are two ways to pass parameters to subroutines: passing variables by value and passing variables by reference.
When a variable is passed by value as a parameter to a subroutine, a copy of the variable is made in a different location in memory under a different name.
When a variable is passed by reference as a parameter to a subroutine, the address of the variable is used to provide direct access to that variable. In this way, you can use the original variable inside the subroutine that you call. Using this method lets you reduce memory usage and use fewer global variables in your macro.
The
& operator is used when passing a variable by address. This operator is called the
“Address Operator,” and it tells the function or procedure to create a reference for this variable. The Address Operator is required both in the procedure call and in the procedure parameter list.
Here is an example of passing the address of a variable to modify its value. Procedures, unlike functions, cannot return values; however, in this case, the original value of the variable is modified by passing the variable by address to the procedure.
nNumber := 10 ChangeNumber ( &nNumber ) MessageBox (retVal; "New Value"; "The variable nNumber has been _ modified. The new value is " + nNumber +".")
Understanding macro concepts 65
Quit Procedure ChangeNumber( &nNum ) nNum := nNum + 45 EndProc
If the preceding macro code were compiled and run, the MessageBox would display a value of
55.
A function can return only one value. Sometimes, however, you need a function to generate two values to be returned and used later in the macro. In the following example, two values must be returned or changed: can return only one value by using the
Return command, so the other value can be
OriginalCount and vBMName. You
modified by passing the other variable by address.
nOriginalCount := 0 MessageBox ( retVal; "Original Value"; nOriginalCount ) ForEach ( sString; {"One"; "Two"; "Three"; "Four"; "Five"}) //The line below passes nOriginalCount by address sBookMarkName := CreateBookMarkName( sString; &nOriginalCount ) Prompt( "BookMark Names"; "New bookmark name: " + sBookMarkName; _ NoButtons!) Wait( 5 ) EndFor EndPrompt MessageBox ( retVal; "New Value"; nOriginalCount ) Quit Function CreateBookMarkName( sInputString ; &nCount) nCount := nCount + 1 sBMName := sInputString + "_" + nCount Return ( sBMName ) EndFunc
By passing the variable OriginalCount by address to the CreateBookMarkName function, we can manipulate the original value of the variable without having to return the variable. When the function receives the variable, it does not make a copy but references the original variable declared at the beginning of the code.
66 Understanding macro concepts
Passing arrays to functions and procedures
Like normal variables, arrays can be passed to subroutines. (For more information, see “Working with arrays” on page 20.) If you are passing the entire array, you must assign a value to each array element; any undefined element will be identified as an error at run-time.
Arrays can be passed by address.
Consider the following example:
Declare aOldArray[10] ForNext ( x; 1; 10 ) // initialize all elements aOldArray[x] := x EndFor aNewArray[ ] := Test( aOldArray[ ] ) // aNewArray[] is assigned the returned value Type( aNewArray[10] ) // aNewArray[10] equals 100 HardReturn() Type( aOldArray[10] ) // aOldArray[10] equal to 10 Quit Function Test( aTestArray[ ] ) ForNext( x; 1; 10 ) // multiply all elements by 10 aTestArray[x] := x * 10 EndFor Return( aTestArray[ ] ) EndFunc
In the preceding example, if you precede the calling-statement parameter and the corresponding function parameter with an ampersand (
aOldArray[10], and all of the elements in aOldArray[] are modified to contain the
new values in
Declare aOldArray[10]
Understanding macro concepts 67
aNewArray[]. The following code illustrates this change.
&), 100 is returned in
ForNext ( x; 1; 10 ) // initialize all elements aOldArray[x] := x EndFor aNewArray[ ] = Test( &aOldArray[ ] ) // aNewArray[] is assigned the returned value Type( aNewArray[10] ) // aNewArray[10] equals 100 HardReturn() Type( aOldArray[10] ) // aOldArray[10] equal to 100 Quit Function Test( &aTestArray[ ] ) ForNext( x; 1; 10 ) // multiply all elements by 10 aTestArray[x] := x * 10 EndFor Return( aTestArray[ ] ) EndFunc
Calling functions and procedures
To create a calling statement from a function or procedure, you specify the name of the function or procedure and one or more parameters that contain values passed to the function or procedure. (If there are no parameters, empty parentheses must follow the function name or procedure name.)
The following rules apply to calling functions and procedures:
• Functions and procedures do not execute unless they are called. They can be called from within another subroutine, or they can be called recursively (that is, they can call themselves).
• The number of parameters in a calling statement must match the number of parameters in the function or procedure. When a function or procedure requires multiple parameters, use semicolons (
Structuring functions
;) to separate those parameters.
The basic structure of a function is as follows:
68 Understanding macro concepts
Function MyFunction() . . . statement block EndFunction
The Function keyword is followed by the actual function name. Statements are added to the function, after which the function is ended by the keyword. A function can return a value by means of the
nOriginalValue := 6 nNewValue := AddNumbers( nOriginalValue ) MessageBox( nretVal; "New Value"; "The old value was " +
nOriginalValue + ". The new value is " + nNewValue + "."; IconInformation! )
Quit Function AddNumbers( nInputValue ) nTempValue := nInputValue + 13 Return (nTempValue) EndFunc
EndFunc or EndFunction
Return command, as follows:
In the preceding example, nOriginalValue is initialized with a value of 6. This value is passed as a parameter to the
13 to nInputValue and stores the result in nTempValue. nTempValue is returned to
the calling statement as a parameter of the assigned to
nNewValue. The values of the nOriginalValue and nNewValue variables
are then displayed by using the
AddNumbers function. The AddNumbers function adds
Return command. The return value is
MessageBox command.
In the preceding example, the value of a parameter to the function. If the to access
nOriginalValue without passing the value to the function, an error
would have occurred. This is because
AddNumbers function.
Structuring procedures
nOriginalValue had to be passed as
AddNumbers macro function had attempted
nOriginalValue was out of scope of the
The basic structure of a procedure is as follows:
Procedure MyProcedureName( ) . . . statement block EndProc
The Procedure command begins the block of code, with the actual name of the procedure following. The end of the procedure is marked by the
Understanding macro concepts 69
EndProc or
EndProcedure keyword. The contents of the subroutine are placed between the Procedure and EndProcedure commands. If a procedure requires parameters, the
code is similar to the following:
Procedure MyProcedureName( value1; value2 ) . . . statement block EndProc
To call the preceding procedure, you would use the following code:
MyProcedureName( 1; 2 )
An example of a procedure call without parameters would resemble the following:
Procedure CreateFooter() FooterA (Create!) FontSize(10p) InsertFilenameWithPath () Tab() DateText () FlushRight () PageNumberDisplay () SubstructureExit () EndProc
In the preceding example, the CreateFooter procedure creates a footer in a document. This footer contains the text for path and filename, the date, and a page number — all formatted by using the specified formatting codes. The procedure does not receive any parameters.
We c o ul d m o di f y t h e
CreateFooter (10) // Calls the procedure CreateFooter with the FontSize of // 10 Quit Procedure CreateFooter( nFontSize ) nFontSize := 16.6 * nFontSize // This calculates the correct font size value in WP units FooterA (Create!) FontSize( nFontSize)
70 Understanding macro concepts
CreateFooter procedure to accept a value for the font size:
// Recalculated value used InsertFilenameWithPath () Tab() DateText () FlushRight () PageNumberDisplay () SubstructureExit () EndProc
In the preceding example, the call made by the CreateFooter command passes one
10, to the procedure. This value is received into a procedure variable that is
value, named
nFontSize. This variable can be used and manipulated only inside the
procedure. In the example, a calculation is made to determine the proper font height in WordPerfect units, and then the variable is used by the
FontSize command. After this
routine has ended, the variable is discarded by PerfectScript.
Storing functions and procedures in macro libraries
Macro libraries contain files that store functions or procedures (or both) that can be called from another macro and must be compiled.
The following example contains two functions. Function
x. 50 is added to x and returned to the caller of the function. Function Subtract
receives a value in another variable named
x. 25 is subtracted from x and returned to
Add receives a value in variable
the caller of the function.
Function Add(x) x := x + 50 Return (x) EndFunc Function Subtract(x) x:= x - 25 Return (x) EndFunc
The Use command lets you use functions and procedures that are stored in another macro. This command usually precedes calling statements to a macro library.
If the preceding example were saved and compiled as
Subtract functions could be called as in the following example. After function Add is
Understanding macro concepts 71
LIBRARY.WCM, its Add and
called, 100 is returned in variable z. After function Subtract is called, 75 is returned in variable
Application (WP; "WordPerfect"; Default; "EN") Use ("C:\...\LIBRARY.WCM") z := Add(50) z := Subtract(z) If (z = 75) Beep // computer beeps because z equals 75 EndIf
z. The computer then beeps because the expression z = 75 is true.
The preceding example can be written in shortand notation, as follows:
Application (WP; "WordPerfect"; Default; "EN") Use ("C:\...\LIBRARY.WCM") z := Add(Subtract(50)) If (z = 75) Beep // computer beeps because z equals 75 EndIf
Use
is a non-executing statement that can occur anywhere in a macro. A macro that
makes a call to a function or procedure in another macro file must include a
Use
statement that identifies the file.
A macro library that includes only function statements or procedure statements (or both) must be compiled like any macro file. PerfectScript automatically compiles uncompiled libraries. Macro execution stops if the macro library file will not compile.
Many programmers create library files that contain just functions and procedures that may be used with other macros. These functions and procedures are generic enough to be applicable to many different macros.
Here is an example of a macro that uses a function from another macro:
Macro1 Use( "Library.wcm" ) vDefDir := GetMyDefaultDirectory() MessageBox ( retVal; "Docs Directory"; vDefDir" ) Quit
72 Understanding macro concepts
Library.wcm (macro library that contains the following code) Function GetMyDefaultDirectory() Return ( ?PathDocument ) EndFunc
If one macro “uses” another macro, the second macro becomes a dependent of the main macro. If you want to deploy the main macro throughout your organization or send it to a customer, You must include the second macro.
Macro files included by using multiple
Use commands are searched from beginning to
the end of the macro. Thus, a parent macro always calls the first occurrence of a function or procedure with the same name in different
Macro1 Use( "Library1.wcm" ) Use( "Library2.wcm" ) vDefDir := GetMyDefaultDirectory() MessageBox ( retVal; "Docs Directory"; vDefDir" ) Quit Library1.wcm (contains) Function GetMyDefaultDirectory() Return ( ?PathDocument ) EndFunc Library2.wcm (contains) Function GetMyDefaultDirectory() Return ( ?PathCurrent ) EndFunc
Use files. Consider the following example:
In the preceding example, the library function called by the macro is Library1.wcm because it is the first macro library included by
Macro1.
When a macro uses a subroutine in a macro library, playing that macro incurs an error if the syntax of the call to the subroutine is incorrect. Using a function prototype or procedure prototype forces the compiler to check the parameter count of a function or procedure in a macro library; if the syntax is incorrect, a compiler error occurs.
Understanding macro concepts 73
The prototype directs the compiler to validate the syntax of a function or procedure. Creating a prototype helps you keep track of the parameters of a function or procedure. Place prototypes at the beginning of your macro, as in the following example:
Function Prototype Check(nBeep; HdReturn) HdReturn := NTOC(0F90Ah) x := 4 nBeep := 1 While(x = 4) BEEP x := Check(nBeep; HdReturn) nBeep := nBeep + 1 EndWhile MessageBox( retVal; "RETURN"; "The value of variable vStatus (" + x _ + ") is returned to variable x, which ends the loop."; _ IconExclamation!) Function Check(nBeep; HdReturn) MESSAGEBOX(vStatus; "FUNCTION EXAMPLE"; "Beeps: " + nBeep + _ HdReturn + HdReturn + "Choose Retry to beep again." + HdReturn; _ IconInformation! | RetryCancel!) RETURN(vStatus) EndFunc

Understanding callbacks

Callbacks are special functions that enable a macro to respond immediately, and in specific ways, to events. When a macro executes a callback routine, the macro system automatically creates variables that are accessible to that callback. The callback can access the parameter array for information about the callback event, and the callback can place its return value (if any) in the return variable.
The parameters for a callback are placed into a global array variable that has the same name as the callback label. Any return value for the callback routine is placed in a (non-array) global variable that has the same name as the callback label. For example, parameters would be passed to callback routine
74 Understanding macro concepts
'MsgHandler' in an array called 'MsgHandler[ ]', and any return value
would be placed into a variable called
'MsgHandler'.
PerfectScript currently supports three types of callbacks, all of which are discussed in greater detail in the “Support for callback entries” topic in the PerfectScript Command Reference section of the PerfectScript Help file (psh.chm):
• product-command callbacks
• dialog-box callbacks
• message-box callbacks
Perhaps the most useful of these callback types is the dialog-box callback, which lets the macro gather information from an active dialog box (rather than waiting until the dialog box is closed to gather that information). For more information on dialog-box callbacks, see “Setting up callbacks for dialog boxes” on page 124.

Creating calling statements from subroutines

You can create calling statements by using PerfectScript commands, such as the following:
Call — calls the specified subroutine. For more information, see “Using the Call
• command in calling statements” on page 75.
Go — jumps to the specified subroutine. For more information, see “Using the Go
command in calling statements” on page 76.
Case or Case Call — creates a conditional statement that tests for matching
• expressions, and calls a label if a match is found. For more information, see “Understanding Case conditions” on page 55.
For more information about these (and other) PerfectScript commands, please see the PerfectScript Command Reference in the PerfectScript Help file (psh.chm).
Using the Call command in calling statements
The Call command has one parameter, which is the name of a subroutine to call. The
Return command directs macro execution to the statement that follows Call.
In the following example, where the statement block is executed. statement after
Call (ExSub) ...other statements...
Understanding macro concepts 75
Call(ExSub).
Call(ExSub) directs macro execution to Label(ExSub),
Return directs macro execution to the first
Label (ExSub) ...statement block... Return
Using a subroutine name to form a calling statement performs the same action as creating a example, a function or procedure that is named
Call statement that specifies that subroutine name as a parameter. For
InitializeVariables can be called
as follows:
Call InitializeVariables (<Parameter>; <Parameter>)
or
InitializeVariables (<Parameter>;<Parameter>)
If the second example calls a function, you can assign a return value to a variable with a statement such as the following:
x := InitializeVariables (<Parameter>;<Parameter>)
For information about return values, see “Understanding return values” on page 52.
For information about variables, see “Understanding variables” on page 10.
Using the Go command in calling statements
The Go command has one parameter, which is the name of a subroutine to which to jump. Macro execution continues from the point of the subroutine and does not return (so statements between directs macro execution to the statement that follows a
Go and the subroutine do not execute). Return ends a macro or
Run command.
In the following example, where the statement block is executed.
Go (ExSub) ...other statements... Label (ExSub) ...statement block... Return
Go(ExSub) directs macro execution to Label(ExSub),
Return ends the macro.
76 Understanding macro concepts

Using comment statements in macros

Comment statements contain notes and other information that do not affect macro play. You can use comment statements to explain the purpose of your macro, describe its components, or to prevent a statement from playing.
A comment statement can consist of a single line of text or instead span several lines of text. However, the syntax for a single-line comment statement is different from that of a multi-line comment statement:
• single-line comment statement — begins with
• multi-line comment statement — begins with
// and ends with a hard return
/* and ends with */

Accessing external applications in macros

PerfectScript provides the following advanced features, which let macros access applications outside of WordPerfect Office:
OLE Automation — lets PerfectScript control applications that support OLE. For more information, see “Understanding OLE Automation” on page 77.
Dynamic Data Exchange (DDE) — lets PerfectScript control applications that support DDE. For more information, see “Understanding Dynamic Data Exchange (DDE)” on page 80.

Understanding OLE Automation

PerfectScript can send commands that control WordPerfect, Quattro Pro, and Presentations. However, through a Windows-standard interface known as OLE Automation, PerfectScript can send commands that control other OLE-enabled applications, which are called OLE Automation servers. For this reason, PerfectScript is called an OLE Automation controller.
OLE Automation servers define OLE Automation objects, which have names that are registered with Windows. (For information about the OLE Automation objects that are defined for an application, refer to the manufacturer’s documentation for that application.)
OLE Automation objects can have methods and properties.
Understanding macro concepts 77
A method is a command or function that performs an action on an object. Many methods, like product commands, have parameters and return values. Here is a sample method for the OLE Automation object Excel.Application:
Worksheets ().Activate
A property is an object value that can be retrieved and set. Many properties have parameters and return values. Unlike WordPerfect system variables, many properties can be set by placing the property name on the left side of an assignment statement (see “Using assignment statements in macros” on page 54). Properties can take parameters when being retrieved (similarly to a method call) or when being set. Here is a sample property for the OLE Automation object Excel.Application:
ActiveSheet.Name
IMPORTANT: You must set optional parameters when using OLE Automation.
Working with OLE Automation objects
Before an OLE Automation object can be used in a PerfectScript macro, the Object statement must be used. The
Object statement is similar to the Application
statement for products: It defines an object-prefix variable that is used to call methods and to retrieve and set object properties. The name of the object is also specified, along with information about whether this prefix is to be used as the default object for non­prefixed methods and properties.
The object-prefix variable that is specified in the
Object statement identifies a variable
that contains an instance handle to the object at run-time. As a variable, this prefix can be used in many places where most, but not all, other macro variables can be used. For example, the macro language operators
+ and - cannot be used with object variables,
and automatic type conversions are not defined for object variables. Object variables can be assigned to other object variables of the same type, and they can be passed as parameters to user-defined macro routines.
As with other macro variables, object variables exist at run-time in a specific macro variable pool. You can specify this pool by using
Declare, Local, Global and Persist
statements (see “Understanding variables” on page 10). If the object variable is not specified, it exists in the local variable pool (unless
PersistAll is in effect, in which
case the object variable exists in the persistent variable pool).
Before making a call to the methods for an object, and before retrieving or setting the properties for an object, an instance handle to a specific object must be obtained through the
78 Understanding macro concepts
CreateObject statement or the GetObject statement. These statements
return an instance handle to a specific instance of an object. Because many OLE Automation servers support multiple instances of the objects they define, an instance handle to a specific object must be obtained to distinguish instances of the same object. Multiple object variables can be created, and multiple instances can be obtained if the OLE Automation server supports multiple instances.
After getting an instance handle, an object variable is said to be connected to the OLE Automation server. Like other variables, the
Exists statement can be used on object
variables to determine whether an object variable exists and, if so, which variable pool it exists in. Even if an object variable exists, it may not be currently connected to the OLE Automation server, but this connection information can be obtained from the
ObjectInfo command.
When an instance of an OLE Automation object is no longer needed, the connection can be terminated by using the
Discard statement. Variables for OLE Automation
objects, like other variables, are automatically discarded when the macro terminates or when the user-defined routine in which the variable is defined ends. This discarding automatically disconnects the object from an OLE Automation server (if connected to one).
After an object is connected to its OLE Automation server, the methods and properties of that object can be accessed by prefixing the method name or property name with the variable name for the OLE Automation object followed by a period ( object variable is the default object variable (specified by statement, or specified in a by two leading periods (
With statement), the object-prefix variable can be replaced
..). Leading periods are necessary to inform the macro compiler
Default! in the Object
.). If the OLE
that the method name being called is not the name of a user-defined macro routine but the method name (or property name) of the current default OLE Automation object.
A macro can use more than one application product and OLE Automation object. Commands to the non-default application or OLE Automation object require a prefix, which is specified in a PerfectScript statement. In the example
A1.AboutDlg (), the prefix A1. tells the compiler
to use the application or object that is assigned
Application or Object statement.
Application or Object
A1 in a PerfectScript
To establish a new default object for a localized block of code, you can use a With­EndWith compound statement. The object-prefix variable is specified in the
With
statement; all statements to access methods, and properties preceded by two periods (..) until the
Understanding macro concepts 79
EndWith statement, are assumed to be references to that object.
The NewDefault statement can be used to establish a new default object-variable prefix for the remainder of a macro (or until the macro encounters another
NewDefault
statement).
For more information about PerfectScript support for OLE Automation, please see the “Support for OLE Automation” topic in the PerfectScript Command Reference section of the PerfectScript Help file (psh.chm).

Understanding Dynamic Data Exchange (DDE)

Dynamic Data Exchange (DDE) Execute is a Windows feature that enhances product integration by allowing applications to instruct each other to perform specific tasks (that is, to execute commands). For example, you can use the DDE Execute feature to create macros in WordPerfect that send commands to control other Windows applications that accept DDE Execute strings.
WordPerfect, Quattro Pro, and Presentations are DDE servers, and they provide support to DDE clients through the PerfectScript language.
An instance of DDE-based communication between two applications is called a DDE conversation. WordPerfect, Quattro Pro, and Presentations each handle DDE conversations in their own way.
For more detailed information about using DDE, see the WordPerfect Office Software Development Kit (SDK), which is included in the Professional Edition of WordPerfect Office. For more information, see “Using the WordPerfect Office Software Development Kit (SDK)” on page 81.
Understanding DDE conversations for WordPerfect
WordPerfect can act as a server for DDEExecute commands.
To access the PerfectScript-based product commands for WordPerfect, the DDE client must initiate a DDE conversation by using
Commands as the topic name.
Understanding DDE conversations for Quattro Pro
WPWin15_Macros as the service name and
Quattro Pro can act as a server for DDERequest commands.
To access request topics, application status, or properties from Quattro Pro, the DDE client must initiate a DDE conversation by using
QPW as the service name and System
as the topic name.
80 Understanding macro concepts
To read and write to spreadsheet cells, or to execute PerfectScript-based product commands for Quattro Pro, the DDE client must initiate a DDE conversation by using
QPW as the service name and the path and file of an open notebook as the topic name.
Understanding DDE conversations for Presentations
Any eligible Windows application can use the DDE Execute feature to control Presentations. To begin, the DDE client must initiate a DDE conversation by using
Presentations as the service name and Command as the topic name. Before
terminating the conversation, the client can send DDE Execute strings that include PerfectScript-based product commands for Presentations (provided that those commands do not contain variables or expressions).
Eligible Windows applications can also send commands to Presentations as a DDE Request item. In this scenario, Presentations returns an ANSI® text string that represents the return value of the command.
The DDE client must send DDE Execute strings and DDE Request items in ANSI text format. If Presentations returns an error, the DDE client can determine what went wrong by sending a DDE Request item for
LastCmdError; Presentations then returns
an ANSI text string that contains a three-digit error code and a description of the error.

Learning more about macros

If you want to learn more about macros, you can consult the WordPerfect Office Software Development Kit (SDK) or the Corel Web site.
This section contains the following topics:
• Using the WordPerfect Office Software Development Kit (SDK)
• Using the Corel Web site

Using the WordPerfect Office Software Development Kit (SDK)

The WordPerfect Office Software Development Kit (SDK) is a set of tools that lets you customize WordPerfect Office applications for commercial or business use. The WordPerfect Office SDK includes documentation, samples, and various tools and utilities.
The WordPerfect Office SDK is included with certain editions of WordPerfect Office.
Understanding macro concepts 81

Using the Corel Web site

The Corel Web site provides additional information about WordPerfect Office and about the products and services that are offered by Corel Corporation. Visit the Corel Web site at www.corel.com, or access it directly from WordPerfect, Quattro Pro, or Presentations by clicking Help ` Corel on the Web and then choosing a destination.
82 Understanding macro concepts

Getting started with macros

Now that you understand the basics about PerfectScript, you are ready to get started with macros by learning how to use the PerfectScript utility.
This section contains the following topics:
• Using the PerfectScript utility
• Specifying PerfectScript settings

Using the PerfectScript utility

To get started with PerfectScript macros for WordPerfect Office, you can use the PerfectScript utility.
WordPerfect, Quattro Pro, and Presentations provide a To o l s ` Macro menu, which lets you work with macros from directly within the application. (WordPerfect also provides a To o l s ` Template macro menu, which lets you work with template macros and QuickMacros from directly within WordPerfect.) For information about working with macros from directly within WordPerfect, Quattro Pro, or Presentations, please see the Help file for the application.
The PerfectScript utility provides the following tools for creating PerfectScript macros:
Command Browser — displays a list of all available programming commands for PerfectScript, as well as all available product commands for WordPerfect, Quattro Pro, and Presentations.
Dialog Editor — lets you create dialog boxes for your macros.
The PerfectScript utility provides context-sensitive Help for many of its controls, as well as Help for all of the macro commands in its Command Browser.
You can quit the PerfectScript utility when you have finished using it.
This section contains the following procedures:
• To start the PerfectScript utility
• To display the Command Browser
• To display the Dialog Editor
Getting started with macros 83
• To access context-sensitive Help for the PerfectScript utility
• To access Help for a macro command
• To quit the PerfectScript utility
To start the PerfectScript utility
•Click Start ` All programs ` WordPerfect Office nn ` Utilities ` PerfectScript, where nn is the version number of the software.
To display the Command Browser
• In the PerfectScript utility, click Help ` Macro Command Browser.
For information about using the Command Browser to create macros, see “Writing and editing macros” on page 93.
To display the Dialog Editor
• In the PerfectScript utility, click To o l s ` Dialog Editor.
The Dialog Editor works only with macros that are in WordPerfect format. For this reason, you can open the Dialog Editor from directly within WordPerfect by clicking Dialog Editor on the Macro toolbar when editing a macro.
For information about using the Dialog Editor, see “Creating dialog boxes for macros” on page 101.
To access context-sensitive Help for the PerfectScript utility
• Click (or press Shift + F1), and then click the desired control.
To access Help for a macro command
• In the Command Browser, right-click the desired command.
To quit the PerfectScript utility
•Click File ` Exit.
84 Getting started with macros

Specifying PerfectScript settings

From within the PerfectScript utility, you can specify various PerfectScript settings.
This section contains the following procedures:
• To specify general macro settings
• To specify settings for compiling macros
• To specify settings for debugging macros
• To specify settings for editing macros
• To specify settings for playing macros
• To specify settings for recording macros
• To specify settings for the PerfectScript toolbar
To specify general macro settings
1 Click To o l s ` Settings, and then click the General tab.
2 Do any of the following:
• Specify a default macro folder.
• Enable the Use enhanced file dialogs check box if you want to view detailed
dialog-box information.
• Enable the Display icons in system tray check box if you want to display macro
icons in the Windows system tray.
• Enable the Check file associations on startup check box if you want to check
file associations at startup.
Click Reset all to defaults to return all settings to their original state.
To specify settings for compiling macros
1 Click To o l s ` Settings, and then click the Compile tab.
2 Enable any of the following check boxes:
• Show progress
• Include debug information
• Warn when using unsupported features
• Generate listing file
To specify settings for debugging macros
1 Click To o l s ` Settings, and then click the Debug tab.
Getting started with macros 85
2 Do any of the following:
• Enable the Invoke Debugger on macro start check box, if you want.
• Enable the Invoke Debugger on errors check box, if you want.
• Enable the Debugger event logging check box, if you want.
• In the Animate settings area, enable the desired ‘Run to’ option, and specify the
desired delay (in seconds).
Debug, a menu item for the Windows shell, appears on the context menu for the desktop icon of any macro.
To specify settings for editing macros
1 Click To o l s ` Settings, and then click the Edit tab.
2 Specify the path and filename of the macro editor that you want to use.
3 Specify a file format that is compatible with the macro editor that you’ve chosen.
You must specify a macro editor if you want to edit macros.
Some macro statements are too lengthy to fit into a single line of macro code. If your macro editor automatically inserts a hard return at the end of every line, you must insert an underscore character (
Although you can use any ASCII-based text editor to edit macros, some editors offer special features. For example,
• When you use Notepad, you can create a macro just by specifying its filename.
• When you use WordPerfect, you can use the PerfectScript Command Inserter (on the Macro toolbar) to insert macro commands into your macros or to edit existing macro commands.
_ ) at the end of each line that wraps.
To specify settings for playing macros
1 Click To o l s ` Settings, and then click the Play tab.
2 Do any of the following:
• Specify a value in the Play repeat count box.
• Enable the Security for JavaScript® check box, if you want.
• Enable the Show elapsed time check box, if you want.
86 Getting started with macros
To specify settings for recording macros
1 Click To o l s ` Settings, and then click the Record tab.
2 Do any of the following:
• From the Script language list box, choose the script language that you want to
use.
• From the File format list box, choose the file format in which you want to save
macros. (This file format must be compatible with the macro editor that you specify on the Edit page.)
• From the Parameters per line list box, choose One or Multiple to set the
number of parameters in each macro line.
• In the Maximum line length box, specify a maximum line length for macro
text.
• Enable the Named parameters required check box if you want to use only
named parameters in your macros.
• Enable the Record product prefixes on all commands if you want to insert
product prefixes in your macros.
To specify settings for the PerfectScript toolbar
1 Click To o l s ` Settings, and then click the To o l b a r tab.
2 Do any of the following:
• Enable the Use large icons on toolbar buttons check box, if you want.
• Enable the Show text on toolbar buttons check box, if you want.
• Assign macros to the available toolbar buttons, if you want. The macro buttons on the PerfectScript toolbar can be configured to play any desired macro.
The PerfectScript toolbar appears as a flat toolbar, similarly to other toolbars in WordPerfect Office.
Getting started with macros 87
88 Getting started with macros

Creating macros

Now that you know how to use the PerfectScript utility, you are ready to create PerfectScript macros.
This section contains the following topics:
• Migrating legacy macros
• Recording macros
• Writing and editing macros
• Compiling macros
•Playing macros
• Making macros user-friendly

Migrating legacy macros

You can use the PerfectScript utility to migrate PerfectScript macros from previous versions of WordPerfect Office to a later version of the software.
With each new version of WordPerfect Office, some commands are added, some commands are changed, and some commands become obsolete and are removed altogether. Because of such changes, macros from earlier versions of WordPerfect Office might need minor corrections when migrated to a later version of the software.
This section contains the following procedures:
• To migrate a legacy macro
Converting non-PerfectScript macros to PerfectScript format
You may also be able to use the migration process to convert a non-PerfectScript macro to PerfectScript format. (For example, if you record a macro in a non-PerfectScript language — JavaScript, Microsoft® Visual Basic®, Corel SCRIPT™, or Borland® Delphi®, as explained in “To specify settings for recording macros” on page 87 — you may subsequently want to convert that macro to PerfectScript format.) However, you must be sure to take certain precautions when converting macros.
Creating macros 89
First, be sure to review each variable, label, procedure, and function name in your existing macro, and change any names that have become reserved words. Each new version of WordPerfect Office adds PerfectScript keywords, which are reserved words that cannot be used as variable or label names in macros; in addition, the names of all macro commands are considered reserved words because they cannot be used as variable or label names. For more information on reserved words, please see the “Reserved words” topic in the PerfectScript Command Reference section of the PerfectScript Help file (psh.chm).
Next, be sure to review any arrays in your existing macro (see “Working with arrays” on page 20). Please note the following:
• You can pass array slices to repeating parameter groups of commands. In early versions of PerfectScript, you could pass only entire arrays. Empty slices can now be specified, if the end index is less than the first index.
• Negative array indexes can be used in array slices. If negative, the index is considered to be end-relative, not start-relative. An index of last element,
[-2] represents the second-to-last element, and so on.
[-1] represents the
• You can assign non-arrays to arrays, and arrays to non-arrays. If an array is assigned to a non-array variable, the assignment is actually made to the array variable with the same name as the non-array variable, and the non-array variable is left untouched. If a non-array is assigned to an array variable, the non-array value is converted into a single element array with that value, and it is assigned to the array variable.
• Non-array values and arrays can be combined by using the operators
^^ or \.
However, undefined array elements will be ignored and skipped over.
90 Creating macros
Non-array values and arrays can also be combined by using the following operators (although undefined array elements will be ignored and skipped over):
• unary operators — for information, see “Understanding operators” on page 25.
• arithmetic operators — for information, see “Understanding assignment operators” on page 27.
• relational (comparison) operators — for information, see “Understanding relational operators” on page 28.
• logical operators — for information, see “Understanding logical operators” on page 31.
• bitwise operators — for information, see “Understanding bitwise operators” on page 35.
• JavaScript operators — for information on specifying JavaScript as the macro-recording language, see “To specify settings for recording macros” on page 87.
Finally, when converting a native QuattroPro macro to PerfectScript format, you may want to know how to manually convert the syntax of each Quattro Pro command. For more information, see “Understanding the native Quattro Pro macro language” in the Quattro Pro Command Reference section of the PerfectScript Help file (psh.chm).
To migrate a legacy macro
1 In the PerfectScript utility for the later version of WordPerfect Office, click File `
Play.
2 Select the legacy macro that you want to migrate.
3 Specify a path and filename for the migrated macro, and then click Play.
The macro is compiled for use with the later version of WordPerfect Office.
4 Make note of any errors that are encountered by the macro compiler, and make the
necessary fixes to the macro.
For tips on resolving macro-compilation errors, see “Troubleshooting macro­compilation errors” on page 97.
Creating macros 91

Recording macros

You can create a basic PerfectScript macro by using the PerfectScript utility to record keyboard actions in WordPerfect, Quattro Pro, or Presentations. Keyboard actions are actions that you perform by using the keyboard — for example, typing text or saving a file.
You cannot record mouse actions. However, you can use the keyboard to position the cursor by pressing an arrow key or a navigation shortcut key.
You cannot record some actions at all. However, you may be able to manually code such actions by using a macro editor (see “Writing and editing macros” on page 93).
You can also record macros from directly within WordPerfect, Quattro Pro, or Presentations. For information, please see the Help file for the application.
You can also record template macros and QuickMacros from directly within WordPerfect. For information, please see the Help file for WordPerfect.
When you record a PerfectScript macro, you record the results of your actions rather than your actual actions. For example, if you record a macro that changes the top margin of a page to 2 inches in a WordPerfect document, PerfectScript records the WordPerfect product command step-by-step method that you used to change the margin. The correct PerfectScript syntax (see “Understanding macro commands” on page 47) is automatically applied to all recorded product commands; for this reason, recording a macro helps you avoid typos and similar errors that can occur when manually coding macros.
MarginTop(MarginWidth:2.0") rather than the
Only product commands can be recorded. If you want to include programming commands (or complex functions such as assignments or loops) in a macro, you must manually code them. For information, see “Writing and editing macros” on page 93.
This section contains the following procedures:
• To record a macro
To record a macro
1 Open the desired WordPerfect Office application.
2 In the PerfectScript utility, click File ` Record.
92 Creating macros
3 Type a name for the macro, and then click Record.
4 Switch to the WordPerfect Office application, and then perform the keyboard
actions that you want to record.
Although you cannot record mouse actions, you can use the keyboard to position the cursor by pressing an arrow key or a navigation shortcut key.
5 When you have finished recording the macro, click File ` Stop in the PerfectScript
utility.
When you record a macro, the PerfectScript utility automatically records the
Application command for the appropriate WordPerfect Office application.
This command indicates the application to which the macro belongs.
Some actions cannot be recorded. However, you may be able to manually code these actions by using a macro editor (see “Writing and editing macros” on page 93).
If you need to stop recording temporarily (for example, to locate a feature or to experiment with the effect of a feature before you record the command), click File ` Pause in the PerfectScript utility. Click Pause again to resume recording the macro.
You can specify the settings to use when recording macros. For information, see “To specify settings for recording macros” on page 87.

Writing and editing macros

If you prefer to write (rather than record) a PerfectScript macro, you can do so by using a macro editor — or even by typing in a blank document. Manually coding a PerfectScript macro requires an understanding of both the PerfectScript language and the principles of computer programming.
A macro editor, as its name implies, lets you edit the code for an existing macro. You can edit a macro if you want to change how that macro operates.
If you choose WordPerfect as your macro editor, you can easily insert PerfectScript macro commands into your macro code by using the Command Inserter feature of the Command Browser. The Command Inserter feature lets you choose macro commands and parameters from the provided lists and then insert the resulting syntax into your macro code. Using the Command Inserter saves you time and helps you avoid typos and similar errors that can occur when manually coding macros.
Creating macros 93
If you choose WordPerfect as your macro editor, you must disable the SmartQuotes feature. To disable SmartQuotes in WordPerfect, click To o l s `
QuickCorrect™, click the SmartQuotes tab, and then disable the Use double quotation marks as you type check box.
If you do not choose WordPerfect as your macro editor, you must be sure to apply the correct syntax to all the macro commands that you type. For information about macro-command syntax, see “Understanding macro commands” on page 47.
This section contains the following procedures:
• To write a macro
• To edit a macro
• To insert a macro command into macro code
Formatting macros
If you want to improve the readability of a macro, you can format it to include tabs, spaces, and even font styles or other text-appearance changes. Formatting a macro does not affect how it works.
For example, WordPerfect records the following macro in this default format:
PosDocBottom() Type("Sincerely") HardReturn() HardReturn() HardReturn() HardReturn() Type("Ms. Sharon Openshaw") HardReturn() Type("Vice President, Marketing")
However, you can type spaces between components and blank lines between tasks, as follows:
PosDocBottom()
Type ("Sincerely")
HardReturn()
94 Creating macros
HardReturn() HardReturn() HardReturn()
Type ("Ms. Sharon Openshaw")
HardReturn() Type ("Vice President, Marketing")
To write a macro
1 Type the macro code in a macro editor or in a blank document.
2 Save the macro as a file with a .wcm extension.
You can specify the settings to use when writing macros in a macro editor (see “To specify settings for editing macros” on page 86).
To edit a macro
1 In the PerfectScript utility, click File ` Edit.
2 Select the macro that you want to edit, and then click Edit.
If necessary, click Convert to convert the macro for editing.
3 Make the desired changes to the macro, and close the macro editor.
In Windows, you can access the Edit command for a macro by right-clicking that macro.
You can specify the settings to use when editing macros (see “To specify settings for editing macros” on page 86).
To insert a macro command into macro code
1 In the macro code, click where you want to insert a macro command.
2 In the PerfectScript utility, click Help ` Macro Command Browser.
3 From the Command type list box, choose the type of command that you want to
insert.
4 In the Commands list, double-click the command that you want to insert.
Creating macros 95
5 In the Parameters list, double-click the parameter that you want to insert.
If the parameter has enumerations, double-click the desired enumeration to insert both the parameter and its enumeration.
6 Repeat step 5 for each additional parameter.
7 Click Return values if you want to return value enumerations for commands that
have enumerations as return values.
8 If desired, manually edit the command in the Command edit list box.
9 Click Insert to copy the command from the Command edit box and insert it into
the macro code.
You can use the Command Inserter feature only when using WordPerfect as your macro editor. For information about choosing a macro editor, see “To specify settings for editing macros” on page 86.
For most macro commands, a default value is passed when an optional enumeration parameter is omitted — and in some cases, omitting an optional enumeration parameter performs a different function altogether. In the Command Browser, any default enumeration values for a parameter are displayed in bold text in the Parameters list.
For some macro commands, the default parameter value is a combination of enumerations. In this scenario, several enumerations may be defined as synonyms that have the same value; in the Command Browser, any such enumerations are highlighted.
You can display Help for any macro command in the Command Browser by right-clicking that command in the Commands list.

Compiling macros

To create a functioning macro from macro code, you must use a “compiler.” PerfectScript macros are automatically compiled when they are recorded or played, but they can be manually compiled at any time by using the PerfectScript utility.
You can also compile macros from directly within WordPerfect or Presentations. For information, please see the Help file for the application.
96 Creating macros
Loading...