Object of type 'System.UInt32' cannot be converted to type 'Inventor.CommandType

Object of type 'System.UInt32' cannot be converted to type 'Inventor.CommandType

SometimesInventorMakesMeAngry
Advocate Advocate
1,073 Views
4 Replies
Message 1 of 5

Object of type 'System.UInt32' cannot be converted to type 'Inventor.CommandType

SometimesInventorMakesMeAngry
Advocate
Advocate

I'm trying to simply create parameters in a list of parts with error checking. Every time the macro is run, it creates these variable, so if I run it more than once it will create new parameters with "_1", "_1_2", etc appended to the end. My code should delete all old parameters and create new ones every time it runs. I've spent several hours trying to debug this, but I can't figure out what's wrong. Below is my full code. Note that I have neglected %Path because it contains sensitive company information. I'm new to programming and recently started using VBA so please excuse bad coding practices. 

Option Explicit

Sub CreateCoverParameters()

Dim sSectionPath As String
sSectionPath = "C:\Work\%Path\"

'Assign cover file names to array elements
Dim sCover(2) As String
sCover(0) = sSectionPath & "1343565.ipt"
sCover(1) = sSectionPath & "1343322.ipt"
sCover(2) = sSectionPath & "1343321.ipt"
'MsgBox sCover(2)
'MsgBox UBound(scover)

'Iterate and create parameters in each cover
'Declare user parameters
Dim sUserParams() As String
sUserParams = Split("lPatternLength,lPatternLengthShort", ",")

'Declare iteration variables
Dim iCoverCount As Integer
Dim oCoverParam As parameter
Dim iParamTest As Integer
Dim sParamTest As String
Dim iParameterCount As Integer
Dim iUserParamCount As Integer

For iCoverCount = 0 To UBound(sCover)

    'Test if parameter is duplicate and delete
    iParameterCount = ThisApplication.Documents.ItemByName(sCover(iCoverCount)). _
                      ComponentDefinition.Parameters.UserParameters.Count
    For iParamTest = 1 To iParameterCount
        'MsgBox ThisApplication.Documents.ItemByName(sCover(iCoverCount)). _
                     ComponentDefinition.Parameters.UserParameters.Item(iParamTest).Name
        sParamTest = ThisApplication.Documents.ItemByName(sCover(iCoverCount)). _
                     ComponentDefinition.Parameters.UserParameters.Item(iParamTest).Name
        
        For iUserParamCount = 0 To UBound(sUserParams)
                If InStr(1, sParamTest, sUserParams(iUserParamCount)) > 0 Then
                ThisApplication.Documents.ItemByName(sCover(iCoverCount)). _
                ComponentDefinition.Parameters.UserParameters.Item(iParamTest).Delete
            End If
        Next
    Next
    
    'Create parameter
    
    For iUserParamCount = 0 To UBound(sUserParams)
        Set oCoverParam = ThisApplication.Documents.ItemByName(sCover(iCoverCount)).ComponentDefinition. _
        Parameters.UserParameters.AddByExpression(sUserParams(iUserParamCount), 0, "in")
    Next
Next
End Sub

When I run this, I get 

"Run-time error '-2147024809 (80070057)':
Object of type 'System.UInt32' cannot be converted to type 'Inventor.CommandTypesEnum'."

The weird thing is that if I run and debug, the first portion of pink text is highlighted sometimes. Other times, the second portion of pink text is highlighted. Also, this code has worked perfectly before, but now I can't get it to work. Edit: It works perfectly when I delete all related user parameters then run it, so I guess the parameter creation part is working but the "error checking" part is not, which kind of defeats the purpose.

I first thought maybe I had declared sParamTest with the wrong data type, but checking the object browser, the Name property is, indeed a string. Then I thought maybe I made a mistake in the InStr function, but everything looks correct.

Any help is greatly appreciated.

0 Likes
1,074 Views
4 Replies
Replies (4)
Message 2 of 5

JamieVJohnson2
Collaborator
Collaborator

I can't quite find your exact issue, because I don't know where the system is looking for Inventor.CommandTypesEnum in your code. (in my copy I changed ThisApplication to invApp for use in visual studio vb.net) There are some things you can clean up, and maybe they can help you get closer:

1.  Your reuse of the line invApp.Documents.ItemByName(sCover(iCoverCount)).ComponentDefinition.Parameters.UserParameters...

Just do this (inside of your loop):

"Dim userParams As UserParameters = invApp.Documents.ItemByName(sCover(iCoverCount)).ComponentDefinition.Parameters.UserParameters"

Then just reuse userParams instead of the whole long line.

2.  Your delete for loop.  I've learned the hard way its best to loop in reverse when deleting items that belong to the loop:  "For iParamTest = userParams.Count To 1 Step -1"

3.  Your assumption in item 1 above that the invApp.Documents.ItemByName(anythinghere) actually returned a document is bravery at its best.  The rest of your code .ComponentDefinition... is using that assumption.  This may be the actual problem, with Inventor returning some goofy error.  try this first:

dim invDoc as Inventor.Document = invApp.Documents.ItemByName(sCover(iCoverCount))

