CorelDraw & VBA
Back to the Main Menu
VBA Introduction
Artistic Text
Paragraph Text
Finding & Changing Text
Opening Other Applications
User Interface
Event Programming
Storing User Data
Error Handling
Speeding Up CorelDraw
CQL
VBA Security
 
Guide to CorelDraw VBA


VBA Introduction

VBA is an abbreviation but its full name is Visual Basic for Application. It is a computer language to control a computer's applications.
It is a self contained branch of VB (Visual Basic). VB is independent of applications whereas VBA is always attached to applications.
If the VBA code is written in CorelDraw then CorelDraw must be open to run the VBA code.

VBA and VB can interact but here we will confine ourselves to VBA.

VBA is included in the following applications;

CorelDraw 9 through to X7
Microsoft Excel
Microsoft Word
Microsoft Access
Microsoft PowerPoint
Microsoft Outlook
Microsoft Publisher
Microsoft Visio
AutoCAD


VBA can also control, to some extent, other applications but it can be limited or much more difficult. Such applications are;

Adobe Acrobat
Adobe Illustrator
Adobe In-Design
Adobe Photo-Shop
CuteFTP
DOS applications
Internet Explorer
mailSend
Microsoft Windows
Stroke Scribe


There is also a lot of other programs mainly created by Microsoft that allows VBA to to read, set, alter or run programs, files and web pages.

CDDBControl 1.0 Type Library
jscript.dll
Microsoft Forms Object 2.0 Library
Microsoft Forms Object Model
Microsoft Graph 14.0 Object Library
Microsoft HTML Object Library
Microsoft Internet Tools
Microsoft Office 15.0 Object Library
Microsoft Script Control 1.0
Microsoft Scripting Runtime
Microsoft VBScript Regular Expressions 5.5
Microsoft Windows Common Controls 6.0
Microsoft WinHTTP Services v5.1
Microsoft WMI Scripting V1.2 Library
Microsoft XML, v6.0
mscomct2.ocx
RegObj.dl
shell32.dll
VBE
Windows API Functions
Windows Script Host Object Model


Using VBE it is possible to have VBA code create new VBA code and if required run that code automatically.

It can also be possible to convert some VBA code to VBS (Visual Basic Script) (.vbs) files.
A VBS file can be converted to an exe file that does not need a VBA compatible program to run.


The CorelDraw VBA Editor

All VBA code is accessed via the VBA Editor. Each application that fully supports VBA has its own VBA Editor but all of the editors are very similar.

Open a new CorelDraw document.
Press the 2 buttons Alt+F11 or alternatively select Tools on the main toolbar then Macros, then Visual Basic Editor.
The VBA Editor will now open.



The view above shows how the Corel VBA Editor looks the first time it is opened. Three sub windows will be visible. Two smaller windows one above the other will be on the left and the third window will be on the right. The window on the left on top is the "Project" window, below it is the "Properties Window". The large window is for the code.

Notice the red circle. On this line you can adjust the width of the Code window. Also by selecting the line between the "Project" and "Properties" windows you can alter the vertical size of these windows. Should the Project or Properties windows not be displayed then they can be redisplayed using the View button in the toolbar and selecting the window you wish to display. These windows can be relocated to other locations on the screen such as on the right hand side.

There are other windows which can also be selected via View. These are "Immediate Window", "Locals Window" and "Watch Window".

The VBA code files you create can be selected in the "Projects" window. There are at least 2 folders where code files can be stored. They are the "GlobalMacros" folder and the VBA Project folder. The "GlobalMacros" folder is where code can be stored so that is is available to be run when ever CorelDraw is opened. It does not require a particular corel document to be open. The "VBAProject(Graphic1)" is this current unsaved document you have open. Once saved the "Graphic1" will change to the saved file name. If you save code in the VBAProject folder then you are saving the code inside the currently opened corel file and so it is only available when this particular corel file is open.

