Export all multi-value parameters to spreadsheet

Export all multi-value parameters to spreadsheet

ahmed.hagi
Enthusiast Enthusiast
3,638 Views
45 Replies
Message 1 of 46

Export all multi-value parameters to spreadsheet

ahmed.hagi
Enthusiast
Enthusiast

Hello,

 

I am trying to compare values which I import from a spreadsheet to the values in my user parameters, i need to compare all the possible values as opposed to the ones which are currently set, for example: If one parameter has imported from the spreadsheet as "Blue" (for a multi value parameter called colour), I want to check that blue is a value in the list for colour. 

Is there a way to do this?

0 Likes
Accepted solutions (2)
3,639 Views
45 Replies
Replies (45)
Message 21 of 46

j.haggenjos
Advocate
Advocate

His code has the same issue as mine did with the boolean parameter.

0 Likes
Message 22 of 46

ahmed.hagi
Enthusiast
Enthusiast

how do i modify your code to just append to the string?

0 Likes
Message 23 of 46

j.haggenjos
Advocate
Advocate
Dim ParameterList As New List(Of String)
For Each oParameter As UserParameter In ThisDoc.Document.ComponentDefinition.Parameters.UserParameters
	If oParameter.ExpressionList IsNot Nothing AndAlso oParameter.ExpressionList.Count <> 0 Then
		ParameterList.AddRange(oParameter.ExpressionList.GetExpressionList().ToList)
	End If
Next
0 Likes
Message 24 of 46

WCrihfield
Mentor
Mentor

Good point @j.haggenjos  about the True/False (Boolean) type parameters.  But to simplify that check even more, all you really need to check is if "IsNot Nothing", then you don't really need to check the "Count".  That passes the Boolean type test, and still gets all my multi-value parameters.

The code I posted was a bit longer than it needed to be, just because I wanted to show some other alternative/possible results.

Here's a shorter version of it, that simply gathers all options into one list, then shows you that list.  It uses the "If oParam.ExpressionList IsNot Nothing Then" check, and works for my tests, when I have both numerical, Text, and True/False (Boolean) type parameters.

Dim oDocType As DocumentTypeEnum = ThisApplication.ActiveDocumentType
Dim oParams As Parameters
If oDocType = DocumentTypeEnum.kPartDocumentObject Or _
	oDocType = DocumentTypeEnum.kAssemblyDocumentObject Then
	oParams = ThisApplication.ActiveDocument.ComponentDefinition.Parameters
ElseIf oDocType = DocumentTypeEnum.kDrawingDocumentObject Then
	oParams = ThisApplication.ActiveDocument.Parameters
End If
Dim oParam As Inventor.Parameter
Dim oAllOptions As New List(Of String)
For Each oParam In oParams
	If oParam.ExpressionList IsNot Nothing Then
		Dim oOptions() As String = oParam.ExpressionList.GetExpressionList
		oAllOptions.AddRange(oOptions)
	End If
Next
InputListBox(" ", oAllOptions)

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 have time, please... Vote For My IDEAS 💡or you can Explore My CONTRIBUTIONS

Inventor 2021 Help | Inventor Forum | Inventor Customization Forum | Inventor Ideas Forum

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 25 of 46

j.haggenjos
Advocate
Advocate

@WCrihfield wrote:

But to simplify that check even more, all you really need to check is if "IsNot Nothing", then you don't really need to check the "Count". 

 

 Any parameter that is not boolean will pass that first check. You need to check the count to get only the multivalue parameters. However, the ExpressionList is Empty in case of single value parameter so it will not matter too much in this use case.

0 Likes
Message 26 of 46

WCrihfield
Mentor
Mentor

On further, more dynamic testing, I found that you were right about needing the secondary test, but I ended up putting that secondary test on the next line, after the "IsNot Nothing" test, because it was throwing the "Object Reference not set to an instance of an object" error, when I did it on the same line, due to it trying to get a "Count" from a non-existent "ExpressionList".

