I have recently written a couple of, what I call, “Quick and Dirty” macros. These are so quick, all you have to do is make a selection and run the macro. In this article, I am going to discuss some of the thoughts and development processes behind writing one of these macros.
Please keep in mind that not all of the information you need is included in this article. There may be a few cases where I jumped to the code that I used without a thorough explanation of how I go there. The information provided here should be a good guideline for
The Setup:
SolidWorks allows you to have multiple visibility (display) schemes that allow you to change many of the visibility properties of components within an assembly. You can use DisplayStates to do this, but for the purposes of this article, we will be showing and hiding components within the current DisplayState of the current assembly.
There are many instances where you may want to show or hide various components in the assembly. Currently, when you need show or hide components, you need to select some components and show them, then select more components and hide them. This is a four (4) step (select, hide, select, show) process. Let’s see if we can get that down to two (2) steps (select, show/hide).
If you would like to follow along with what I did, you can download the sample macros here. Please note that this macro was written in SolidWorks 2007. It has been tested in SolidWorks 2006 after the SolidWorks Type Libraries have been changed. In the Macro Editor, click on the “References” menu and select the SolidWorks 2006 Type Libraries, then resave the macro.
Phase 1 – Record a Macro:
First thing we need to do is figure our how the SolidWorks API selects a component, shows a components and hides a component. This is a great time to use the macro recorder. Here is how we will capture what we need to know.
- Load an assembly into SolidWorks.
- Turn on the Macro Recorder.
- Select a visible component.
- Hide the component.
- Select a hidden component.
- Show the component.
- Stop the Macro recorder and save the new recorded macro.
When we edit the recorded macro, we get something very similar to the following:
' ******************************************************************************
' VisibilityToggle.swb - macro recorded on 09/24/07 by lkikstra
' ******************************************************************************
Dim swApp As Object
Dim Part As Object
Dim SelMgr As Object
Dim boolstatus As Boolean
Dim longstatus As Long, longwarnings As Long
Dim Feature As Object
Sub main()
Set swApp = Application.SldWorks
Set Part = swApp.ActiveDoc
Set SelMgr = Part.SelectionManager
boolstatus = Part.Extension.SelectByID2("Part1-1@Assem1", "COMPONENT", 0, 0, 0, False, 0, Nothing, 0)
Part.HideComponent2
Part.ClearSelection2 True
boolstatus = Part.Extension.SelectByID2("Part1-2@Assem1", "COMPONENT", 0, 0, 0, False, 0, Nothing, 0)
Part.ShowComponent2
Part.ClearSelection2 True
End Sub
By looking at the above code, we can see that the macro attached to SolidWorks, then attached to the active document, enabled the selection manager, selected a component, hid it, selected the component again, displayed it, then ended. These are the same steps we did when we initially recorded the macro. So far, so good.
When you attempt to run this macro on the same assembly, nothing happens. Why? Because the display states of components were changed while you were recording the macro. In order for the macro to work properly, the same conditions must exist in SolidWorks now, as they did when you initially recorded the macro. Put the components back to the condition they were in prior to recording the macro. Open the macro in the Macro Editor. Use the [F8] key to step thru the macro line-by-line. You can now watch as the macro executes each step and see that the macro does everything as recorded. Now everything should work as expected.
As we step thru the macro, we can learn that the following:
- “boolstatus = Part.Extension.SelectByID2” selects the component.
- “Part.HideComponent2” will hide the component.
- “Part.ShowComponent2” will show the component.
- “Part.ClearSelection2 True” will clear the current selection
At this point, the macro will only work for an assembly that has the two components in with the display states that match the specific conditions when the macro was recorded. If these components do not exist in the assembly, the macro will run, but nothing will happen.
Phase 2 – Modify the recorded macro for “universal” use:
We can modify this macro, or use what we learned, to build a new macro that will work on any assembly, and any mates, but before we can do that we need to decide how we want the macro to work. Here are my thoughts:
- Require user to select a component before running macro.
- Check the visibility state of the selected component.
- Toggle the visibility state.
We now have 2 things for us to learn and develop for this macro. Component pre-selection and checking the current visibility state of the selected component.
From the original recorded macro, we can see that the macro enabled a selection manager (“Set SelMgr = Part.SelectionManager”) before selecting the mate. We will need to add this line to our code because we need to access the selection made by the user.
The next thing we need to look at is how to access the user’s selection. We know the line “boolstatus = Part.Extension.SelectByID2” makes the selection, but we don’t know the name of the component at this time, so we need to look for other ways to access the user’s selection. In the SolidWorks API and Add-ins help file (API Help File), go to the “Index” tab and enter “Get” and start scrolling down the list to see if anything makes sense. I do know from past experience that “GetSelectedObject6” works for our needs. This brings us to the page “SelectionMgr::GetSelectedObject6”. This is the same selection routine we used for the MateToggle tutorial. We can read this page for more information. Because a selection set is lost after it is used, we can only work with the first selection in the set.
We will need to modify our selection to read as follows:
Set MySelection = SelMgr.GetSelectedObject6(1, -1)
To check the visibility state, we can go to the API Help File and search for “Visible”. I found “Component2.Visible” and “Component2.GetVisibility”. What’s the difference? The “Component2.GetVisibility” collects and array of the component’s visibility state in various configurations of the assembly model. For this “Quick & Dirty” macro, I am only concerned about the current configuration. The “Component2.Visible” has an “Examples” link. Let’s check them out. The page “Make All Assembly Components Visible Example (VB)” shows us how to check the component’s visibility, and hide the component. Here are the lines we are going to borrow:
If swComponentHidden = swChildComp.Visible Then
swChildComp.Visible = swComponentVisible
End If
I am going to modify these lines to correspond with my own code. These lines will now look like this:
If MySelection.Visible = swComponentHidden Then
MySelection.Visible = swComponentVisible
Else
MySelection.Visible swComponentHidden
End If
You will notice that in the “If” line, I put the “swComponentHidden“ on the opposite side of the equal sign. In most cases, this is unimportant. I just like ordering the comparison statement in this manner: “What am I checking?” = “What value do I want it compare it to?” By being consistent in my programming techniques, it makes easier for me, and others, to understand my macros.
Keep in mind, because a selection set is lost after it is used, we can get rid of the “Part.ClearSelection2 True” line.
Our updated macro now looks like this:
' ******************************************************************************
' VisiblityToggle2.swb - macro modified on 09/24/07 by lkikstra
' ******************************************************************************
Dim swApp As Object
Dim Part As Object
Dim SelMgr As Object
Dim boolstatus As Boolean
Dim longstatus As Long, longwarnings As Long
Dim Feature As Object
Dim MySelection As Object
Sub main()
Set swApp = Application.SldWorks
Set Part = swApp.ActiveDoc
Set SelMgr = Part.SelectionManager
Set MySelection = SelMgr.GetSelectedObject6(1, -1)
If MySelection.Visible = swComponentHidden Then
MySelection.Visible = swComponentVisible
Else
MySelection.Visible swComponentHidden
End If
End Sub
It works pretty slick. You can end the development here if you like because you now have a macro that does what you need.
Phase 3 – Optional Enhancements:
The macro works, but there are a few more things we need to consider:
What if the person selects a mate instead of a component? What if nothing was selected? In these cases, you can add filters between the selection, and the visibility check. To check if something was selected, we can add a line testing the contents of “MySelection”. To ensure a component was selected, we can add a line to check the type of “MySelection”. The MateToggle3.swp macro illustrates how to do this. Here is how that portion of the code looks:
If Not MySelection Is Nothing Then ' Is something selected
If SelMgr.GetSelectedObjectType3(1, -1) = swSelCOMPONENTS Then
' Filter selection
Set MySelection = SelMgr.GetSelectedObject6(1, -1) ' Get selection
If MySelection.Visible = swComponentHidden Then ' Is it hidden?
MySelection.Visible = swComponentVisible ' Yes, Show it
Else
MySelection.Visible swComponentHidden ' No, Hide It
End If
Else
MsgBox "No component selected."
End If ' Filter selection
Else
MsgBox "Nothing selected."
End If ' Is something selected
At this stage, I added message boxes to inform the user of improper selections that the macro will not handle. I also indented the code so the user can see the nested statements, and I added comments at the end of a few lines. Both of these techniques are not mandatory, but they do make the code a little easier to follow and understand.
Because this macro should only work within a SolidWorks assembly, the macro should check to see if the current document is an assembly.
One final enhancement would be to make the macro work on more than one component at a time? This does get tricky because a selection set is lost after it is used. To keep track of all of the selections, we need to put them into a temporary placeholder, and then traverse thru them one at a time, checking and changing the suppression state. In the case of improper selections, we can filter the selections before storing them. This is a needed enhancement to the macro, and it was a big change to the code. You can look at VisibilityToggle4.swp to for an example of how to do this.
Here are a few interesting notes about selections via the SolidWorks API.
- Once a selection is used, it is cleared and cannot be reselected by the API.
- Selections made via “SelectByID2” operate from the current document level and do not require setting an object, but they do require document level commands to modify.
- Selections made via “GetSelectedObject6” do require setting an object for the selection set. Selection set based commands are required to modify the objects in the selection set.
These differences in the selection sets, along with the enhancements I made to store multiple selections, and reselecting each component in the saved selection set, did require me to go back to using the “Part.ShowComponent2” and “Part.HideComponent2” commands in the first recorded macro.
Keep in mind that there may be more than one way to complete a task, as shown above. If you are getting unexpected results, you need to look at other methods to accomplish your task. Look at existing examples, and research the different methods before continuing on with your development. This may help you to discover a more efficient method for completing the tasks you need done.
Don’t forget, if you would like to follow along with what I did, you can download the sample macros here.
Even the “finished” macro is not complete. This macro will only work if the components are selected in the feature manager at the left. It may not work correctly if a component has been selected in the graphics window. This macro also does not ensure that the user selected a component in the top level of the assembly.
Conclusion:
This is the second tutorial that stems from a discussion that brought on a few comments like “My recorded macro does not work when I run it again.” or “How and where do I start writing a macro?” and “Where can I find help on writing a macro for SolidWorks?”.
When you write a macro, follow these simple steps:
- Record a macro to “discover” API calls you may need.
- Study the recorded macro to “discover” how and when things happen.
- Upgrade the recorded macro to make it more “universal” and capable of working with other models and features.
- If you are getting unexpected results, you need to look at other methods to accomplish your task.
- Add additional code to expand on the macro’s functionality. (ex: multiple pre-select)
- Add your user interface, if needed. Again, start small, test functions, and work your way up.
- Add code to accommodate improper selections.
- Let it loose and see how others use the macro.
- Be ready to add updates as problems are “discovered”.
When is any macro actually done? It can be done as soon as you get it to work as expected, or it may not be done until it has been “idiot-proofed” meaning that you have thought of, and added code to accommodate all of the potential ways the macro could be misused (intentional or not). This decision is up to the developer, the user(s), and the environment the macro will be used (or abused) in. Keep in mind that changes to the SolidWorks API, due to SolidWorks upgrades, may force you to make additional changes to the macro.
If you look at the two tutorials, MateToggle and VisibilityToggle, and examples closely, you will see that about 90-95% of these macros are identical. We could have easily modified the MateToggle macro to serve a different purpose, and create the new VisibilityToggle macro. Once again, proof that old macros don’t die!
You can find a few more macros built on this concept by going to the “Quick and Dirty” (http://www.lennyworks.com/solidworks/default.asp?ID=44) macro page on my website.