Your programming knowledge should help you learn to automate the software, regardless of your level of experience with Microsoft Visual Basic for Applications (VBA) or Microsoft Visual Studio Tools for Applications (VSTA).
The Script Editor formats all VBA coding for you (see Formatting code automatically). The only way to customize the formatting is to change the size of the indentations.
VBA can be used to create object-oriented classes. However, this function is a feature of the programming language and is therefore not discussed in detail in this documentation.
In VBA, the construction for declaring variables is as follows:
Dim foobar As Integer
The built-in data types are Byte, Boolean, Integer, Long, Single, Double, String, Variant, and several other less-used types including Date, Decimal, and Object.
Byte
Boolean
Integer
Long
Single
Double
String
Variant
Date
Decimal
Object
Variables can be declared anywhere within the body of a function, or at the top of the current module. However, it is generally a good idea to declare a variable before it is used; otherwise, the compiler interprets it as a Variant, and inefficiencies can be incurred at run time.
Booleans take False to be 0 and True to be any other value, although converting from a Boolean to a Long results in True being converted to a value of –1.
False
0
True
–1
To get more information about one of the built-in data types, type it in the Code window of the Macro Editor, select it, and then press F1.
Data structures can be built by using the following VBA syntax:
Public Type fooType item1 As Integer item2 As String End Type Dim myTypedItem as fooType myTypedItem.item1 = 5
Declaring strings
Using strings is much simpler in VBA than in C. In VBA, strings can be added together, truncated, searched forwards and backwards, and passed as simple arguments to functions.
To add two strings together in VBA, simply use the concatenation operator ( & ) or the addition operator ( + ):
&
+
Dim string1 As String, string2 As String string2 = string1 & " more text" + " even more text"
In VBA, there are many functions for manipulating strings, including InStr(), Left(), Mid(), Right(), Len(), and Trim().
InStr()
Left()
Mid()
Right()
Len()
Trim()
Declaring enumerations
To declare an enumeration in VBA, use the following construction:
Public Enum fooEnum ItemOne ItemTwo ItemThree End Enum
By default, the first item in an enumerated type is assigned a value of 0.
Declaring arrays
To declare an array in VBA, use parentheses — that is, the ( and ) symbols:
(
)
Dim barArray (4) As Integer
The value defines the index of the last item in the array. Because array indexes are zero-based by default, there are five elements in the preceding sample array (that is, elements 0 thru 4, inclusive).
4
Arrays can be resized by using ReDim. For example, the following VBA code adds an extra element to barArray but preserves the existing contents of the original five elements:
ReDim
barArray
ReDim Preserve barArray (6)
Upper and lower bounds for an array can be determined at run time by using the functions UBound() and LBound().
UBound()
LBound()
Multidimensional arrays can be declared by separating the dimension indexes with commas, as in the following VBA example:
Dim barArray (4, 3)
VBA uses both functions and subroutines (or "subs"). Functions can be used to return a value, but subs cannot.
In VBA, functions and subs do not need to be declared before they are used, nor before they are defined. In fact, functions and subs need to be declared only if they actually exist in external system DLLs.
Typical functions in a language such as Java or C++ can be structured as follows:
void foo(string stringItem) { // The body of the function goes here }
double bar(int numItem) { return 23.2; }
In VBA, however, functions are structured as in the following example:
Public Sub foo (stringItem as String) ' The body of the subroutine goes here End Sub
Public Function bar (numItem as Integer) as Double bar = 23.2 End Function
To force a function or sub to exit immediately, you can use Exit Function or Exit Sub (respectively).
Exit Function
Exit Sub
In VBA, each statement must exist on its own line, but no special character is required to denote the end of each line. (In contrast, many other programming languages use a semicolon to separate individual statements.)
To break a long VBA statement over two or more lines, each of the lines (other than the last line) must end with an underscore ( _ ) preceded by at least one space:
_
newString = fooFunction ("This is a string", _ 5, 10, 2)
You can combine several statements in a single VBA line by separating them with colons:
a = 1 : b = 2 : c = a + b
A VBA line cannot end with a colon. VBA lines that end with a colon are labels that are used by the Goto statement.
Goto
Comments in VBA — similarly to in ANSI, C++, and Java — can be created only at the end of a line. Comments begin with an apostrophe ( ' ) and terminate at the end of the line.
'
Each line of a multi-line comment must begin with its own apostrophe in VBA:
a = b ' This is a really interesting piece of code that ' requires so much explanation that I needed to break ' the comment over multiple lines.
To comment out large sections of VBA code, use the following syntax (similarly to in C or C++):
#If 0 Then ' That's a zero, not the letter 'oh'. ' All this code will be ignored by ' the compiler at run time! #End If
VBA does not support C-style memory pointers. Memory allocation and garbage collection are automatic and transparent, just as in Java and JavaScript (and some C++ code).
Passing arguments
Most languages, including C++ and Java, pass an argument to a procedure as a copy of the original. If the original must be passed, then one of two things can happen:
Microsoft Visual Basic (VB) has the same requirements for passing arguments. In VB, passing a copy of the original argument is called "passing by value" and passing a reference to the original is called "passing by reference."
By default, function and subroutine parameters are passed by reference. A reference to the original variable is passed in the argument of the procedure; changing the value of that argument, in effect, changes the value of the original variable value as well. In this way, more than one value can be returned from a function or subroutine. To explicitly annotate the code to indicate that an argument is being passed by reference, you can prefix the argument with ByRef.
ByRef
If you want to prevent a procedure from changing the value of the original variable, you can force the copying of an argument. To do this in VBA, prefix the argument with ByVal, as shown in the example that follows. The functionality of ByRef and ByVal is similar to the ability of C and C++ to pass a copy of a variable, or to pass a pointer to the original variable.
ByVal
Private Sub fooFunc (ByVal int1 As Integer, _ ByRef long1 As Long, _ long2 As Long) ' Passed ByRef by default
In the preceding VBA example, arguments long1 and long2 are both, by default, passed by reference. Modifying either argument within the body of the function modifies the original variable; however, modifying int1 does not modify the original because it is a copy of the original.
You can define the scope of a data type or procedure (or even an object). Data types, functions, and subroutines (and members of classes) that are declared as private are visible only within that module (or file). By contrast, functions that are declared as public are visible throughout all the modules; however, you may need to use fully qualified referencing if the modules are almost out of scope — for example, if you are referencing a function in a different project.
Unlike C, VBA does not use braces — that is, the { and } symbols — to define local scope. Local scope in VBA is defined by an opening function or subroutine definition statement (that is, Function or Sub) and a matching End statement (that is, End Function or End Sub). Any variables declared within the function are available only within the scope of the function itself.
{
}
Function
Sub
End
End Function
End Sub
In Microsoft Visual Basic (VB), Boolean comparison and Boolean assignment are both performed by using a single equals sign ( = ):
=
If a = b Then c = d
By contrast, many other languages use a double equals sign for Boolean comparison and a single equals sign for Boolean assignment:
if( a == b ) c = d;
The following code, which is valid in C, C++, Java, and JavaScript, is invalid in VBA:
if( ( result = fooBar( ) ) == true )
The preceding example would be written in VBA as the following:
result = fooBar( ) If result = True Then
For other Boolean comparisons, VBA uses the same operators as other languages (except for the operators for "is equal to" and "is not equal to"). All the Boolean-comparison operators are provided in the following table.
==
<>
!=
>
<
>=
<=
The result of using a Boolean operator is always either True or False.
In VBA, logical operations are performed by using the keywords And, Not, Or, Xor, Imp, and Eqv, which perform the logical operations AND, NOT, OR, Exclusive-OR, logical implication, and logical equivalence (respectively). These operators also perform Boolean comparisons.
And
Not
Or
Xor
Imp
Eqv
The following code shows a comparison written in C or a similar language:
if( ( a && b ) || ( c && d ) )
This example would be written as follows in VBA:
If ( a And b ) Or ( c And d ) Then
Alternatively, the preceding VBA code could be written in the following full long-hand form:
If ( a And b = True ) Or ( c And d = True ) = True Then
The following table provides a comparison of the four common VBA logical and bitwise operators, and the C-style logical and bitwise operators that are used by C, C++, Java, and JavaScript.
&&
~
!
|
||
^
In VBA, you can present simple messages to the user by using the MsgBox function:
Dim retval As Long retval = MsgBox("Click OK if you agree.", _ vbOKCancel, "Easy Message") If retval = vbOK Then MsgBox "You clicked OK.", vbOK, "Affirmative" End If
You can also get strings from the user by using InputBox function:
Dim inText As String inText = InputBox("Input some text:", "type here") If Len(inText) > 0 Then MsgBox "You typed the following: " & inText & "." End If
If the user clicks Cancel, the length of the string returned in inText is zero.
inText
For information on creating more complex user interfaces, see Making macros user-friendly.
If you want to create a reference to an object so that you can treat that reference like a variable (sh, in the following VBA example for Corel DESIGNER and CorelDRAW), you can use the Set keyword.
sh
Set
Dim sh As Shape Set sh = ActiveSelection.Shapes.Item(1)
After you create this reference, you can treat it as though it were the object itself.
sh.Outline.Color.GrayAssign 35
If the selection is changed while sh is still in scope, sh references the original shape from the old selection and is unaffected by the new selection. You cannot simply assign the object to the variable as in the following example:
Dim sh As Shape sh = ActiveSelection.Shapes.Item(1)
To release an object, you must set its reference value to Nothing.
Set sh = Nothing
You can also test whether a variable references a valid object by using the Nothing keyword.
Nothing
If sh Is Nothing Then MsgBox "sh is de-referenced."
Objects do not need to be explicitly released. In most cases, VB releases the object upon disposal of the variable when you exit the function or subroutine.
Many objects are members of collections. A collection is similar to an array, except that it contains objects rather than values. However, members of collections can be accessed in the same way as arrays. For example, a collection that is used frequently in Corel DESIGNER and CorelDRAW is the collection of shapes on a layer: The object ActiveLayer references either the current layer or the layer that is selected in the Object Manager docker.
ActiveLayer
Corel DESIGNER and CorelDRAW contain many collections: A document contains pages, a page contains layers, a layer contains shapes, a curve contains subpaths, a subpath contains segments and nodes, a text range contains lines and words, a group contains shapes, and the application contains windows. All these collections are handled by VBA in the same way.
Referencing collection items
To reference the shapes on a layer, the collection of shapes for that layer is used: ActiveLayer.Shapes. To reference the individual shapes in the collection, the Item() property is used. Here is a VBA example for Corel DESIGNER and CorelDRAW:
ActiveLayer.Shapes
Item()
Dim sh As Shape Set sh = ActiveLayer.Shapes.Item(1)
Most elements of a collection start at 1 and increase. For the collection ActiveLayer.Shapes, Item(1) is the item at the "top" or "front" of the layer — in other words, it is the item that is in front of all other shapes. Furthermore, because each item in the ActiveLayer collection is an object of type Shape, you can reference any item in VBA merely by appending the appropriate dot-notated member:
1
Item(1)
Shape
ActiveLayer.Shapes.Item(1).Outline.ConvertToObject
Sometimes, individual items have names. If the item you are looking for has an associated name (and you know what the name is and which collection the item is in), you can use that name to reference the item directly, as in the following VBA example for Corel DESIGNER and CorelDRAW:
Dim sh1 As Shape, sh2 As Shape Set sh1 = ActiveLayer.CreateRectangle(0, 5, 7, 0) sh1.Name = "myShape" Set sh2 = ActiveLayer.Shapes.Item("myShape")
Also, because an item is usually the implied or default member of a collection, it is not strictly required. For this reason, the last line of the preceding VBA code can be rewritten as follows:
Set sh2 = ActiveLayer.Shapes("myShape")
Counting collection items
All collections have a property called Count. This read-only property gives the number of members in the collection, as in the following VBA example for Corel DESIGNER and CorelDRAW:
Count
Dim count As Long count = ActiveLayer.Shapes.Count
The returned value is not only the number of items in the collection: Because the collection starts from 1, it is also the index of the last item.
Parsing collection items
It is often necessary to parse through the members of a collection to check or change the properties of each item.
By using the Item() and Count members, it is straightforward to step through a collection of items. With each iteration, it is possible to test the properties of the current item, or to call its methods. The following VBA code for Corel DESIGNER and CorelDRAW restricts all shapes on the layer to no wider than ten units:
Dim I As Long, count As Long count = ActiveLayer.Shapes.Count For I = 1 to count If ActiveLayer.Shapes.Item(i).SizeWidth > 10 Then ActiveLayer.Shapes.Item(i).SizeWidth = 10 End If Next I
There is, however, a more convenient way of parsing a collection in VBA. Instead of using the Count property and a For-Next loop, this technique uses a For-Each-In loop:
Dim sh As Shape For Each sh In ActiveLayer.Shapes If sh.SizeWidth > 10 Then sh.SizeWidth = 10 End If Next sh
If you want to copy the selection and then parse it later when it is no longer selected, copy the selection into a ShapeRange object:
ShapeRange
Dim sr As ShapeRange Dim sh As Shape Set sr = ActiveSelectionRange For Each sh In sr ' Do something with each shape Next sh
Shortcuts are provided for some frequently accessed objects. Using shortcuts requires less typing, so shortcuts are easier to use than their longhand versions. (Also, using shortcuts can improve run-time performance because the compiler does not need to determine every object in a long dot-separated reference.)
For Corel DESIGNER and CorelDRAW, a shortcut can be used on its own as a property of the Application object. The following table provides these shortcuts and their long forms. (For a description of any item, see the API section for Corel DESIGNER and CorelDRAW.)
For Corel PHOTO-PAINT, a shortcut can be used on its own as a property of the Corel PHOTO-PAINT Application object. The following table provides these shortcuts and their long forms. (For a description of any item, see the API section.)
For Corel DESIGNER and CorelDRAW, the following shortcuts can also be used as members of a given Document object:
Document
For Corel PHOTO-PAINT, the following shortcuts can also be used as members of a given Document object:
ForCorel DESIGNER and CorelDRAW, the Document object also has the properties Selection and SelectionRange, which let you get the selection or selection range (respectively) from a specified document regardless of whether that document is active.
Selection
SelectionRange
While running, Corel DESIGNER, CorelDRAW, and Corel PHOTO-PAINT raise various events to which macros can respond through the use of event handlers — subroutines with specific, defined names. Each macro project defines its event handlers in one of the following code modules:
The GlobalMacroStorage object is a virtual object that represents each and all open documents. The GlobalMacroStorage object has several events that are raised at the time of any event, such as opening, printing, saving, or closing a document (although the range of events is actually greater than this because each one has a "before" and "after" event).
To respond to an event, you must provide an event handler — a subroutine in any ThisMacroStorage module with a specific name for which the application is pre-programmed to search. However, the application does check all ThisMacroStorage modules in all installed projects; for this reason, you can create an event-driven solution and distribute it as a single project file just as you would provide any other solution. Each project can have only one ThisMacroStorage module, and it is automatically created when the project is first created.
In VBA, you can add event handlers to a ThisMacroStorage module by using the Macro Editor. For example, aCorel DESIGNER or CorelDRAW macro solution may need to respond to the closing of a document by logging the closure in a file as part of a workflow-management system. To respond to the opening of a document, the solution must respond to the OpenDocument event for the GlobalMacroStorage class. To create this event handler in VBA, do the following:
OpenDocument
GlobalMacroStorage
The Macro Editor creates a new, empty subroutine called GlobalMacroStorage_DocumentOpen()— or, if that subroutine already exists, the Macro Editor places the cursor into it. To then add the name of the opened file to the log, you need only write some code. To reduce the size of the ThisMacroStorage module, you can assign this event-logging task to a public subroutine in another module. This technique lets the run-time interpreter more easily parse all the ThisMacroStorage modules each time an event is raised. The following VBA code illustrates this example for Corel DESIGNER and CorelDRAW:
GlobalMacroStorage_DocumentOpen()
Private Sub GlobalMacroStorage_OpenDocument(ByVal Doc As Document, _ ByVal FileName As String) Call LogFileOpen(FileName) End Sub
Here is a small sample of the events available in Corel DESIGNER and CorelDRAW:
Event handlers for frequent events — such as events related to the Shape class — should be as efficient as possible, to keep the application running as quickly as possible.