Quantity Macro

We have a macro that someone did that goes thru the assembly & counts all of the components and adds a property to the parts with the quantity that we use in our part callouts. The one thing that this does not do is to take into account those parts that are marked “EXCLUDE FROM BOM”. Does anyone have a macro or can someone look at the macro we have & modify it so that it doesn’t include those parts marked exclude. I’ve included the macro that we have. If you’re able thank you many times over & if you’re not able thank you as well.
QtyMacroFeature.swp.zip (18.2 KB)

I’d try replacing the lines:

If tCmp.ReferencedConfiguration = Cfg Then
	cCnt = cCnt + 1
End If

With these:

If tCmp.ReferencedConfiguration = Cfg Then
	Dim configOpt as Integer
	Dim configNames as Object
	If Not tComp.GetExcludeFromBOM2(configOpt, configNames) Then
		cCnt = cCnt + 1
	End If
End If

Austin,
I tried that and it failed. The debugger came up & it did not have a variable created for the tCOMP so I changed that to just tCmp like the other lines above it had but it still failed. When I changed that & ran it, the debugger came up & errored in this area telling me that theres no if with the Next & then no if with the Else. I ran the debugger on the original & it didn’t fail in those two areas.

Next j
CmpDoc.AddCustomInfo3 Cfg, “AutoQty”, 30, “”
CmpDoc.AddCustomInfo3 Cfg, “QtyIn”, 30, “”
CmpDoc.CustomInfo2(Cfg, “AutoQty”) = cCnt
CmpDoc.CustomInfo2(Cfg, “QtyIn”) = Assembly.GetTitle & " Cfg " & Assembly.ConfigurationManager.ActiveConfiguration.Name
End If
Else

Yes, I also downloaded “QtyMacroFeature.swp.zip”
and replaced

             'If tCmp.ReferencedConfiguration = Cfg Then
              'cCnt = cCnt + 1
             'End If

with this

              If tCmp.ReferencedConfiguration = Cfg Then
                Dim configOpt As Integer
                Dim configNames As Object
                If Not tComp.GetExcludeFromBOM2(configOpt, configNames) Then
                    cCnt = cCnt + 1
                 End If
              End If

and When I changed the
Component Properties.jpg
status of one of the items it still wanted to ignore that I did not want to include it when I ran the macro
It counted the excluded item anyway.

Sorry, John. Try this?

If tCmp.ReferencedConfiguration = Cfg Then
	If Not tCmp.GetExcludeFromBOM2(swInConfigurationOpts_e.swThisConfiguration, tCmp.ReferencedConfiguration) Then
		cCnt = cCnt + 1
	End If
End If

I tried also BUT

Using this code:

If tCmp.ReferencedConfiguration = Cfg Then
                  If Not tCmp.GetExcludeFromBOM2(swInConfigurationOpts_e.swThisConfiguration, tCmp.ReferencedConfiguration) Then
                     cCnt = cCnt + 1
                  End If
              End If

When I run it I get this:
---- test — type mismatch 01.jpg

Then the debug This:
---- test — type mismatch 02.jpg

Finally got an assembly made to test it…

            
If Not tCmp.GetExcludeFromBOM2(swInConfigurationOpts_e.swThisConfiguration, tCmp.ReferencedConfiguration)(0) Then
	cCnt = cCnt + 1

Need to add (0) after the function, and it does work for myself (up to that point)

I replaced the lines
“If tCmp.ReferencedConfiguration = Cfg Then
cCnt = cCnt + 1
End If”
with the code you have and it will run. However the quantity I am getting is now 118 for everything including those marked as exclude from BOM.

Do you try.
I am using it and maybe it will answer your question.
MontajaAdetEkleme.swp

I’ve been trying to follow along with what you’re looking to do with this macro so maybe this will help.

This is only the code from your rebuild function, the rest is unmodified.

Public Function swmRebuild(swAppIn As Variant, partIn As Variant, featureIn As Variant) As Variant
    Dim Assembly As ModelDoc2
    Dim myAsy As AssemblyDoc
    Dim myCmps
    Dim Cfg As String
    Dim CmpDoc As ModelDoc2
    Dim i As Long
    Dim j As Long
    Dim cCnt As Long
    Dim NoUp As Long
    Dim myCmp As Component2
    Dim tCmp As Component2
    Dim tm As Double
    tm = Timer
    
    Set swApp = swAppIn
    Set Assembly = swApp.ActiveDoc
    Set myAsy = Assembly
'    If Assembly.ConfigurationManager.ActiveConfiguration.Name <> Assembly.CustomInfo2("", "Cfg4Qty") Then
'     Assembly.Extension.ShowSmartMessage "Qtys not updated due to config", 1000, True, True
'     Exit Function
'    End If
    NoUp = 0
    myCmps = myAsy.GetComponents(False)
    For i = 0 To UBound(myCmps)
     Set myCmp = myCmps(i)
     Debug.Print myCmp.Name & vbTab & "Excl: " & myCmp.ExcludeFromBOM
     If (myCmp.GetSuppression = 3) Or (myCmp.GetSuppression = 2) Then
      cCnt = 0
      Set CmpDoc = myCmp.GetModelDoc
      If Not CmpDoc Is Nothing Then
        Cfg = myCmp.ReferencedConfiguration
        For j = 0 To UBound(myCmps)
         Set tCmp = myCmps(j)
         Debug.Print vbTab & tCmp.Name & vbTab & "Excl: " & tCmp.ExcludeFromBOM
         If tCmp.GetSuppression <> 0 And tCmp.ExcludeFromBOM = False And myCmp.ExcludeFromBOM = False Then
          If tCmp.GetModelDoc2 Is CmpDoc Then
           If tCmp.ReferencedConfiguration = Cfg Then
            cCnt = cCnt + 1
           End If
          End If
         End If
        Next j
        CmpDoc.AddCustomInfo3 Cfg, "AutoQty", 30, ""
        CmpDoc.AddCustomInfo3 Cfg, "QtyIn", 30, ""
        CmpDoc.CustomInfo2(Cfg, "AutoQty") = cCnt
        CmpDoc.CustomInfo2(Cfg, "QtyIn") = Assembly.GetTitle & " Cfg " & Assembly.ConfigurationManager.ActiveConfiguration.Name
      End If
     Else
      NoUp = NoUp + 1
     End If
    Next i
    Assembly.Extension.ShowSmartMessage NoUp & " Parts not updated due to lightweight (" & Timer - tm & "s)", 10000, True, True
    swmRebuild = True
End Function

This will place a 0 quantity for any component that is marked as “Exclude from BOM”. Good luck!

AlexB » Tue Aug 10, 2021 11:24 am

I’ve been trying to follow along with what you’re looking to do with this macro so maybe this will help.

This is only the code from your rebuild function, the rest is unmodified.

That works on my assembly just fine.

Thanks

Just a question?
note question.jpg
note question 02.jpg

The macro you are running creates a macro feature. It’s a feature that contains macro code that runs every time you rebuild. This particular macro feature is set up to always be at the end of the feature tree (to make sure it runs last during rebuild and counts everything). The code contained in the macro feature is what counts parts and writes custom properties. You should not run the macro more than once on any given assembly, unless you delete the macro feature from the tree first. Otherwise you’ll just be counting twice. It will not make your quantities wrong/double/etc, it will just waste time.

A macro feature gets inserted into the feature tree so its “Rebuild” function gets called every time the model/assy rebuilds. In this case, it updates the quantities in child components when the assembly rebuilds to keep them accurate.

Thanks for the explanation Josh & AlexB
I do not want to co-opt this thread at all, but, I just wanted to see what the macro did or did not do
Turns out it did/does more than I expected.
With AlexB’s correction it did seem to add up correctly on my small assembly
But
I wanted to test it a bit more and ran it on a larger assembly with 5 or so deep sub assemblies and it
and it did not add things up right
(One of the major subassemblies that had subassys under it was excluded but the macro still counted the parts in it
in the total, where as the SW BOM did not count the excluded sub assy parts)
I did dissect the macro a bit more to see how… VB SW macro code works… I probably could read a book…
Or well nowadays watch a you tube to learn… but I like to take things apart to see how they work.
Thanks again for the explanation.

I added a bit of code to help check for the top level component’s “Exclude from BOM” value. This should work for the rebuild function now. I tested it on an assembly that was a couple levels.

Public Function swmRebuild(swAppIn As Variant, partIn As Variant, featureIn As Variant) As Variant
    Dim Assembly As ModelDoc2
    Dim myAsy As AssemblyDoc
    Dim myCmps
    Dim Cfg As String
    Dim CmpDoc As ModelDoc2
    Dim i As Long
    Dim j As Long
    Dim cCnt As Long
    Dim NoUp As Long
    Dim myCmp As Component2
    Dim tCmp As Component2
    Dim parentCmp As Component2
    
    Dim tm As Double
    tm = Timer
    
    Set swApp = swAppIn
    Set Assembly = swApp.ActiveDoc
    Set myAsy = Assembly
'    If Assembly.ConfigurationManager.ActiveConfiguration.Name <> Assembly.CustomInfo2("", "Cfg4Qty") Then
'     Assembly.Extension.ShowSmartMessage "Qtys not updated due to config", 1000, True, True
'     Exit Function
'    End If
    NoUp = 0
    myCmps = myAsy.GetComponents(False)
    For i = 0 To UBound(myCmps)
     Set myCmp = myCmps(i)
     'Debug.Print myCmp.Name & vbTab & "Excl: " & myCmp.ExcludeFromBOM
     
     Set parentCmp = myCmp
     While Not parentCmp.GetParent Is Nothing
        Set parentCmp = parentCmp.GetParent ' Get the top level parent to so we can check for BOM exclusion
     Wend
     
     If (myCmp.GetSuppression = 3) Or (myCmp.GetSuppression = 2) Then
      cCnt = 0
      Set CmpDoc = myCmp.GetModelDoc
      If Not CmpDoc Is Nothing Then
        Cfg = myCmp.ReferencedConfiguration
        For j = 0 To UBound(myCmps)
         Set tCmp = myCmps(j)
         'Debug.Print vbTab & tCmp.Name & vbTab & "Excl: " & tCmp.ExcludeFromBOM
         If tCmp.GetSuppression <> 0 And tCmp.ExcludeFromBOM = False And parentCmp.ExcludeFromBOM = False Then
          If tCmp.GetModelDoc2 Is CmpDoc Then
           If tCmp.ReferencedConfiguration = Cfg Then
            cCnt = cCnt + 1
           End If
          End If
         End If
        Next j
        CmpDoc.AddCustomInfo3 Cfg, "AutoQty", 30, ""
        CmpDoc.AddCustomInfo3 Cfg, "QtyIn", 30, ""
        CmpDoc.CustomInfo2(Cfg, "AutoQty") = cCnt
        CmpDoc.CustomInfo2(Cfg, "QtyIn") = Assembly.GetTitle & " Cfg " & Assembly.ConfigurationManager.ActiveConfiguration.Name
      End If
     Else
      NoUp = NoUp + 1
     End If
    Next i
    Assembly.Extension.ShowSmartMessage NoUp & " Parts not updated due to lightweight (" & Timer - tm & "s)", 10000, True, True
    swmRebuild = True
End Function

I replaced this area
image.png
with the text you included here plus the others up the way & tried to run it. It didnt appear to work correct as there was no macro feature created at the bottom of the tree. With all of the changes that are up thru the posts can you attach your complete macro so I can make sure I didn’t miss anything along the way. Thanks.

The full macro code is below. It creates the macro feature at the bottom of the feature tree as in the image below.
image.png

Option Explicit

Dim swApp As SldWorks.SldWorks
Dim Part As ModelDoc2
Dim fso As New Scripting.FileSystemObject

Sub main()
    Dim myPath As String
    Dim myFolder As String
    Dim myFeat As Feature
    Dim myMethods(8) As String
    Dim vMethods As Variant
    
    Set swApp = Application.SldWorks
    Set Part = swApp.ActiveDoc
    
    Dim Names As Variant
    Dim Types As Variant
    Dim Values As Variant
    Dim vEditBodies As Variant
    Dim dimTypes As Variant
    Dim dimValue As Variant
    Dim icons(2) As String
    Dim vIcons As Variant
    
    Names = Empty
    Types = Empty
    Values = Empty
    vEditBodies = Empty

    myPath = swApp.GetCurrentMacroPathName
    myFolder = swApp.GetCurrentMacroPathFolder & "\"
    
    myMethods(0) = myPath
    myMethods(1) = "MacroFeatureModule"
    myMethods(2) = "swmRebuild"
    myMethods(3) = myPath
    myMethods(4) = "MacroFeatureModule"
    myMethods(5) = "swmEdit"
    myMethods(6) = ""
    myMethods(7) = ""
    myMethods(8) = ""
    vMethods = myMethods
    
    icons(0) = myFolder + "QtyMacroFeature.bmp"
    icons(1) = myFolder + "QtyMacroFeature.bmp"
    icons(2) = myFolder + "QtyMacroFeature.bmp"
    vIcons = icons


    Set myFeat = Part.FeatureManager.InsertMacroFeature3("QtyMacro", "", vMethods, Names, Types, Values, dimTypes, dimValue, vEditBodies, vIcons, swMacroFeatureByDefault + swMacroFeatureAlwaysAtEnd + swMacroFeatureEmbedMacroFile)
    
End Sub

Public Function swmRebuild(swAppIn As Variant, partIn As Variant, featureIn As Variant) As Variant
    Dim Assembly As ModelDoc2
    Dim myAsy As AssemblyDoc
    Dim myCmps
    Dim Cfg As String
    Dim CmpDoc As ModelDoc2
    Dim i As Long
    Dim j As Long
    Dim cCnt As Long
    Dim NoUp As Long
    Dim myCmp As Component2
    Dim tCmp As Component2
    Dim parentCmp As Component2
    
    Dim tm As Double
    tm = Timer
    
    Set swApp = swAppIn
    Set Assembly = swApp.ActiveDoc
    Set myAsy = Assembly
'    If Assembly.ConfigurationManager.ActiveConfiguration.Name <> Assembly.CustomInfo2("", "Cfg4Qty") Then
'     Assembly.Extension.ShowSmartMessage "Qtys not updated due to config", 1000, True, True
'     Exit Function
'    End If
    NoUp = 0
    myCmps = myAsy.GetComponents(False)
    For i = 0 To UBound(myCmps)
     Set myCmp = myCmps(i)
     'Debug.Print myCmp.Name & vbTab & "Excl: " & myCmp.ExcludeFromBOM
     
     Set parentCmp = myCmp
     While Not parentCmp.GetParent Is Nothing
        Set parentCmp = parentCmp.GetParent ' Get the top level parent to so we can check for BOM exclusion
     Wend
     
     If (myCmp.GetSuppression = 3) Or (myCmp.GetSuppression = 2) Then
      cCnt = 0
      Set CmpDoc = myCmp.GetModelDoc
      If Not CmpDoc Is Nothing Then
        Cfg = myCmp.ReferencedConfiguration
        For j = 0 To UBound(myCmps)
         Set tCmp = myCmps(j)
         'Debug.Print vbTab & tCmp.Name & vbTab & "Excl: " & tCmp.ExcludeFromBOM
         If tCmp.GetSuppression <> 0 And tCmp.ExcludeFromBOM = False And parentCmp.ExcludeFromBOM = False Then
          If tCmp.GetModelDoc2 Is CmpDoc Then
           If tCmp.ReferencedConfiguration = Cfg Then
            cCnt = cCnt + 1
           End If
          End If
         End If
        Next j
        CmpDoc.AddCustomInfo3 Cfg, "AutoQty", 30, ""
        CmpDoc.AddCustomInfo3 Cfg, "QtyIn", 30, ""
        CmpDoc.CustomInfo2(Cfg, "AutoQty") = cCnt
        CmpDoc.CustomInfo2(Cfg, "QtyIn") = Assembly.GetTitle & " Cfg " & Assembly.ConfigurationManager.ActiveConfiguration.Name
      End If
     Else
      NoUp = NoUp + 1
     End If
    Next i
    Assembly.Extension.ShowSmartMessage NoUp & " Parts not updated due to lightweight (" & Timer - tm & "s)", 10000, True, True
    swmRebuild = True
End Function

Public Function swmEdit(swAppIn As Variant, partIn As Variant, featureIn As Variant) As Variant
    swmEdit = True
End Function

Hi,
Not for nothing, But I did try the latest, above code, on my “Top level” multi level assy
And it did not count correctly, My “Main” top level, level 1" assy calls out a sub assy, “clamp slide assy”, as a level 2 that it in turn calls out/has in it several of the same sub assemblies, “Clamp assy” a level 3 assy
the level 2 assy “clamp slide” calls to suppress “one” of the “clamp assy” level 3 sub-assemblies in it. Yet the above code still counts the parts in the suppressed level 3 “clamp assy”
Where as the SW BOM does not count the parts in the suppressed sub assy.
I just wanted to try the code to see how it worked, but at least for me it did not.
I am just trying to learn by looking at code.

I’ve tried to reproduce the scenario you’re describing and am getting correct values in my top-level assembly of several hundred parts. I’m not sure what the potential issue is.
image.png