AutoCAD

Programming with Class, Part 2

15 Dec, 2004 By: Mike Tuersley Cadalyst

Going a step further with those often-unfamiliar yet very useful class modules


Last month I introduced the Class Module (click here for column archives), and this month I am going to expand upon it. To refresh, a Class in layman's terms is a user-defined programming object. It is just like an internal VBA or AutoCAD object -- it can have properties, methods, and events.

I've started with the TitleBlock example from last month and have expanded it to include more functionality (figure 1). I couldn't talk my editor into posting all the code for the project within this document, so download the code from last month. It might help you to download the sample project now, so you have it loaded as you read this after opening the example, be sure to add references to Microsoft VBScript Regular Expressions v5.5 (or later) and Microsoft ActiveX Data Objects v2.8 Library (or later) if they are missing. This project also uses an Excel spreadsheet to store data, so you must change its location within the TitleBlock class module's Read_Excel function.

figure
Figure 1. Completed class example project.

Example Project Scope
Last month, the code wrote the values stored by the class module to a text box to demonstrate how the class module worked. This month, the TitleBlock class has methods that will do a lot of the work for this project. Remember, one of the reasons for using class modules is to simplify your code. When completed, this class module can be sent to another programmer, and all he needs to do is add it and use it. He doesn't need to understand how to access an Excel spreadsheet through an ADO connection or how to retrieve the logged-in user's name through the Windows' API. To demonstrate, here is all the code from the basic module that runs this program:

Option Explicit

Public oTb As Titleblock

Sub Test()
  Set oTb = New Titleblock
  Dim vTmp As Variant
  Dim iIndex As Integer
  Dim oForm As New UserForm1
  Load oForm
  With oForm
    For Each vTmp In oTb.Drawings
      .cboDrawings.AddItem vTmp
    Next
    .txtShtTitle.Text = .cboDrawings.Text & _
            " - " & .cboDwgType.Text
    oTb.DwgTitle = .txtShtTitle
    .cboDrawings.ListIndex = 0
    .txtDrwnBy = oTb.UserInitials
    .Show
  End With
End Sub

The code for the module is short and clean. I start by declaring a public instance of the TitleBlock class. Then, I set it to a New instance remembering that using the New command within the declaration statement is not a good idea with classes. If the New is within the declaration, the class is not initialized until a reference is made to it. Using the separate Set line with New initializes the class then, so it is populated with information. To see about this, set a break point immediately after the Set line, or add a watch to oTB, and check out the information that has been populated at that point to the TitleBlock object. Then look at the CLASS_INITIALIZE event within the TitleBlock class module. Within the Initialize event, I:

  • Set up my ADO connection
  • Retrieve the user name from the Windows login through the API
  • Query the Excel spreadsheet for the user's initials
  • Retrieve the "base" drawings
  • Preset the drawing discipline to Architectural and retrieve its "base" drawing types
  • Set the drawing number's alpha value
FRIEND Scope
Opening the TitleBlock class module and looking at its code, you might notice a command that you haven't seen before now. Friend is a declarative scope statement just like Private and Public. Everyone should know the difference between the two, but in case you don't:
  • Private: This restricts the visibility of the object to the module within which it was declared.
  • Public: This opens the object's visibility to everything -- within the creation module, to other modules within its host project, and to any projects that reference the host project.
Friend hovers between Private and Public. Anything that is declared via Friend is visible within the host project as if it were Public, but it is not visible by another project that references the host project just as if it were Private. Suppose I have a class method called ReadDataBase that I declare using Friend:

Friend Function ReadDataBase() As Recordset

In my project, TESTCLASS.DVB, I add a module. From this module, I can access the ReadDataBase method of my class object. This is just as it would be if I declared ReadDataBase using Public. Now I create another project called TESTCLASS2.DVB, and I add a reference to TESTCLASS.DVB. From the new TESTCLASS2.DVB, I cannot access the ReadDataBase method. (Note: Friend can only be used in Class modules or forms, not basic modules.)

Using Enums
Here's a reoccurring scenario. My program needs to keep making decisions based on a particular state. If it's a black-and-white situation, a public Boolean value will suffice. But rarely are situations black-and-white -- usually they are varying shades of gray! A typical solution would be to create a public integer value and keep testing it. This too works well, providing I remember the meanings of all the possible integer values. But what happens if someone else works on my project? Will they know the values' meanings that I've put to memory? Of course not!

A better method for tracking something with more values than true/false is using Enums (enumerated constants). With this Class project, I wanted to track which drawing discipline the user chose because the discipline controls the drawing types, drawing number prefix, and the SQL statement for retrieving the drawing types from the Excel spreadsheet. So, with Frank's help, I decided to use Enums. (Thanks, Frank!)

Public Enum dwgDiscipline
  Architectural = 1
  Electrical = 2
  HVAC = 3
  Plumbing = 4
End Enum

The syntax is simple. Just declare the Enum with a unique name, then define its possible constant values. The constant values must evaluate to a long data type -- no strings, integers, or other such values. Once declared, these values are available through Intellisense.

Now I, or any other programmer looking at this code, will know what I'm testing without the typical trial-and-error, hunt-and-peck methods of trying to read the original programmer's mind.

Kick It UP a Notch!
This wraps up a two-month blitz on the Class module. I hope I've met my goal of getting readers comfortable with Class modules. If so, you won't really need this month's Kick It Up a Notch! Those who feel more comfortable will dive right in and extend the functionality of their projects. For those still on the fence, do some research on the Internet or at your public library. Both have plenty of Visual Basic resources that present different approaches to learning and using Class modules. Take care until next month!


About the Author: Mike Tuersley


AutoCAD Tips!

Lynn Allen

Autodesk Technical Evangelist Lynn Allen guides you through a different AutoCAD feature in every edition of her popular "Circles and Lines" tutorial series. For even more AutoCAD how-to, check out Lynn's quick tips in the Cadalyst Video Gallery. Subscribe to Cadalyst's free Tips & Tools Weekly e-newsletter and we'll notify you every time a new video tip is published. All exclusively from Cadalyst!
Follow Lynn on Twitter Follow Lynn on Twitter


Poll
Which file format do you use most often for CAD drawing/model exchange?
Native format
PDF
3D PDF
DWF
STEP or IGES
JT
IFC
Other
Submit Vote