You are on page 1of 7

Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

VBA/API - Part 2
By Neil Munro

Last time, we built the user interface for a center of gravity tracker for Autodesk Inventor assemblies. This month we'll add the
programming code to insert a special center of gravity (Marker) part, position the Marker part at the assembly, and display the assembly
COG coordinates in the current document units.

Download Files
First download, unzip, and save to a folder in your current project, the COG_A.zip file. It is important that the Marker.ipt file in the zipped
file be placed in a folder included in the active project.

COG_A.zip (zip - 90Kb)


You can download the files used in this tutorial from here.

Figure 1: Sizing and alignment tools.


The zipped file contains the following files:

Marker.ipt
COG_A.ivb

The included part file (Marker.ipt) is designed specifically for use as an assembly COG marker and the part has the following properties:

1. All part features are controlled by a user-defined scale variable.


2. The part's material is defined as having zero density.
3. The part will not affect COG calculations. The part is symmetrical about the origin geometry. The part's origin planes, axes, and
center point can be used as a COG coordinate system in the assembly.

The COG_A.ivb file contains the results of last month's tutorial. Feel free to continue on with your own file, but if you missed out, rename
this file to COG.ivb and load the project through the Autodesk Inventor VBA IDE.

1. Select Tools > Macro > Visual Basic Editor from the Autodesk Inventor pull-down menu.
2. Select File > Load Project from the VBA pull-down menu. Browse to the folder containing COG.ivb and load it.

Review and a Tip


Last month's tutorial concentrated on building a user interface for our macro. We placed controls on a form, and then adjusted property
values of the controls to format the form to our liking. Finally, we added program code that runs when a user clicks the Cancel or More
buttons on the form.

The VBA IDE contains a number of tools for sizing and aligning the controls on a form. By default, controls snap to a grid. You can
control the grid spacing on the General tab of the Options dialog box (select Tools > Options from the VBA pull-down menu). A selection
of alignment and sizing tools is available on the Userform toolbar (select View > Toolbars > Userform from the VBA pull-down menu).
You can align and size controls at the same level on a form. Controls within a Frame control are at a different level than controls outside

1 of 7 1/21/2010 6:36 PM
Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

the Frame control. You can select any number of controls, and the last control selected is used as the seed for alignment and sizing.

In the top image of Figure 1, the two label controls are selected. The topmost label control is the seed control for sizing and alignment
(white grip points). In the middle image, the controls are aligned on their left edges (Label2 aligned to Label1). The bottom image has
both controls matched in height and width. Additional spacing and grouping controls are available on the toolbar and from the Format
menu.

Autodesk Inventor Objects

Figure 2: Assembly COG project object hierarchy.


If you have not read the API overview included in the Autodesk Inventor Programming Help, do so before proceeding. You don't need to
understand everything presented there, but it provides a background for this tutorial.

Our macro requires access to a number of Autodesk Inventor objects. We'll look at specific objects in detail as we access them. Figure
2 includes a hierarchy of all objects required for our program. You can download a PDF file outlining the complete Autodesk Inventor
object hierarchy from the Autodesk Inventor Product Resources on Autodesk.com.

Figure 3: Require variable declaration.


The object tree may look quite complicated, but don't be frightened off. Object names are usually quite descriptive and the relationships
are similar to the hierarchy shown in Autodesk Inventor browsers.

Let's quickly overview the objects depicted in Figure 2. The two objects directly below the Application object are the AssemblyDocument
and TransientGeometry objects.

TransientGeometry objects, such as points and matrices, are placeholders for geometric information required to place or move real
geometry. In our macro, we'll use a Matrix object (contains position and rotation information) to hold information required to move the
Marker part to the current assembly COG.
The AssemblyDocument object represents an assembly file. There are two first-level children of this object that are of interest to us
for this macro, the UnitsOfMeasure object and the AssemblyComponentDefinition object.
All Autodesk Inventor parameters are unit specific for each document. The UnitsOfMeasure object enables us to retrieve and set unit
types and precision. Our program will display the assembly COG coordinates in the current length units for the document.
While the AssemblyDocument object represents the assembly file, its first-level child, the AssemblyComponentDefinition object
contains the geometry in the file. It is through this object that we can obtain assembly mass properties and information about
assembly components.
The MassProperties object is a key object in our program. It contains a CenterOfMass property that holds the X, Y, and Z
coordinates of the assembly COG. No complex calculations are required; our goal is simply to retrieve this information and move our
Marker part there.
An assembly is made from parts and subassemblies related by assembly constraints. You can access assembly components in the
assembly through the API, and we'll use this to find the Marker part across Autodesk Inventor sessions. You can then move the
Marker part into position, scale it, and control the visibility of its origin geometry. We'll examine these objects in more detail later in
the tutorial.