The Code Window has the headings "(General)" on the left and "(Declarations)" on the right. The code window is where the opened code file can be written and read.

"Option Explicit" should be at the top of the code in every code window. You can type it but it can automatically appear by default. To make it appear by default within Tool on the main toolbar in the VBA window select Options and then select "Require Variable Declaration". It is not absolutely necessary, but it will reduce the number of errors you make and whilst you write code the VBA Editor will help you by providing list boxes of possible methods and properties. "Option Explicit" means that if you create any names, otherwise known as variables, to represent something such as a shape, e.g. "BIG_RECTANGLE", you must specify that it is a shape.
This would be written as;

Dim BIG_RECTANGLE as Shape

You should not let the program wait until the name is first used for it to guess that it is a shape and not the size or color of the rectangle etc. By explicitly defining what the variable represents then the VBA Editor will prompt you with suggestions as you write your code.


An Example Of Automation

For this example we will let CorelDraw record what we do so that it can be repeated later. Now get out of the VBA editor and go back to CorelDraw. Select CorelDraw from the TaskBar at the bottom of the screen, or press Alt+F11 or View in the toolbar then CorelDraw in the drop down. Alt+F11 alternates between the CorelDraw VBA Editor and CorelDraw.

We will store the code in this document. Click the small plus sign to the immediate left of the text "VBAProject". This will expand to reveal another folder "CorelDraw X4 Object." Expand further to reveal another folder called "ThisDocument" Now double click "ThisDocument". The large Code window will change to an empty window with only "Option Explicit" at the top.

Back in CorelDraw in the Toolbar select Tools - Macros - Start Recording. A dialog box will appear. This dialog box varies for each version of CorelDraw. However, Leave the default name, it is often Macro1, but click "VBAProject" to save the macro in this document. You can select "GlobalMacros" if you wish. Saving in "GlobalMacros" makes your code available in every CorelDraw document opened on your computer.

Now many of the thing you do in CorelDraw will be recorded as VBA code until you turn-off the Macro Recorder.

Draw a rectangle on the page.
Now fill the rectangle with a uniform fill, CMYK red color where C=0, M=70, Y=90 and K=0.
Now stop recording by going to Tools - Macros - Stop Recording.

Now press Alt+F11 to go back to the VBA Editor. In the Project window on the left there will be several entries. Usually about four with plus signs beside them to indicate they can be expanded. Double click "VBAProject". It will expand to show something like "CorelDrawObjects" and "Modules". Double click "Modules" to further expand it. There will now be a line "RecordedMacros". Double click "RecordedMacros" and your recorded code will appear in the code window on the left of the screen. Your code should be similar to that below although the numbers in the code will be different as your rectangle size and position will not be the same as mine.


Sub Macro1()
    ' Recorded 08/07/16
    Dim s1 As Shape
    Set s1 = ActiveLayer.CreateRectangle(1.289362, 4.300362, 3.035772, 2.09526)
    s1.Fill.ApplyNoFill
    s1.Outline.SetProperties 0.007874, OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100), ArrowHeads(0), ArrowHeads(0), cdrFalse, cdrFalse, cdrOutlineButtLineCaps, cdrOutlineMiterLineJoin, 0#, 100, MiterLimit:=5#
    s1.Fill.UniformColor.CMYKAssign 0, 70, 90, 0
End Sub



The Project window on the left displays all the CorelDraw macros installed on your computer plus any you have written or recorded. For this particular document its macros are stored in "VBAProject". "VBAProject" is divided into "CorelDraw Objects" and Modules. There is only one this "CorelDraw Object" and it is "ThisDocument".

ThisDocument
"ThisDocument" is where the code is stored that only manipulates and alters the CorelDraw pages in the this document. It cannot contain code that will manipulate other CorelDraw documents or other files, folders, computers or applications etc. Any code in "ThisDocument" does not have to explicitly refer to which document it is altering since it cannot alter any other document. Note that each opened CorelDraw document will have its own ThisDocument.

Modules
This folder can contain as many modules as you wish. Modules contain code that can alter any CorelDraw document, files, folders, computer or applications etc. To alter a document you must refer to which object or document you mean. In the example above it refers to the ActiveLayer. Since you have an active CorelDraw document open it must be its active layer but the line  Set s1 = ActiveLayer.CreateRectangle............  could have been written

Set s1 = Documents(1).Pages(1).Layers(1).CreateRectangle(1.289362, 4.300362, 3.035772, 2.09526)

The default name of a recorded macro is RecordedMacros. If you insert a blank module in Project Window the default names of the modules are Module1, Module2 etc. Module names can be altered in the Properties Window to something more meaning-full. Select the module in the Project Window then alter the name in the Properties Window beside where is says (Name).

Sub Macro1() is the start of the code known as a sub-routine and it has the name in this instance of Macro1. The name can be changed to something more meaningful and has the same naming rules as variables, see NAMING VARIABLE below. Sub-routines all end with an opening and closing bracket.

' Recorded 08/07/16 This is a comment and is there for clarification. A comment starts with an apostrophe. Anything on the same line after an apostrophe is a comment and is not code. A comment can be on the same line as code but must be after this code. If you are keeping the code it is a good idea to supply plenty of comments through-out your code so as to remind you in months or years time what you are doing at each stage of the code.
Blank lines have no effect to the code but can break-up the code into sections and so make understanding easier.
Indenting code is another way of helping to understand the code. The start and finish of code-loops should have equal indentation and that in between indented further. The easiest way to indent is to use the tab key.

Unlike algebra an equal sign "=" has a different meaning in computer programming.
In algebra the equal sign means that both sides of the equation equal each other.
In computer programming the equal sign is a command.
The left hand side is always only 1 variable and not a mathematical formula.
The equal sign specifies that the left hand side variable represents the object/s or value on the right hand side.
As a result the following is acceptable in programming but not in algebra.
    X = X + 1
If initially the variable X equalled 3 then the line of code above would increase the value of X to 4.

Set means that the s1 it going to represent something, an object or objects, that has multiple properties or in other words multiple values. It is not only a rectangle but s1 represents values for width, height, color, position, line thickness etc. If s1 had been only the rectangle width then the use of the word Set would not be required.

s1 is the shape object. For clarity it is a good idea to rename this variable to something more meaningful such as SHAPE1 or SHAP or shRECT or shRect etc.

Documents(1) means the first document you have open.

Pages(1) means the first page of the document.

Layers(1) means the first layer.

End Sub() is the end of the sub-routine Macro1. A new sub-routine could follow and it would begin with Sub MACRO_NAME() and also end with End Sub.


The numbers after inside the brackets after the word CreateRectangle represent the size and position of the rectangle on the page in inches. To determine what number is what use your mouse to select the first bracket and retype the bracket. In yellow a prompt will appear explaining what the numbers mean.


Naming Variables

Variable names are not case sensitive but the capitalisation is preserved. They must start with a letter and not a number and can be a total of up to 255 characters long. You can't use a space, full-stop (.), comma (,), exclamation mark (!), apostrophe ('), or the characters @, &, $, # in the name but you can use the under-score character (_). The under-score character is handy to separate words in a variable name to make the variable easier to read.

Try to avoid variable names that are pre-defined by VBA.
e.g. Dim SHAPE As SHAPE
It is clearer to name the object by another name. e.g. SHAPE1, SH or shRECTANGLE etc.

Many people writing code use the first 1 or 3 characters in each variable name to indicate the type of variable.
e.g. intLENGTH as an integer. Here are some common prefixes.

