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.
Introduction1
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 macroprogramming 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 macroprogramming 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 concepts3
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.
4Understanding 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 concepts5
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.
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 concepts7
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.
8Understanding macro concepts
ExampleResult
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 concepts9
vCount is used as a variable, while the values 0, 4, and -1 are used
- and = are used to create expressions from these values:
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.
10Understanding 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 concepts11
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
Similarly, variables that have a numeric value should have a name that begins with a
lowercase
nAge := 25
nTotal := 145.97
12Understanding 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
(
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 concepts13
/* 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
/* 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 concepts15
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:
/* 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 variabledeclaration 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 following example illustrates scope by using local and persistent variables:
Persist ( x := "This is persistent variable x" )
CreateOutline()
Understanding macro concepts17
// 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! ) )
18Understanding 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 concepts19
// 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
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
20Understanding 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:
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 onedimensional array that contains five elements:
•
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.
22Understanding 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 concepts23
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
24Understanding 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 concepts25
OperatorActionExample 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.
26Understanding 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.
OperatorActionExample 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.
OperatorActionExample 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 concepts27
OperatorActionExample and result
%
MOD
DIV
**
Floating point modulus division
— returns remainder of floatingpoint 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.
28Understanding macro concepts
OperatorActionExample 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 concepts29
OperatorActionExample 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
30Understanding macro concepts
OperatorActionExample 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 concepts31
OperatorActionExample 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
32Understanding macro concepts
OperatorActionExample 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 ExampleResult
x := 5
y := (x<10)
z := NOT(x<10)
Understanding macro concepts33
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 ExampleResult
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 ExampleResult
x := 1
y := 2
If ((x = 0) XOR (y = 2))
Beep
EndIf
34Understanding 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.
OperatorActionExample 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 concepts35
OperatorActionExample 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
36Understanding macro concepts
OperatorActionExample 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 concepts37
OperatorActionExample 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 levelOperators
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 (
+)
-)
<)
>)
<)
>)
38Understanding macro concepts
Precedence levelOperators
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.
ExampleResult
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 concepts39
ExampleResult
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.
+),
40Understanding 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
ExampleExplanation
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 5Note: 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 measurementIdentifier
Inches
Centimeters
Millimeters
Understanding macro concepts41
" or i
c
m
Unit of measurementIdentifier
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.
ExampleExplanation
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
42Understanding macro concepts
A through F.
The available radix choices, and their associated identifiers, are as follows.
RadixIdentifier
16 (hexadecimal system)
8 (octal system)
2 (binary system)
x or h
o
b
The following examples are valid radix expressions.
ExampleResult
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.
ExampleResult
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 concepts43
ExampleResult
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.
ExampleExplanation
"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.
ExampleResult
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)
44Understanding 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.
ExampleResult
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
ExampleResult
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.
ExampleResult
w := (x < y)
w equals False (becuase uppercase A is less
than, or comes before, uppercase B)
Understanding macro concepts45
ExampleResult
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.
ExampleResult
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.
46Understanding macro concepts
Bitwise operatorExample 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 concepts47
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
48Understanding 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 concepts49
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.
50Understanding 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:
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:
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.
52Understanding 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 concepts53
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
54Understanding 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 concepts55
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
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):
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 concepts57
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)
58Understanding 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 concepts59
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.
60Understanding 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 concepts61
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.
62Understanding 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 concepts63
"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 )
64Understanding 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 +".")
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.
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.
66Understanding 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 concepts67
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:
68Understanding 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! )
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 concepts69
EndProc or
EndProcedure keyword. The contents of the subroutine are placed between the
Procedure and EndProcedure commands. If a procedure requires parameters, the
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)
70Understanding 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 concepts71
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:
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
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 concepts73
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
74Understanding 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 concepts75
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
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.
76Understanding 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 concepts77
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 nonprefixed 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
78Understanding 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 WithEndWith 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 concepts79
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.
80Understanding 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 concepts81
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.
82Understanding 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 macros83
• 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.
84Getting 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 macros85
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.
86Getting 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 macros87
88Getting 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 macros89
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.
90Creating 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 macrocompilation errors” on page 97.
Creating macros91
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.
92Creating 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 macros93
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:
However, you can type spaces between components and blank lines between tasks, as
follows:
PosDocBottom()
Type ("Sincerely")
HardReturn()
94Creating 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 macros95
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.
96Creating macros
Loading...
+ hidden pages
You need points to download manuals.
1 point = 1 manual.
You can buy points or you can get point for every manual you upload.