Then check "If invDoc isnot nothing Then" contain the rest of the contents between then and the End If inside of the loop.  here you can use an Else 'meaning nothing was found and place a msgbox "file not found".

4.  The other assumption is that you have a document of type that uses .ComponentDefinition.  Only PartDocments and AssemblyDocuments have ComponentDefinition, other document types may just throw an error here.

    Public Function GetPartOrAssemblyComponentDefinition(invdoc As Inventor.Document) As ComponentDefinition
        Dim cd As ComponentDefinition = Nothing
        If invdoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
            cd = CType(invdoc, PartDocument).ComponentDefinition
        ElseIf invdoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
            cd = CType(invdoc, AssemblyDocument).ComponentDefinition
        End If
        Return cd
    End Function

Anyway, clean some of that, and check for those assumptions, to break down that one repeated long line to get to user parameters into small segmented lines that check for assumptive values to exist, and you may better be able to see the exact point of error.

 

 

Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
0 Likes
Message 3 of 5


@JamieVJohnson2 wrote:

I can't quite find your exact issue, because I don't know where the system is looking for Inventor.CommandTypesEnum in your code. (in my copy I changed ThisApplication to invApp for use in visual studio vb.net) There are some things you can clean up, and maybe they can help you get closer:

1.  Your reuse of the line invApp.Documents.ItemByName(sCover(iCoverCount)).ComponentDefinition.Parameters.UserParameters...

Just do this (inside of your loop):

"Dim userParams As UserParameters = invApp.Documents.ItemByName(sCover(iCoverCount)).ComponentDefinition.Parameters.UserParameters"

Then just reuse userParams instead of the whole long line.

2.  Your delete for loop.  I've learned the hard way its best to loop in reverse when deleting items that belong to the loop:  "For iParamTest = userParams.Count To 1 Step -1"

3.  Your assumption in item 1 above that the invApp.Documents.ItemByName(anythinghere) actually returned a document is bravery at its best.  The rest of your code .ComponentDefinition... is using that assumption.  This may be the actual problem, with Inventor returning some goofy error.  try this first:

dim invDoc as Inventor.Document = invApp.Documents.ItemByName(sCover(iCoverCount))

Then check "If invDoc isnot nothing Then" contain the rest of the contents between then and the End If inside of the loop.  here you can use an Else 'meaning nothing was found and place a msgbox "file not found".

4.  The other assumption is that you have a document of type that uses .ComponentDefinition.  Only PartDocments and AssemblyDocuments have ComponentDefinition, other document types may just throw an error here.

    Public Function GetPartOrAssemblyComponentDefinition(invdoc As Inventor.Document) As ComponentDefinition
        Dim cd As ComponentDefinition = Nothing
        If invdoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
            cd = CType(invdoc, PartDocument).ComponentDefinition
        ElseIf invdoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
            cd = CType(invdoc, AssemblyDocument).ComponentDefinition
        End If
        Return cd
    End Function

Anyway, clean some of that, and check for those assumptions, to break down that one repeated long line to get to user parameters into small segmented lines that check for assumptive values to exist, and you may better be able to see the exact point of error.

 

 


1. Wow. I had no idea that was possible. I didn't think it was possible to nest objects and variables inside other variables. That should make it a lot cleaner.

2. Why do you think that is? Is it because Inventor updates parameter indeces live? So if you have 10 paramters (0 through 9) and your loop deletes item 2, does Inventor update indeces immediately, thus leaving only 9 parameters (o thorugh 8)? If that were the case, then wouldn't the program simply skip checking the parameter immediately after the deleted parameter? I will give it a shot.

3. Is that a problem even though I specifically make reference to a 1D array containing a list of file names that I know exist? The reason I'm doing this is that some components in this assembly are released in Vault and others I simply don't need. Otherwise, I'd use a for each in all referenced components in the assembly where these components are or something like that then I would have to check that each document has component definition.

4. Similar to 3., is that really a problem if I'm telling it exactly which documents to look at? I know for a fact they are part documents, which I think all have componentdefinition.

 

Thank you for the feedback. I will make the changes you suggested and report back.

0 Likes
Message 4 of 5

JamieVJohnson2
Collaborator
Collaborator

1.  Each loop is a separate construct, as well as if / end if, and do / loop.  During those code processes you can define new variables that exist only in that loop, and only have the life cycle of that loop.  Its up to the programmer to decide the necessary life span of the variable and where to define it so that it lives as long as necessary.

2.  Most enumerated (indexed) lists are based on the basic array.  The array can not redefine its own size, the user had to do so (remember redefine).  But that is far to basic for todays programming, so todays lists are very enhanced with auto resizing taking place.  Look up List(of T) in the VB.Net reference.  So if you delete the item in the list and the size gets smaller, you may be working with an integer that is beyond the list size (index out of range error), or worse doing work on an item that you have already done work on (no error, just twice the incorrect calculation!).  If you plan on running a routine that changes the size of a loop, yes index based looping is correct, and if it is going to remove items from the list, then cycle backwards to ensure you keep the intended indexes.