With that in mind, I created another fun/informative code that one could use to copy/transfer all multi-value parameters to another document, or Excel spreadsheet.  It incorporates a 'Dictionary', to store the parameter's name, and a list of all of its options within each dictionary entry.  That dictionary could then be sent to another routine that would populate some other document or spreadsheet.

I'm sure you've also noticed that I've been using a longer route to get the 'Parameters' variable.  This is because I also work with Parameters within my Drawing documents, and you have to retrieve them a slightly different way, and I wanted my example codes to be a bit more universal, for my (and others) use later.

Here's that code:

Dim oDocType As DocumentTypeEnum = ThisApplication.ActiveDocumentType
Dim oParams As Parameters
If oDocType = DocumentTypeEnum.kPartDocumentObject Or _
	oDocType = DocumentTypeEnum.kAssemblyDocumentObject Then
	oParams = ThisApplication.ActiveDocument.ComponentDefinition.Parameters
ElseIf oDocType = DocumentTypeEnum.kDrawingDocumentObject Then
	oParams = ThisApplication.ActiveDocument.Parameters
End If
Dim oMVParams As New Dictionary(Of String, List(Of String))
For Each oParam As Inventor.Parameter In oParams
	If oParam.ExpressionList IsNot Nothing Then
		If oParam.ExpressionList.Count > 0 Then
			oMVParams.Add(oParam.Name, oParam.ExpressionList.GetExpressionList.ToList)
		End If
	End If
Next
'this is just to confirm it was successful, and show how to work with this type of Object
For Each oPair As KeyValuePair(Of String, List(Of String)) In oMVParams
	oChosen = InputListBox(" ", oPair.Value, " ", " ", oPair.Key & " Options")
Next

 

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

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 27 of 46

j.haggenjos
Advocate
Advocate

@WCrihfield wrote:

On further, more dynamic testing, I found that you were right about needing the secondary test, but I ended up putting that secondary test on the next line, after the "IsNot Nothing" test, because it was throwing the "Object Reference not set to an instance of an object" error, when I did it on the same line, due to it trying to get a "Count" from a non-existent "ExpressionList".

If you use "AndAlso" instead of "And", the second part of the condition is only checked when the first part is true. So you have no error and you keep it all in one line.

 

Your code is more complete and can be run by itself. My code was more meant as a snippet to integrate inside a bigger logic. It lacks error handling and document type checks.

In my opinion, Dictionary is the correct way to keep multivalue parameter in memory for longer as they provide easy access to each item. With my AddIn, I'm making heavy use of the multivalue parameter and at first I kept accessing the parameter when I needed the value and it is a very slow process. Reading the value once and keeping it in a Dictionary will give you much better performance in case you need to use the value multiple time.

Message 28 of 46

ahmed.hagi
Enthusiast
Enthusiast

Is there a way to run this but only add the current value of the parameter to the list?

0 Likes
Message 29 of 46

WCrihfield
Mentor
Mentor

I'm not 100% sure what you mean, but try this:

