CATIA Annotation to Usersurface link - vba

I have been trying to get surface data from annotation and measure the curve and check if the annotation mentioned correctly or not.
using
annotation.getsurfaces(variant1())
but this is returning a string instead of surface.
I cant goto surface by using
part1.createreferencefromname(variant(0)) or part1.findobjectbyname(variant(0))
I need to measure that surface returned from annotation.getsurfaces(variant1())
thank you,

Hi i have played with annotations a very little so I might not give the best answer.
You could change the string from something like this (sorry i make myself a extrude :))
"Part1/Geometrical Set.1/Extrude.1/Face"
To
"Part1/Geometrical Set.1/!Extrude.1"
Then use
Dim PartDoc as PartDocument 'your part document
Dim Ref as Reference
Set Ref = PartDoc.Product.CreateReferenceFromName("Part1/GeometricalSet.1/!Extrude.1")
Another option is get the name of the feature "Extrude.1" and use:
Dim Shape as HybridShape 'here you have to declare the right type for you
Set Shape = PartDoc.Part.FindObjectByName("Extrude.1")
Be careful because you can get differed object if you have the same with same name somewhere else!
You can explore the BRep sytax more if you are brave enough and create something like this (just example from api documentation)
CreateReferenceFromName("Produit1/Column_2/!Selection_FVertex:(Vertex:(Neighbours:(Face:(Brp:(StrFunRibSweep.1;0:(Brp:(GSMLine.1);Brp:(IntSection.1;9999)));None:();Cf11:());Face:(Brp:(StrFunRibSweep.1;1);None:();Cf11:());Face:(Brp:(StrFunRibSweep.1;0:(Brp:(GSMLine.1);Brp:(IntSection.1;10018)));None:();Cf11:()));Cf11:());StrFunRibSweep.1;Z0;G4702)")
To measure something you can use the object Measurable from Space Analysis and there you can use Func GetMeasurable(Reference iMeasuredItem) As Measurable

Related

Accessing Dynamic Dims

