Converting the VBA examples from the Inventor documentation into iLogic rules

Monday, June 8, 2026

When automating Inventor with iLogic, the best source of examples is not some distant forum: it is already installed on your machine. Inventor's local documentation contains hundreds of code snippets covering almost every method in the API.

On a standard installation, these examples are located in:

C:\Users\Public\Documents\Autodesk\Inventor 202x\Local Help

(replace 202x with your release year). There you will find the programming help, in which every API object comes with a complete example.

There is one catch, however: these examples are written in VBA, Inventor's old macro language. iLogic, on the other hand, runs on VB.NET. The two languages are extremely similar, but a few syntax differences prevent a direct copy-paste. The good news is that the conversion is mechanical: once you have internalized the few rules below, adapting an example takes a few seconds.

Converting a VBA example from the Inventor documentation into an iLogic VB.NET rule

The conversion rules

1. Remove the procedure declaration

In VBA, the code is wrapped in a Sub ... End Sub (or Function ... End Function) procedure. In an iLogic rule, the code runs directly: there is no wrapper to keep.

So you remove the first line (Public Sub ...) and the last one (End Sub).

2. Remove the Set keyword

In VBA, assigning an object reference must be prefixed with the Set keyword. In VB.NET, this distinction no longer exists: the assignment is the same whether it is an object or a value.

' VBA
Set oPartDoc = ThisApplication.Documents.Add(...)

' VB.NET (iLogic)
oPartDoc = ThisApplication.Documents.Add(...)

3. Remove the Call keyword

In VBA, Call is used to invoke a procedure explicitly. In VB.NET it is unnecessary: you call the method directly.

' VBA
Call oExtrudeDef.SetDistanceExtent(0.25, kNegativeExtentDirection)

' VB.NET (iLogic)
oExtrudeDef.SetDistanceExtent(0.25, PartFeatureExtentDirectionEnum.kNegativeExtentDirection)

4. Add parentheses to method calls

This is the most subtle pitfall. In VBA, you can call a method with arguments without parentheses when you do not use its return value. In VB.NET, the parentheses are mandatory.

' VBA
oPaths.Add oTextBox

' VB.NET (iLogic)
oPaths.Add(oTextBox)

The rule also applies to methods called with no arguments at all (including those whose arguments are all optional), which VBA accepts under their name alone: you must add an empty pair of parentheses.

' VBA
oProfile = oSketch.Profiles.AddForSolid
oSketch.Edit

' VB.NET (iLogic)
oProfile = oSketch.Profiles.AddForSolid()
oSketch.Edit()

5. Qualify enumeration constants

In VBA, constants such as kPartDocumentObject or kJoinOperation are exposed globally: you write them as is. In VB.NET, each constant belongs to an enumeration and must be prefixed with the name of its type.

This matters all the more because in iLogic, Option Explicit is disabled: a constant written without its type is not flagged as a compilation error. It is silently interpreted as a new empty variable, and the rule then produces an incorrect result — with no message at all. So always qualify them.

  • kPartDocumentObjectDocumentTypeEnum.kPartDocumentObject
  • kJoinOperationPartFeatureOperationEnum.kJoinOperation
  • kNegativeExtentDirectionPartFeatureExtentDirectionEnum.kNegativeExtentDirection

To find the type of a constant, just search for its name in the API help: the enumeration page lists all of its values.

Note: the ThisApplication object is available both in VBA and in iLogic. There is no need to obtain it differently: most examples in the documentation rely on it and remain valid.

6. Replace Debug.Print with a log entry

In VBA, Debug.Print sends text to the Immediate window of the VBA editor. In iLogic, that window does not exist: you write to the iLogic log via the Logger object, whose output appears in the iLogic Log window.

' VBA
Debug.Print "Area: " & oMassProps.Area

' VB.NET (iLogic)
Logger.Info("Area: " & oMassProps.Area)

Logger offers several levels: Logger.Info() for information, Logger.Warn() for a warning and Logger.Error() for an error. For simply displaying results, Logger.Info() is enough. Note in passing that Logger.Info is a method: its parentheses are mandatory, as required by rule 4.

7. Adapt array declarations

VBA allows the explicit declaration of an array's lower bound (Dim arr(1 To 3)). VB.NET does not: every array starts at index 0 and you only declare the upper bound. To keep indices 1 to 3 used by the rest of the code, you therefore declare an array with an upper bound of 3 — index 0 simply stays unused.

' VBA
Dim adPrincipalMoments(1 To 3) As Double

' VB.NET (iLogic)
Dim adPrincipalMoments(3) As Double

Conversely, a declaration that specifies only the upper bound (Dim oNames(1) As String) converts without any change: in both languages, it creates an array with indices 0 to 1. Only the explicit x To y form needs to be adapted.

8. Beware of multiple declarations on one line

VBA and VB.NET do not interpret a line like Dim a, b As Type the same way. In VBA, only b is of the given type; a is a Variant. In VB.NET, both variables are of the given type.

' VBA  → oEdge1 is a Variant, oEdge2 is an Edge
Dim oEdge1, oEdge2 As Edge

' VB.NET → oEdge1 AND oEdge2 are Edge
Dim oEdge1, oEdge2 As Edge

The code does not change, but the meaning does. In most of the documentation examples, this difference is harmless (you wanted two typed objects anyway) — you just need to be aware of it.

First example: extruding text

Let's take the example provided by the documentation to create an extrusion from sketch text. Here is the original VBA code:

Public Sub ExtrudeSketchText()
    ' Create a new part document, using the default part template.
    Dim oPartDoc As PartDocument
    Set oPartDoc = ThisApplication.Documents.Add(kPartDocumentObject, _
                ThisApplication.FileManager.GetTemplateFile(kPartDocumentObject))

    ' Set a reference to the component definition.
    Dim oCompDef As PartComponentDefinition
    Set oCompDef = oPartDoc.ComponentDefinition

    ' Create a new sketch on the X-Y work plane.
    Dim oSketch As PlanarSketch
    Set oSketch = oCompDef.Sketches.Add(oCompDef.WorkPlanes.Item(3))

    ' Set a reference to the transient geometry object.
    Dim oTransGeom As TransientGeometry
    Set oTransGeom = ThisApplication.TransientGeometry

    ' Create a text box at (0,0)
    Dim oTextBox As TextBox
    Set oTextBox = oSketch.TextBoxes.AddFitted(oTransGeom.CreatePoint2d(0, 0), "Inventor")

    ' Add the text box to an object collection
    Dim oPaths As ObjectCollection
    Set oPaths = ThisApplication.TransientObjects.CreateObjectCollection
    oPaths.Add oTextBox

    ' Create a profile.
    Dim oProfile As Profile
    Set oProfile = oSketch.Profiles.AddForSolid(False, oPaths)

    ' Extrude the text.
    Dim oExtrudeDef As ExtrudeDefinition
    Set oExtrudeDef = oCompDef.Features.ExtrudeFeatures.CreateExtrudeDefinition(oProfile, kJoinOperation)
    Call oExtrudeDef.SetDistanceExtent(0.25, kNegativeExtentDirection)
    Dim oExtrude As ExtrudeFeature
    Set oExtrude = oCompDef.Features.ExtrudeFeatures.Add(oExtrudeDef)
End Sub

And here is the same code converted for iLogic, after applying the first five rules:

' Create a new part document, using the default part template.
Dim oPartDoc As PartDocument
oPartDoc = ThisApplication.Documents.Add(DocumentTypeEnum.kPartDocumentObject, _
            ThisApplication.FileManager.GetTemplateFile(DocumentTypeEnum.kPartDocumentObject))

' Set a reference to the component definition.
Dim oCompDef As PartComponentDefinition
oCompDef = oPartDoc.ComponentDefinition

' Create a new sketch on the X-Y work plane.
Dim oSketch As PlanarSketch
oSketch = oCompDef.Sketches.Add(oCompDef.WorkPlanes.Item(3))

' Set a reference to the transient geometry object.
Dim oTransGeom As TransientGeometry
oTransGeom = ThisApplication.TransientGeometry

' Create a text box at (0,0)
Dim oTextBox As TextBox
oTextBox = oSketch.TextBoxes.AddFitted(oTransGeom.CreatePoint2d(0, 0), "Inventor")

' Add the text box to an object collection
Dim oPaths As ObjectCollection
oPaths = ThisApplication.TransientObjects.CreateObjectCollection
oPaths.Add(oTextBox)

' Create a profile.
Dim oProfile As Profile
oProfile = oSketch.Profiles.AddForSolid(False, oPaths)

' Extrude the text.
Dim oExtrudeDef As ExtrudeDefinition
oExtrudeDef = oCompDef.Features.ExtrudeFeatures.CreateExtrudeDefinition( _
    oProfile, PartFeatureOperationEnum.kJoinOperation)
oExtrudeDef.SetDistanceExtent(0.25, PartFeatureExtentDirectionEnum.kNegativeExtentDirection)
Dim oExtrude As ExtrudeFeature
oExtrude = oCompDef.Features.ExtrudeFeatures.Add(oExtrudeDef)

The changes boil down to: removing the Sub/End Sub wrapper, removing all the Set keywords, removing the Call, adding parentheses on oPaths.Add(...), and qualifying the three enumeration constants. Everything else — Dim declarations, line continuations _, method calls — is identical between the two languages.

Second example: retrieving mass properties

This second example retrieves a part's mass properties without "dirtying" the document, that is, without caching the computed results in the file. It is specific to a part here, but the MassProperties object can equally be obtained from an assembly or from a component occurrence.

It illustrates two additional rules: the many Debug.Print statements and the lower-bound array declarations. Here is the original VBA code:

Public Sub GetPartMassPropsWithoutDirtying()
    ' Set a reference to the part document.
    ' This assumes a part document is active.
    Dim oPartDoc As PartDocument
    Set oPartDoc = ThisApplication.ActiveDocument

    ' Set a reference to the mass properties object.
    Dim oMassProps As MassProperties
    Set oMassProps = oPartDoc.ComponentDefinition.MassProperties

    'Check if mass property results are already available
    'at a high accuracy level or better. If so, simply
    'print out the results, else, set a flag to not cache
    'the results in the document.
    If oMassProps.AvailableAccuracy <> k_High And _
      oMassProps.AvailableAccuracy <> k_VeryHigh Then
      ' Set the accuracy to high.
      oMassProps.Accuracy = k_High

      'Set CacheResultsOnCompute property to False
      'so that results are not saved with the document
      'and hence the document is not 'dirtied'.
      oMassProps.CacheResultsOnCompute = False
    End If

    ' Display the mass properties of the part.
    Debug.Print "Area: " & oMassProps.Area

    Debug.Print "Center of Mass: " & _
    oMassProps.CenterOfMass.X & ", " & _
    oMassProps.CenterOfMass.Y & ", " & _
    oMassProps.CenterOfMass.Z

    Debug.Print "Mass: " & oMassProps.Mass
    Dim adPrincipalMoments(1 To 3) As Double
    Call oMassProps.PrincipalMomentsOfInertia(adPrincipalMoments(1), _
    adPrincipalMoments(2), _
    adPrincipalMoments(3))
    Debug.Print "Principal Moments of Inertia: " & _
    adPrincipalMoments(1) & ", " & _
    adPrincipalMoments(2) & ", " & _
    adPrincipalMoments(3)

    Dim adRadiusOfGyration(1 To 3) As Double
    Call oMassProps.RadiusOfGyration(adRadiusOfGyration(1), _
    adRadiusOfGyration(2), _
    adRadiusOfGyration(3))
    Debug.Print "Radius of Gyration: " & _
    adRadiusOfGyration(1) & ", " & _
    adRadiusOfGyration(2) & ", " & _
    adRadiusOfGyration(3)

    Debug.Print "Volume: " & oMassProps.Volume

    Dim Ixx As Double
    Dim Iyy As Double
    Dim Izz As Double
    Dim Ixy As Double
    Dim Iyz As Double
    Dim Ixz As Double
    Call oMassProps.XYZMomentsOfInertia(Ixx, Iyy, Izz, Ixy, Iyz, Ixz)
    Debug.Print "Moments: "
    Debug.Print " Ixx: " & Ixx
    Debug.Print " Iyy: " & Iyy
    Debug.Print " Izz: " & Izz
    Debug.Print " Ixy: " & Ixy
    Debug.Print " Iyz: " & Iyz
    Debug.Print " Ixz: " & Ixz