(It just gets the current 'Value' of each multi-value parameter, and adds that 'Value' to the list, then shows you the list at the end, but it doesn't show you the name of the parameter which corresponds to the value.  If you need a Param.Name = Param.Value type of output list, we can do that too, but likely with something like the Dictionary (or other two part collections).

Dim oDocType As DocumentTypeEnum = ThisApplication.ActiveDocumentType
Dim oParams As Parameters
If oDocType = DocumentTypeEnum.kPartDocumentObject Or _
	oDocType = DocumentTypeEnum.kAssemblyDocumentObject Then
	oParams = ThisApplication.ActiveDocument.ComponentDefinition.Parameters
ElseIf oDocType = DocumentTypeEnum.kDrawingDocumentObject Then
	oParams = ThisDrawing.Document.Parameters
End If
Dim oCurrentOptions As New List(Of Object)
For Each oParam As Inventor.Parameter In oParams
	If oParam.ExpressionList IsNot Nothing AndAlso oParam.ExpressionList.Count > 0 Then
		oCurrentOptions.Add(oParam.Value)
	End If
Next
oChosen = InputListBox("", oCurrentOptions,"","","Current Values")

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

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 30 of 46

ahmed.hagi
Enthusiast
Enthusiast

Thanks for your time.

Essentially what I am trying to do is get the list of all parameters initially, then import parameters (this part is already done), then check the parameters I imported against the original list, when a parameter is imported it essentially drives the selection of the multi value from a spreadsheet, but occasionally the spreadsheet may have a different value or a space and hence the imported values won't correspond to the parameters that drive the model in the rest of the rules.

 

It would be nice if i could get an out put like, 

 

" x from parameter y is either custom or not in the original list"

 

I tried something like below but it would include every single paremeter:

 

Dim UserParam As UserParameters 'Get the Parameters
UserParam = ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters


Dim T As New ArrayList
For Each Item In UserParam
		T.Add(Item.Value())
	Next
For Each Value In T
	'MsgBox(Value)
	If Not oAll.Contains(Value) Then
		MsgBox(Value & " Is not a standard option, or inconsitent with paramaters in Template")
	End If
	Next
0 Likes
Message 31 of 46

WCrihfield
Mentor
Mentor

Let me see if I've got this right then...

  • The document you are dealing with is always going to be either a Part or an Assembly, right (not a drawing)?
  • You only want to check 'UserParameters', and not any ModelParameters, ReferenceParameters, Sheet Metal Parameters, TableParameters, etc, right?
  • Are you just trying to make sure that the current 'Value' of each user parameters that has a multi-value list, is set to one of the available options within its multi-value list, and not to some other value?
    • In order for that to be possible, I thought you would have to actually check (turn on) the setting within each multi-value parameter to "Allow custom values".  That setting is un-checked (off) by default, unless you turned them on within your Template.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 32 of 46

ahmed.hagi
Enthusiast
Enthusiast

Hi

 

1) Yes

2) Yes

3) I Just want to flag to the user that the value of a parameter that has been imported for example, Width is not in the preset list.

 

printing a message Something along the lines of, " 225, Width, Either Doesn't Match the preset or is custom"

For each parameter that was imported.

0 Likes
Message 33 of 46

WCrihfield
Mentor
Mentor

OK. So when looping through all UserParameters, how do you if the UserParameter is 'Imported'?  Do you have some sort of list of parameter names that are being imported?  If so, within the UserParameters loop, we could first check if its name is one from that list.

 

1) And what 'preset list' are you talking about there?  Is it the list of existing options already within that UserParameter's ExpressionList, or is it some other list of values, like the ExpressionList of a UserParameter by that name within the Template document (not the current document)?

 

2) Are you trying to make sure that, when you 'Import' the group of UserParameters from [the Template] into [the other document], the current value of [the other document] doesn't get changed to whatever the current value might have been within [the Template]?

 

3) Are you trying to make sure that, when you 'Import' the group of UserParameters from [the Template] into [the other document], the current value of [the other document] does not remain some value that is not available within [the Template]?

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 34 of 46

ahmed.hagi
Enthusiast
Enthusiast

Thats one of the problems, the paramaters that are imported have been defined in the rule, it goes something like:

Width = Some cell from an excel value.

and this is repeated for all the required paramaters, so i dont really have a list within the rule.

 

1) the presets are the list of existing options already within that UserParameter's ExpressionList.

2) No, the value should change.

3) Its a multi department effort so the spreadsheet we use to get parameters is created by sales, sometimes the values don't align. So I just want to flag to the engineer that which ever value for such and such parameter isn't in the list, and the engineer will hence have to double check with the sales team or pick a value from the list in the form if for example the error was that there was an extra space in the imported value then this would affect make the template fallover, so it would be best to indicate when something has gone wrong.

0 Likes
Message 35 of 46

WCrihfield
Mentor
Mentor

I think I understand now.  I attempted to create a couple variations of, what I assumed would be a solution for your problem, but neither of them seem to be working 100% the way I was expecting in my tests.

Here is what I've got right now for those two variations.  If you believe these are 'on the right track', maybe we can continue to tweak them until we get them working right for you.  If I'm still not understanding and these aren't attempting to do what you want, then...I don't know, maybe you'll have to find to find some local help (someone who can see what you're seeing, and work with the things you're working with).

