How do I run a rule on all individual parts of an assembly?

How do I run a rule on all individual parts of an assembly?

Anonymous
Not applicable
1,752 Views
19 Replies
Message 1 of 20

How do I run a rule on all individual parts of an assembly?

Anonymous
Not applicable

Hello,

 

I am working on a rule that reads select parameters from an inventor part and lists all the parameters in an excel spreadsheet. I have the code working well for a single part, however I'm having a hard time figuring out how to automatically run this rule for every single part of an assembly. Is there a way to iterate through and run a rule on every part of an assembly? I don't want to have to manually run the rule 30+ times for each assembly.

 

Thanks!

0 Likes
Accepted solutions (2)
1,753 Views
19 Replies
Replies (19)
Message 2 of 20

WCrihfield
Mentor
Mentor

Do you only want it to run for PartDocument type documents within your assembly, or do you also need it to run on sub-assembly (AssemblyDocument) type documents within the assembly (if there are any)?

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 20

WCrihfield
Mentor
Mentor

Is your rule a 'local' rule (saved within the document), or an external rule?

If document type doesn't matter, and you want the rule to run on every referenced document in all levels of the assembly, then this rule should do the trick.  If your rule is a 'local' rule (located within the main assembly), then we will have to set things up differently.  You will also need to change name of the rule within the code first before it will work.

 

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
	MsgBox("An Assembly Document must be active for this rule (" & iLogicVb.RuleName & ") to work. Exiting.",vbOKOnly+vbCritical, "WRONG DOCUMENT TYPE")
	Exit Sub
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
For Each oRefDoc As Document In oADoc.AllReferencedDocuments
	iLogicVb.Automation.RunExternalRule(oRefDoc, "External Rule Name")
Next

 

But if you only want your your rule to work on the Part documents only, and not for any sub-assemblies, then you can use this version of the code.  I just added a If...Then statement in there to check each document's type, before running the rule on it.

 

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
	MsgBox("An Assembly Document must be active for this rule (" & iLogicVb.RuleName & ") to work. Exiting.",vbOKOnly+vbCritical, "WRONG DOCUMENT TYPE")
	Exit Sub
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
For Each oRefDoc As Document In oADoc.AllReferencedDocuments
	If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		iLogicVb.Automation.RunExternalRule(oRefDoc, "External Rule Name")
	End If
Next

 

Or, if you only want your rule to effect top level components, and not components within sub-assemblies, then you would need to loop through each component in the main assemblies component occurrences, like this:

 

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
	MsgBox("An Assembly Document must be active for this rule (" & iLogicVb.RuleName & ") to work. Exiting.",vbOKOnly+vbCritical, "WRONG DOCUMENT TYPE")
	Exit Sub
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition
For Each oOcc As ComponentOccurrence In oADef.Occurrences
	Dim oOccDoc As Document = oOcc.Definition.Document
	If oOccDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		iLogicVb.Automation.RunExternalRule(oRefDoc, "External Rule Name")
	End If
Next

 

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)

0 Likes
Message 4 of 20

WCrihfield
Mentor
Mentor

Another thing you will have to keep in mind is how your rule is referencing the document it is supposed to be acting upon.  If your rule is working with the 'active' document, and the main assembly will likely still be the 'active' document that your rule will try to target, which I'm sure you don't want.  Using the 'iLogicVb.Automation.RunExternalRule()' line, where you can actually specify a document, instead of the iLogicVb.RunExternalRule(), helps to target the specific document for the rule to effect, but I believe that within the rule itself, it should be using the 'ThisDoc.Document' reference to refer to the document it is targeting, instead of 'ThisApplication.ActiveDocument'.  Here is a link to one of my contribution posts that goes into document references in more detail, in case you are interested in learning more.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 20

Anonymous
Not applicable

Part Document

0 Likes
Message 6 of 20

Anonymous
Not applicable

When running the code i am reciveing the following error message:

 

Unable to cast COM object of type 'Inventor._DocumentClass' to interface type 'Inventor.PartDocument'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{29F0D463-C114-11D2-B77F-0060B0F159EF}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

 

Not sure what this means?

0 Likes
Message 7 of 20

WCrihfield
Mentor
Mentor

Which version code from above did you end up trying?

I did notice that in the last code I posted, where it loops through components, I forgot to change my document variable from 'oRefDoc' to 'oOccDoc' within the line that runs the rule.  Sorry about that.  Maybe that's where it is throwing the error.  Here is the corrected version of that one:

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
	MsgBox("An Assembly Document must be active for this rule (" & iLogicVb.RuleName & ") to work. Exiting.",vbOKOnly+vbCritical, "WRONG DOCUMENT TYPE")
	Exit Sub
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
Dim oADef As AssemblyComponentDefinition = oADoc.ComponentDefinition
For Each oOcc As ComponentOccurrence In oADef.Occurrences
	Dim oOccDoc As Document = oOcc.Definition.Document
	If oOccDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		iLogicVb.Automation.RunExternalRule(oOccDoc, "External Rule Name")
	End If
Next

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 8 of 20

Anonymous
Not applicable

I actually used the middle code that you originally shared. Still getting that same error. 

 

I have attached my working external rule that i am trying to run for every part in an assembly for reference

 

 

''Inventor to excel properties automation
Excel_file = "test2.xlsx"

Material_type = parameter("Material")
Material_size = parameter("MaterialSize")
Material_thic = parameter("Thickness")
Length_val = SheetMetal.FlatExtentsLength
Bend_rad = Parameter("BendRadius")
part_type = parameter("PartType")
part_number = iProperties.Value("Project", "Part Number")
quant_per = length_val / 12

If material_type = "Aluminum"
	If material_thic = 0.25
		If Material_size = 1
			comp_item = "12006JA16H"
		ElseIf Material_size = 1.5
			comp_item = "12006JA16P"
		ElseIf Material_size = 1.75
			comp_item = "12006JA16R"
		ElseIf Material_size = 2
			comp_item = "12006JA16T"
		ElseIf Material_size = 2.5
			comp_item = "12006JA16W"
		ElseIf material_size = 3
			comp_item = "12006JA16Y"
		ElseIf Material_size = 4
			comp_item = "12006JA17D"
		ElseIf Material_size = 5
			comp_item = "12006JA17H"
		ElseIf Material_size = 6
			comp_item = "12006JA17N"
		ElseIf Material_size = 7
			comp_item = "12006JA17P"
		ElseIf Material_size = 8
			comp_item = "12006JA17Q"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
	End If
	
ElseIf Material_type = "Copper"
	If material_thic = 0.125
		If Material_size = 1
			comp_item = "13402GI5L6"
		ElseIf Material_size = 1.5
			comp_item = "13402AD5LE"
		ElseIf Material_size = 2
			comp_item = "13402GI5LS"
		ElseIf Material_size = 8
			comp_item = "13406MS13Y"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	ElseIf Material_thic = 0.312
		If Material_size = 1
			comp_item = "13406MS2AJ"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	ElseIf Material_thic = 0.25
		If material_size = 1
			comp_item = "13406MS16H"
		ElseIf material_size = 1.25
			comp_item = "13406MS16L"
		ElseIf material_size = 1.5
			comp_item = "13406MS16P"
		ElseIf Material_size = 1.75
			comp_item = "13406MS16R"
		ElseIf material_size = 2
			comp_item = "13406MS16T"
		ElseIf Material_size = 2.5
			comp_item = "13406MS16W"
		ElseIf Material_size = 2.75
			comp_item = "13406MS16X"
		ElseIf Material_size = 3
			comp_item = "13406MS16Y"
		ElseIf material_size = 4
			comp_item = "13406MS17D"
		ElseIf material_size = 5
			comp_item = "13406MS17H"
		ElseIf material_size = 6
			comp_item = "13406MS17N"
		ElseIf material_size = 7
			comp_item = "13406MS17P"
		ElseIf material_size = 8
			comp_item = "13406MS17Q"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
	End If
	
ElseIf Material_type = "Tin Plated"
	If material_thic = 0.25
		If material_size = 1
			comp_item = "13406MT16H"
		ElseIf material_size = 1.5
			comp_item = "13406MT16P"
		ElseIf material_size = 2
			comp_item = "13406MT16T"
		ElseIf material_size = 3
			comp_item = "13406MT16Y"
		ElseIf material_size = 4
			comp_item = "13406MT17D"
		ElseIf material_size = 5
			comp_item = "13406MT17H"
		ElseIf material_size = 6
			comp_item = "13406MT17N"
		ElseIf material_size = 7
			comp_item = "13406MT17P"
		ElseIf material_size = 8
			comp_item = "13406MT17Q"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
	End If
Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
End If


