Loop "Try" and "Catch" until success.

Loop "Try" and "Catch" until success.

C_Haines_ENG
Collaborator Collaborator
1,749 Views
14 Replies
Message 1 of 15

Loop "Try" and "Catch" until success.

C_Haines_ENG
Collaborator
Collaborator

Hello, im trying to write a Try and Catch script that will attempt to rename solidbodies until it succeeds. I am assigning certian solids to become "Duplicates" , thus being named a part number such as 660000_DUPLICATE_1, 660000_DUPLICATE_2 but when it gets to a new duplicate of a new part number I want it to reset back to 1. So as a list it might look something like this

 

660001

660002

660002_DUPLICATE_1

660002_DUPLICATE_2

660003

660003_DUPLICATE_1

 

Here is the code, but im not sure how to loop such a command.

 

Dim SB As SurfaceBody
Dim oDoc As PartDocument = ThisDoc.Document
Dim SBs As SurfaceBodies = oDoc.ComponentDefinition.SurfaceBodies
Dim DupNum As Integer = 1

'CLEAR ALL PREVIOUS NUMBERS
For Each SB In SBs

If InStr(SB.Name,"_") <> 0
	Try
		SB.Name = "DUPLICATE_" & DupNum
	Catch
		DupNum += 1
		SB.Name = "DUPLICATE_" & DupNum
	End Try
DupNum = 1
End If

Next

 In my mind it would loop until it no longer gets an error.

0 Likes
Accepted solutions (1)
1,750 Views
14 Replies
Replies (14)
Message 2 of 15

WCrihfield
Mentor
Mentor

Hi @C_Haines_ENG.  How do you determine which ones will be duplicates?  When you start out, none of the bodies are allowed to have the exact same name, so each name will already be unique.  In that situation, how are you determining which one needs the "_Duplicate_#" after its name?  Do these bodies represent other model files that have been derived into this part, and the name reflects the part number of that derived in model?  If that is the case, I'm gessing it would want naturally create a body named something Solid3, then you would rename it to reflect that model's PN, right?  In a situation like this, I would be tempted to use a separate custom Function, similar to the following.

Function NameUsed(oBodys As SurfaceBodies, sName As String) As Boolean
	If (oBodys Is Nothing OrElse oBodys.Count = 0) Or sName = "" Then Return False
	For Each oBody As SurfaceBody In oBodys
		If oBody.Name = sName Then Return True
	Next
	Return False 'that name was not found
End Function

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 15

C_Haines_ENG
Collaborator
Collaborator

The user will manually enter a "_" character into the solid body name. This tells the program that it is a duplicate and a manual pick is used to select which part number it is a duplicate of. Ive updated my code to better reflect this process.

 

Dim SB As SurfaceBody
Dim oDoc As PartDocument = ThisDoc.Document
Dim SBs As SurfaceBodies = oDoc.ComponentDefinition.SurfaceBodies
Dim DupNum As Integer = 1

'CLEAR ALL PREVIOUS NUMBERS
For Each SB In SBs

If InStr(SB.Name, "_") <> 0

	DupeOF = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kPartBodyFilter, "Select what Solid This Part is a Duplicate of") 
	
	Try
		SB.Name = Left(DupeOF.Name, 6) & "_DUPLICATE_" & DupNum
	Catch
		DupNum += 1
		SB.Name = Left(DupeOF.Name, 6) & "_DUPLICATE_" & DupNum
	End Try
DupNum = 1
End If

Next


0 Likes
Message 4 of 15

WCrihfield
Mentor
Mentor

Try this.  Just added a fairly generic For loop in there.

 

Sub Main
	Dim oPDoc As PartDocument = ThisDoc.Document
	Dim SBs As SurfaceBodies = oPDoc.ComponentDefinition.SurfaceBodies
	If SBs.Count = 0 Then Exit Sub
	Dim CM As CommandManager = ThisApplication.CommandManager
	Filter = SelectionFilterEnum.kPartBodyFilter
	Dim i As Integer = 0
	For Each SB As SurfaceBody In SBs
		i = i + 1
		If i = 1 Then Continue For 'skip first body
		If InStr(SB.Name, "_") <> 0 Then
			Dim DupeOF As SurfaceBody = CM.Pick(Filter, "Select what Solid This Part is a Duplicate of")
			If DupeOF Is Nothing Then Continue For
			For DupNum As Integer = 1 To 100
				Try
					SB.Name = Left(DupeOF.Name, 6) & "_DUPLICATE_" & DupNum
					Exit For
				Catch
					'do nothing here, and let the DupNum increment naturally
					'otherwise it will throw an error if both try & catch fail
				End Try
			Next 'DupNum
		End If
	Next
End Sub

 

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 15

C_Haines_ENG
Collaborator
Collaborator

Doesnt seem to do anything unfortunately.

 

It renames the first correctly but does not incriment, I dont understand why.

0 Likes
Message 6 of 15

WCrihfield
Mentor
Mentor

Maybe you need to include the current name of the current body within the Pick prompt message, that way you know which one it is referring to, so you know which other one to pick in that situation.  I know these types of situations can be tricky.  When I first posted that last code, I forgot to include the 'Exit For' clause in there, for when the 'Try' part succeeds at renaming the body.  So, I went back and edited that little bit in there.  Otherwise it would rename that body like 90x times.

I'm also thinking that the initial filter might be more accurately changed from:

If InStr(SB.Name, "_") <> 0 Then

...to this:

If SB.Name.EndsWith("_") Then

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 7 of 15

C_Haines_ENG
Collaborator
Collaborator