Variable Type Prefixes Range
Byte byt 0 to 255
Integer int -32,768 to 32,767
Long lng or l -2,147,483,648 to 2,147,483,647
LongLong llng or ll Only avaiable in 64 bit applications.
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
LongPtr llng or ll Range varies on depending on the application.
In a 32 bit applicataion it is the same as Long.
In a 64 bit application it is the same as LongLong.
Single sng -3.402823E38 to -1.401298E-45 for negative values;
1.401298E-45 to 3.402823E38 for positive values
Double dbl -1.79769313486231E308 to -4.94065645841247E-324 for negative values;
4.94065645841247E-324 to 1.79769313486232E308 for positive values
Currency cur or ccy -922,337,203,685,477.5808 to 922,337,203,685,477.5807
String str 0 to approximately 2 billion characters
Variant var Any numeric value up to the range of a Double or for a string 2 billion characters
Date dat or dte January 1, 100 to December 31, 9999
Boolean bln or b True or False
Object obj
Hyperlink hyp
Shape sh

Most people do not bother with Bytes, Singles, Currency and Decimal. Integer, Long & Double are the most commonly used number types.

Now lets run this macro. Select Alt-F11 to go back to the CorelDraw document. Delete the rectangle. Now select Tools - Macros - Run Macros. Select Macro1 and then select Run. A rectangle will now appear on the document.

Below the macro "Sub Macro1()" enter some blank lines by pressing Enter repeatedly. Blank lines have no meaning so they can be added in most places without effecting the running of code but make the code easier to read. Now copy and paste the macro EXAMPLE below.

This new macro does what the first macro does but is easier to read. Recording a macro gives you some initial code from which to build further.

In the example below all the code has been indented between the opening and closing of the macro. This makes it easier to understand.

The rectangle dimensions have been simplified but you can still specify a location to 6 decimal places if you wish. Also we have relied on the default settings for arrow heads etc and so have not specified as many variables in the line SHAP.Outline.SetProperties (0.008), OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100) in the example above.


Sub EXAMPLE()
    Dim SHAP As Shape
    Set SHAP = ActiveLayer.CreateRectangle(1, 4, 3, 2)
    SHAP.Outline.SetProperties (0.008), OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100)
    SHAP.Fill.UniformColor.CMYKAssign 0, 70, 90, 0
End Sub



We can now independently run each macro. Now when you go into Tools - Macros - Run Macro you will have a choice of macros to run.

Play around with the code. Change the CMYK values to change the colors, change the rectangle size and position.

In the macro EXAMPLE at the end of the code, before the line End Sub, on a new line, add the word Macro1. This will cause the macro EXAMPLE to branch to Macro1 just before it ends. The macro Macro1 will then run and then the code procedure will return to EXAMPLE to finally finish. It will create two rectangles. To run the two macros together you need only start EXAMPLE.

Your code will be similar to this.

Option Explicit

Sub Macro1()
    ' Recorded 08/07/16
    Dim s1 As Shape
    Set s1 = ActiveLayer.CreateRectangle(1.289362, 4.300362, 3.035772, 2.09526)
    s1.Fill.ApplyNoFill
    s1.Outline.SetProperties 0.007874, OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100), ArrowHeads(0), ArrowHeads(0), cdrFalse, cdrFalse, cdrOutlineButtLineCaps, cdrOutlineMiterLineJoin, 0#, 100, MiterLimit:=5#
    s1.Fill.UniformColor.CMYKAssign 0, 70, 90, 0
End Sub


Sub EXAMPLE()
    Dim SHAP As Shape
    Set SHAP = ActiveLayer.CreateRectangle(1, 4, 3, 2)
    SHAP.Outline.SetProperties (0.008), OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100)
    SHAP.Fill.UniformColor.CMYKAssign 0, 70, 90, 0
    Macro1  'This automatically runs the macro Macro1.
End Sub




Calculations Involving Mixed Variable Types

Be very, very careful multiplying, add etc variables where there are mixed variable types and expecting the answer in another number type.

Multiplying integers where the result is to be long still is limited by the maximum size of an integer. ie 32,767. Multiplying an integer by a long number will create a long number.

