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.
Note: As of SolidWorks 2015, Equation-Triggered Macros do not appear to be working at all. They are also not supported by SolidWorks Corporation. Use at your own risk.
Case Study
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!
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 a macro named “macro.swp” with a sub-procedure named “main” in a module named “mMain”. Once you add the appropriate equation, each time your part or assembly rebuilds, the macro will be run.
Embedding
"Var1"= 1::swApp.RunAttachedMacro "macro.swp", "mMain", "main"
Referencing
"Var2"= 1::Dim lngErr As Long::swApp.RunMacro2 "C:\macro.swp", "mMain", "main", swRunMacroDefault, lngErr
Important comments:
- 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. In other words, unless your macro is named “macro.swp” and contains a sub-procedure called “main” in a module called “mMain”, using the code above verbatim will not trigger your macro!
- 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. Please note that as long as the check next to the equation is gray, the equation has not been accepted and will not work.
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.
Note: As of SolidWorks 2014, ETMUtil no longer works, because the ability to suppress equations was removed. An alternative solution exists using event notifications, but I have not had time to implement it.
Examples
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
Conclusion
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,
Keith
Want to keep up with future CADSharp.com content, webinars, and special offers? Sign up for our newsletter.
Really nice article. I love the idea/concept of how it works and can immediately see many potential uses/applications. I like the “Track part usage in assemblies” example as this is useful for BOM-related functions.
This is a very useful article. I now aim to use equation triggered macros to automate my designs. Thanks Keith!
Awesome! I think this will help a lot with users who don’t always follow protocol.
Have you tried massive assemblies where every part has ETM? I think executing on open will cause the users the least delay.
What is the overhead on file size when you have a macro in the design binder? I never tested. I know some colleague’s found bugs in design binder before.
I have not tried using ETMs on such a large scale. Also, as far as I know, the ETM in a part will not run while you have the assembly open.
Concerning part size, I did a test just now. In 2013, a part that is 450 KB alone became 800 KB with a 180 KB macro.
Very interesting method of using macros!
Will be definitely thinking about where this could be used in the future.
Well done to all in figuring this method out.
Hey Keith,
Implementing a macro in a part looks pretty cool, because you don’t have to teach somebody, you just say: “Hey, if you write new properties, it will sort automatically.” (or what ever your macro have to do) And that’s the way we like it! Do nothing…get all!
This way you get the “intelligence” part without the extra steps involved. You don’t forget to run a macro or what else. I’ll use it for sure. Thanks a lot for this new advice.
Greetings from Germany,
Steffen
In the last example where the form comes up on the 1st rebuild and then is suppress until it is saved. Would it not be simpler and easier to just have the form be triggered by the fileopennotify event, there for you would not need to suppress and unsuppresss the equation?
Hi David,
The part is already open by the time the equation triggers the macro, so I don’t think that notification would fire. Maybe swAppFileOpenPostNotify would work. Let me know if you test it out.
Keith,
I can’t say I understand why but the part must open and rebuild before the events are triggered. I just did a test and DocumentLoadNotify, DocumentLoadNotify2, FileOpenNotify, FileOpenNotify2, and FileOpenNotify2 all fired after the part is opened and the macro is running.
I have this setup working in a sheet metal template file that has a user form to fill out the part parameters. This is only needed the 1st time the file is loaded and then never again so for my needs I suppress the equation as it is not needed anymore for that file but you can keep it unsuppressed and it will run only when the file is loaded. The only drawback I have found so far is I don’t know how to stop my NotificationClass after it is finished so any file opened after that triggers the userform. I have to add some code to set swApp to nothing after the form is finished to keep that from happening.
Hi David,
Thanks for doing those tests and pointing this out to me. I just tested it out myself, and “FileOpenNotfy2” does fire. So apparently whatever triggers doesn’t occur until after the equations are first calculated. Certainly, then, you could use this approach to run a macro only when the part loads. Of course, as you noted, if you want to prevent the macro from running on subsequent loads then you still need to suppress the equation using IEquationMgr::Suppression.
If you want to prevent the notifications from firing later then you need to set the listener class to Nothing. Declare the listener class as a Public variable. Do not auto-instantiate it. There’s an example of killing the listener class in the Macro Library. Check out the example “Determine whether new or existing file was opened”.
Thanks Keith. I finally had time to try this and it works better.
Hi Keith,
Thank you very much for the article, however, it seems that this method does not work in Solidworks 2015. I have tried to automate a macro that I need to run on all parts without success. If I create a Macro Button I get the results needed but when trying to register the macro to an equation to automatically run I get syntax related errors and the macro does not run. Would you be able to test SW2015 to see if it is possible to use the methods advised in this article.
Regards,
Leslie
That’s correct, it no longer works as of SolidWorks 2015.
Hi Keith,
I’m having trouble adding the equation. I followed all your steps and either Solidworks do not accept the equation or when it does, the macro is not running on rebuild! I have Solidworks 2015 SP4, do you know if the feature is still supposed to be working?
Thanks,
Unfortunately, this technique no longer works as of SolidWorks 2015.