Variables and Variable Scope


Variables are named storage locations that can be modified during program execution. They can store either a single instance or arrays

2 of 7 1/21/2010 6:36 PM
Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

of numbers, strings, and even objects. Good programming practice includes declaring each variable to hold only a specific type of
information, such as an integer, string, or a CenterOfMass object.

When you declare a variable as a specific object type, it enables the IntelliSense feature in VBA to present the properties and
methods associated with the object as you use it in a program statement. Failure to declare variable types often results in difficult-
to-solve program errors. VBA can check for undeclared variables if you check the Require Variable Declaration option on the Editor tab
of the Options dialog box. (Select Tools > Options from the VBA pull-down menu.) (See Figure 3.)

Figure 4: IntelliSense variable type selection.


Variable scope is the life span of a variable. Our program consists of a number of separate procedures (subroutines and functions),
some of which have variables that are only accessible by code in that procedure. Other variables must be accessed from different
procedures in the program. You can declare a variable outside a procedure to make it accessible throughout all or parts of a program. If
you are not familiar with this programming concept, take a minute to read the VBA Help topics Understanding Scope and Visibility.
Search for scoping levels in the VBA Help Index.

Declaring Form-Level Variables


Still confused? Let's declare some object variables that will be accessed from a number of different procedures in our program.

1. Right-click frmCog in the project explorer and select View Code from the shortcut menu.

2. Scroll to the top of the code window. Enter Option Explicit as the first line in the code window if it is not already present. This turns on
variable declaration checking (for all code in the form) even if it was not specified in the Options dialog box.

You must declare variables that will hold the objects outlined in our project object model (see Figure 2). Because you are declaring them
outside a specific procedure, but inside the form, they will be available from all the procedures created within the form.

3. Type Private m_oDoc as asse under the Option Explicit line (see Figure 4).

4. Note the IntelliSense window scrolls to the first type that matches the current text after the word as. Select AssemblyDocument as the
object type for this variable.

What about the notation used for the variable name? It is common practice to precede variable names that are declared outside a
procedure with an m_ (module) or g_ (global) to indicate the scope of the variable. The variable was preceded by the word Private,
making it accessible to all procedures defined inside the form (called module- or form-level variable scope).

Procedures in other forms or modules will not be able to access this variable. A Public declaration would make the variable accessible in
all procedures in all program modules (a global variable). Declaring Public variables should be avoided if possible; it is easy to lose track
of when and where the value of a global variable is changed. The lower case o that precedes the variable name is a reminder that the
variable holds an object.

Note: Variables that hold objects are often referred to as object variables.
5. Declare the following variables as Private variables in the form (for example, Private m_oTG as TransientGeometry).

Variable Name Variable Type

m_oTG TransientGeometry

M_oCompDef AssemblyComponentDefinition

m_oMassProps MassProperties

m_oOccMarker ComponentOccurence

m_ouom UnitsOfMeasure
Document Checking and Form Initialization
When a user runs the macro for the first time in an Autodesk Inventor session, the form is loaded by the frmCog.Show statement in the
macro. Since the macro only makes sense in an assembly document, we'll add a few lines of code to check if the active document is an
assembly.

3 of 7 1/21/2010 6:36 PM
Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

1. In the project explorer, expand the Modules folder and double-click Module1.

2. In the CogTool subroutine, enter the code shown in Figure 5 above the line that loads the form.

The code checks the current document and exits without loading the form if the document is not an assembly.

3. Return to the code window for frmCog.

4. Scroll down to the Userform_Initialize routine. You entered one line of code there in the last tutorial to set the height of the form as it
loads.

During the loading of the form, we'll assign values to the object variables declared earlier in
the tutorial. To assign a value to an object variable, you must use the Set keyword. Variables
that are not objectsare assigned values without the Set keyword.

5. Enter the code shown in Figure 6. ThisApplication is interpreted as the Autodesk Inventor
Application object because VBA is running inside Autodesk Inventor. Refer to our object
model (see Figure 2) to track the relationship of the objects created.