This is the variation that attempts to work strictly with 'Values'.

 

Dim oUParams As UserParameters = ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
Dim oUParam As UserParameter
For Each oUParam In oUParams
	If oUParam.ExpressionList IsNot Nothing AndAlso oUParam.ExpressionList.Count > 0 Then
		Dim oAvailableValues As New ArrayList(MultiValue.List(oUParam.Name))
		If Not oAvailableValues.Contains(oUParam.Value) Then
			MsgBox("UserParameter Name = " & oUParam.Name & vbCrLf & _
			"Value = " & CStr(oUParam.Value) & vbCrLf & _
			"Value doesn't match any of its available options.", vbOKOnly + vbCritical, "Parameter Issue")
		Else
			MsgBox("UserParameter Name = " & oUParam.Name & vbCrLf & _
			"Value = " & CStr(oUParam.Value) & vbCrLf & _
			"Value matches one of its available options.",, "Parameter Is OK")
		End If
	End If
Next

 

And this is the variation that attempts to work strictly with 'Expressions'.

 

Dim oUParams As UserParameters = ThisApplication.ActiveDocument.ComponentDefinition.Parameters.UserParameters
Dim oUParam As UserParameter
For Each oUParam In oUParams
	If oUParam.ExpressionList IsNot Nothing AndAlso oUParam.ExpressionList.Count > 0 Then
		Dim oAvailableExpressions() As String = oUParam.ExpressionList.GetExpressionList
		If Not oAvailableExpressions.Contains(oUParam.Expression) Then
			MsgBox("UserParameter Name = " & oUParam.Name & vbCrLf & _
			"Expression = " & oUParam.Expression & vbCrLf & _
			"It doesn't match anything in its ExpressionList.", vbOKOnly + vbCritical, "Parameter Issue")
		Else
			MsgBox("UserParameter Name = " & oUParam.Name & vbCrLf & _
			"Expression = " & oUParam.Expression & vbCrLf & _
			"It matches an item in its ExpressionList.",, "Parameter Is OK")
		End If
	End If
Next

 

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 36 of 46

ahmed.hagi
Enthusiast
Enthusiast

So I've created a 2d array which contains the names of the parameters in 1 column and the current value corresponding to the paramater in the next column. Can I loop through this array when creating the list of all the parameters, and then use same same array to compare the values after the import?

0 Likes
Message 37 of 46

j.haggenjos
Advocate
Advocate
Accepted solution

If I understand your needs correctly , you don't really need to list all multi value parameter. Just check them against the imported value. I would do something like this:

 

Dim ImportedParamArray(,)={{"test", "a"}, {"test2","a"}}
For index = 0 To ImportedParamArray.GetLength(0) -1
	Dim ParamName As String = ImportedParamArray(index, 0)
	Dim importedValue As String = ImportedParamArray(index, 1)
	'Check value validity against standard parameter range
	If Not MultiValue.List(ParamName).Contains(importedValue) Then
		MsgBox("Imported value " + importedValue + " is not in the standard range of Parameter " + ParamName + ".")
	End If
	'Import value in any case
	Parameter(ParamName)=importedValue
Next

 

Please check the test file attached. In it, the rule will tell you that "a" is not part of the value range of "test2". However, "a" is part of the value range of "test" so the code will just import the value with no question.

0 Likes
Message 38 of 46

ahmed.hagi
Enthusiast
Enthusiast

That works a bit better, but I'm getting this error after it runs a while

 

file3.png

0 Likes
Message 39 of 46

j.haggenjos
Advocate
Advocate

After quickly asking google, this error is related to excel not being "ready" to accept your code inputs. I don't think this issue comes from my code.

 

 

0 Likes
Message 40 of 46

ahmed.hagi
Enthusiast
Enthusiast

Strange, I'm only copying values from the sheet, I'm not really modifying the spreadsheet. , but there error seems to go away when I get rid of:

 

	'excelWorkbook.Close
	'excelApp.Quit

 

0 Likes