It is best to convert numbers to other number types before or as they are calculated.
ie CLng(expression) will convert a number variable to long.


Memory Problems with the Use of Set

Every time you use Set such as Set object = ..... memory is allocated. This memory will not be automatically released when the code has run or even when the application such as CorelDraw has closed. It will be released when the computer restarts. In code where there is loop and Set is within the loop additional memory will be consumed every time Set is encountered even though you are setting the same variable toa different or the same object. If you loop enough times the code will eventually fail. To avoid this when finished with an object
       Set object = Nothing
will release the memory. This means that if there are any Sets within loop you need to Set object = Nothing within the same loop. There should be at least as many Set object = Nothing as Set object = .......

Here is the same code above but corrected for memory loss.

Option Explicit

Sub Macro1()
    ' Recorded 08/07/16
    Dim s1 As Shape
    Set s1 = ActiveLayer.CreateRectangle(1.289362, 4.300362, 3.035772, 2.09526)
    s1.Fill.ApplyNoFill
    s1.Outline.SetProperties 0.007874, OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100), ArrowHeads(0), ArrowHeads(0), cdrFalse, cdrFalse, cdrOutlineButtLineCaps, cdrOutlineMiterLineJoin, 0#, 100, MiterLimit:=5#
    s1.Fill.UniformColor.CMYKAssign 0, 70, 90, 0
    Set s1 = Nothing
End Sub



Here is the same code simplified further.
CorelDraw measures distances in inches.
I have removed the fractions from the dimensions.


Sub EXAMPLE()
    Dim SHAP As Shape
    Set SHAP = ActiveLayer.CreateRectangle(1, 4, 3, 2)
    SHAP.Outline.SetProperties (0.008), OutlineStyles(0), CreateCMYKColor(0, 0, 0, 100)
    SHAP.Fill.UniformColor.CMYKAssign 0, 70, 90, 0
    Macro1  'This automatically runs the macro Macro1.
    Set SHAP = Nothing
End Sub



Below is some code that will create 3 rectangles in various positions of different colors. It shows a loop, the use of Set within a loop and the use of a variable, in this case COUNTER to vary position and color.

The loop here is a While loop. While the variable COUNTER is less than or equal to 3 the code between While and Wend will repeat indefinitely. Notice the line COUNTER = COUNTER + 1 In mathematics this cannot be but in programming it means that the variable on the left takes on a new value that on the right. In this case it COUNTER increases by 1 each time the loop occurs.

When COUNTER is greater than 3 then the code below the Wend will occur. In this case the code ends.

Sub TEST()
    Dim shRECT As Shape
    Dim COUNTER As Integer
    Dim No_SHAPES As Integer

    COUNTER = 1
    While COUNTER <= 3
      Set shRECT = ThisDocument.ActivePage.ActiveLayer.CreateRectangle(1, COUNTER * 2, 5, COUNTER * 2 - 1)
      shRECT.Fill.UniformColor.RGBAssign 0, 255 - COUNTER * 40, 0
      Set shRECT = Nothing
      COUNTER = COUNTER + 1
    Wend
End Sub


In situations where you have an Exit or End within an "If" statement your code may leave the procedure without encountering a "Set =......... Nothing". In these cases place an additional "Set =......... Nothing" within the "If" statement.


Functions

The built-in function CreateRectangle in the example above has brackets around the arguments.
The order of the arguments is naturally important. In this case they are Left, Top, Right and Bottom.
eg
Set SHAP = ActiveLayer.CreateRectangle(1, 4, 3, 2)
You do not use brackets if a function does not equal a variable.
eg
ActiveLayer.CreateRectangle 1, 4, 3, 2

Typing the brackets during coding is useful to get the intellisense tips but them remove the brackets if the function does not equal a variable.

