Fundamental to writing macros and add-ins with the SolidWorks API is knowing how to get the pointer to a particular object. In some cases, this is a simple. If you need a selected object’s pointer then you just use ISelectionManager::GetSelectedObject6. If you need the name of a feature called “CutExtrude1” then you would just use IPartDoc::FeatureByName. These methods, however, assume that you know the name of that object. This isn’t always the case. What to do then?
First, you need to programmatically locate the object. The most common way is to traverse the FeatureManager tree (in the case of a feature or component) or traverse the geometry or topology itself (in the case of a face, edge, vertex, etc.). Once you have the object, however, how does your program “remember” it for later use? You could store its name or perhaps its location, but depending on the object this could be very tedious.
Instead, a much easier option is to use “persistent IDs”. Persistent IDs are a unique identifier for any selectable object. According to the API Help, “The reference IDs persist for the objects in the model document across SolidWorks sessions. Other applications can use persistent reference IDs to locate objects at runtime.” This means that, unless you remove and then recreate that object, you can always locate that object so long as you have its ID.
Obtaining an object’s ID is very simple. Just use IModelDocExtension::GetPersistReference3, which returns an object containing the persistent ID. (Fun fact: Think your password is unique? A persistent ID has 297 digits.) Later, even if its a different SolidWorks session with a different program, you can re-obtain that object’s pointer using IModelDocExtension::GetObjectByPersistReference3.
Want to see how easy they are to use? Open up any existing part or create a new one and add at least one feature. Paste the following code in a new VBA macro and set a breakpoint on the line right after IModelDoc2::ClearSelection2 is used. Now, select a feature in the FeatureManager tree and run the macro. When your code breaks, look at your part and notice that nothing is selected. Click Run to continue the code, and then look at the part again. Why is the feature re-selected? The persistent ID for that feature was obtained right before the selection was cleared. On the line following IModelDoc2::ClearSelection2, the pointer was re-obtained using the persistent ID and then re-selected using appropriate Select method.
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swSelMgr As SldWorks.SelectionMgr
Dim swObj As SldWorks.Feature
Dim swRef As Variant
Sub main()
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
Set swSelMgr = swModel.SelectionManager
Set swObj = swSelMgr.GetSelectedObject6(1, -1)
swRef = swModel.Extension.GetPersistReference3(swObj)
swModel.ClearSelection2 True
Set swObj = swModel.Extension.GetObjectByPersistReference3(swRef, Empty)
swObj.Select2 False, Empty
End Sub
You can make this code work with any selectable object. Just change the data type for swObj to something else—a face, a note, a component, etc.—and then make sure that you use the correct Select method for that object. A version that allows you to re-select multiple entities using persistent IDs is found here.
As you can see, this technique for locating objects can be far simpler than using entity names or attributes, because you don’t even need to assign the ID—it’s already there. Indeed, many people wrongly use attributes when persistent IDs should be used. Attributes will be discussed in part two of this series.
Persisting,
Keith
Want to keep up with new blog posts, videos, and macros we create each month? Sign up for our newsletter!
Great blog Keith! I just have one question, in your code in the PID example you say to put a break after IModelDoc2::ClearSelection2 is used. I don’t seem to see this in the code.
Thanks
Josh,
Thanks!
In the VB Editor I simply put a breakpoint on the line after ClearSelection2. So it isn’t really something I can show in print; I would have to post a picture. However after ClearSelection2 you can write the word “Stop” which will cause the program to break at that line. So your code could look like this:
========
swRef = swModel.Extension.GetPersistReference3(swObj)
swModel.ClearSelection2 True
Stop
Set swObj = swModel.Extension.GetObjectByPersistReference3(swRef, Empty)
========
Keep in mind that the only purpose of using the break point is just so you can actually see that the selection was cleared, and then when you run the rest of your code and the object is re-selected, you can also see that indeed the object was successfuly re-located using PID’s. So it isn’t crucial to the operation of the macro, it just helps to visually prove that everything is working as intended.
Let me know if you have any more questions.
Keith
To get the persistant ID you have to select the object. So it can’t really a substitute for a selection method which I thought it could be. Is there any other method to get the ID without actually selecting the object?
IModelDocExtension.GetPersistReference3 doesn’t require that the entity be selected. You pass in the pointer to that entity as the argument. You could obtain this pointer by many other means. I can’t really give you more advice until I know what you’re trying to accomplish.
Hi Keith,
I’m working on a macro to automatically scan a flat pattern, find the bend lines, and then offset the bend allowances on each side of the bend line. I’m a code klutz, patching together bits that I don’t fully understand so I apologise if my questions are just way out in left field.
Right now I’ve managed to get my macro to draw new lines over the existing bendlines, iterating thru all the bend lines (not really what I want but we’re getting there) and I guess I have two questions for you, how can i get the ID of a line I just drew – i think if I can do this I’ll be able to offset that line.
Question 2 would be do you have any ideas on how to get the ID of those bend lines directly?
Question 3 (and this would be amazing!) If I can get the ID of the bend line can I get the custombendallowance from that ID as well?
Thanks!
Neil
Use this macro to get entity names. In order to the bend allowance for a sheet metal feature you need to get access to that feature’s data interface. For a sketched bend feature it would be ISketchedBendFeatureData. One of its members is GetCustomBendAllowance.
It does not seem the PID has any advantage over attributes.
To get an PID, you have to get a handle to that object. Then you can store that handle in a variable. Why PID is needed?
So, I think there must special situation where PID is useful which is not covered here.
Attributes have to be added to the model geometry, PIDs don’t. They’re already present.