This video summarizes the contents of this post and demonstrates the examples listed below.
Ever wanted a macro so tightly integrated with a part or assembly that 1) the macro always ran as long as the model was open, 2) the macro traveled with the model wherever it went? Using a clever, undocumented trick involving equations and the Design Binder, both of these are possible with little initial setup. The result is what I call Equation-Triggered Macros.
For our case study, let’s consider a problem I received from a friend a few weeks ago. His parts need to have their custom properties listed in alphabetical order. To reduce time and error, he could create an event notification macro that runs on SolidWorks startup and sorts the custom properties on every rebuild. Starting the macro with SolidWorks requires modifying the SolidWorks shortcut arguments on the user’s computer.
Two problems arise. First, you’ve now created a lot of administrative work for yourself because every user’s computer needs to be set up to automatically run this macro. Second, if the user doesn’t open SolidWorks through the modified shortcut then the macro will not run. Here’s how you can alleviate both problems without creating even more administrative work for yourself.
Step One : Write the Macro
Self-explanatory. In our case, we need to write a macro that sorts the custom properties alphabetically when it is run.
Step Two : Embed or Reference the Macro
Embedding versus referencing is essentially the same idea as embedding a design table within a document versus linking to it at an external location. If you embed, the macro travels with the document. No concerns about the macro getting lost or the link path becoming invalid. But if you need to change the macro code in lots of models? That could be a real chore (though you could write a macro that does this for you—more on that in the last section). If you think you’ll need to change the code regularly or simply want to remain in control of the code at all times, referencing is safer.
Embedding a macro in a document is pretty simple. While you have a part or assembly open, right click on the Design Binder (you might have to make it visible using Hide/Show Tree Items if it isn’t already) and choose Add Attachment. Browse for the .swp file, click OK, and you’re done!
Referencing a macro is also simple. Just put the macro in the desired hard-drive / network location and copy the path. We’ll use the path in the next step.
Step Three : Add An Equation That Calls The Macro
This is where it gets interesting. Josh Brady, a long-time SolidWorks API enthusiast, made an incredible discovery back in 2007. Noting that you could use the VBA “iif” function in SolidWorks equations, he decided to see if other VBA equations could be used as well. The answer? Any and all VBA functions can be used as long as you format them properly! He also discovered that the same is true for custom properties. If you want to learn all of the guidelines and caveats for using VBA in equations, you can watch his excellent SolidWorks World 2011 presentation titled “Advanced Equations Using VBA and API Code”. The presentation files can be downloaded here.
Without going into details about formatting, here are the equations you need for embedding and referencing, respectively. Once you add the appropriate equation, each time your part or assembly rebuilds, the macro will be run.
"Var1"= 1::swApp.RunAttachedMacro "macro.swp", "mMain", "main"
"Var2"= 1::Dim lngErr As Long::swApp.RunMacro2 "C:\macro.swp", "mMain", "main", swRunMacroDefault, lngErr
- The variable names are arbitrary and have no effect on the macro itself. If you already have a variable called “Var1” or “Var2”, then use another name.
- The arguments for ISldWorks::RunAttachedMacro and ISldWorks::RunMacro2 need to match your macro name/path, module, and entry point. See the API Help articles for more details.
- Since SolidWorks 2012, the Equation Manager makes it difficult to add these equations due to the equation checker disliking the syntax of equations containing VBA code. To make sure you’ve added the equations properly, you should put the equation in a text file and then import that text file. As shown in the image below, the resulting equation may not successfully evaluate and the syntax may appear incorrect, but it should still work. If you struggle to get the Equation Manager to accept the equation, use Luke Malpass’ equation editor tool that lets you bypass the syntax checker.
Going To The Next Level
At this point you should see the unique flexibility and power offered by equation-triggered macros (ETMs), possibly in conjunction with the Design Binder. With the “vanilla” ETM setup I’ve just shown you, however, the macro always runs when the part rebuilds, and sometimes you need more control over when the macro runs. To give you that control, I’ve created a class called ETMUtil that you can add to a macro (whether embedded or referenced) that gives you the following options:
- Only allow your code to trigger once within a specific time period (e.g., 30 seconds).
- Only trigger your code once when the part is opened.
- Only trigger your code once the first time a part is opened, but never on subsequent openings. This might be used with part or assembly templates for example, to aid the initial configuration of the model.
- Delete the temporary macro files. When a macro is run from the Design Binder, a copy of the macro is created in C:\Users\
\AppData\Local\Temp and then run. Due to known bug (SPR 400218) SolidWorks never deletes these files, so they can build up over time. If you think this could become a problem over time and you don’t want to remember to delete them manually, ETMUtil can help. Obviously this problem is avoided entirely if you reference the macro instead of embedding it using the Design Binder.
Sound appealing? ETMUtil, and instructions on how to use it, is available to CADSharp.com premium members in the Macro Library under Automation / Tools. Watch the video at the beginning of this post to see ETMUtil in action or check out one of the examples below.
Here’s the finished version of the part from the original case study we discussed, along with three other examples.
Sort custom properties – Macro is embedded in a part. Every rebuild, the custom properties are sorted into alphabetical order.
Keep bodies renamed – Macro is embedded in a part. Every rebuild, the solid bodies are renamed Body1, Body2, Body3, etc.
Track part usage in assemblies – Macro is embedded in an assembly. Before the assembly is saved, the part level custom properties are updated to contain the number of times the part is used in an assembly. The custom property is named after the assembly. The code triggers before the assembly is saved instead of during each rebuild to improve performance.
Display user form on part open – (Premium members only) Macro is embedded in a part. When the part is opened, a user form is displayed that allows the user to easily change the part material and modify a custom property called “Edited By”. Uses ETMUtil to allow code to prevent any equation-triggers beyond the first one when the part opens.
Answers to Important Questions
Q: Why can’t I use equation-triggered macros with drawings?
A: Because you can’t add equations to drawings.
Q: Using equation-triggered macros it is possible run code on every rebuild. Is there any way I can listen for other events?
A: Yes. The macro you embed or reference simply needs to listen for that event using event notifications (see our Macro Library for examples). In fact, if you wanted to have your code run post-rebuild instead of when the equation recalculates, you could use ETMUtil to turn on a post-rebuild listener as soon as the part opens, prevent any additional equation-triggers, and use that listener to trigger your code.
Q: My macros are in VB.NET / C#. Is there any way I can still use this technique?
A: Yes. You’ll need to always reference the macros from an external location because .NET macros cannot be run from the Design Binder.
Q: When I edit a macro in the Design Binder and save it, the macro behaves as though I never edited it. Why?
A: You can’t truly edit a macro that’s in the Design Binder. You need to make edits to a macro that is on your hard-drive or network, then delete out the macro in the Design Binder, and add in the edited macro.
Q: I absolutely can’t seem to get the equation editor to accept my equation containing VBA code. What can I do?
A: First, did you try using Luke Malpass equation editor tool, which bypasses the Equation Manager’s syntax checker? Second, does part of the equation contain VBA keywords like “if”? For example, a macro called “modify fillet.swp” will confuse the Equation Manager because it thinks that the letters “if” in “modify” are the beginning of an if-then statement. Third, have you tried using the referencing equation rather than the embedding equation? In some instances I’ve seen the Equation Editor refuse to accept one but not the other.
Q: SolidWorks is crashing when my equation-triggered macro runs. Why?
A: Does your macro edit features or perform any other task that might cause a rebuild? Keep in mind that ETMs run during a model’s rebuild. Causing another rebuild during this first rebuild will probably cause a crash. One way you can avoid this situation is by having your ETM start a post-rebuild listener that performs your task once the model rebuild is finished. The rebuild listener should be set to nothing after it has done its work (see example), otherwise that same task will keep running during every rebuild, even if you’re using ETMUtil (or your own code) to prevent subsequent triggerings of the code.
Q: How can I setup existing models to use equation-triggered macros?
A: You could write a macro that does the following for every model in a folder: open up the model (ISldWorks::OpenDoc6), add the appropriate equation (IEquationMgr::Add2), save the model (IModelDoc2::Save3), close the model (ISldWorks::CloseAllDocuments). If you’re using VBA, use Dir() to traverse the files.
Q: If I do want to embed my macro in the Design Binder for use with equation-triggered macros, how would I go about modifying the embedded macro later?
A: You could write a macro that does the following for every model in a folder: open up the model (ISldWorks::OpenDoc6), delete the existing macro in the Design Binder (IModelDocExtension::DeleteAttachment), save the model (IModelDoc2::Save3), close the model (ISldWorks::CloseAllDocuments). If you’re using VBA, use Dir() to traverse the files.
Q: Using equation-triggered macros, couldn’t SolidWorks models carry viruses?
A: Yes, they could. For that reason you should only accept CAD files from trusted sources. Of course, a virus could be implemented in a macro feature as well, so it is not as though this is a new possibility.
Q: How can equation-triggered macros improve .NET macro features?
A: Unlike VBA macro features, .NET macro features cannot have code that defines the macro feature embedded in the document. This means that if the path to the DLL is invalid, the macro feature will fail. This makes it tedious when sending files containing .NET macro features to other users, because you have to ensure that they have the defining macro and its supporting DLLs in the right path on their end. Using the equation + Design Binder technique, you can place the defining macro and its supporting DLLs in the Design Binder and a macro that verifies that the defining macro exists at the correct location. If it doesn’t, it saves the defining macro and its supporting DLLs to that location.
I hope you enjoyed learning about equation-triggered macros as much as I did. If you have ideas for ways you could use them, I’d love hear about it in the comments.
Onward into new automation frontiers,
Want to keep up with future CADSharp.com content, webinars, and special offers? Sign up for our newsletter.