View Larger
Figure 6: Checking for assembly
document.

Note: The green text items are comments. It is highly recommended that you add comments to your code as you go. You will find it
difficult to understand any lengthy uncommented program when you return to edit it tomorrow or six months from now. Anything after
the first single quote in a line is interpreted as a comment.

Finding the Marker Part

Figure 7: Function creation.


The Marker part may or may not be present in the assembly when the macro is run. The program must check for the Marker part, and
enable or disable various controls based on the answer. How do we check to see if the Marker part is present? Well, there are number
of possible solutions, but some are not yet documented. You could check the browser name of every component in the assembly, but
what if someone renamed the part in the browser? We'll check the file name of all referenced components in the assembly, which could
also fail if the Marker.ipt file is renamed.

The challenge of finding the Marker part in a large assembly still remains. In a five-thousand-part assembly, there will almost certainly be
a smaller number of unique first-level components. The AssemblyComponentDefinition has an object property that contains the unique
component definitions (first level) in the assembly. We'll search through these to find the Marker part. The question of whether the
Marker part is currently in the assembly is one that may be asked at different points in the program. The programming code to ask this
question will be placed in a user-defined procedure, so that it can be called from anywhere in the program.

Note: The information required from this routine is a simple yes or no. The user-defined procedure will be in the form of a function,
rather than a subroutine. A function differs from a subroutine in that the results of the procedure are returned in the function name.
This enables the function to be called in an expression. The subroutine presented in the first VBA tutorial (last month) is shown below
as a function.

Public Function AddTwo (Int1 as Integer, Int2 as Integer) as Integer


AddTwo = Int1 + Int2
End Sub

4 of 7 1/21/2010 6:36 PM
Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

An example of code that calls the function:

Answer = AddTwo (5, 6)

Create the IsMarkerLoaded function.

1. Select Insert > Procedure from the VBA pull-down menu.

2. Enter IsMarkerLoaded as the procedure name (see Figure 7).

3. Select Function and Private as the Type and Scope respectively.

4. Click OK.

5. Enter the code shown in Figure 8 and then enter the code in Figure 9 to complete the
function. The comments are not required but recommended.

Let's review the code in Figures 8 and 9. The unique component definitions in the assembly
are obtained and iterated through using a loop. The component definitions are stored in a
VBA collection (group of common items). The collection has a Count property (number of
items in the collection) and an Item property to enable index-based access to individual
objects in the collection. Check the object model in Figure 2 against the code to help
understand the hierarchy.

View Larger
Figure 8: Function code.
The associated file name of each component definition is compared against Marker.ipt to
find the Marker part in the assembly. If it is found, all extra occurrences of Marker.ipt in the
assembly are deleted (after warning the user). The ImmediateOccurences collection holds
all occurrences of the component in the assembly. When you remove an item from a
collection, all items above the removed item drop down one item number. If there are three
occurrences of the Marker part in the assembly, deleting the second item in the collection
will leave a first and second item in the collection. Deleting the second item again removes
the original number-three item.

The function name is then assigned a value of True to indicate the part was found. Finally,
you assign the Marker part occurrence to the previously declared module-level object
variable m_oOccMarker. View Larger
Figure 9: Function code completed.
Completing the Form Setup
After all that, you can now complete the code in the Userform_Initialize subroutine.

1. Add the code in Figure 10 inside the Userform_Initialize subroutine (at


the end of the existing code).

Based on the answer to the search for Marker.ipt, you set the state of the
controls on the form. Disabled command buttons appear grayed out and do
not react to user interaction (for example, mouse click). The UpdateXYZ
subroutine updates the display of the assembly COG coordinates on our
form. We'll add the UpdateXYZ routine later in the tutorial.

Figure 10: Form initialization based on Marker part


presence.
Inserting the Marker Part
You can now write the code to insert an occurrence of Marker.ipt in the assembly. The code can be inserted into the cmdInsert_Click
subroutine, but we'll call a user-defined subroutine to perform this task.

1. In the cmdInsert_Click subroutine, enter the following line of code:

Call InsertMarker

2. Add a Private subroutine named InsertMarker to the form.

5 of 7 1/21/2010 6:36 PM
Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

3. Add the code shown in Figure 11 to the InsertMarker subroutine.

The code in Figure 11 creates a transient (temporary) matrix that is then filled with the coordinates of the assembly COG. The rotation
portion of the matrix is left at the default of zero rotation about each axis.