I am creating what I believe is the way to create dynamic dims e.g.
Dim browser(DataGridView1.Rows(e.RowIndex).Cells(0).Value)
which basically is creating a something like Dim browser(1)
However I am trying to write a test button to call this browser by using:
browser1.load("http://google.com")
and I have even tried
browser(1).load("http://google.com"
I get the browser part underlined.
What is the correct way to reference them?
I'm not sure what the end goal is, but this construct:
Dim browser(1)
Is effectively the same as:
Dim browser(1) as Object
i.e. it's creating an array of Object of length 2, which is fine in that it can hold anything but makes your life pointlessly hard because you then have to cast the contents every time you want to do something with them; it's bad enough storing a single thing (such as a web browser widget) as an Object:
'this is bad
Dim browser as Object = New WebBrowserWidget
Because you have to cast it every time you use it (when Option Strict is On, which is really the only way you should ever program)
DirectCast(browser, webBrowserWidget).Load("http://google.com)
But to then add the indirection of storing it in an array:
'this is worse
Dim browser(1) as Object
browser(0) = New WebBrowserWidget
browser(1) = New WebBrowserWidget
And casting them to use them:
DirectCast(browser(0), webBrowserWidget).Load("http://google.com)
Just give these things a proper type when you declare them, or use type inference by providing something on the right hand side of an = that is a particular type:
'infer the type from the right hand side
Dim browser = New WebBrowserWidget
'or declare, give a type and create a new instance to assign to it
Dim browser as New WebBrowserWidget
Then it's a lot easier to use it, because Intellisense will know it's a browser and offer you help with the methods and properties, such as Load:
browser.Load("http://google.com")
If you code with Option Strict Off then you can store things in an object and just cross your fingers and hope you get everything right when youre coding, but it's like writing javascript - fumbling round eyes closed not knowing whether you got it right til it blows up at runtime:
Dim x as Object = New WebBrowserWidget
x.Load(...) 'don't get any intelllisense for this, but it'll work at runtime
x.Laod(...) 'dont get any compiler error even though this is a typo - it'll just explode at runtime

SolidWorks VBA - Translating API Help into useable code

I'd like to do what feels like a fairly simple task, and I've found the specific API Help pages which should make it clear, but, I can't actually make things work.
The Key steps that I would like to achieve are:
Rename the active document
Update References to this document to accommodate new name
Save active document.
This help page shows the Usage for renaming the doc, and under the "Remarks" heading, includes links to the next two steps, mentioning them off hand as if implementing them would be easy.
https://help.solidworks.com/2020/English/api/sldworksapi/SolidWorks.Interop.sldworks~SolidWorks.Interop.sldworks.IModelDocExtension~RenameDocument.html?verRedirect=1
The trouble is, I'm a bit of a VBA beginner - usually I get by with the 'record' function, and then tidying things up from there - but undertaking the steps above manually doesn't result in anything being recorded at all for one reason or another.
Assuming I am able to pass in the item to be renamed (I'll define a variable at the start of the Sub for this e.g. swModel = swApp.ActiveDoc), and the new name (NewName = "NEW NAME HERE"), How would I translate the Help API into a Sub that I can actually run?
Two of them suggest declaring as a Function, and one as a Public Interface - I've never used these before - do these just run in a standard Module? Do I need to write a 'master Sub' to call the different functions sequentially, or could these be included directly in the sub, if they're only to be used once?
[Feeling a little lost - it's demoralizing when the help files aren't all that helpful]
Let me know if there's any more information missing that I can add to improve my question - as I said, I'm fairly new to this coding thing...
The "record" function is sometimes a good point to start but there are a lot of functions it can't recognize while you execute them manually.
The API Help is then useful to find out how to use a specific function.
In almost every example the use of a specific method (e.g. RenameDocument) is only shown abstract. There is always a instance variable which shows you the object-type needed to call this method. So you can use these in every sub you want, but beforehand need access to the specific instance objects.
For your example the RenameDocument method is called with an object of the type IModelDocExtension. First thing for you to do is to get this object and then you can call the method as described in the help article.
Under Remarks in the article you find additional information for what you maybe have to do before or after calling a method.
For your example it is mentioned that the renaming takes permanently place after saving the document.
And finally here is what you want to do with some VBA code:
Dim swApp As SldWorks.SldWorks
Dim swModel As ModelDoc2
Sub main()
' get the solidworks application object
Set swApp = Application.SldWorks
'get the current opened document object
Set swModel = swApp.ActiveDoc
' get the modeldocextension object
Dim swModelExtension As ModelDocExtension
Set swModelExtension = swModel.Extension
Dim lRet As Long
lRet = swModelExtension.RenameDocument("NEW NAME")
If lRet = swRenameDocumentError_e.swRenameDocumentError_None Then
MsgBox "success renaming"
Else
MsgBox "failed with error: " & lRet
End If
End Sub
Afterwars you have to process the return value to check for errors described in this article: https://help.solidworks.com/2020/English/api/swconst/SolidWorks.Interop.swconst~SolidWorks.Interop.swconst.swRenameDocumentError_e.html

A null reference could result in runtime

Dim policy_key() As RenewalClaim.PolicyKeyType
policy_key(0).policyEffectiveDt = date_format_string(ld_EffectiveDate)
Getting error at Line2.
An Error occured - Object reference not set to an instance of an object.
Each element of object arrays also needs to be declared as a new object too.
Dim policy_key() As RenewalClaim.PolicyKeyType
Redim policy_key(0)
policy_Key(0) = new RenewalClaim.PolicyKeyType
policy_key(0).policyEffectiveDt = date_format_string(ld_EffectiveDate)
QUICK TIP: When declaring classes structures etc, it is useful to name them so you can see what type they are....
e.g.
cls_Policy_Key for a class
str_Policy_Key for a structure etc.
When you come back to your code after a year.. you will thank yourself for doing so.
Dim policy_key() As RenewalClaim.PolicyKeyType
is part of your problem. When you are declaring policy_key() you are actually declaring it as an array with no elements. If you don't particularly need to use an array, for example, if you don't need to add objects to a particular element number, you might be better using a list and declaring it like this
Dim policy_key As New List(Of RenewalClaim.PolicyKeyType)
This way, you can add items easily without having to resize your array each time - The code is a little longer than Trevor's answer, but less prone to errors when you extend your code -
dim newPolicy_Key as RenewalClaim.PolicyKeyType
newPolicy_Key.policyEffectiveDt = date_format_string(ld_EffectiveDate)
policy_Key.add(newPolicyKey)

How do I measure a non-updated point in CATIA VBA?

I'm trying to make a point measuring tool, but whenever my loop stumbles upon a non-updated point, it crashes my Measurable. How can I measure it?
After searching around, it appears you can't measure any geometry that isn't updated.
You can update one object by using the UpdateObject method in the MecMod Part library. Then run the measurable methods now that you have an updated object.
Like this:
CurPart.UpdateObject Obj1
If the geometry cannot update, due to an issue with the geometry, you can always skip it with error checking (sloppy), or use the command "IsUpToDate" to check if the geometry is updated.
Like this:
If CurPart.IsUpToDate(Obj1) = true then
Meas.GetPoint PTArr
End If
Be sure to keep the object name in an array so you can prompt the user with a list of all objects that did NOT get measured.
you can always isolate geometry, then you can measure and delete it if you dont need it anymore..
here is an example which creates isolated copy of first point in first geometrical set, updated or not, while original stands intact.
Sub makePointDatum()
Dim sPoint As HybridShapePointExplicit, oPart As Part, oHSF As HybridShapeFactory
Set oPart = CATIA.ActiveDocument.Part
Set oHSF = oPart.HybridShapeFactory
Set sPoint = oHSF.AddNewPointDatum(oPart.HybridBodies.Item(1).HybridShapes.Item(1))
oPart.UpdateObject sPoint
oPart.HybridBodies.Item(1).AppendHybridShape sPoint
End Sub

convert early binding to late binding without changing object type

This seems like a simple question but I after chasing forums for several hours I think it might be impossible.
I often want to convert a program from early binding to late binding. Usually, it is a vba, visual basic for applications, program that runs under Excel 2010 and windows 7 pro.
For discussion purposes, let’s pretend it is the following.
Sub EarlyBind()
' use IDE > Tools > references > and select “Microsoft Internet Controls”
Dim shellWins1 as shdocvw.shellwindows
Line1: Set shellWins1 = New SHDocVw.ShellWindows
MsgBox TypeName(shellWins1) ' this will display “IShellWindows”
' other code that expects to be working with an IshellWindows object …..
End Sub
In my experience, converting such a program to late binding is sometimes hard.
For instance, I found some forums that suggest I change it to
Set shellwins1 = createobject("Shell.applicaton")
But that creates a IShellDispatch5 object, not an IshellWindows object. That means I have to change other code to accommodate the new object type. And, of course I have to test that other code for subtle differences.
So, my goal is to find a general solution that will allow me to rewrite “Line1” to create the CORRECT object type with late binding. I also wish to avoid the need setting a reference to "Microsof Internet Controls. In other words, I want the code to look like this:
Sub LateBind()
Dim shellWins1 as object
Line1: Set shellWins1 = createobject(“xxxxxx.yyyyyy”).zzzzzz
MsgBox TypeName(shellWins1) ‘ this should display “IShellWindows”
….. other code that expects to be working with an IshellWindows object …..
End Sub
I know how to use the vba IDE to find the dll associated with the object. In this case the dll is Library SHDocVw C:\Windows\SysWOW64\ieframe.dll.
I have installed OleView and can find the associated IshellWindows “magic numbers” for the clsId, TypeLib, and Inteface (for instance the interface is 85CB6900-4D95-11CF-960C-0080C7F4EE85).
But, I don’t know how to convert them into a program id that can be used in line1 in the sample code posted above.
I hope someone here can help.
------ With MeHow's help, I now have the answer! ------
To switch 'set myObj = new xxxx.yyyyy' to late binding for arbitrary object types
Change set myObj = new xxxx.yyyyy
into set myObj = CreateObject("xxxx.yyyyy")
Very often that will work.
But, in the some cases, (e.g. "shDocVw.ShellWindows.") it gives error 429 ActiveX component cannot be created.
When that occurs I AM COMPLETELY OUT OF LUCK. It is impossible to use late binding with that EXACT object class. Instead I must find a substitute class that does approximately the same thing. (e.g. "Shell.Application").
Your short answer is
IShellWindows is an interface.
It
Provides access to the collection of open Shell windows.
Therefore
Take a look at the CreateObject() method.
Note:
Creates and returns a reference to a COM object. CreateObject cannot
be used to create instances of classes in Visual Basic unless those
classes are explicitly exposed as COM components.
IShellWindows is not exposed as a COM component so that's why there is no way to say CreateObject("SHDocVw.IShellWindows")
When you open your registry (regedit) and search for a key type in IShellWindows. If you find anything that means you've found your Prog ID and if you don't find anything it means that nothing like IShellWindows is registered as a prog Id therefore it would make sense to assume that you can't late bind IShellWindows
I bumped into your question trying to find something for myself. But I don't know if you have tried the following -
Set shellwins1 = createobject("Shell.Application")
MsgBox TypeName(shellWins1.Windows)
This answers your question for datatype. It prints IShellWindows for me. I'm not sure though if it could actually solve your purpose for latebinding meaning if this would be the object required though the datatype is what you need.
So, I would advise you to give it a try.
There is a slightly better approach outlined at https://www.experts-exchange.com/questions/28961564/How-to-find-the-class-id-of-an-arbitrary-object-Example-Set-x-CreateObject-New-1C3B4210-F441-11CE-B9EA-00AA006B1A69.html#a41743468.