Home > The Visual Basic Language > Using custom classes in scripts

Using custom classes in scripts


In this article I will show how to create and use a custom class within a script.  If you program in VBA, VB6 or .NET you might be familiar with building your own classes but you may not know that you can also use them in a script.  In case you are wondering what a class is, I will start by briefly discussing that as well.  I have to admit that I have only used classes inside scripts a handful of times, but in those situations it proved to be very useful.

What is a class?

When you write programs using the CATIA automation API, you are working with objects that represent various “things” in the software.  For example, each document that is open is represented by a separate Document object.  That object has various properties that hold some data or attributes associated with it.  For example, the Document object provides a Path property to retrieve the file path where it is currently saved.  Objects also may provide methods which can be thought of as services or actions that can be performed.  As an example, the document object provides a Save method to save any changes that were made.

All of these objects are actually instances that get each their definition from a master “template”.  That template is called a class and it has three basic purposes:

  • It defines what properties and methods will be provided (called members)
  • It defines how its data will be stored
  • It provides all of the underlying code that gets executed when calls are made to its instances

Why create a class inside of a script?

Adding a class to your script allows you to define a new object type that can be very easily used (instantiated) again and again in the script.  Generally, a class will represent some type of real “thing” so it might make sense to group all attributes and services that “thing” will provide into an easy to use object.  When I have used them, most often they are relatively simple and will duplicate some functionality that is not available in a script language.

Declaring the class

The class definition needs to be separated from the other procedures (subroutines and functions) in the script.  This is done by enclosing all of the class code inside the Class and End Class statements.  So you might have something like this to start:

Sub CATMain()
   'This is the main sub for your program

End Sub

Class
   'All of the code for your class goes here

End Class

Defining Properties

The first step here is to decide what properties your class should provide and their data types.  A good way to think about this is to mimic the way CATIA classes or other objects you may have used in the past are defined.  Most commercial applications have very well thought out object models, so try to follow the same sorts of conventions they do.  Once you have done that, you should declare a private variable inside the class to hold each piece of data.  This step is called encapsulation because it protects that data from being accessed in the program unless it is accessed through the class properties.  Next, you should create a separate procedure to retrieve and set each property value.  This is shown below.

'Declare a private variable to hold the property value
Private p_strName As String

'This procedure is executed when this property is read
Property Get Name() As String
   'Like a function, return the value by assigning it to the property name
   Name = p_strName
End Property

'This procedure is executed when a value is assigned to the property
Property Let Name(iName As String)
   'Simply assign the passed in value to the private variable
   p_strName = iName
End Property

Important notes

  • Properties can be values (number, string, boolean, etc.) or other objects.  To retrieve a property, you will always define a Property Get procedure.  However, to assign a property there are two different ways depending on whether the data type is a value or an object.  To assign a value, you will define a Property Let procedure (as shown above) and to assign an object you will define a Property Set statement as shown below.
Private p_objPart As Part

'This procedure is executed when an object is assigned to the property
Property Set Part(iPart As Part)
   'Simply assign the passed in object to the private variable
   Set p_objPart = iPart
End Property
  • If you want a property to be read only or write only, simply define only one (not both) of the Get Property / Let Property / Set Property procedures.  For example, if there is not a Property Get procedure, that property can be assigned but not read.

Defining Methods

Adding methods to a class is very simple.  All you have to do is include a subroutine or function for each.

An Example

A great example that I have used in some of my scripts is a collection class.  If you have written code in VBA, VB6, .NET, etc. you are probably familiar with collections.  They simply hold a bunch of values or objects.  They generally provide the following basic capabilities:

  • Query the size of the collection (Count)
  • Add items to the collection
  • Remove items from the collection
  • Retrieve an item from the collection

The VB script language does not provide its own collection class.  So, a common alternative is to use an array to store values.  While an array does work, it can require a lot of code throughout your program.  A collection class may contain a fair amount of code, but it can be reused in other scripts easily and it greatly simplifies the rest of the code in the script.  Another option is to use a dictionary object in the Windows Scripting Runtime Library.  This is a good option and I have used it many times as well.

An example collection class is provided below.  I only included the most basic capabilities and it is setup to store and retrieve objects (not values).  If you want to manage values, you will need to replace the Property Set procedures with Property Let Procedures.

'Start the class definition
Class CustCollection

   'Declare private variables.  These cannot be accessed directly.
   'Instead they can only be accessed through a property or method
   Private p_varItemArray() As Variant
   Private p_intCount As Integer

Private Sub Class_Initialize()
   'The initialize procedure will execute whenever a new object instance is created
   'Here you should initialize any default values
   p_intCount = 0
End Sub

Property Get Count() As Integer
   'Used to retrieve how many items are in the collection
   'Simply return the value stored in the private variable
   Count = p_intCount
End Property