How do we know what information is required by the SetTranslation method of the Matrix object? To obtain help on any object, property,
or method, click on the word and press the F1 function key. This displays a help page outlining syntax, argument types, and often
includes example code. Go ahead, try it.

The most important part of the help system is the sample code section. Many short examples demonstrate how to perform basic
operations, such as placing a component in an assembly.

Everything is now in place to insert the Marker part. Thinking ahead like good programmers do, we realize that the Marker part may not
always be in a folder where Autodesk Inventor can find it (in a project path). An error will occur in our program if the Marker part cannot
be found. To handle this possibility, we'll add code to capture and recover from the error. There are numerous techniques for error
handling in VB/VBA; we'll use a technique that handles errors for a single instruction (turn on error handling, execute the code statement
that may produce an error, handle the error if it occurs, and finally turn off error handling).

4. Add the code shown in Figure 12 to the InsertMarker subroutine.

Most of the code in Figures 12 and 13 is easy to understand (again, use comments for your
own benefit). The line of code placing the Marker part occurrence in the assembly assigns
the occurrence to the module-level m_oOccMarker variable. You can now access the
Marker part directly through this variable.

View Larger
Figure 12: Insert Marker part.
5. Complete the subroutine by adding the code in Figure 13 immediately below the On Error
Goto 0 line.

View Larger
Figure 13: Code to complete
InsertMarker subroutine.
Updating the XYZ Labels
Your last task is to update the labels on the form to display the assembly COG coordinates. The form remains visible while you are
working in Autodesk Inventor software, so the assembly COG coordinates are always visible.

1. Scroll down to the end of the code window and enter the code shown in Figure 14. You
can add subroutines and functions without using Insert > Procedure from the pull-down
menu.

You use the m_oMassProps object variable that was set during form initialization to provide
the assembly COG data. For each label, you call a function (value returned in the function
name) named ToFourDec to generate a string containing the coordinate in the current View Larger
document units. Figure 14: Update labels subroutine.
2. Finally, add the ToFourDec function by entering the code shown in Figure 15.

The ToFourDec function is an example of working with values and units in Autodesk
Inventor. All distance values in Autodesk Inventor are stored internally in centimeters. All
angular values are stored in radians. Users will expect that the information displayed will use
the current document units. The UOM object contains methods to convert internal units to
documents units. To obtain help on the VBA functions (for example, Format$, or CStr), click
on the word and press the F1 function key.

View Larger
Figure 15: Generating coordinates in
local units.

6 of 7 1/21/2010 6:36 PM
Autodesk - Autodesk Inventor Services & Support - VBA/API - Part 2 http://usa.autodesk.com/adsk/servlet/item?siteID=123112&id=234599...

Note: The first statement in the ToFourDec function has an underscore chanracter at the end of the first line. VBA interprets this as a
continuation character, with the remainder of the statement on the second line. You can type the statement on a single line; we broke
the line to fit the graphic on the page.
Testing the Macro

Let's test our efforts up to this point.

1. Ensure the Marker.ipt is located in a current project path.

2. Open an assembly containing a few components.

3. Select Tools > Macros from the VBA pull-down menu.

4. Click Run in the Macros dialog box. The form loads, and the Insert command button is the only enabled button.

5. Click the Insert button. The Marker part is placed in the assembly, and the form displays the assembly COG coordinates.

6. Click Cancel.

7. Run the macro again. This time the program finds the Marker part is present in the assembly. The Insert button is disabled, and the
Update button is enabled.

8. Click Cancel.

9. Place one or two additional occurrences of Marker.ipt in the assembly.

10. Run the macro again. A message is displayed warning of the extra Marker part occurrences, and the extra occurrences are deleted.

11. Click Cancel

Conclusion
Learning both the VBA and Autodesk Inventor object models is a substantial task. Examining code written by others is a great learning
opportunity. Another excellent resource is the great number of books available on VB/VBA programming.

Next month we'll conclude (finally) this project by adding an Update routine, code to scale the Marker part, and routines to get and set
the visibility of the Marker part's origin geometry. Also, look for an introduction to the new Autodesk Inventor Series, which includes
Autodesk Inventor 5.3 and Autodesk Mechanical Desktop 6.

Copyright 2010 Autodesk, Inc. All rights reserved.

7 of 7 1/21/2010 6:36 PM

You might also like