CorelDRAW Community
CorelDRAW Community
  • Site
  • User
  • Site
  • Search
  • User
Developer Area
Developer Area
Docs & Tutorials Storing Custom Information in Documents
  • Forums
  • Wikis
  • API References
  • Tags
  • More
  • Cancel
  • New
Developer Area requires membership for participation - click to join
  • +Addons: Extending Application Functionality with VBA and VSTA
  • -General Articles
    • Controlling CorelDRAW or Corel DESIGNER Applications From Other Processes
    • Creating Color Palettes
    • Creating Custom Outline Enhanced Pattern Styles
    • Creating VBA Macros with User Interface in CorelDRAW and Corel DESIGNER
    • Macro Management in CorelDRAW Graphics Suite and CorelDRAW Technical Suite
    • Storing Custom Information in Documents
    • Using Corel Query Language (CQL) to Search for Objects in CorelDRAW and Corel DESIGNER Documents
    • Using JavaScript with CorelDRAW

Storing Custom Information in Documents

Custom solutions can store custom data inside documents to be used later. The custom data can be added to individual objects, layers, pages or the whole documents and can be used to identify those document elements or attach custom properties to be used with the solution.
There are a number of ways custom data can be associated with document elements in CorelDRAW and Corel DESIGNER.

Object Data Manager

CorelDRAW and Corel DESIGNER allow to associate custom data with arbitrary objects in the document right in its user interface by using Object Data Manager docker. This docker can be accessed through Window > Dockers > Object Data Manager (in CorelDRAW) or Window > Object Data Manager (in Corel DESIGNER). This docker can be used to store one of the pre-set properties to an object in a document as well as to manage the properties that can be specified and the data formatting.
Corel DESIGNER’s version of Object Data Manager has more functionality geared towards interoperability with technical drawing data formats such as CGM which use the custom data to tag objects and assign interactive behaviours to the exported document. However both CorelDRAW and Corel DESIGNER allow selecting from the list of pre-set object properties and to create new ones.
Object Data Manager in CorelDRAW with the default set of data fields:

Object Data Manager in Corel DESIGNER:

To add new fields or to change the appearance/formatting of existing data fields, use the Open Field Editor button on the top of the Object Data Manager docker:

The Object Data Manager shows the data associated with the currently selected object in the document. You can also see the data for a number of selected objects by using the Spreadsheet window:

The data associated with objects in a document using Object Data Manager docker can be accessed from custom solutions such as VBA macros.
The list of data properties can be accessed through Document.DataFields collection while the object data assigned to particular object is available through Shape.ObjectData property.
For example, the following VBA macro creates a custom data field “Height”, creates a rectangle on the page and assigns the “Height” property to it with value “2” as well as sets the standard “Name” and “Comments” properties:
Sub CreateCustomData()
  Dim field As DataField
  Dim s As Shape
  Set field = ActiveDocument.DataFields.Add("Height", "General")
  Set s = ActiveLayer.CreateRectangle(0, 0, 2, 2)
  s.ObjectData("Name") = "Rectangle"
  s.ObjectData("Comments") = "Simple rectangle"
  s.ObjectData.Add field, 2
End Sub

After the macro is run, a rectangle object is created and all its assigned data is shown in the Object Data Manager docker:

There are numerous applications where object data can be used in a drawing. For example, in technical drawings of a floor plan, object data can be used to specify cost of materials used and a list of materials can be produced automatically by a custom solution. For a more concrete example, let’s review a simple basement renovation plan for a house. New laminate floors are to be installed and all electrical outlets and light fixtures are to be replaced. To estimate the cost of materials for the basement, a scale drawing of the floorplan is produced:

Here light fixtures, electrical outlets and light switches are indicated by appropriate objects and each of them is assigned an approximate cost to the “Cost” data field and name of the item in the “Comments” field:

Two more layers lay out the subfloor (4’x8’ boards) and laminate wood flooring (individual planks) for the basement:

Each of those objects is tagged with the “Comments” and “Cost” fields as well.
Now, in order to create a VBA macro to automatically generate list of materials needed for the renovation and their cost, create a new VBA macro project in Macro Manager:

