Download as pdf or txt
Download as pdf or txt
You are on page 1of 25

VBA Debugging Tips for SolidWorks API Programmers

Version 1.6

Keith Rice, Technical Director, CADSharp LLC


www.cadsharp.com

Questions to ask yourself if you’re stuck while debugging:

 Are you sure you have arguments correct?


o For example, the following line will fail to select the plane called “Front Plane” because the second
argument should be “PLANE” and not “REFPLANE”.

swModel.Extension.SelectByID2 "Front Plane", "REFPLANE", 0, 0, 0, False, 0, Nothing, 0

 Are you sure the API call does what you think it does?
 Are you sure you are using the correct API call?
o For example, sometimes people get ISldWorks::ActivateDoc and ISldWorks::ActiveDoc confused.
 Are you sure that you aren’t trying to force the method do something it cannot do?
o Example: if you rename a drawing sheet to “Sheet1” but a sheet with that name already exists
o Example: if you have two planar faces selected and try to apply a concentric mate

Error prevention tips:

 Type enumerations and member names in lowercase, so that when your cursor moves the next line, you can see
if certain letters “snapped” to uppercase, indicating that the name is recognized.
 Use Intellisense’s auto-complete to prevent misspellings
 If you use Find and Replace, replace instances one at a time to make sure you don’t accidentally cause an
unintended replacement

Programming Advice

 Focus on code in order of its significance. For example, let’s say you’re going to write a macro that opens,
modifies, and saves every drawing file in a folder specified via a user form. I would recommend writing the code
in this order:
1. Drawing modification (the “meat” of the macro)
2. Traversing every file in a folder
3. GUI (user form)
4. Error handling (e.g., preventing invalid folder paths)
 Modularize your code as much as possible. Ask yourself, “Is this code I plan on using in other macros in the
future?” If yes, then why not take the time to create a separate class, function, or sub-routine for it right now?
 Keep your SolidWorks API code separate from your user form or PropertyManager page event handlers. These
sub-routines should only call other sub-routines. This way, your user interface classes/modules only contain
code related to the interface.
 When you need to experiment with some API calls to learn how they work, create a brand new macro and then
copy the appropriate code to your main macro once the code is working. It will require a little more work
upfront, but in the long run it will save you a great deal of time while trying to debug.
Common VBA Errors

The follow pages are an assortment of compile or run-time errors that may occur while programming SolidWorks using
Visual Basic for Applications.

Page 3 – “Compile error: variable not defined”


Page 4 – "Run-time error '450': Wrong number of arguments or invalid property assignment"
Page 5 – "Run-time error '91': Object variable or With block variable not set"
Page 6 – "Run-time error '5': Invalid procedure call or argument"
Page 7 – "Run-time error '13': Type mismatch"
Page 8 – "Code execution has been interrupted"
Page 9 – "Run-time error '438': Object doesn't support this property or method"
Page 10 – "Run-time error '-2147417848 (80010108)': Automation error The object invoked has disconnected from its
clients"
Page 11 – "Run-time error '98': A property or method call cannot include a reference to a private object, either as an
argument or as a return value"
Page 12 – "Compile error: Method or data member not found"
Page 13 – "Run-time error '424': Object required"
Page 14 – "Compile error: Expected user-defined type, not project"
Page 15 – "Run-time error '-2147417851 (80010105)': Automation error The server threw an exception."
Page 16 – "Run-time error '445': Object doesn't support this action"
Page 17 – "Compile error: Can't find project or library"
Page 18 – “Compile error: User-defined type not defined”
Page 19 – “Run-time error ‘-2147417848 (80010108)’: Method ‘IDisplayWireFrameXOR’ of object ‘IBody2’ failed”
Page 20 – “Compile error: ByRef argument type mismatch”
Page 21 – “Compile error: The code in this project must be updated for use on 64-bit systems. Please review and update
Declare statements and then mark with the PtrSafe attribute.”
Page 22 – “Could not load some objects because they are not available on this machine.”
Page 23 – “Run-time error ‘53’: File not found: <DLL name>”
Page 24 – “Compile error: Expected variable or procedure, not project”
Page 25 – “Compile error: Object library feature not support”
Cause: You may have Option Explicit present and did not declare a variable
Cause: You mistyped something or you forgot to use the Set keyword.
Example:
swFaces = CircularEdgeCollection.Item(i).GetTwoAdjacentFaces(2)

The two should not be in parentheses:


swFaces = CircularEdgeCollection.Item(i).GetTwoAdjacentFaces2

Example:
Dim fso As New FileSystemObject
Dim myFolder As Folder
Dim files As Variant

Set myFolder = fso.GetFolder(strPath)


files = myFolder.Files

The last line should be:


Set files = myFolder.Files
Cause: This occurs when you try to use a function or
property of a variable that is still set to Nothing. That
variable might bave been declared, but no pointer was
ever assigned to it. In other words, you are trying to do
something with Nothing.

Solution: Assign a pointer to the object variable you are


trying to use.

Example 1:

If no part is open and you try to run this you will get the error on line with “Set swCustPropMgr”. The reason is that
swModel was never set since there is no document open. It remains “Nothing”. And you cannot get the custom property
manager of Nothing.

Dim swApp As SldWorks.SldWorks


Dim swModel As SldWorks.ModelDoc2
Dim swCustPropMgr As SldWorks.CustomPropertyManager

Sub main()
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
Set swCustPropMgr = swModel.Extension.CustomPropertyManager("")

Debug.Print swCustPropMgr.Count

End Sub

Example 2:

In this next example, swFace(i+1) should only be swFace(i); the 3rd element does not exist

For i = 0 To 1
Set swFace(i) = swSelMgr.GetSelectedObject6(i + 1, -1)
Set swSurface(i) = swFace(i + 1).GetSurface
Next i

Example 3:

This error can also occur if a method requires an array of doubles and you declare the array as a variant.

Example 4:

This error can also occur when programming attributes. If the attribute definition already exists and fails to register,
IAttributeDef::CreateInstance5 can fail, in which case calls to IAttribute members will cause this error. You may need to
create an attribute definition with a different name or restart SolidWorks.
Example:

Dim vFaces As Variant


Dim i As Integer

For i = 0 To collCircEdges.Count
vFaces = collCircEdges.Item(i)
Next i

Cause: There is nothing in the collection, because the code earlier that added to the collection was commented out.
Cause: This can occur for many different reasons, such as a variable not getting set properly, or a method being run on
an empty variable, or when you accidentally declare an object as the wrong type.

Example 1:

Set vEdges = swFace.GetEdges


Should be
vEdges = swFace.GetEdges

Example 2:

Or, if vCustPropNames is Empty:

vCustPropNames = swCustPropMgr.GetNames
For Each vName In vCustPropNames
Debug.Print " " & vName
Next vName

Example 3:

Set swSurface1 = vFaces(0)


Should be
Set swSurface1 = vFaces(0).GetSurface

Example 4:

Dim swApp as SldWorks.SldWorks


Dim swModel as SldWorks.SldWorks

Sub main()
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
End Sub

You will get a type mismatch error on Set swModel … because you declared swModel as SldWorks.SldWorks and not
SldWorks.ModelDoc2
Cause: If you are trying to traverse entities and you misused or left out the code that gets the next entity.

Example:

Set swLoop = swFace.GetFirstLoop


While Not swLoop Is Nothing
'If Not swLoop.IsOuter Then
' swEdges = swLoop.GetEdges
' For i = 0 To UBound(swEdges)
' Set swCurve = swEdges(i).GetCurve
' If swCurve.IsCircle Then
' 'add to a circular face collection
' collCircEdges.Add swEdges(i)
' End If
' Next i
'End If
swLoop.GetNext
Wend

The line in red should be "Set swLoop = swLoop.GetNext".


Cause: This can occur if the object was not set. This can also occur if you try using an API call that doesn’t exist in the
currently referenced SolidWorks type libraries.

Example 1:

Set swLoop = swFace.GetFirstLoop


While Not swLoop Is Nothing
' Do something here
swLoop = swLoop.GetNext -->Needs "Set" in front
Wend

Example 2:

If swSelMgr.GetSelectedObjectType3(i, -1) = swSelectType_e.swSelEDGES Then


vEdges(i) = swSelMgr.GetSelectedObject6(i, -1)
End If

Need to include Set in front of vEdges(i)

Example 3:

IAssemblyDoc::InsertNewVirtualPart became available in the SolidWorks 2010 type library. If you tried using this API call
in a macro or add-in that is referencing earlier type libraries, you’ll get this error

Example 4:

This can occur if you’re trying to return a variant instead of an object.


Cause: The pointer to an object was lost. (In other words, you lost access to that object’s interface because the object
reference no longer exists.)

Example 1:

Please see the macro examples involving safe entities on how to use safe entities to prevent an entity object pointer
from being destroyed. Certain API calls will destroy object pointer, even though you may not have wanted that to occur.

Example 2:

Also, you may have accidentally destroyed the object pointer yourself in your code. In the following example, the
IModelDoc2 pointer is going to be lost as soon as the document is closed. Then as soon as a member from the
IModelDoc2 interface is called, the error will occur:

Dim swApp As SldWorks.SldWorks


Dim swModel As SldWorks.ModelDoc2

Sub main()
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
swApp.CloseDoc swModel.GetTitle
swModel.ForceRebuild3 False
End Sub

Example 3:

This can also occur in macro features in the rebuild routine, when an IBody2 member is used on an IBody2 pointer that
doesn’t exist anymore. You will need to re-obtain the IBody2 pointer.
Cause: This occurs when a module’s instancing is on Private and not PublicNotCreatable. Frequently this will happen
when a macro written on one computer is run on a different computer. The solution is to change the instancing from
Private to PublicNotCreatable in the class module’s properties.
Cause: You probably misspelled an API call.
Cause: You may have tried to set an object equal to an API call that returns an array, not an object. You may have also
used the argument “Null” instead of Nothing.

Example 1:

Dim swApp As SldWorks.SldWorks


Dim swDoc As SldWorks.ModelDoc2
Dim swPart As SldWorks.PartDoc
Dim swBodies As SldWorks.Body2

Sub main()
Set swApp = Application.SldWorks
Set swDoc = swApp.ActiveDoc
Set swPart = swDoc
Set swBodies = swPart.GetBodies2(SwConst.swBodyType_e.swSolidBody, True)
End Sub

The line in red is incorrect. First, if you look in the API Help, you see that IPartDoc::GetBodies2 returns an array, not an
object. Second, you do not use Set with an array. After the declaration for swBodies is renamed to “vBodies” and
declared as type Variant, the second-to-last line should be corrected to this:

vBodies = swPart.GetBodies2(SwConst.swBodyType_e.swSolidBody, True)

Example 2:

swFilletFeatData.AccessSelections swModel, Null

The last argument should be Nothing. “Null” is not used in VBA to indicate that an object is nothing.

Example 3:

This can also occur if you have unrecognized references checked relating to controls. For example, you may get this with
the Visible property of a control. Try unchecking control-related references and see if the problem disappears.
Cause: This can occur if you write…

Dim swApp as SldWorks

…during your variable declaration, rather than…

Dim swApp As SldWorks.SldWorks.


Cause: This can occur when an object needs to be passed as an argument, and Nothing is passed instead. This can also
occur if you try to run a method on a lightweight component or feature that requires the component or feature to be
fully resolved. This might also occur if IDisplayDimension::GetNext5 is used instead of
IFeature::GetNextDisplayDimension when trying to traverse all dimensions in a feature, beginning with
IFeature::GetFirstDisplayDimension.

Example:

Note: you need to select a face before running this code.

Dim swApp As SldWorks.SldWorks


Dim swModel As SldWorks.ModelDoc2
Dim swSelMgr As SldWorks.SelectionMgr
Dim swLoop As SldWorks.Loop2
Dim swEdge As SldWorks.Edge
Dim vLoops As Variant
Dim vEdges As Variant
Dim i As Integer
Dim j As Integer

Sub main()
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
Set swSelMgr = swModel.SelectionManager

Set swFace = swSelMgr.GetSelectedObject6(1, -1)


vLoops = swFace.GetLoops
For i = 0 To UBound(vLoops)
Set swLoop = vLoops(i)
vEdges = swLoop.GetEdges
For j = 0 To UBound(vEdges)
Set swEdge = vEdges(j)
swLoop.Select Nothing, True, Nothing
Next j
Next i
End Sub

The Nothing in red needs to be changed to “swEdge” (without quotes).


Cause: This occurs when you use an API call that is not available.

Example: If you use the API call “IModelDoc2::Close”. According to the API Help, “This function is currently unavailable.
Use ISldWorks::CloseDoc.”
Cause: This can happen when a macro is run on a new computer. The SolidWorks Type libraries may not be loaded in
correctly. To fix this, remove and re-add the references in ToolsReferences within the VB Editor, or copy all of the
code into a new macro and run that macro.
Causes:

1. This can occur if the appropriate library is not referenced.


2. This can occur if you declare an enumeration but do not include it at the top of the module or class, or at least
above all function, sub-procedure, and property declarations.

Example:

1. The PropertyManagerPage2Handler9 interface became available in SolidWorks 2012. If you had the SolidWorks
2011 type library referenced and tried to implement this interface, you would get this compile error.
Cause: After using two temporary bodies with IBody2::Operations2, the pointer to these temporary bodies is lost. If you
try to re-use these pointers, this error will occur. To prevent this, create a copy of the temporary bodies using
IBody2::Copy and use these copies after using IBody2::Operations2. For more information, see the Remarks section of
the IBody2::Operations2 Help article.
Cause: This occurs if the parameter you are passing is a type other than what is expected by the function.

Example 1: If you pass any data type other than integers to this function, the error will occur:

Function Add(int1 As Integer, int2 As Integer)


Add = int1 + int2
End Function

Example 2: A more subtle instance of this error occurs when you are trying to pass the element of an array that does
correspond to the correct data type, yet a type mismatch error occurs simply because you are passing an array element
and not the element itself. Consider:

Sub main()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.SldWorks
Dim swPart As SldWorks.PartDoc
Dim vBodies As Variant
Dim swBody As SldWorks.Body2
Dim i As Integer

Set swApp = Application.SldWorks


Set swModel = swApp.ActiveDoc
Set swPart = swModel
Set vBodies = swPart.GetBodies2(swAllBodies, False)
If IsEmpty(vBodies) = False Then
For i = 0 To UBound(vBodies)
Debug.Print GetBodyName(vBodies(i))
Next i
End If
End Sub

Sub GetBodyName(body As SldWorks.Body2)


GetBodyName = body.Name2
End Sub

To fix this, vBodies(i) should be assigned to an IBody2 variable and then that IBody2 variable should be passed to the
function.
Cause: This occurs if your macro makes calls to a DLL without using the PtrSafe keyword in the Declare statement. This is
necessary when using VBA7, which is the version of VBA used in SolidWorks starting with SolidWorks 2013.

Example: Using the SHGETPathFromIDList Win32 API call looks different on VBA6 (32 bit) versus VBA7 (64 bit). Changes
are indicated in red.

32 bit
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal
pszPath As String) As Long

64 bit
Private Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As
LongPtr, ByVal pszPath As String) As LongPtr

To summarize the necessary changes:


1. The PtrSafe keyword must be present after the Declare keyword.
2. All Long return values associated with the DLL must be changed from Long to LongPtr. This includes return
values, arguments, and any other Long variables associated with the function. If you fail to make all of the
necessary data type conversions, you may get a type mismatch error or SolidWorks may even crash.

To learn more about VBA and 64 bit compatibility, visit this article.
Cause: This can occur if your macro user form contains ActiveX controls that are not compatible with VBA7 (the 64 bit
version of VBA included in SolidWorks 2013 and later).

Solution: There are no simple workarounds to this issue, but here are some ideas:

1. Find an alternative control that is 64 bit compatible


2. Contact the control creator and ask them to recompile for 64 bit*
3. If you wrote the control yourself, recompile it for 64 bit
4. Write your own control that offers the same functionality
5. Convert your VBA macro to VB.NET or C# and use a similar control

*Note that Microsoft has chosen not recompile its Microsoft Common Controls (mscomctl.ocx) for 64 bit compatibility.
Cause: This can occur for two reasons.

1. Your macro calls a function from a DLL, but the path for that DLL in its Declare statement is invalid.
2. Your macro calls a function from a DLL that is not 64 bit compatible.

Solution: Corresponding to the aforementioned causes:

1. Correct the search path in your Declare statement, or change the path to include on the DLL name and move the
DLL to your C:\Windows\System32 folder.
2. You will need to obtain a 64 bit version of the DLL. See the workaround suggestions for the previous issue for a
known list.
Cause: One of your variable / sub-procedure / function names is the same name as your project name.

Solution: Change either your variable / sub-procedure / function name or the project name to prevent the conflict.

Example: In the image below, note that the project name (left) is the same as a variable name (right).
Cause: Your macro contains bad references.

Solution: In the VB Editor, go to ToolsReferences and uncheck any unused or missing references. If missing, replace
them with the correct references.

Example: This line of code in a macro created in SolidWorks 2016 was generating the error above:

Set swApp = Application.SldWorks

Unchecking the SOLIDWORKS Utilities 2015 Type Library from ToolsReferences resolved the problem.

You might also like