If you wish to vary the argument order you can specifically specify the arguments in any order by using ":="
eg
ActiveLayer.CreateRectangle Right:=3, Top:=4, Bottom:=2, Left:=1


CorelDraw's in-built VBA functions use imperial measurements ie inches. To convert mm to inches divide by 25.4

You can create your own functions. These return a value.

Here is a simple example of a user created function. Place the following in a Module and run TEST.

Sub TEST()
    MsgBox "The area of a 30.5mm x 80mm rectangle in inches² = " & dblInches(30.5) * dblInches(80), , "Example"
End Sub

Function dblInches(dblLength As Double) As Double
    dblInches = dblLength / 25.4
End Function


When you run the macro TEST it will create a message box.
When the code encounters dblInches(30.5) the code diverts to the user function dblInches(dblLength As Double) As Double.
The function requires a number that is of the double type.
In this case it is 30.5
The function divides the number it is given by 25.4 and equates the answer 1.18110236220472 to the function variable dblInches.
The procedure then returns to the original TEST macro but again returns to the function dblInches to convert 80mm to inches.
The result of multiplying the inch values together is displayed in a message box.

Msgbox is a VBA built-in function.
Msgbox(Message, [Button Style], [Title], [Help File, Context])
The square brackets [ ] indicate that that between is optionally required.
If a Help File, a chm file, is specified a Context must also be specified such as 0.
Don't bother with a Help file. It is rarely used and is very advanced.

In the Msgbox Message section, which is the section before the first comma, text is indicated by quotation marks.
There is also an ampersand (&) to add more text or in this case the value of dblInches(30.5) * dblInches(80).
VBA is very tolerant here as it automatically converts your multiplied answer to a string (text) without you using of CStr to convert the double to a string.
The Button Style is not specified as there are 2 commas with nothing between and so it uses the default style.
The default style is only 1 button "OK".
Next is the Title and it is specified as Attention.

For Each Function

For Each is a piece of code that enables you to look at each open document, page, layer or shape in a document.
If you want to step through every page in a document you must declare a variable as a page.
eg.
    Dim pgSheet as Page
    For each pgSheet in ThisDocument.Pages
        'Some code. You could add a page No, Color the page or add or modify text etc.
    Next pgSheet

Similarly for layers on a page.
    Dim lyObject as Layer
    For each lyObject in ThisDocument.Pages(1).Layers
        'Some code. You could examine each layer to see if it contains any objects, delete it etc.
    Next lyObject

Similarly for shapes on a page.
    Dim shObject as Shape
    For each shObject in ThisDocument.Pages(1).Layers("Layer 1").Shapes
        'Some code. You could examine each shape to see if it is the type, size or location and modify it or give it a name, etc.
    Next shObject

It is not necessay to specify the Next ...... such as Next pgSheet.
Simply Next if enough but you can embed For Each statements such that you could look at every layer and every shape on every page.
It can get confusing reading that Next means the next pgSheet and not next shape.

For Each can enable you to step through every open CorelDraw document.
However the code must be in a Module not in ThisDocument.
    Dim doc As Document
    For Each doc In Application.Documents
        'Some code. You could examine each document and get the name or full file path, the number of pages etc.
    Next doc

Note that the last object in the For Each line of code is represents multiple objects of the type that you are stepping through.
eg.
In the next line you ae looking for shape objects in a set of shapes.
For each shObject in ThisDocument.Pages(1).Layers("Layer 1").Shapes

The following does not work as you are looking for shapes in a set of pages.
For each shObject in ThisDocument.Pages

The following will work.
For each shObject in ThisDocument.ActivePage.ActiveLayers.Shapes

You can also declare a variable to represent a set of shapes.
    Dim shObjects as Shapes
    Set shObjects = ThisDocument.ActivePage.ActiveLayers.Shapes
    Dim shObject as Shape
    For each shObject in shObjects
        'Some code.
    Next shObject
    'The next line avoids memory problems.
    Set shObjects = Nothing


2017_08_02