Nested if statement for replace component does not work

Nested if statement for replace component does not work

Anonymous
Not applicable
662 Views
7 Replies
Message 1 of 8

Nested if statement for replace component does not work

Anonymous
Not applicable

Hi!

I am writing a code to replace content center components by other content center components, which may be placed in a different folder than my assembly itself is placed. I am starting with coding for inventor, so this is my code:

 

Sub Main

	For Each oDoc In ThisApplication.ActiveDocument.AllReferencedDocuments
     	If oDoc.DocumentType <> kPartDocumentObject Then Continue For
     
     	If oDoc.ComponentDefinition.isContentMember Then
            
				Dim asfile As String

				If Component.IsActive("ISO 4017 M12x20_A4-80:4") = True Then
					asfile = "C:\VaultWS\Library\en-US\ISO 4014(2)\B001916.ipt"
					Component.Replace("ISO 4017 M12x20_A4-80:1", asfile, True)
				ElseIf Component.IsActive("ISO 4017 M8x20_A4-80:1") = True Then
					asfile = "C:\VaultWS\Library\en-US\ISO 4014(2)\B001895.ipt"
					Component.Replace("ISO 4017 M8x20_A4-80:3", asfile, True)
			
				End If
			
    	 End If
	 Next oDoc
		End Sub

 

The problem is that if my rule do not find the first component exposed in my if state (I mean If Component.IsActive("ISO 4017 M12x20_A4-80:4") = True) It stops to run for the other possible if statements and returns the message below:

 

aliciafonsecadasilva_0-1638440302882.png

In this case the component  M12x20 is not found because the rule itself replaced it when I run it.

However, the component M8x20 is not replaced even if it is still in the assembly, I just get the error message.

 

Does anyone can see where is my mistake?

My ultimate goal is to make the nested if statement even bigger so I can replace a larger number of components.

 

@MjDeck 

@Thomas.Long 

@Curtis_Waguespack 

@MechMachineMan 

0 Likes
Accepted solutions (2)
663 Views
7 Replies
Replies (7)
Message 2 of 8

Thomas.Long
Advocate
Advocate
Accepted solution

I apologize, but why is this an else if statement rather than two fully separate if statements?

 

You have a part you want to replace if a part is active, and you have a fully separate part you want to replace if a fully separate part is active. 

 

If you use an elseif statement then it's going to look for the first true statement in your line of if's and when it finds one that's true it will execute it and leave. That's probably why it's skipping it even if it's still in the assembly.

 

The reason you're getting your error message is you're doing an isactive check on an item that you're assuming is in the assembly. You aren't actually checking it's in there before you check if it's active. It would be better to nest an if statement looking for the item in the assembly and if it's found then execute your component replace. It will be slower (possibly much depending on the size of your assembly) however it will eliminate the error as it will confirm the existence of the item before attempting to replace.

Message 3 of 8

WCrihfield
Mentor
Mentor
Accepted solution

Hi @Anonymous.  I'm not sure why you are looping through all of the main assembly's referenced documents, if you are simply going to call out a few very specific components by their names to check and or replace.  That part doesn't make sense to me, so when I created an alternative iLogic code, I left that whole process out.  The document you are checking to make sure it is a PartDocument then checking to make sure it is a Content Center member, is not necessarily guaranteed to be the same document as any of the named components you are specifying within the code after that, so I was not sure which of the named components you may have needed to check these aspects of before proceeding.  My code is laid out quite differently than yours, and includes a lot of code that is attempting to avoid potential errors.  I am also avoiding use of those Component.IsActive() and Component.Replace() calls (iLogic snippets) and trying to use purely API type calls, to help avoid any confusion.

 

Here is the new code I created.  I obviously have not tested it yet though, because I do not have your data set to test on.

Sub Main
	Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
	oADef = oADoc.ComponentDefinition
	oOccs = oADef.Occurrences
	
	'get the 4 named components (from any level of the assembly)
	oOcc1 = GetNamedComponent(oOccs, "ISO 4017 M12x20_A4-80:4")
	If IsNothing(oOcc1) Then
		MsgBox("The component named '" & oOcc1.Name & "' could not be found. Exiting rule.", vbCritical, "iLogic")
		Exit Sub
	End If
	oOcc2 = GetNamedComponent(oOccs, "ISO 4017 M12x20_A4-80:1")
	If IsNothing(oOcc2) Then
		MsgBox("The component named '" & oOcc2.Name & "' could not be found. Exiting rule.", vbCritical, "iLogic")
		Exit Sub
	End If
	oOcc3 = GetNamedComponent(oOccs, "ISO 4017 M8x20_A4-80:1")
	If IsNothing(oOcc3) Then
		MsgBox("The component named '" & oOcc3.Name & "' could not be found. Exiting rule.", vbCritical, "iLogic")
		Exit Sub
	End If
	oOcc4 = GetNamedComponent(oOccs, "ISO 4017 M8x20_A4-80:3")
	If IsNothing(oOcc4) Then
		MsgBox("The component named '" & oOcc4.Name & "' could not be found. Exiting rule.", vbCritical, "iLogic")
		Exit Sub
	End If
	
	Dim asfile As String
	If oOcc1.Suppressed = False Then 'not suppressed  = IsActive
		asfile = "C:\VaultWS\Library\en-US\ISO 4014(2)\B001916.ipt"
		Try
			oOcc2.Replace(asfile, True)
		Catch oEx As Exception
			MsgBox("The attempt to replace '" & oOcc2.Name & "' with '" & asfile & "' Failed." & vbCrLf & _
			oEx.Message & vbCrLf & oEx.StackTrace, vbCritical, "iLogic")
		End Try
	ElseIf oOcc3.Suppressed = False Then
		asfile = "C:\VaultWS\Library\en-US\ISO 4014(2)\B001895.ipt"
		Try
			oOcc4.Replace(asfile, True)
		Catch oEx As Exception
			MsgBox("The attempt to replace '" & oOcc4.Name & "' with '" & asfile & "' Failed." & vbCrLf & _
			oEx.Message & vbCrLf & oEx.StackTrace, vbCritical, "iLogic")
		End Try
	End If
End Sub

Function GetNamedComponent(oComps As ComponentOccurrences, oCompnentName As String) As ComponentOccurrence
	For Each oComp As ComponentOccurrence In oComps
		If oComp.Name = oCompnentName Then
			Return oComp
		End If
		If oComp.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			oSComp = GetNamedComponent(oComp.Definition.Occurrences, oCompnentName)
			If Not IsNothing(oSComp) Then Return oSComp
		End If
	Next
	'if code reaches this point, the component was not found, so return Nothing
	Return Nothing
End Function

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.

If you want and have time, I would appreciate your Vote(s) for My IDEAS 💡 or you can Explore My CONTRIBUTIONS

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 4 of 8

Anonymous
Not applicable

@WCrihfield , thanks for your attention. I tested your code and i got the same outcome of mine. However, your commentaries help me to write better my question and understand better the code. I am new at coding, so I still learning about the language and how to use it. I hope I can describe better my problem below:

 

Anyway my objectives with the code is :

1st Find out if a specific content center component (here I call it by A) is in my assembly;

2nd If I find the content center component A , then all its occurrences  will be replaced by a specific content center component (here I call it by B)

0 Likes
Message 5 of 8

Anonymous
Not applicable
Please, ignore my previous reply to your post. I look again you code and got a solution to my code. Thank you very much!
0 Likes
Message 6 of 8

Anonymous
Not applicable
Thank you very much your post helped me understand better the concept. now my code works!
0 Likes
Message 7 of 8

WCrihfield
Mentor
Mentor

You are welcome.  I'm glad I was able to help.  By the way, if all of those components are within the top level of the main assembly, there is a much simpler way to get them by name than using the custom function I was using.  Under the AssemblyDocument.ComponentDefinition.Occurrences is a Property called ItemByName.  You could use that within a Try...Catch...End Try block of code, to get it directly.  I would put in within that Try...Catch...End Try block of code, because if it can't find a component by that specific name, it will normally stop the code with an error, but when used within the Try portion of that block of code, it will suppress the error, and you can specify an alternative action within the Catch part of that block of code to do when it fails, like a 'component not found' message.

Here is a simplified example of doing it that way, just for your reference:

Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
oOccs = oADoc.ComponentDefinition.Occurrences
Dim oOcc1 As ComponentOccurrence
oOcc1Name ="Component1:1"
Try
	'try to find/get that component, within the top level, by name
	oOcc1 = oOccs.ItemByName(oOcc1Name)
	MsgBox("Found that component.", vbInformation, "iLogic")
Catch oEx As Exception
	'it was not found, what to do as an alternative/result
	MsgBox("Could not find a component named '" & oOcc1Name & "'. Exiting rule." & vbCrLf & _
	oEx.Message & vbCrLf & oEx.StackTrace, vbCritical, "iLogic")
	Exit Sub 'or Return
End Try
'now do something with that component

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 8 of 8

MechMachineMan
Advisor
Advisor
Don't use else if. Just use brand new if statements for each component.

Ideally you would add in some error handling too.

To revise the whole thing, I would actually make a 2d array and pass that
continually to a custom "ReplaceComponent" function within the for loop.
Would save a lot of typing and handle the errors easier. Can't quite recall
exactly what this would look like in VB.nt... but in VBA, it would be
similar too:

Dim InputArray(0 to 1, 0 to 1000) as String
InputArray = {{component1name, file name to replace that}.....}

For ndx = 0 to Ubound(InputArray, 2)
Call CustomReplace(InputArray(0, ndx), InputArray(1, ndx)
Next

End if
Next

Sub Component Replace
... Replace code here to handle errors/Replace functionality
End Sub

Sorry I'm not of more help. Good luck!

--------------------------------------
Did you find this reply helpful ? If so please use the 'Accept as Solution' or 'Like' button below.

Justin K
Inventor 2018.2.3, Build 227 | Excel 2013+ VBA
ERP/CAD Communication | Custom Scripting
Machine Design | Process Optimization


iLogic/Inventor API: Autodesk Online Help | API Shortcut In Google Chrome | iLogic API Documentation
Vb.Net/VBA Programming: MSDN | Stackoverflow | Excel Object Model
Inventor API/VBA/Vb.Net Learning Resources: Forum Thread

Sample Solutions:Debugging in iLogic ( and Batch PDF Export Sample ) | API HasSaveCopyAs Issues |
BOM Export & Column Reorder | Reorient Skewed Part | Add Internal Profile Dogbones |
Run iLogic From VBA | Batch File Renaming| Continuous Pick/Rename Objects

Local Help: %PUBLIC%\Documents\Autodesk\Inventor 2018\Local Help

Ideas: Dockable/Customizable Property Browser | Section Line API/Thread Feature in Assembly/PartsList API Static Cells | Fourth BOM Type
0 Likes