Dim oPDoc As PartDocument = ThisApplication.ActiveDocument
	Dim oPDef As PartComponentDefinition = oPDoc.ComponentDefinition

	Dim oSMDef As SheetMetalComponentDefinition = oPDoc.ComponentDefinition

	If oSMDef.Bends.Count > 0 Then
		have_bend = "Yes"
	Else
		have_bend = "No"
	End If
	
GoExcel.Open (Excel_file, "sheet1")	

RowStart = 2
RowEnd = 100
For count = RowStart To RowEnd
	If String.IsNullOrEmpty(GoExcel.CellValue("B" & count)) Then 
		i = i + 1
	End If
Next
EmptyRow = RowEnd - i + 1	



GoExcel.CellValue(Excel_file, "sheet1", "B" & EmptyRow) = part_number
GoExcel.CellValue(Excel_file, "sheet1", "C" & EmptyRow) = part_type
GoExcel.CellValue(Excel_file, "sheet1", "D" & EmptyRow) = comp_item
GoExcel.CellValue(Excel_file, "sheet1", "E" & EmptyRow) = Length_val
GoExcel.CellValue(Excel_file, "sheet1", "F" & EmptyRow) = quant_per
GoExcel.CellValue(Excel_file, "sheet1", "G" & EmptyRow) = Have_bend

GoExcel.Save
0 Likes
Message 9 of 20

WCrihfield
Mentor
Mentor

OK. I can better understand the whole situation now.  There are some things in your rule that will have to change, if you want to use it as an external rule that is being ran from a main assembly.  I'll see what I can do to modify is as needed.

Here's what I've got right now, but I'm leaving soon.  I included some code at the start that looks for a value that can be passed to this rule from the line in the other rule that is used to run this rule.  If you supply 'aguments' (a NameValueMap) as the last input variable in the line that runs the rule iLogicVb.Automation.RunExteralRuleWithArguments(), it then supply that oOccDoc variable as the Value of a Name/Value pair (called "TargetDoc") within that NameValueMap, it will supply that to this rule.

''Inventor to excel properties automation
Dim oTargetDoc As PartDocument
If RuleArguments.Exists("TargetDoc") Then
	oTargetDoc = RuleArguments.Value("TargetDoc")
Else
	If TypeOf ThisDoc.Document Is PartDocument Then
		oTargetDoc = ThisDoc.Document
	End If
End If
If IsNothing(oTargetDoc) Then
	MsgBox("Target Document not found. Exiting rule.", , "")
	Exit Sub
End If
If Not TypeOf oTargetDoc.ComponentDefinition Is SheetMetalComponentDefinition Then
	MsgBox("This Part is not a Sheet Metal Part.  Exiting rule.", , "")
	Exit Sub
End If
Dim oSMDef As SheetMetalComponentDefinition = oTargetDoc.ComponentDefinition
Dim oParams As Inventor.Parameters = oSMDef.Parameters

If oSMDef.Bends.Count > 0 Then
	have_bend = "Yes"
Else
	have_bend = "No"
End If

Excel_file = "test2.xlsx"

Material_type = oParams.Item("Material").Value

Material_size = oParams.Item("MaterialSize").Expression
Material_thic = oParams.Item("Thickness").Expression
Length_val = oSMDef.FlatPattern.Length
Bend_rad = oParams.Item("BendRadius").Expression
part_type = oParams.Item("PartType").Expression
part_number = oTargetDoc.PropertySets.Item(3).Item("Part Number").Value
quant_per = Length_val / 12

If Material_type = "Aluminum"
	If Material_thic = 0.25
		If Material_size = 1
			comp_item = "12006JA16H"
		ElseIf Material_size = 1.5
			comp_item = "12006JA16P"
		ElseIf Material_size = 1.75
			comp_item = "12006JA16R"
		ElseIf Material_size = 2
			comp_item = "12006JA16T"
		ElseIf Material_size = 2.5
			comp_item = "12006JA16W"
		ElseIf Material_size = 3
			comp_item = "12006JA16Y"
		ElseIf Material_size = 4
			comp_item = "12006JA17D"
		ElseIf Material_size = 5
			comp_item = "12006JA17H"
		ElseIf Material_size = 6
			comp_item = "12006JA17N"
		ElseIf Material_size = 7
			comp_item = "12006JA17P"
		ElseIf Material_size = 8
			comp_item = "12006JA17Q"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
	End If
	
