The follow error gets thrown immediately when I try to run the rule.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at ThisRule..ctor()
--- End of inner exception stack trace ---
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at Autodesk.iLogic.Exec.AppDomExec.CreateObjectWithInterface(Assembly a, String interfaceName)
at Autodesk.iLogic.Exec.AppDomExec.ExecRuleInAssembly(Assembly assem)
at iLogic.RuleEvalContainer.ExecRuleEval(String execRule)
The code I try to run is as follows. Can someone help to debug this?
'Sub Routing to Define Sub Run Order
Sub Main()
CreateEmptyDictionary()
CreateFastenerDictionary()
CreateVirtualParts()
End Sub
'Public Declarations for use in all functions
Public Dim PartPropertiesFileAddr As String = "04_Part_iProperties.xlsm"
Public Dim FastenerPropertyFileAddr As String = "C:\Downloads\Fastener_Project_Properties.xlsm"
Public Dim oPartDictionary As New Dictionary(Of String, Dictionary(Of String, Integer))
Public Dim oAssy As AssemblyDocument = ThisDoc.Document
Public Dim oAsmCompDef As AssemblyComponentDefinition = oAssy.ComponentDefinition
'Prepopulates the oPartDictionary from an Excel Sheet master
Sub CreateEmptyDictionary
'Find Max Iterations in Parts Sheet
GoExcel.Open(PartPropertiesFileAddr,"Parts")
Dim PartsMaxIterations As Integer = GoExcel.CellValue("F1")
For Rows = 4 To PartsMaxIterations
'Compare the Material Setting to weed out non-screwed/fastened pieces
If GoExcel.CellValue("D" & Rows) = "Aluminum" Then
Dim PartName As String = GoExcel.CellValue("A" & Rows)
Dim EmptyDictionary As New Dictionary(Of String, Integer)
oPartDictionary.Add(PartName, EmptyDictionary)
End If
Next
GoExcel.Close
End Sub
Public Dim oFastDictionary As New Dictionary(Of String, Integer)
Sub CreateFastenerDictionary()
GoExcel.Open(FastenerPropertyFileAddr, "Fasteners")
oNumFast = GoExcel.CellValue("J" & 1)
oNumExtr = GoExcel.CellValue("F" & 1)
For extrusionID = 4 To NumExtr
' Holds name of Extrusion in Each Iteration
UnitExtrusion = GoExcel.CellValue("A" & extrusionID)
' If the unit has the extrusion checked in excel sheet, then fill out fastener dictionary
If oPartDictionary.Contains(UnitExtrusion) Then
For fastenerID = 2 To oNumFast
'Changes the Character for Clumn
FastenerCol = "A" + fastenerID - 1
FastQuantity = GoExcel.CellValue(FastenerCol & fastenerID)
If FastQuantity <> 0 Then
' Grab ID of every Fastener that does have a # of parts
Dim ofastenerName As String = GoExcel.CellValue(FastenerCol & 3)
oFastDictionary.Add(ofastenerName,FastQuantity)
End If
Next
'Skip to next fastener
End If
'End searching for the part
Next
GoExcel.Close
End Sub
'Loop through the assembly to check how many virtual parts are to be made
Sub CreateVirtualParts
'Once the Level 1 Dictionary is created, the FastenerDictionary needs to be generated
Dim i As Integer = 0 ' Holding Index Variable
Dim identity As Matrix = ThisApplication.TransientGeometry.CreateMatrix
' Loop through all the Parts
For Each oOcc As ComponentOccurrence In oAsmCompDef.Occurrences
'Only look to check if the part itself is not already virtual
If Not TypeOf oOcc.Definition Is VirtualComponentDefinition Then
On Error Resume Next
oDocFile = oOcc.Definition.Document
oDocFileName = oDocFile.displayname
'Set your delimiter
Delimiter = InStr(oDocFileName, "-")
Description = Left(oDocFileName, Delimiter - 1)
' Check if Part Dictionary contains the part for the model
If oPartDictionary.ContainsKey(Description) Then
' If it does have the Part, then get the Fastener dictionary and create the number of virtual parts
' This for loop uses the oOcc to find keys in the map instead of looping through the map
For Each oFastenerType As String In oPartDictionary(Description).Keys
For i = 1 To oPartDictionary(Description)(oFastenerType)
' Loop through each fastener type within the Fastener dictionary ^
' Virtual Part Parameters
FastenerName = oFastenerType & ":" & i
'oProp1 = oFastenerType
'Create a new component occurrence
Dim oNewOcc As ComponentOccurrence = oAsmCompDef.Occurences
virtOcc = oNewOcc.AddVirtual(FastenerName, identity)
'Create Virtual Component Definition
Dim oCVirtualCompDef As VirtualComponentDefinition
oCVirtualCompDef = oNewOcc.Definition
'iProperties.Value(FastenerName & ":1", "Project", "Description") = oProp1
i = i + 1
Next
Next
End If
End If
Next
End Sub
The excel document has the following template:
Solved! Go to Solution.
Solved by ABoaro. Go to Solution.
Solved by omartin. Go to Solution.
At first glance; Public Dim PartPropertiesFileAddr As String = "04_Part_iProperties.xlsm"
looks suspicious is this the correct file you want to use? Also when you are assigning objects to variables it is good to check for null before using them. this will help with debugging or you can use try/catch blocks with a messageBox for these assignment to know exactly where it is failing
I will try the null approach. I am coming from C++ and I am wondering how is NULL checked in VBA.Net specifically.
And yes, the Parts Properties excel file is a macro enabled sheet that has code within the sheet to feed information to iLogic. Could it be that iLogic only likes .xls style files?
Thank you for a point in a debugging direction.
I have not used goExcel myself, but I read it has a lot of finickey behaviour. you can do a small test to ensure that file is being loaded properly with xlsm, otherwise it is some other object that is failng on assignment, you can use is the, "is nothing" to check for null objects
Best Regards
I went ahead and adjusted the format. The sub feature of the set up was what was throwing null exceptions. Now I am getting a similar error but for the Dictionary Definition.
I am wondering if you know how to set objects either as NULL or set the dictionary to am empty dictionary. I am hoping after that it should be fixed.
But to answer your other point, yes it is an excel file. The path for xlsm is just a type of excel sheet with macros that I programmed into that myself. I haven't had issues with that before.
As soon as you new up the dictionary, it wont be null, it will be empty and you will be able to add to it, as long as the key you are adding is not null or duplicate.
You do not want to set it to null or nothing after it has been new'd up other wise you wont be able to add to it and you will get a null excepton, you just want to clear() it out.
Im just looking at the CreateEmptyDictionary() is this where it is failing, what was the error message it may leave some clues
After tediously going line by line and commenting out and determining what works, I found that the invocation error was fixed when I did the following change:
Dim EmptyDictionary As New Dictionary(Of String, Integer)
to this:
Dim EmptyDictionary = New Dictionary(Of String, Integer)
The null error appeared to have gone away with this fix. Unsure how this differs from the first declaration of the empty dictionary.
My next error occurs when I am looping through the excel columns. GoExcel seems to only like character indices when getting a specific value. I get an error message about looping through the columns:
System.ArgumentException: Argument 'Limit' is Nothing.
at Microsoft.VisualBasic.CompilerServices.ObjectFlowControl.ForLoopControl.ForLoopInitObj(Object Counter, Object Start, Object Limit, Object StepValue, Object& LoopForResult, Object& CounterResult)
at ThisRule.Main()
at Autodesk.iLogic.Exec.AppDomExec.ExecRuleInAssembly(Assembly assem)
at iLogic.RuleEvalContainer.ExecRuleEval(String execRule)
Not sure if you can help with that at least. I know you are weary of Excel.
I have provided the updated code below that has fixed all the bugs I was having. I needed to convert some of the cell types from Excel to strings and others to numbers to ensure my looping worked.
Although, taking you suggestion, I may steer away from Excel come the future.
'Public Declarations for use in all functions Dim PartPropertiesFileAddr As String = "W:\Projects-Walters-Wolf\2019\19-04_MSCM_Samm\4-Production_Drawings\19-04_Part_iProperties.xlsm" Dim FastenerPropertyFileAddr As String = "C:\Users\aboaro\Downloads\Fastener_Project_Properties.xlsm" Dim oPartDictionary = New Dictionary(Of String, Dictionary(Of String, Integer)) Dim oAssy As AssemblyDocument = ThisDoc.Document Dim oAsmCompDef As AssemblyComponentDefinition = oAssy.ComponentDefinition Dim List = New String(){"B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T","U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM"} 'Find Max Iterations in Parts Sheet GoExcel.Open(PartPropertiesFileAddr,"Parts") Dim PartsMaxIterations As Integer = GoExcel.CellValue("F1") For Rows = 4 To PartsMaxIterations 'Compare the Material Setting to weed out non-screwed/fastened pieces If GoExcel.CellValue("D" & Rows) = "Aluminum" Then Dim PartName As String = GoExcel.CellValue("A" & Rows) Dim EmptyDictionary As New Dictionary(Of String, Integer) oPartDictionary.Add(PartName, EmptyDictionary) End If Next GoExcel.Close Dim oFastDictionary As New Dictionary(Of String, Integer) GoExcel.Open(FastenerPropertyFileAddr, "Fasteners") Dim oNumFast As Integer = GoExcel.CellValue("J" & 1) Dim oNumExtr As Integer = GoExcel.CellValue("K" & 1) 'Row number matched to specific Extrusion For extrusionID = 4 To oNumExtr ' Holds name of Extrusion in Each Iteration Dim oUnitExtrusion As String = GoExcel.CellValue("A" & extrusionID) ' If the unit has the extrusion checked in excel sheet, then fill out fastener dictionary If oPartDictionary.Keys.Contains(oUnitExtrusion) Then For fastenerID = 2 To List.Length ' Selects Column Letter FastenerCol = List(fastenerID - 2) 'Number of Fasteners FastQuantity = GoExcel.CellValue(FastenerCol & extrusionID) If FastQuantity <> 0 Then ' Grab ID of every Fastener that does have a # of parts Dim ofastenerName As String = CStr(GoExcel.CellValue(FastenerCol & 3)) 'MsgBox(ofastenerName) -> show fastener name 'MsgBox(FastQuantity) -> show Fastener Quantity 'Add fastener to the fastener dictionary for specific part oFastDictionary.Add(ofastenerName, FastQuantity) End If Next ' End Fastener Check oPartDictionary(oUnitExtrusion) = oFastDictionary oFastDictionary = New Dictionary(Of String, Integer) End If 'End searching for the part Next GoExcel.Close 'Loop through the assembly to check how many virtual parts are to be made 'Once the Level 1 Dictionary is created, the FastenerDictionary needs to be generated 'Dim i As Integer = 0 ' Holding Index Variable '' Loop through all the Parts For Each oOcc As ComponentOccurrence In oAsmCompDef.Occurrences 'Only look to check if the part itself is not already virtual If Not TypeOf oOcc.Definition Is VirtualComponentDefinition Then On Error Resume Next Dim identity As Matrix = ThisApplication.TransientGeometry.CreateMatrix oDocFile = oOcc.Definition.Document oDocFileName = oDocFile.displayname 'Set your delimiter Delimiter = InStr(oDocFileName, "-") Description = Left(oDocFileName, Delimiter - 1) MsgBox(Description) ' Check if Part Dictionary contains the part for the model If oPartDictionary.ContainsKey(Description) Then ' If it does have the Part, then get the Fastener dictionary and create the number of virtual parts ' This for loop uses the oOcc to find keys in the map instead of looping through the map MsgBox(oPartDictionary(Description).Keys.Count) For Each oFastenerType As String In oPartDictionary(Description).Keys 'MsgBox(oPartDictionary(Description)(oFastenerType)) For i = 0 To oPartDictionary(Description)(oFastenerType) ' ' Loop through each fastener type within the Fastener dictionary ^ ' ' Virtual Part Parameters FastenerName = oFastenerType & ":" & (i + 1) 'oProp1 = oFastenerType ' 'Create a new component occurrence Dim oNewOcc As ComponentOccurrence oNewOcc = oAsmCompDef.Occurrences.AddVirtual(FastenerName, identity) Dim oCVirtualCompDef As VirtualComponentDefinition oCVirtualCompDef = oNewOcc.Definition 'Create Virtual Component Definition 'Dim oCVirtualCompDef As VirtualComponentDefinition 'oCVirtualCompDef = oNewOcc.Definition 'iProperties.Value(FastenerName & ":1", "Project", "Description") = oProp1 ' i = i + 1 Next Next End If End If Next
Glad to hear it all worked out! some times you got to do what ya got to do and now you know more things to look out for.
you can look in to creating excel as an object and then using the native excel commands, I find this more predictable.
Cheers
Can't find what you're looking for? Ask the community or share your knowledge.