In VBA Editor, add a new class module for the project (Insert > Class Module), name it “Material” and create the following three properties for it:
Public Name As String
Public Cost As Double
Public Count As Long

These will be used to accumulate the data retrieved from the document.
Now create the macro to collect the material data from all the objects in the current CorelDRAW document and create the list of materials used and their cost:
Sub CreateBillOfMaterials()
  Dim materials As Collection
  Dim m As Material
  Dim s As String, total As Double
  Set materials = CollectMaterials(ActiveDocument)
  s = "Count" & vbTab & "Cost" & vbTab & "Materials"
  s = s & vbCrLf & "--------------------------------------------------------------"
  For Each m In materials
    s = s & vbCrLf & m.Count & vbTab & Format(m.Cost, "$#,##0.00") & vbTab & m.Name
    total = total + m.Cost
  Next m
  s = s & vbCrLf & "--------------------------------------------------------------"
  s = s & vbCrLf & "Total:" & vbTab & Format(total, "$#,##0.00")
  MsgBox s
End Sub

The above macro creates a list of materials used by calling CollectMaterials() helper function which returns a list of all the materials it encountered in the active document. Then it goes through all the materials and creates a text string listing them and their cost.
The CollectMaterials() helper function is implemented as follows:
Private Function CollectMaterials(ByVal doc As Document) As Collection
  Dim materials As New Collection
  Dim p As Page, s As Shape
  For Each p In doc.Pages
    For Each s In p.Shapes
      If s.ObjectData("Comments").Value <> "" Then
        AddMaterial materials, s
      End If
    Next s
  Next p
  Set CollectMaterials = materials
End Function

It simply goes through all the pages of the document and all the objects on each page and looks for objects whose “Comments” data field is set. As soon as it is found, the object’s data is added to the list of materials by using AddMaterial() helper method:
Private Sub AddMaterial(ByRef materials As Collection, ByVal s As Shape)
  Dim m As Material
  For Each m In materials
    If m.Name = s.ObjectData("Comments").Value Then
      m.Count = m.Count + 1
      m.Cost = m.Cost + s.ObjectData("Cost").Value
      Exit Sub
    End If
  Next
  m = New Material
  m.Name = s.ObjectData("Comments").Value
  m.Cost = s.ObjectData("Cost").Value
  m.Count = 1
  materials.Add m
End Sub

This method extracts the “Comments” and “Cost” data fields from the object and then adds the data to the list of materials. If an object with the same name (the value of “Comments” field) is already in the list, then the Count property is incremented and the total cost of the materials is added up. Otherwise a new entry is added to the list.
Now, running this macro with the basement floorplan document open will show the following message:

Programmatic Data (Properties collection)

Data associated with objects using Object Data Manager is very easy to use because there is build-in user interface support right inside CorelDRAW/Corel DESIGNER. However there are a number of limitations with it as well:

1.      Object Manager data can be assigned only to individual objects such as rectangles or curves. You cannot store custom data inside the document itself or structural elements such as pages and layers.

2.      Object Manager data is limited to a few very basic types (numbers and strings mainly). So if you want to store a more complicated structured data you would need to either use several data fields, or encode the data into, say a string.

3.      Object Manager data is visible to the user. While this is its strong point, sometimes it is not desired to allow application users to see or edit the data inserted by a custom solution.

All of the above shortcomings are resolved by Properties object which is available on Document, Page, Layer, and Shape classes in CorelDRAW/Corel DESIGNER’s object model. Each Properties object can hold multiple pieces of data. In order to prevent different solutions from overriding each other’s data, each property is identified by two elements: a unique string ID and an integer index. It is recommended that the string ID to be a unique string specific for a concrete solution. The easiest way to guarantee uniqueness is to use Globally Unique Identifiers (GUIDs) for the string ID. You can use integer index to identify various properties belonging to your solution.
For example, let’s create a simple macro that remembers each object’s position on the page inside that object’s Properties collection. Then another macro can restore the objects’ positions after they have been inadvertently moved around the document:
Private Const SolutionID As String = "41AC5941-219D-492C-896D-5D4D9EFABF5D"
Sub Store()
  Dim s As Shape
  Dim x As Double, y As Double
  For Each s In ActiveSelection.Shapes
    s.GetPositionEx cdrCenter, x, y
    s.Properties(SolutionID, 1) = x
    s.Properties(SolutionID, 2) = y
  Next s