ElseIf Material_type = "Copper"
	If Material_thic = 0.125
		If Material_size = 1
			comp_item = "13402GI5L6"
		ElseIf Material_size = 1.5
			comp_item = "13402AD5LE"
		ElseIf Material_size = 2
			comp_item = "13402GI5LS"
		ElseIf Material_size = 8
			comp_item = "13406MS13Y"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	ElseIf Material_thic = 0.312
		If Material_size = 1
			comp_item = "13406MS2AJ"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	ElseIf Material_thic = 0.25
		If Material_size = 1
			comp_item = "13406MS16H"
		ElseIf Material_size = 1.25
			comp_item = "13406MS16L"
		ElseIf Material_size = 1.5
			comp_item = "13406MS16P"
		ElseIf Material_size = 1.75
			comp_item = "13406MS16R"
		ElseIf Material_size = 2
			comp_item = "13406MS16T"
		ElseIf Material_size = 2.5
			comp_item = "13406MS16W"
		ElseIf Material_size = 2.75
			comp_item = "13406MS16X"
		ElseIf Material_size = 3
			comp_item = "13406MS16Y"
		ElseIf Material_size = 4
			comp_item = "13406MS17D"
		ElseIf Material_size = 5
			comp_item = "13406MS17H"
		ElseIf Material_size = 6
			comp_item = "13406MS17N"
		ElseIf Material_size = 7
			comp_item = "13406MS17P"
		ElseIf Material_size = 8
			comp_item = "13406MS17Q"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
	End If
	
ElseIf Material_type = "Tin Plated"
	If Material_thic = 0.25
		If Material_size = 1
			comp_item = "13406MT16H"
		ElseIf Material_size = 1.5
			comp_item = "13406MT16P"
		ElseIf Material_size = 2
			comp_item = "13406MT16T"
		ElseIf Material_size = 3
			comp_item = "13406MT16Y"
		ElseIf Material_size = 4
			comp_item = "13406MT17D"
		ElseIf Material_size = 5
			comp_item = "13406MT17H"
		ElseIf Material_size = 6
			comp_item = "13406MT17N"
		ElseIf Material_size = 7
			comp_item = "13406MT17P"
		ElseIf Material_size = 8
			comp_item = "13406MT17Q"
		Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
		End If
	Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
	End If
Else
			MessageBox.Show("Material type or dimensions do not fit a component item class", "MATERIAL ERROR")
End If
	
GoExcel.Open(Excel_file, "sheet1")	
RowStart = 2
RowEnd = 100
For count = RowStart To RowEnd
	If String.IsNullOrEmpty(GoExcel.CellValue("B" & count)) Then 
		i = i + 1
	End If
Next
EmptyRow = RowEnd - i + 1	
GoExcel.CellValue(Excel_file, "sheet1", "B" & EmptyRow) = part_number
GoExcel.CellValue(Excel_file, "sheet1", "C" & EmptyRow) = part_type
GoExcel.CellValue(Excel_file, "sheet1", "D" & EmptyRow) = comp_item
GoExcel.CellValue(Excel_file, "sheet1", "E" & EmptyRow) = Length_val
GoExcel.CellValue(Excel_file, "sheet1", "F" & EmptyRow) = quant_per
GoExcel.CellValue(Excel_file, "sheet1", "G" & EmptyRow) = have_bend
GoExcel.Save

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 10 of 20

Anonymous
Not applicable

Thank you for identifying that the external rule is the issue here. However,  i am confused as to what you added and what else needs to be added in order to complete this rule?

 

0 Likes
Message 11 of 20

WCrihfield
Mentor
Mentor
Accepted solution

If you are not familiar with using RuleArguments, NameValueMap, or passing data between iLogic rules, it can be a little intimidating and maybe a little hard to understand at first, so I created a contribution post about this topic to help others out.  Basically a NameValueMap is a single variable that can hold one or multiple name/value pairs of data.  It is widely used for storing things like context information, settings, or options, so they can be sent or provided to another block of code or iLogic Rule all at once.  Then the RuleArguments object is a tool used to retrieve those NameValueMap objects within the other block of code or iLogic rule.

 

The idea I had was to use these two tools to send either the referenced PartDocument object itself, or the FullFileName, or FullDocumentName of the referenced PartDocument, to the external rule so that the external rule knows very specifically which document it is supposed to be targeting (working with).  Since I wasn't 100% sure if I could send the PartDocument object itself, I decided to switch to using the part's FullDocumentName instead, just to be sure.  I don't know if you looked into the one link I included in my earlier post about document references or not, but there are many iLogic specific lines of code that are supposed to make doing some things much easier, but many of those tools are designed to always target whichever document is either currently 'active' or 'local'.  But sometimes you need to target a document that is neither 'active' nor 'local', and in those cases, you need to specify the exact document you intend for the code to be targeting, to avoid errors and unintended stuff happening.  This is one of those cases, because the Part document the external rule is supposed to be targeting is not the 'local' document, and it isn't going to be the 'active' document either.  So we need to specify exactly which document the rule is supposed to be targeting, one way or another.

 

Here is the slightly revised assembly level rule, for running your external rule.  I am now using the other line I mentioned for running the rule 'with arguments'.  Just before that line, I create a variable (oArgs) as a NameValueMap, then create a new empty NameValueMap as its value.  Then I add one Name/Value pair to it, with the Name being "TargetDoc", and the Value being the FullDocumentName of the referenced part document.  Then I supply the variable (oArgs) as the third input variable in the line that runs the external rule.  This will send that data to the specified external rule that it will run.

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
	MsgBox("An Assembly Document must be active for this rule (" & iLogicVb.RuleName & ") to work. Exiting.",vbOKOnly+vbCritical, "WRONG DOCUMENT TYPE")
	Exit Sub
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
For Each oRefDoc As Document In oADoc.AllReferencedDocuments
	If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		Dim oPDoc As PartDocument = oRefDoc
		Dim oArgs As NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap
		oArgs.Add("TargetDoc", oPDoc.FullDocumentName)
		iLogicVb.Automation.RunExternalRuleWithArguments(oPDoc, "External Rule Name", oArgs)
	End If
Next

That extra code at the beginning of the external rule is designed to retrieve the data being sent to it.  Since I changed the plan from sending/receiving a PartDocument object to sending/receiving the part's FullDocumentName (String/text), I now have to slightly change that code at the beginning of the external rule to expect and handle that different data.  I set-it up so that if it doesn't find this data being sent to it, it will then revert back to using 'ThisDoc.Document' to define which document to target (that way it can still be used directly on an open part document, like it was originally if needed).

So at the top of the external rule, change this code:

Dim oTargetDoc As PartDocument
If RuleArguments.Exists("TargetDoc") Then
	oTargetDoc = RuleArguments.Value("TargetDoc")
Else
	If TypeOf ThisDoc.Document Is PartDocument Then
		oTargetDoc = ThisDoc.Document
	End If
End If

to this code:

Dim oTargetDoc As PartDocument
Dim oFullDocumentName As String
If RuleArguments.Exists("TargetDoc") Then
	oFullDocumentName = RuleArguments.Value("TargetDoc")
	oTargetDoc = ThisApplication.Documents.ItemByName(oFullDocumentName)
Else
	If TypeOf ThisDoc.Document Is PartDocument Then
		oTargetDoc = ThisDoc.Document
	End If
End If

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 12 of 20

Anonymous
Not applicable

Ok, I'm starting to understand the idea of valuemaps. However, now I am getting this error when running the rule:

 

Error in rule: external_rule1, in document: LAD4H33LB00H01.ipt

Unable to cast object of type 'System.String' to type 'Inventor.PartDocument'.

 

Any  idea what is causing this??

0 Likes
Message 13 of 20

WCrihfield
Mentor
Mentor
Accepted solution

2 questions:

1) The error you posted seems to indicate that a rule named "external_rule1" is located within a part document named "LAD4H33LB00H01.ipt".  If that were true, the rule that generated that error would be a 'local' rule (saved within the part document), instead of an external rule.  I assumed your assembly level rule (the rule that loops through referenced documents then runs the other rule) was either 'local' to the main assembly document, or an external rule itself.  Then I also assumed that the other main rule was an external rule (not saved within any document).  If this were true, then this error is being generated by a third rule.  Do you still have a copy of the original main (larger) rule saved within your individual Part documents?  If so, you may have to either delete or suppress that 'local' rule within those part documents, so that they don't get automatically triggered to run when things change.

 

2) Did you change both rules as specified in my last post above?  If the assembly level rule was updated, but the larger main external rule was not updated, it might cause a similar error, because it would still be trying to retrieve and use a PartDocument object directdly, but would actually be receiving a String and trying to use that as a PartDocument.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 14 of 20

Anonymous
Not applicable

I figured it out and the rule works perfectly now. Thank you so much for your help!!

0 Likes
Message 15 of 20

WCrihfield
Mentor
Mentor

Glad to hear it. 😅

By the way, I just created two very simple 'local' iLogic rules for the sole purpose of testing the theory I mentioned earlier about sending a PartDocument object from one rule to another rule using the NameValueMap & RuleArguments method.  I don't think I had ever attempted to send anything other than textual, numeric, or basic reference type data this way before, so I wasn't 100% sure if it would work.  Well I just tested it with these two simple iLogic rules, and it worked.  I also tested sending the document to a simple external rule, to make sure, and that worked too.  This is great news, because that simplifies the code a bit.  This way you can just directly send the document object reference from the calling rule, to the called rule, then called rule can then just directly use that as its target document. 

Here are the two simple rules I used to tested this theory with:

Rule 1 was named "Send Document To Other Rule"

Dim oDoc As Document = ThisDoc.Document
Dim oArgs As NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap
oArgs.Add("Doc", oDoc)
iLogicVb.RunRule("Receive Doc From Other Rule", oArgs)
'iLogicVb.RunExternalRule("Receive Doc From Other Rule", oArgs)

Rule 2 was named "Receive Doc From Other Rule" (I had a local one and an external one with the same name to test)

Dim oRecievedDoc As Document
If RuleArguments.Exists("Doc") Then
	oRecievedDoc = RuleArguments.Value("Doc")
End If
MsgBox(oRecievedDoc.FullFileName,,"")

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 16 of 20

Anonymous
Not applicable

Hi, 

 

I had a quick follow up question. So I noticed that this rule that iterates through the whole assembly will only write to the excel sheet if the excel file is in the same folder as the assembly parts. However, if I run the main code for only a specific part I can change the path for the excel file to any location. Is there a way to run the assembly code and write the data to an excel file located outside of the folder where the assembly parts are located? 

 

Here is the code that im using:

Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
For Each oRefDoc As Document In oADoc.AllReferencedDocuments
	If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		Dim oPDoc As PartDocument = oRefDoc
		Dim oArgs As NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap
		oArgs.Add("TargetDoc", oPDoc.FullDocumentName)
		iLogicVb.Automation.RunExternalRuleWithArguments(oPDoc, "Run for Part", oArgs)
	End If
Next

 

0 Likes
Message 17 of 20

WCrihfield
Mentor
Mentor

Yes, I believe it is possible to set it up that way, but I don't think it has anything to do with the rule that loops through the referenced documents and runs the other rule.  Your main rule, that actually does the writing to a spreadsheet is where the change would need to happen.  I believe this is mainly because the line you use to specify the spreadsheet file is using a partial or relative path, instead of a full path.

In your rule you are using these two lines:

Excel_file = "test2.xlsx"
GoExcel.Open(Excel_file, "sheet1")

You are not specifying the full path of that spreadsheet file, so it assumes it is located within the same folder as the 'currently active' document.  This normally works OK for a local rule & local document, but when using an external rule and looping through a bunch of documents that may not all be located within the same folder, this is no longer a good idea.  I believe that if you specify the full path and file name of that spreadsheet document, it will work better in this situation.  Give that a try.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 18 of 20

Anonymous
Not applicable

I actually did already try that. It will work if I just run that main rule on a single part, but when I try to loop through every part in an assembly it will not write anything to the excel file. Was really confused why this will work for a single part but when I run the loop rule it no longer works? 

0 Likes
Message 19 of 20

Anonymous
Not applicable

I got it to work, for some reason I had to delete and then re-add the external rule once I updated the file path, thanks for the help!

0 Likes
Message 20 of 20

Anonymous
Not applicable

Hi again,

 

I was wondering if you knew of a way to count the number of times each unique part number was used in an assembly?

For example, I want to return in excel something like:

 

Part A qty. 2

Part B qty. 5

Part C qty. 1

 

Any ideas on how to do this for an assembly?

Thanks!

0 Likes