Sub Add(iObject)
   'Used to add an item to the collection
   'Increment the size of the collection
   p_intCount = p_intCount + 1

   'Resize the array preserving all of the existing items
   ReDim Preserve p_varItemArray(p_intCount)

   'Add the new item to the array
   Set p_varItemArray(p_intCount) = iObject
End Sub

Function Item(ByVal iIndex As Integer) As Object
   'Used to retrieve an item from the collection
   'If the requested index exists, return it
   'Otherwise raise an error
   If iIndex <> 0 And iIndex <= p_intCount Then
      Set Item = p_varItemArray(iIndex)
   Else
      Err.Raise vbObjectError + 1, "Collection.Item()", "Index out of range"
   End If
End Function

Sub Remove(ByVal iIndex As Integer)
   'Used to remove an item from the collection
   Dim intIndex As Integer

   'From the requested index to the upper bound of
   'the array move all existing items down one index
   For intIndex = iIndex To p_intCount - 1
      Set p_varItemArray(iIndex) = p_varItemArray(iIndex + 1)
   Next

   'Resize the array destroying the last element
   p_intCount = p_intCount - 1
   ReDim Preserve p_varItemArray(p_intCount)
End Sub

End Class

The following example shows how to use the class in your script.  Each of the properties and methods provided by the new CustCollection class are demonstrated.

Sub CATMain()

   Dim objCol As CustCollection     'Declare a new variable
   Dim objItem As Object

   'Instantiate a new collection object
   Set objCol = New CustCollection

   'Display the current collection count
   MsgBox objCol.Count, 0, "Count (Initial)"

   'Add the 3 std planes from the active part to the collection
   objCol.Add CATIA.ActiveDocument.Part.OriginElements.PlaneXY
   objCol.Add CATIA.ActiveDocument.Part.OriginElements.PlaneYZ
   objCol.Add CATIA.ActiveDocument.Part.OriginElements.PlaneZX

   'Display the current collection count
   MsgBox objCol.Count, 0, "Count (After adding std planes)"

   'Get the 2nd item in the collection and display its name
   Set objItem = objCol.Item(2)
   MsgBox objItem.Name, 0, "Name of 2nd Item"

   'Remove the 2nd Item
   objCol.Remove 2

   'Display the current collection count
   MsgBox objCol.Count, 0, "Count (After removing 2nd item)"

   'Get the 2nd item in the collection and display its name
   'When the original 2nd item was removed the 3rd item moved to the 2nd index
   Set objItem = objCol.Item(2)
   MsgBox objItem.Name, 0, "Name of 2nd Item"
End Sub

Wrap up

Once you create a class such as the collection example shown above, you can reuse it in future script projects by just pasting in the class definition.  Creating easy to use custom classes takes some practice.  As you create more of them, you will begin to learn good and bad practices but in general, try to mimic the way other objects work in other applications.  For example, I made the collection class above provide the properties and methods you would expect to see and the way they are used is familiar.

Please take a moment to rate this article…Just click the stars up near the title.

Add to: del.icio.us del.icio.us, StumbleUpon StumbleUpon, Digg Digg, Google Google

Advertisements
  1. Julian50
    April 14, 2010 at 1:44 pm

    nothing to say, just perfect, please don’t stop and keep going!

  2. Karteek
    April 16, 2010 at 12:30 am

    Mike,

    You are introducing us to the many possibilities of Macros. A great easy to understand explanation.
    Onus is on us to learn and use it.

    Thanks,
    Karteek

  3. Vishal
    April 27, 2010 at 12:11 am

    Please provide another example which works in vba.
    I copy/pasted the code in vba but it did not work.
    A demonstration/example will be more useful.

    Thanks

    • April 27, 2010 at 5:23 am

      This doesn’t work in VBA, it is only supported in VBScript (so it should work with CATScript and catvbs). To make your own custom classes in VBA, just right click on the project and select insert class module. From there, the idea is basically the same except you will not use the Class and End Class statements. Those statements are used only in script to separate the class code from the rest of the code since it is all listed together, but in VBA each class is defined in a separate module so they aren’t needed.

  4. Calin
    May 14, 2010 at 1:11 pm

    Congratulations Mike for your tremendous effort and for the competent explanations you provide!

    Well done job!

    One remark I would like to put up. When you describe how to define the properties you say “This step is called encapsulation because it protects that data from being accessed in the program unless it is accessed through the class properties”. Wouldn’t be correct to say that the data is being accessed by the class methods (not properties)?

    Thank you.

    • May 14, 2010 at 3:57 pm

      Thanks! Glad you like the site. As for your question, either is technically correct. I mentioned properties because private variable values are most often retrieved or set through a property procedure, not a method. With that said, properties and methods both have access to the private variables inside the class so it is possible either way. The basic idea of encapsulation is just that you cannot directly get the value or change the value of those private variables directly – you only have access via a property procedure or a method.

  5. Vinod
    April 18, 2012 at 9:57 am

    Wow awsme dude keep going

  1. No trackbacks yet.

Leave a Reply to v5vb Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: