Continue to Site

Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations cowski on being selected by the Eng-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to traverse assembly to check custom properties 2

Status
Not open for further replies.

shawn76o

Nuclear
Nov 14, 2006
31
I'm new to Solidworks API, and I've checked the built-in API help, searched these forums, and Google'd the web for help but found nothing that suits my needs so far.

I'm looking for a code example that traverses an open assembly in SW and scans every component for it's custom properties. For example, if it finds the "Material" property to have a value of "20115", then it looks for Custom Properties "Volume" and "Thickness" to have valid values as well.

Can anyone help me with this?
 
Replies continue below

Recommended for you

You want to look up "Assembly- traverse" in the API help. There are examples of code to get you started. Getting and setting custom properties of files can be performed on each file during the traversal.
I'll look for a project I found on a German site that was very helpful, although you have to tranlate the cooments in the code.

 
Thanks for all the replies. I realize I'm probably being naive, but I'm hoping for an example that is more bare-bones and just scans the whole assembly. I want something like that, where I have something simple to start with, and I can add the functionality as I learn and go along.

Gwubs, I've already looked up "Assembly - Traverse" in the SW API help, and I didn't understand why it was outputting components as (example) "AA00007-2-3/AB00007-1-1/AB00007-S1-1" instead of "AA0007-2-3" ? I couldn't figure that out.
Also, Lenny's AssemblyBOM macro looks like it traverses the assembly the way I want to, but like I said - I am new to the SW API, and I need something SIMPLER to start with. I have the same dilemna with TheTick's suggested example.
I'm not sure if there exists such a simplified example, but - I just want to traverse an assembly, opening each part one-by-one from the top down. If I could find an example that does just that (and nothing else) so I can understand the process, that would be PERFECT!

Thank you guys for your help. I really do appreciate it!
 
I found an example, I think it's the closest thing to what I'm looking for. Only problem is, when I run it I get an error:

Object variable or With block variable not set (Error 91)

This is the code:

Const swDocASSEMBLY = 2

Dim swApp As SldWorks.SldWorks
Dim ModelDoc As SldWorks.ModelDoc2
Dim childlevel As Integer
Dim strText As Variant

Sub Main()

Dim swRootComp As SldWorks.Component2
Dim swConf As SldWorks.Configuration
Dim ModelLevel As Integer
Set swApp = Application.SldWorks
Set ModelDoc = swApp.ActiveDoc


If Not ModelDoc Is Nothing Then
If ModelDoc.GetType = swDocASSEMBLY Then
Set swConf = ModelDoc.GetActiveConfiguration
Set swRootComp = swConf.GetRootComponent
'Traverse the assembly
TraverseComponent swRootComp
End If
End If

'ModelDoc.AddCustomInfo3 "", "Level", swCustomInfoText, ""
'ModelLevel = (childlevel + 1)
'ModelDoc.CustomInfo2("", "Level") = ModelLevel
'MsgBox ("ASSEMBLY FILE NOT SKIPPED")


End Sub


Sub TraverseComponent(swComp As SldWorks.Component2)
'this recursively traverses all of the components in an assembly
Dim vChildComp As Variant
Dim swChildComp As SldWorks.Component2
Dim childlevel_temp As String
Dim ModDoc As Object ' ModelDoc2 of child component
Dim ModName As String


vChildComp = swComp.GetChildren
childlevel_temp = 0
childlevel = 0
For i = 0 To UBound(vChildComp)
Set swChildComp = vChildComp(i)
ModName = swChildComp.Name
Set ModDoc = swChildComp.GetModelDoc()
childlevel_temp = CInt(ModDoc.GetCustomInfoValue("", "Level"))
If childlevel_temp > childlevel Then
childlevel = childlevel_temp
End If
Next i
End Sub


I haven't figured out what is wrong... I've SET the ModDoc object - any ideas?
 
To traverse a tiered structure like an assembly, the "TraverseComponent" sub will have to call itself if there are components on the next level. I don't see that in your code.
 
One possibility is that when you execute the macro it's not actually running "main" first. Try assigning the macro to a button. This allows you to specify which method the execution starts in.

A simpler method than traversing the assembly would be to traverse all open files. That way you don't have to worry about levels of subassemblies.

When you open an assembly, SolidWorks actually opens all unsuppressed components of that assembly, whether parts or subassemblies, in memory. These can be interacted with by the API code without giving them a visible window.

What this means is that as long as you don't have any parts open that you don't want to check custom properties on you could use a bit simpler code. If you're interested I can post some such code tomorrow.
 
Here's code that will traverse all open parts. I forgot that I had posted it (well, something much like it) previously. There may be some extra variables declared. I cut this out of some longer code.

Code:
Sub AllOpenParts()
Dim swDoc As SldWorks.ModelDoc2
Dim swAllDocs As EnumDocuments2
Dim FirstDoc As SldWorks.ModelDoc2
Dim dummy As Boolean
Dim NumDocsReturned As Long
Dim DocCount As Long
Dim i As Long
Dim sMsg As String
Dim swApp As SldWorks.SldWorks

Set swApp = Application.SldWorks
Set swAllDocs = swApp.EnumDocuments2
Set FirstDoc = swApp.ActiveDoc

DocCount = 0
swAllDocs.Next 1, swDoc, NumDocsReturned
While NumDocsReturned <> 0 [green]
    'Replace these comment lines with
    'the custom property actions you wish to take.[/green]
    swAllDocs.Next 1, swDoc, NumDocsReturned
    DocCount = DocCount + 1
Wend

sMsg = DocCount & " Documents are open."
MsgBox sMsg

End Sub
 
Thanks for your help everyone. I do appreciate the time you've taken. With your help, I've figured out what I needed to do.
Now I have another question. First, here's the code I've used so far to traverse an assembly and it's components:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Const swDocAssembly = 2

Option Explicit
Public docType As Integer
Public swApp As SldWorks.SldWorks
Public swModel As SldWorks.ModelDoc2
Dim returnOK As Boolean
Public Part As Object

Private Sub Main()

Dim swRootComp As SldWorks.Component2
Dim swConf As SldWorks.Configuration


Set swApp = CreateObject("SldWorks.Application")
swApp.visible = True
Set swModel = swApp.ActiveDoc

If swModel Is Nothing Then
Call MsgBox("A SolidWorks document needs to be loaded!", vbExclamation, "Custom Properties") ' Display error message
returnOK = False
swApp.visible = True

End ' If no model currently loaded, then exit
Else
docType = swModel.GetType
If (docType = swDocAssembly) Then
Set swConf = swModel.GetActiveConfiguration
Set swRootComp = swConf.GetRootComponent

Open "C:\BOM Export Files\Output.txt" For Output Access Write Lock Write As #1


'Traverse assembly
TraverseComponent swRootComp

Close #1

Else
MsgBox ("File is not assembly")
End 'Exit if file is not assembly
'Code for parts and drawings to be added later


End If
End If

End Sub

Sub TraverseComponent(swComp As SldWorks.Component2)
'this recursively traverses all of the components in an assembly
Dim vChildComp As Variant
Dim swChildComp As SldWorks.Component2
Dim ModName As String
Dim i As Integer
Dim vChildComp2 As Variant
Dim i2 As Integer
Dim swChildComp2 As SldWorks.Component2
Dim vChildComp3 As Variant
Dim i3 As Integer
Dim swChildComp3 As SldWorks.Component2

'Get the childrent of this component
vChildComp = swComp.GetChildren

'Get children on 1st level
For i = 0 To UBound(vChildComp)
Set swChildComp = vChildComp(i)
ModName = swChildComp.Name
'Set the Part object
Set Part = swChildComp.GetModelDoc()
If Not swChildComp.IsSuppressed() And Not swChildComp.ExcludeFromBOM Then
Print #1, swChildComp.Name
'Set the Child variant
vChildComp2 = swChildComp.GetChildren
'Get children on 2nd level
For i2 = 0 To UBound(vChildComp2)
Set swChildComp2 = vChildComp2(i2)

Set Part = swChildComp2.GetModelDoc()

If Not swChildComp2.IsSuppressed() And Not swChildComp2.ExcludeFromBOM Then
Print #1, swChildComp2.Name
'Set the Child variant
vChildComp3 = swChildComp2.GetChildren
'Get childrent on 3rd level
For i3 = 0 To UBound(vChildComp3)
Set swChildComp3 = vChildComp3(i3)

Set Part = swChildComp3.GetModelDoc()

If Not Part.IsSuppressed And Not Part.ExcludeFromBOM Then
Print #1, swChildComp3.Name
End If
Next i3

End If
Next i2
End If
Next i
End Sub

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

The problem I'm having is where I use If...Then statements to skip any SUPRESSED components and those with an "EXCLUDE FROM BOM" property defined.
I've set a watch to "trip" when either "suppressed" or "exclude" is TRUE. The problem is that (with my IF NOT and AND NOT statements) the statement is supposed to execute as long as the component is neither suppressed nor excluded from BOM, but it executes regardless of the returned value.
How can this be? I've tried running the same code with different expressions (If Not 2 = 3 And Not 3 = 3 Then) and I get the same results...

Help!!

Thanks again :)
 
I have run into issues processing boolean operations in SW VBA. They are spotty and intermittent and hard to pin down, though. It's not nearly as elegant, but you may want to try a nested if with true comparisons, like:

Code:
If (false = swChildComp.IsSuppressed()) then
  If (false = swChildComp.ExcludeFromBOM) Then
  'do your stuff here
  end if
end if
 
Try adding some parentheses to ensure that VB is interpreting it as you intend. For instance:
Code:
(Not swChildComp.IsSuppressed()) And (Not swChildComp.ExcludeFromBOM)

An alternative and logically equivalent form would be:
Code:
Not (swChildComp.IsSuppressed() Or swChildComp.ExcludeFromBOM)

Eric
 
Thanks handleman, your suggestion worked nicely.
'''''''''''''''''''''''''''''''''''''''''''
If (False = swChildComp.IsSuppressed) And _
(False = swChildComp.ExcludeFromBOM) Then

'some actions

End If
'''''''''''''''''''''''''''''''''''''''''''''

For some reason, that changes the way the expressions are evaluated. Could this have something to do with the way the VBA compiler handles "order of execution" or maybe "short-circuiting"? I found some information that may shed some light on this anomaly, but I haven't had time to read it thoroughly.


For now, I've bookmarked the link so I can get back to work on this project. Thanks for the help everyone!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor