Influenced by the topic “Gemini for macro code?” I decided to write a macro that I needed for a long time in Gemini.
The macro should go through all the components of the assembly at all levels and find the parts whose construction tree is in a rollback state. Then it should isolate the found parts in the model window and ask: Roll back their construction tree down or just leave them isolated.
Gemini didn’t cope cleanly:
-
He decided to use the built-in Message box from SolidWorks, and gave fictitious names to the icons of the message body (swMessageBoxIcon_Warning, swMessageBoxBtn_Ok).
-
He made up “swPart.FeatureManager.RollbackState”, as if there is a function that allows you to immediately find out the rollback state for a component (if you get it in swPart as SldWorks.PartDoc)
-
I pointed out to him in two messages that such a method does not exist, but he resisted. We had already started arguing
. He still did not admit that this was fiction
. -
I had to offer him a ready-made ISRollBack function and just force him to use it
. He said that this was a bad idea
, but accepted it
. -
He also came up with “RollForward” and I had to tell him about: EditRollback(swMoveRollbackBarToEnd, “”), this time he agreed the first time and rewrote the code as needed
. -
Everything else is done correctly, with abundant comments.
-
In the end, josh proposed a reverse search function with FeatureByPositionReverse(0), which is more efficient, for the reasons described in his answer.
' Forces explicit declaration of all variables, which helps prevent errors
Option Explicit
' ' ================================================================================
' Optimized function to check the rollback state of a part.
' Based on the principle that if any feature is rolled back, the last one must be.
' It takes a model document and returns True if it is rolled back, otherwise False.
' ================================================================================
Function ISRollBack(Mod2 As SldWorks.ModelDoc2) As Boolean
' By default, assume it is not rolled back
ISRollBack = False
' Check that a part document was passed
If Mod2 Is Nothing Or Mod2.GetType <> swDocPART Then Exit Function
Dim swLastFeature As SldWorks.Feature
' Get the very last feature in the FeatureManager design tree
Set swLastFeature = Mod2.FeatureByPositionReverse(0)
' If the last feature exists, its IsRolledBack status reflects the entire part's state.
If Not swLastFeature Is Nothing Then
ISRollBack = swLastFeature.IsRolledBack
End If
End Function
' ================================================================================
' Main macro procedure
' ================================================================================
Sub main()
' Variable declaration
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swAssembly As SldWorks.AssemblyDoc
Dim vComponents As Variant
Dim swComponent As SldWorks.Component2
Dim swCompModel As SldWorks.ModelDoc2
Dim i As Long
Dim bAppend As Boolean
' Collection to store components with a rollback state
Dim rolledBackComponents As New Collection
' Get the current instance of the SolidWorks application
Set swApp = Application.SldWorks
' Get the active document
Set swModel = swApp.ActiveDoc
' --- Initial Checks ---
' Check if any document is open
If swModel Is Nothing Then
swApp.SendMsgToUser2 "An assembly document must be open.", swMessageBoxIcon_Warning, swMessageBoxBtn_Ok
Exit Sub
End If
' Check if the active document is an assembly
If swModel.GetType <> swDocASSEMBLY Then
swApp.SendMsgToUser2 "This macro is intended to work only with assemblies (*.sldasm).", swMessageBoxIcon_Warning, swMessageBoxBtn_Ok
Exit Sub
End If
' --- Main Logic ---
' Cast the ModelDoc2 type to AssemblyDoc to access components
Set swAssembly = swModel
' Get an array of all components at all levels (True = recursive).
' Set to False to only check the top level of the assembly.
vComponents = swAssembly.GetComponents(True)
' Check if there are any components in the assembly
If IsEmpty(vComponents) Then
swApp.SendMsgToUser2 "No components found in the assembly to check.", swMessageBoxIcon_Info, swMessageBoxBtn_Ok
Exit Sub
End If
' Start iterating through all components
For i = 0 To UBound(vComponents)
Set swComponent = vComponents(i)
' Check that the component is resolved and not suppressed
If Not swComponent Is Nothing Then
If swComponent.IsSuppressed = False Then
' Get the model document for the component
Set swCompModel = swComponent.GetModelDoc2
' Ensure the document is loaded (e.g., for lightweight components)
If Not swCompModel Is Nothing Then
' Check that the component is a part (*.sldprt)
If swCompModel.GetType = swDocPART Then
' Call the function to check the rollback state
If ISRollBack(swCompModel) Then
' If the function returns True, add the component to the collection
rolledBackComponents.Add swComponent
End If
End If
End If
End If
End If
Next i
' --- Processing Results ---
' Check if any parts in a rollback state were found
If rolledBackComponents.Count > 0 Then
' 1. Zoom to fit the model to the screen
swModel.ViewZoomtofit2
' 2. Select all found components in the assembly tree
bAppend = False
For Each swComponent In rolledBackComponents
' Select4 is the modern selection method. The first parameter (Append) determines
' whether to add to the existing selection or start a new one.
swComponent.Select4 bAppend, Nothing, False
bAppend = True ' After the first component, all subsequent ones are added to the selection
Next swComponent
' 3. Isolate the selected components
swModel.Extension.RunCommand swCommands_Comp_Isolate, "Isolate"
' 4. Ask the user for confirmation
' Build the message for the user
Dim msg As String
Dim userResponse As Long
msg = "Found " & rolledBackComponents.Count & " parts in a rollback state." & vbCrLf & vbCrLf & "YES - Roll forward all found parts." & vbCrLf & "NO - Leave the found parts isolated for review."
' Show a dialog box with a question (Yes/No)
userResponse = MsgBox(msg, vbYesNo + vbQuestion, "Rolled Back Parts Detected")
' 5. Perform actions based on the response
' If the user clicked "Yes"
If userResponse = vbYes Then
' Exit the isolate mode
swModel.Extension.RunCommand swCommands_Comp_Isolate_Exit, "Exit Isolate"
' Clear the selection so that components do not remain highlighted
swModel.ClearSelection2 True
Dim swRolledBackPartDoc As SldWorks.PartDoc
' Iterate through all the found components
For Each swComponent In rolledBackComponents
' Get the part document from the component
Set swRolledBackPartDoc = swComponent.GetModelDoc2
If Not swRolledBackPartDoc Is Nothing Then
' Perform the roll forward
swRolledBackPartDoc.FeatureManager.EditRollback swMoveRollbackBarToEnd, ""
End If
Next swComponent
MsgBox "Operation completed." & vbCrLf & "All " & rolledBackComponents.Count & " parts have been rolled forward." & vbCrLf & "Do not forget to save the assembly and the modified parts.", vbInformation, "Done"
Else
' If the user clicked "No", do nothing and leave the components isolated for manual review.
End If
Else
' If no parts in a rollback state were found
MsgBox "Scan complete. No parts in a rollback state were found.", vbInformation, "Scan Complete"
End If
End Sub
icon
![]()
RollDownAllComponents.zip (908 Bytes)