3. & 4.  Yes I am fishing here for issues.  If your assumptions are always correct, then there should be no error, but this is also the line you are getting errors from right?  So in those cases, I break down each step of the line into individual lines and test their stability before continuing down the rabbit hole.  

 

Bear in mind the error capturing process.  If a sub routine throws an error, but does not have a try/catch error trapping system, the error will bubble up to the next routine.  Let's say it bubbles up to 3 levels out of the hole, and the 3rd level has a typical error message for its own code, but nothing in the sub routine was expected to fail, so there are no other error messages to be more specific.  That is when you get an error message that makes no sense.  Generally that error message points you to the higher level code that captured the unhandled exception from the sub sub sub routine.

 

Jamie Johnson : Owner / Sisu Lissom, LLC https://sisulissom.com/
0 Likes
Message 5 of 5

1. That's good to know. I was wondering why I wasn't getting a duplicate declaration error when I declared a few things in for next loops. Do you know if one is more efficient that the other (maybe the compiler has to process the same thing for every loop?) 

2. That makes sense. Maybe I will do this for every for loop in every project to avoid any problems.

 

I tried using a try catch block initially but it looks like inventor vba doesn't support them. So I'm using if statements and InStr. But what you're saying makes sense. If you don't have error checking, you might get an error deep down somewhere and it will make it more difficult to find because the error thrown will be in the top level. Fortunately, I think I only have one level for this project.

 

I will keep working on this but here is a quick update:

I applied your suggestions 1, 2 and 3 and the code looks A LOT cleaner now, thanks for that. Sadly, I don't know how to use functions yet so I couldn't apply suggestion 4. I will look into it and do it tomorrow. 

I moved a few variables to declare them outside of the subroutines so they can all access them. Because of this, I had to create another subroutine where these variables are set and each subroutine calls this sub. in the process of rewriting, I came upon a invalid argument error, because the UserParameter.Item() index starts at 1, not 0 but that's been fixed.

Unfortunately, the same error I was getting initially keeps popping up, but this time it's only on one line (in pink below).:/ I think that's progress. 🙂

Option Explicit

'Declare private vars
Private sSectionPath As String
Private scover(2) As String
Private sSideRail(1) As String
Private sCUserParams() As String
Private sSRUserParams(3) As String
Sub SetPrivateVars()

sSectionPath = "C:\Work\%Path\"

'Assign cover file names to array elements
scover(0) = sSectionPath & "1343565.ipt"
scover(1) = sSectionPath & "1343322.ipt"
scover(2) = sSectionPath & "1343321.ipt"

'Assign side rail file names to array elements
sSideRail(0) = sSectionPath & "1343320.ipt"
sSideRail(1) = sSectionPath & "1343323.ipt"

'Set C user parameters
sCUserParams = Split("lPatternLength,lPatternLengthShort", ",")

'Set SR user parameters
sSRUserParams(0) = "lCover1PatternLength"
sSRUserParams(1) = "lCover2PatternLength"
sSRUserParams(2) = "lCover2PatternLengthShort"
sSRUserParams(3) = "lCover3PatternLength"

End Sub
Sub CreateCoverParameters()

Call SetPrivateVars

'/////////////////////////////COVERS//////////////////////////////////////////////////////


'Iterate and create parameters in each cover
'Declare C user parameters
Dim sCUserParams(1) As String
Dim iUserParamCount As Integer
sCUserParams(0) = "lCover" & iUserParamCount + 1 & "PatternLength"
sCUserParams(1) = "lCover" & iUserParamCount + 1 & "PatternLengthShort"

'Declare iteration variables
Dim iCoverCount As Integer
Dim oCoverParam As Parameter
Dim iParamTest As Integer
Dim sParamTest As String
Dim iParameterCount As Integer
Dim oUserParams As UserParameters
Set oUserParams = ThisApplication.Documents.ItemByName(scover(iCoverCount)). _
                                       ComponentDefinition.Parameters.UserParameters
Dim oInvDoc As Document

For iCoverCount = UBound(scover) To 0 Step -1
    Set oInvDoc = ThisApplication.Documents.ItemByName(scover(iCoverCount))
    
    If Not oInvDoc Is Nothing Then
    
        'Test if parameter is duplicate and delete
        iParameterCount = oUserParams.Count
            For iParamTest = iParameterCount To 1 Step -1
            'MsgBox ThisApplication.Documents.ItemByName(sCover(iCoverCount)). _
                         ComponentDefinition.Parameters.UserParameters.Item(iParamTest).Name
            sParamTest = oUserParams.Item(iParamTest).Name
            
                For iUserParamCount = UBound(sCUserParams) To 0 Step -1
                    If InStr(1, sParamTest, sCUserParams(iUserParamCount)) > 0 Then
                    oUserParams.Item(iParamTest).Delete
                    End If
                Next
            Next
    
    'Create parameter
    For iUserParamCount = 0 To UBound(sCUserParams)
        Set oCoverParam = oUserParams.AddByExpression(sCUserParams(iUserParamCount), 0, "in")
    Next
    
    Else
    MsgBox "File Not Found. You Are Bad at Coding"
    End If
Next

End Sub

 

0 Likes