End Sub
Sub Restore()
  Dim s As Shape
  Dim x As Double, y As Double
  For Each s In ActiveSelection.Shapes
    If s.Properties.Exists(SolutionID, 1) And s.Properties.Exists(SolutionID, 2) Then
      x = s.Properties(SolutionID, 1)
      y = s.Properties(SolutionID, 2)
      s.SetPositionEx cdrCenter, x, y
    End If
  Next s
End Sub
Sub Clear()
  Dim s As Shape
  For Each s In ActiveSelection.Shapes
    If s.Properties.Exists(SolutionID, 1) Then s.Properties.Delete(SolutionID, 1)
    If s.Properties.Exists(SolutionID, 2) Then s.Properties.Delete(SolutionID, 2)
  Next s
End Sub


Here, Store() macro goes over all the selected objects in the document and stores their center’s position on a page inside the shape’s Properties object. SolutionID string is used to identify properties belonging to ObjectPositions macros and property #1 stores the horizontal (X) coordinate of the position of the object, while property #2 stores the vertical (Y) coordinate.
Restore() macro performs the opposite operation. For each object in the selection, if the object has its previous position stored, move the object back to that location.
Finally, the Clear() macro removes any stored object positions.

Application Session Data

Both Object Data Manager and Properties collection store their data inside the document and its elements. Many solutions need to store some data to be reused when the macro or plugin is called again. Of course solutions can use custom implementations to persist their data by writing the data to a file or system registry. This can be done, but its tedious, error-prone (need to select the file location your solution has write access to, for example).
Fortunately CorelDRAW/Corel DESIGNER offer functionality just like that for the developers. The Application class offers two properties, GlobalUserData and SessionUserData, which can store the data not associated with any document.
Both objects follow the same interface as Properties object of a document. Each property is identified by a string ID/integer index pair. Properties stored inside GlobalUserData will be saved on disk when CorelDRAW/Corel DESIGNER quits, while SessionUserData is not saved on application shutdown and can be used to store temporary information while the application is running.
For example, a simple macro that asks the user for a text string and creates an artistic text object with this string on the page:
Sub CreateTextObject()
  Dim text As String
  text = InputBox("Text", "Enter Text String")
  If text = "" Then Exit Sub
  ActiveLayer.CreateArtisticText 0, 0, text
End Sub

Each time the InputBox() function is called, it will have an empty text box to provide the input in:

However, if you want to pre-populate the text box with the value entered previously, you need to save the previous text string somewhere and then recall it next time the macro is invoked. That’s where GlobalUserData and SessionUserData come in:
Sub CreateTextObject()
  Dim text As String
  If SessionUserData.Exists("MyCreateTextObjectMacro", 1) Then
    text = SessionUserData("MyCreateTextObjectMacro", 1)
  End If
  text = InputBox("Text", "Enter Text String", text)
  If text = "" Then Exit Sub
  SessionUserData("MyCreateTextObjectMacro", 1) = text
  ActiveLayer.CreateArtisticText 0, 0, text
End Sub

Here we store the text entered in InputBox() into SessionUserData object as property #1 for “MyCreateTextObjectMacro” solution. And if the text string has previously been saved, it is recalled at the beginning of the macro and passed to InputBox() function as the string to be placed inside the text box by default. And if the last time the macro was run, a “Hello, world!” string was entered, then it will be automatically displayed in the dialog box the next time the macro is launched:

Using SessionUserData means that if you quit CorelDRAW and restart it, the last text string used by the macro will not be remembered the next time the macro is run. If this behaviour is desired though, you can replace SessionUserData with GlobalUserData in the example above.

Download source: CustomData.zip

  • Share
  • History
  • More
  • Cancel
Related
Recommended

© Corel Corporation. All rights reserved. The content herein is in the form of a personal web log ("Blog") or forum posting. As such, the views expressed in this site are those of the participants and do not necessarily reflect the views of Corel Corporation, or its affiliates and their respective officers, directors, employees and agents. Terms of Use / Privacy​ ​/ ​Cookies / Terms and Conditions / User Guidelines.