Creating an Input Calculator in VBA

28 Feb, 1998 By: Bill Kramer

Listing 1. Inputcal.dvb Global Variables
' Global variables for example application
' Language: VBA inside AutoCAD R14.01
Dim RefNam(500) As String
Dim RPnts(500, 2) As Double
Dim ICur As Integer
Dim Dst, Angl, XV, YV, XB, YB, PI, TXTSIZE As Double
Dim Nam As String
Private Sub ExitButton_Click()
End Sub
Private Sub UserForm_Initialize()
PI = 3.14159265358979
Nam = "Origin"
XV = 0#
YV = 0#
ICur = 0
Call Save_Data
Call Clear_Data
XB = 0#
YB = 0#
TXTSIZE = ThisDrawing.GetVariable("TEXTSIZE")
End Sub
Listing 2. Inputcal.dvb Basic Input Handling
Private Sub RName_Change() 'record changes to reference name
Nam = RName.Value
End Sub
Private Sub Ang_Change() 'record changes to the angle
Angl = Val(Ang.Value)
Angl = Angl * PI / 180# 'convert to radians
End Sub
Private Sub Dist_Change() 'record changes to distance
Dst = Val(Dist.Value)
End Sub
Private Sub XC_Change() 'record changes to delta X
XV = Val(XC.Value)
End Sub
Private Sub YC_Change() 'record changes to delta Y
YV = Val(YC.Value)
End Sub
Private Sub Refs_Click() 'new refence object selected
Dim II As Integer
II = Refs.ListIndex 'get index value
XB = RPnts(II, 1) 'update the base points
YB = RPnts(II, 2)
End Sub
Listing 3. Inputcal.dvb Accepting or Saving Data Input
Private Sub SAVE_Click() 'command button to accept data
If ((Dst <> -9999.99) And (Angl <> -9999.99)) Or _((XV <> -9999.99) And (YV <> -9999.99)) Then 'continue with routine, we have data to work with...
Call Calc_Point
Call Save_Data
Call Draw_a_Point
Call Draw_Name
Call Clear_Data
MsgBox "Data is still missing."
End If
End Sub
Private Sub DRAW_Click() 'command button to accept and draw
If ((Dst <> -9999.99) And (Angl <> -9999.99)) Or _((XV <> -9999.99) And (YV <> -9999.99)) Then
Call Calc_Point
Call Save_Data
Call Draw_a_Line
Call Draw_a_Point
Call Draw_Name
Call Clear_Data
XB = RPnts(ICur - 1, 1)
YB = RPnts(ICur - 1, 2)
Refs.ListIndex = ICur - 1
MsgBox "Missing data!"
End If
End Sub
Listing 4. Inputcal.dvb Data Handling
Private Sub Calc_Point() 'calculate XV,YV from input and XB,YB
If (XV = -9999.99) Then XV = 0#
If (YV = -9999.99) Then YV = 0#
If (Dst = -9999.99) Then Dst = 0#
If (Angl = -9999.99) Then Angl = 0#
If (XV = 0#) And (YV = 0#) Then
XV = XB + (Dst * Cos(Angl))
YV = YB + (Dst * Sin(Angl))
XV = XB + XV
YV = YB + YV
End If
End Sub
Private Sub Save_Data() 'append data to arrays and list box
If (Nam = "") Then Nam = "Unnamed"
RefNam(ICur) = Nam
RPnts(ICur, 1) = XV
RPnts(ICur, 2) = YV
ICur = ICur + 1
Refs.AddItem Nam &" [" & Format(XV, "###,##0.0###") & _ ", " & Format(YV, "###,##0.0###") & "]"
End Subg
Private Sub Clear_Data() 'clear the globals for next iteration
'Clear the global values
XV = -9999.99
YV = -9999.99
Dst = -9999.99
Angl = -9999.99
Nam = ""
'Clear input areas on form
RName.Value = ""
XC.Value = "0"
YC.Value = "0"
Ang.Value = ""
Dist.Value = ""
End Sub
Listing 5. Inputcal.dvb Objects Output
Private Sub Draw_a_Line() 'draw line from XB,YB to XV,YV
Dim P1(0 To 2) As Double
Dim P2(0 To 2) As Double
Dim anObj As AcadLine
P1(0) = XB
P1(1) = YB
P1(2) = 0#
P2(0) = XV
P2(1) = YV
P2(2) = 0#
Set anObj = ThisDrawing.ModelSpace.AddLine(P1, P2)
End Sub
Private Sub Draw_a_Point() 'insert Point object at XV,YV
Dim P1(0 To 2) As Double
Dim anObj As AcadPoint
P1(0) = XV
P1(1) = YV
P1(2) = 0#
Set anObj = ThisDrawing.ModelSpace.AddPoint(P1)
End Sub
Private Sub Draw_Name() 'insert text with name at XV,YV
Dim P1(0 To 2) As Double
Dim anObj As AcadText
If ((Nam <> "") And (Nam <> "Unnamed")) Then
P1(0) = XV
P1(1) = YV
P1(2) = 0#
Set anObj = ThisDrawing.ModelSpace.AddText(Nam, P1, _TXTSIZE)
End If
End Sub
Listing 6. Inputcal.dvb User Form
End Sub
The Visual Basic for Applications (VBA) programming interface that is available inside AutoCAD R14 presents a very powerful tool for the development of interactive programs that accept input from users and generate drawings. VBA allows quick and easy implementation of dialog box-based applications. The "visual" in VBA is very appropriate, since the programming environment contains numerous windows that present helpful information that changes as you write your programs. VBA also provides productivity aids for programmers that represent a quantum leap in development methods (especially for those of us who started with cards).

This month's example illustrates one of the reasons for using VBA over other options for the development of a particular class of applications inside AutoCAD. That is, it can be implemented with fewer lines of code involved than any other choice to date. VBA also stands out as a programming tool in the area of interactive input systems for AutoCAD. Programs can be quickly written to accept user input and then convert that input into graphical objects in AutoCAD.

First, let's describe the application to be solved. The program we'll be developing this month is a simplified input calculator. This program will accept geometric data along with optional information to be drawn along with the points. It is expected to handle data coming in relative to a variable point. Output options include placing a label at a given point and drawing a line from the reference point to the new point. A running copy of the Input dialog box. The controls (buttons, list, text boxes and so on) in the example dialog box include labels for the text fields, five edit boxes for the input fields, a list box for selection of reference base points and three command buttons. Operator input consists of a name and either a distance/angle or x, y displacement. The options are then to accept the data point or to accept and draw a line from the relative point to the new point. Pressing the Exit button will terminate the program and return control to the AutoCAD system with all the drawing updates applied.

We've greatly simplified the demands on the programmer for this application, but it is easy to grow the program example into a powerful tool for reducing survey field notes or similar data into usable graphics. The program was modeled after a primitive Coordinate Geometry (COGO) program which essentially is a "game" of connect-the-dots used by surveyors and civil engineers to start a drawing based on information gathered in the field. The idea is to be able to input points relative to previously defined points such as one would see coming from surveying instruments. The entry of point data in our example program will support both xy displacement and polar coordinate methods. Points can be named to coincide with survey note data, and when named, the text will appear at the datum point when the program is run.

The process involved in developing a program of this nature is relatively straightforward. Start the VBA editor with the command VBAIDE at the AutoCAD prompt and proceed directly into the definition of a new form. To define a new form, start with an empty editor, then select the Insert Pulldown menu and then the User Form option. Forms are dialog boxes. A blank form appears as an empty dialog box with a grid displayed over the top of it. We build the dialog box by selecting various controls and inserting them into the dialog box work area. When you started the form editor, a toolbar should have appeared containing various controls that can be inserted into the empty form. If you don't see that, select the View, Form options inside the VBA editor. Select the List box control (to learn what each icon does, just hold the pointer over the icon for a few seconds a tool tip help dialog will appear). After selecting the List control, move the pointer to the empty form and locate the corners of the list box. Next, locate the Properties window and change the (Name) item to be Refs. That is all there is to laying out a dialog box in VBA. Pick a control, move it into the dialog box at the position desired, then name it something you can work with in the properties tile.

Repeating the basic steps from above, insert the text boxes, labels and command buttons needed to run the program. Note that the names of the objects have been modified from the defaults created by dragging the controls into the form and then changing the property value for the (Name) of the object. Creating and editing dialog boxes is very easy in Visual Basic, but it does take a little practice to get comfortable, and once you do, you will find the development of new dialog boxes to be very quick.

After the basic dialog box has been defined, the code can be created in segments. One of the nicest features of using Basic and other interpretive language environments is that code can be developed and tested in modules without creating a large front-end to drive it. When developing this program, I started with the global declarations section and then proceeded into basic input handling. As I discovered that I needed another global variable in the input form, I simply added it to the appropriate section of code. To work in the Code View window, select the View pulldown menu and then the Code option. A full-screen text editor is presented for this form in the global declarations section of the program. Visual Basic will attempt to start things off for you by placing you in a subroutine definition for the control last referenced in the dialog editor for the form itself. Use the pulldown options at the top of the text editor to select the subroutine you want to edit or create. To create a subroutine not on the list, simply type the SUB keyword followed by the new name and press [Enter]. The END SUB will automatically appear, and you're into the middle of defining a new subroutine.

Listing 1 shows the global declarations you enter with the subroutine called when the form is initiated. To enter the global variables, select the General category in the left pulldown list and then select the Declarations option in the right pulldown. Then start typing.

Also found in Listing 1 is the subroutine UserForm_Initialize, which is called when the macro first invokes when the dialog box is started. The initialization function sets up the global variables defined in the General Declaration section. The variables in the General Declaration section of the form are local only to this form and will be reinitialized each time you restart the program. But that's a different subject that we might have to cover in the future.

Much of the required code for the basic input handling is seen in Listing 2, which actually contains several subroutines. The subroutines demonstrate how easy it is to respond to dialog-box input in VBA. The Value property of the object is simply obtained, converted to the appropriate data type via one of many BASIC conversion routines and then stored into a variable. It doesn't get much easier than that! The properties of an object tell us virtually everything we need to know about the status and details involved. For edit boxes, the data is retrieved using the Value property; however, do note that the _Change subroutine will be called each time the data field changes. Thus, you should keep field validity checking to a minimum.

The subroutine Refs_Click is the call back function for the Reference names list box control called Refs. When the user selects one of the members from the list, the Refs_Click subroutine is called. The property ListIndex tells us where in the list the user selected. This value is a variant that can be equated to an integer for access into an array. Note that we could have stored all the data in the control and parsed the data point from the text strings. This would have been more efficient in terms of storage used; however, taking the alternative approach would have required more coding, and that was a trade off we were willing to make.

Listing 3 contains the code for the two subroutines that act as call-back functions for the two command buttons for accepting or saving the data input. When the button labeled Accept is selected, the point is added to the references list, a point object is created at the specified location and if a reference name has been provided, it is output at the same point. The other command button, Accept and Draw, performs all of the functions of the Accept button but also draws a line from the reference point to the new point. Both of these functions call numerous subroutines defined in Listings 4 and 5 to accomplish their tasks.

The data-handling subroutines can be found in Listing 4. These include the function to calculate the point given the polar or displacement coordinates, a function to save the data in the arrays and in the list control and a function to clear the input fields and data elements to prepare for the next input. Note how easy it is to add a new element to a list using the AddItem method for the list box object. That is one of the strongest points in a Visual Basic program-the ability to succinctly interface with a dialog box interface.

If you already know Visual Basic, what we've seen thus far is pretty tame stuff and not that difficult to implement. What remains are the routines that output the data to AutoCAD. Because we have quick access to the object-oriented environment of AutoCAD in VBA, these functions are surprisingly short and easy. Listing 5 contains three subroutines that output various objects to the drawing database. All we have to do is fill in the parameters with data, which, as it turns out, is easy to do using the VBA editor features.

Creating new subroutines that output AutoCAD information is very easy. First, start a new subroutine such as MY_LINE, and in the subroutine, start typing ThisDrawing and then a dot. At this point, a pop-up list box is shown with the valid options for the object "ThisDrawing." One of them is Model Space, which can be selected by typing enough characters to uniquely select it in the list and then pressing [Tab]. Next, pick the object you want to add, such as AddLine, and once again press [Tab] to continue on. The required parameters are then shown one by one. Generally, I just type in a variable name similar to that shown, define it and then fill it in before the call to the method to add the new object. This is extremely fast and easy to use once you get used to it, which doesn't take very long. Plus, it's a fast and easy way to learn how the interface works.

The last step required is to define a module containing a macro that is a public function (not private) that can be called by the user to start the dialog box interface. Listing 6 contains this short macro description, which simply starts the dialog box using the SHOW method of Visual Basic. That's all there is to it. Now, the operator can select the macro from the list presented in the dialog box for VBARUN after the macro set has been loaded.

If you already know BASIC or Visual Basic, it will not take long to get comfortable with VBA inside AutoCAD. It is possible to create very powerful applications using just the VBA supplied with AutoCAD R14 even though not all the features of the professional version of Visual Basic are found in VBA. The key to success is not only in learning how to best utilize this tool, but also in selecting the proper type of application for it. This article demonstrates that one suitable area for Visual Basic is in anything that involves the use of a dialog box for preparing input from one format to one accepted by AutoCAD. Visual Basic excels at that sort of activity.

Here's a tip. Rather than keyboarding all of the VBA code we provided with these examples, please download the DVB file. Until next time, keep on programmin'!

About the Author: Bill Kramer

More News and Resources from Cadalyst Partners

For Mold Designers! Cadalyst has an area of our site focused on technologies and resources specific to the mold design professional. Sponsored by Siemens NX.  Visit the Equipped Mold Designer here!

For Architects! Cadalyst has an area of our site focused on technologies and resources specific to the building design professional. Sponsored by HP.  Visit the Equipped Architect here!