I cant seem to get this to work even with the revised code.

 

It runs once, tries to rename with a value of 1, and then promptly gives up.

0 Likes
Message 8 of 15

Curtis_Waguespack
Consultant
Consultant

Hi @C_Haines_ENG 

 

Maybe just a different approach? Something like this:

 

 

Dim oCollection As ObjectCollection
oCollection = ThisApplication.TransientObjects.CreateObjectCollection
Dim hSet As HighlightSet = ThisDoc.Document.HighlightSets.Add()
Dim SB As SurfaceBody

SelectAgain :

While True

	For Each SB In oCollection
		hSet.AddItem(SB)
	Next

	SB = ThisApplication.CommandManager.Pick(
	SelectionFilterEnum.kPartBodyFilter, "Select a set of duplicate bodies ( [press ESC to continue]")

	' If nothing gets selected then we're done	
	If IsNothing(SB) Then Exit While

	oCollection.Add(SB)

	If oCollection.Count = 1 Then
		oCollection.Item(1).Name = "$" & Left(oCollection.Item(1).Name, 6)
		InventorVb.DocumentUpdate()
	End If

	For i = 2 To oCollection.Count
		oCollection.Item(i).Name = oCollection.Item(1).Name &  i & "_Temp"
	Next

	oCollection.Item(1).Name = Left(oCollection.Item(1).Name, 6+1)
	For i = 2 To oCollection.Count
		oCollection.Item(i).Name = oCollection.Item(1).Name & "_DUPLICATE_" & i - 1
	Next

End While

Dim sName As String 
For i = 1 To oCollection.Count
	oCollection.Item(i).Name = oCollection.Item(i).Name.Replace("$", "")
Next

hSet.Clear
oCollection.Clear

oInput = MessageBox.Show("Select another set?", "ilogic", MessageBoxButtons.YesNo)

If oInput = vbYes Then
	GoTo SelectAgain
End If

 

 

 

I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com

EESignature

0 Likes
Message 9 of 15

C_Haines_ENG
Collaborator
Collaborator

While this is a neat solution, im trying to integrate the whole thing into a much much larger script that will also renumber everything. Once it gets to a SB with a "_" it will highlight the panel and you will select what its a copy of.

 

Is there truly no way of looping the Try command?

0 Likes
Message 10 of 15

Curtis_Waguespack
Consultant
Consultant

Hi @C_Haines_ENG 

 

I think maybe Inventor ( or the API) has an internal error check that catches same name solid bodies and handles the error during processing, and that is what is getting in the way if the Catch statement here.

 

I'll take another look at your original approach, though and see if I can slip in some temp naming to deal with that.

 

I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com

 

EESignature

0 Likes
Message 11 of 15

C_Haines_ENG
Collaborator
Collaborator

I have found the root cause, the "Exit For" loop under the "Try" line STILL RUNS even if the command line above it fails. I have simplified the code to see what exactly whats going wrong and that was infact the problem.

 

First solid it succeeds, but then it goes to the next one, starts at one, and then counts it as a successfull rename even though it did not rename it at all. Is it because the solid body already exists so it thinks it succeeding in renaming it?

 

Dim oPDoc As PartDocument = ThisDoc.Document
Dim SBs As SurfaceBodies = oPDoc.ComponentDefinition.SurfaceBodies

For Each SB As SurfaceBody In SBs	
	
	If InStr(SB.Name, "_") <> 0
		For DupNum As Integer = 1 To 5
			Try
				SB.Name = "DUPLICATE_" & DupNum
				MessageBox.Show(DupNum, "Duplicate Number")

				Exit For '<<<< THIS STILL RUNS IF THE LINE FAILS?
			Catch
			End Try
		Next
	End If
Next
Message 12 of 15

WCrihfield
Mentor
Mentor

Interesting thought.  If (SB.Name = "DUPLICATE_" & DupNum) is True, it will continue to run whatever code is on the next line, so it must be encountering that situation (that body's name is already that name that you are trying to set it as).  You could maybe create a Boolean (inside the loop, so it resets to False each time), then check the body's name 'before' and 'after' the attempt to change it, and if it is different, set the Boolean to True (representing - it changed its name).  And if True, proceed to next body, instead of trying to rename the same body again.  You may need to put a document update in there, just to be sure.  Just some thoughts.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 13 of 15

Curtis_Waguespack
Consultant
Consultant

that seems to fit with what I was seeing, with the original example... I think it was not ever getting the Catch statement

EESignature

0 Likes
Message 14 of 15

C_Haines_ENG
Collaborator
Collaborator
Accepted solution

I "fixed" the code?

 

Dim oPDoc As PartDocument = ThisDoc.Document
Dim SBs As SurfaceBodies = oPDoc.ComponentDefinition.SurfaceBodies

For Each SB As SurfaceBody In SBs	
	
	If InStr(SB.Name, "_") <> 0
		For DupNum As Integer = 1 To 5
			Try
				SB.Name = "DUPLICATE_" & DupNum
				
				If SB.Name = "DUPLICATE_" & DupNum = True
					MessageBox.Show("True " & DupNum, "Duplicate Number")
					Exit For
				Else 
					MessageBox.Show("False " & DupNum, "Duplicate Number")
				End If
			Catch
			End Try
		Next
	End If
Next

This is absolutely stupid. 

0 Likes
Message 15 of 15

Frederick_Law
Mentor
Mentor

Do you need the Try-Catch?

How about check 

If SB.Name = "DUPLICATE_" & DupNum

 before

SB.Name = "DUPLICATE_" & DupNum

 Fix the problem before the program crash.

0 Likes