End Sub

And the same code converted for iLogic:

' Set a reference to the part document.
' This assumes a part document is active.
Dim oPartDoc As PartDocument
oPartDoc = ThisApplication.ActiveDocument

' Set a reference to the mass properties object.
Dim oMassProps As MassProperties
oMassProps = oPartDoc.ComponentDefinition.MassProperties

' Check if mass property results are already available
' at a high accuracy level or better. If so, simply
' print out the results, else, set a flag to not cache
' the results in the document.
If oMassProps.AvailableAccuracy <> MassPropertiesAccuracyEnum.k_High And _
  oMassProps.AvailableAccuracy <> MassPropertiesAccuracyEnum.k_VeryHigh Then
  ' Set the accuracy to high.
  oMassProps.Accuracy = MassPropertiesAccuracyEnum.k_High

  ' Set CacheResultsOnCompute property to False
  ' so that results are not saved with the document
  ' and hence the document is not 'dirtied'.
  oMassProps.CacheResultsOnCompute = False
End If

' Display the mass properties of the part.
Logger.Info("Area: " & oMassProps.Area)

Logger.Info("Center of Mass: " & _
  oMassProps.CenterOfMass.X & ", " & _
  oMassProps.CenterOfMass.Y & ", " & _
  oMassProps.CenterOfMass.Z)

Logger.Info("Mass: " & oMassProps.Mass)

Dim adPrincipalMoments(3) As Double
oMassProps.PrincipalMomentsOfInertia(adPrincipalMoments(1), _
  adPrincipalMoments(2), _
  adPrincipalMoments(3))
Logger.Info("Principal Moments of Inertia: " & _
  adPrincipalMoments(1) & ", " & _
  adPrincipalMoments(2) & ", " & _
  adPrincipalMoments(3))

Dim adRadiusOfGyration(3) As Double
oMassProps.RadiusOfGyration(adRadiusOfGyration(1), _
  adRadiusOfGyration(2), _
  adRadiusOfGyration(3))
Logger.Info("Radius of Gyration: " & _
  adRadiusOfGyration(1) & ", " & _
  adRadiusOfGyration(2) & ", " & _
  adRadiusOfGyration(3))

Logger.Info("Volume: " & oMassProps.Volume)

Dim Ixx As Double
Dim Iyy As Double
Dim Izz As Double
Dim Ixy As Double
Dim Iyz As Double
Dim Ixz As Double
oMassProps.XYZMomentsOfInertia(Ixx, Iyy, Izz, Ixy, Iyz, Ixz)
Logger.Info("Moments: ")
Logger.Info(" Ixx: " & Ixx)
Logger.Info(" Iyy: " & Iyy)
Logger.Info(" Izz: " & Izz)
Logger.Info(" Ixy: " & Ixy)
Logger.Info(" Iyz: " & Iyz)
Logger.Info(" Ixz: " & Ixz)

Here, the constants k_High and k_VeryHigh are qualified with MassPropertiesAccuracyEnum, the Debug.Print statements become Logger.Info(...), the (1 To 3) arrays become (3), and the Call keywords before PrincipalMomentsOfInertia, RadiusOfGyration and XYZMomentsOfInertia disappear — since those methods return their results through ByRef arguments, you call them directly.

In summary

Inventor's local documentation is a goldmine of examples that is often overlooked because they are written in VBA. By keeping these few rules in mind, you can turn them into working iLogic rules in a matter of seconds:

  1. Remove the Sub / End Sub declaration.
  2. Remove the Set keywords.
  3. Remove the Call keywords.
  4. Add the missing parentheses to method calls (including no-argument calls: AddForSolid()).
  5. Qualify enumeration constants with their type.
  6. Replace Debug.Print with log entries (Logger.Info).
  7. Adapt lower-bound array declarations (1 To n → upper bound only).
  8. Check multiple declarations (Dim a, b As Type) whose meaning differs between the two languages.

Coup de pouce Need an Inventor (iLogic, .NET, VBA, C++) or Fusion 360 (Python, C++) development? Contact me for a free quote.

On the same topic