Formatting and Creating a Parts List with iLogic

Formatting and Creating a Parts List with iLogic

Anonymous
Not applicable
7,282 Views
18 Replies
Message 1 of 19

Formatting and Creating a Parts List with iLogic

Anonymous
Not applicable

Posted below is the iLogic code that I am planning on using to create a Parts List with the columns that I want included.  The issue I have is that several lines have a "Reference to a non-shared member requires an object reference." error, I am not sure how to solve this problem and after finding other posts with similar problems it is not any clearer to me.

 

I have been using the Inventor 2021 API Help to get the code snippets and copied most of the sample code for creating a Parts List.

 

The code has been commented so that it hopefully makes sense what I am trying to do in each section.

 

Any help with this and learning what text from the syntax pages needs to be included when writing code would be much appreciated.

 

The specific lines that result in the error are:

PartsListStyle.AddColumn(kFileProperty, [Project], [Title], "Detail Name")
PartsListStyle.AddColumn(kFileProperty, [Project], [Vendor], "MAT'L",,kTextCenter)
PartsListStyle.AddColumn(kFileProperty, [Project], [Description], "Finish Size")
PartsListColumn.Reposition("Title", "Description")
PartsListColumn.Reposition("Vendor", "Description")

 

The following is my code:

'This program will format the parts list to the company standard
'by choosing the correct columns and removing unnecessary ones,
'it will then place the parts list on the drawing.
'This specific program is for the Detail List.

'Setup for document and sheets
Dim DrawingDoc As DrawingDocument
DrawingDoc = ThisApplication.ActiveDocument

Dim Sheet As Sheet
Sheet = DrawingDoc.ActiveSheet

Dim PartsList As PartsList = Sheet.PartsLists.Item(1)

Dim PropSet As PropertySet

Dim DrawingView = Sheet.DrawingViews(1)

' Set a reference to th sheet's border
Dim Border As Border
Border = Sheet.Border
    
Dim PlacementPoint As Point2d
    
If Not Border Is Nothing Then
' A border exists. The placement point
' is the top-right corner of the border.
PlacementPoint = Border.RangeBox.MaxPoint
Else
' There is no border. The placement point
' is the top-right corner of the sheet.
PlacementPoint = ThisApplication.TransientGeometry.CreatePoint2d(Sheet.Width, Sheet.Height)
End If

'Pre-Format Parts List
'Change Title
PartsList.Title() = "Detail List"

'Show Title
PartsList.ShowTitle = True

'Add Columns
FMTID = PropSet.InternalName
PartsListStyle.AddColumn(kFileProperty, [Project], [Title], "Detail Name")
PartsListStyle.AddColumn(kFileProperty, [Project], [Vendor], "MAT'L",,kTextCenter)
PartsListStyle.AddColumn(kFileProperty, [Project], [Description], "Finish Size")

'Remove Columns
PartsList.PartsListColumns("Part Number").Remove

'Reposition
PartsListColumn.Reposition("Title", "Description")
PartsListColumn.Reposition("Vendor", "Description")
    
'Rename Columns

' Create the parts list.
PartsList = Sheet.PartsLists.Add(DrawingView, PlacementPoint

 

0 Likes
Accepted solutions (4)
7,283 Views
18 Replies
Replies (18)
Message 2 of 19

Anonymous
Not applicable

I've written quite a few posts about BoM's, this one uses the API sample (click on the image below)

autodesk-inventor-ilogic-bom-export.png

Message 3 of 19

WCrihfield
Mentor
Mentor

You created the variable "PropSet" and set its type, but you haven't set the value to one of the available iProperty sets yet at that point.  And it looks like you are trying to assign its internal name to a new variable (or local Parameter), which won't work either, without the value of "PropSet" having been set.

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 19

WCrihfield
Mentor
Mentor

Also, you shouldn't name a variable the exact same spelling and capitalization as an Object Type (Class).

In your case you should rename your border variable from "Border" to "oBorder" or something else.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 19

Anonymous
Not applicable

Would the following code solve the issues I am having with the first error?

 

Dim PropSet As PropertySet
PropSet = Summary

Dim PropId As String
PropId = Title

I made the assumption that Property Set is referring to the tabs in the iProperty Window, and that PropertyIdentifier is the specific iProperty value.

0 Likes
Message 6 of 19

WCrihfield
Mentor
Mentor

There are a couple ways to access iProperties properly.

One is similar to this:  Dim oTitle As String = iProperties.Value("Summary","Title")

(after you have defined oDoc)

The other is similar to this Dim oTitle As String = oDoc.PropertySets.Item("Inventor Summary Information").Item("Title").Value

 

I also noticed that your variable named "Sheet" needed to be renamed, because is is the same spelling and capitalization as the Type.

 

Try this:

The only part I'm not really sure about is the Reposition portion.

I'm also thinking that the string name at the ends of the new columns should be different, based on which properties are to be shown within them, but I don't know what your intent is.

'This program will format the parts list to the company standard
'by choosing the correct columns and removing unnecessary ones,
'it will then place the parts list on the drawing.
'This specific program is for the Detail List.

Dim oDDoc As DrawingDocument = ThisApplication.ActiveDocument
Dim oSheet As Sheet = oDDoc.ActiveSheet
Dim oPList As PartsList = oSheet.PartsLists.Item(1)

Dim oSumSet As PropertySet = oDDoc.PropertySets.Item("Inventor Summary Information")
Dim oPropSetID As String = oSumSet.InternalName
Dim oTitle As [Property] = oSumSet.Item("Title")
Dim oTitleId As Integer = oTitle.PropId

Dim oDTPropSet As PropertySet = oDDoc.PropertySets.Item("Design Tracking Properties")
Dim oDTPId As String = oDTPropSet.InternalName
Dim oVendor As [Property] = oDTPropSet.Item("Vendor")
Dim oVendorId As Integer = oVendor.PropId
Dim oDesc As [Property] = oDTPropSet.Item("Description")
Dim oDescId As Integer = oDesc.PropId

Dim oView = oSheet.DrawingViews(1)
Dim oBorder As Border = oSheet.Border
Dim oPoint As Point2d
If Not oBorder Is Nothing Then
	' A border exists. The placement point
	' is the top-right corner of the border.
	oPoint = oBorder.RangeBox.MaxPoint
Else
	' There is no border. The placement point
	' is the top-right corner of the sheet.
	oPoint = ThisApplication.TransientGeometry.CreatePoint2d(oSheet.Width, oSheet.Height)
End If

oPList.Title() = "Detail List"
oPList.ShowTitle = True


Dim oPListStyle As PartsListStyle = oPList.Style
oPListStyle.AddColumn(PropertyTypeEnum.kFileProperty, oPropSetID, oTitleId, "Detail Name")
oPListStyle.AddColumn(PropertyTypeEnum.kFileProperty, oDTPId, oVendorId, "MAT'L",,HorizontalTextAlignmentEnum.kAlignTextCenter)
oPListStyle.AddColumn(PropertyTypeEnum.kFileProperty, oDTPId, oDescId, "Finish Size")

Dim oColumns As PartsListColumns = oPList.PartsListColumns

Dim oPos1 As Integer
Dim oPos2 As Integer
Dim oPos3 As Integer
'Reposition
For i As Integer = 1 To oColumns.Count
	If oColumns.Item(i).Title = "Part Number" Then
		oColumns.Item(i).Remove
	End If
	If oColumns.Item(i).Title = "Title" Then
		oPos1 = i
	ElseIf oColumns.Item(i).Title = "Description" Then
		oPos2 = i
	ElseIf oColumns.Item(i).Title = "Vendor" Then
		oPos3 = i
	End If
Next
oColumns.Item(oPos1).Reposition(oPos2, True)
oColumns.Item(oPos3).Reposition(oPos2,True)


' Create the parts list.
oPList = oSheet.PartsLists.Add(oView, oPoint) 

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 19

WCrihfield
Mentor
Mentor
Accepted solution

Here are a couple of links to help you with iProperties.

https://knowledge.autodesk.com/search-result/caas/simplecontent/content/write-all-available-info-abo... 

https://knowledge.autodesk.com/search-result/caas/simplecontent/content/list-all-iproperties-and-how... 

There is also a PDF attached that has been floating around this forum, that lays out all of the iProperties for you in sort of like an Excel spreadsheet style.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 8 of 19

Anonymous
Not applicable

I think this will work but I tried to run this code and got the following error:

 

The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))

 

is this a directory issue?

0 Likes
Message 9 of 19

Anonymous
Not applicable

It seems that the line:

 

Dim oPList As PartsList = oSheet.PartsLists.Item(1)

 

is creating the error.

 

Would this create an error if it is not the first ever Parts List in the drawing?

0 Likes
Message 10 of 19

WCrihfield
Mentor
Mentor
Accepted solution

Since oSheet was defined as being the ActiveSheet, it is only looking on the active sheet for Parts lists.  If there isn't one on the sheet that was active when the code was ran, then yes, it will cause an error.

If your only Parts List is on another sheet, other than the sheet that was active when you started the code, you would need to find it another way, to avoid errors.  Also, if there isn't a parts list yet, within the drawing, trying to access and modify one will cause errors.

If need be, we can loop through all sheets of the drawing, while looking for either the first, or a specific parts list within any of the sheets.

I modified the code with this process to see if it works better for you.

Keep in mind that in this new code it is looking for a Parts List which has "Detail List" as its title.  If it doesn't find one I set up an additional check that will let you know, then exit the code.

I also slightly modified it's Border check If...Then statement, for clarity.

I also put a check in there for the View you are attempting to specify for use within the line to place a new Parts List.

Here's the updated code:

'This program will format the parts list to the company standard
'by choosing the correct columns and removing unnecessary ones,
'it will then place the parts list on the drawing.
'This specific program is for the Detail List.

Dim oDDoc As DrawingDocument = ThisApplication.ActiveDocument
Dim oSheet As Sheet
Dim oPList As PartsList
For Each oSheet In oDDoc.Sheets
	If oSheet.PartsLists.Count > 0 Then  'there is at least one parts list on the sheet
		For Each oList As PartsList In oSheet.PartsLists
			If oList.Title = "Detail List" Then
				oPList = oList
				Exit For
			End If
		Next
	End If
Next
If oPList Is Nothing Then
	MsgBox("It didn't find a Parts List with the title 'Detail List', so it is exiting.", vbOKOnly, "Parts List Not Found")
	Return
End If
oPList.ShowTitle = True

Dim oSumSet As PropertySet = oDDoc.PropertySets.Item("Inventor Summary Information")
Dim oPropSetID As String = oSumSet.InternalName
Dim oTitle As [Property] = oSumSet.Item("Title")
Dim oTitleId As Integer = oTitle.PropId

Dim oDTPropSet As PropertySet = oDDoc.PropertySets.Item("Design Tracking Properties")
Dim oDTPId As String = oDTPropSet.InternalName
Dim oVendor As [Property] = oDTPropSet.Item("Vendor")
Dim oVendorId As Integer = oVendor.PropId
Dim oDesc As [Property] = oDTPropSet.Item("Description")
Dim oDescId As Integer = oDesc.PropId

Dim oBorder As Border = oSheet.Border
Dim oPoint As Point2d
If oBorder IsNot Nothing Then
	' A border exists. The placement point
	' is the top-right corner of the border.
	oPoint = oBorder.RangeBox.MaxPoint
Else
	' There is no border. The placement point
	' is the top-right corner of the sheet.
	oPoint = ThisApplication.TransientGeometry.CreatePoint2d(oSheet.Width, oSheet.Height)
End If

Dim oPListStyle As PartsListStyle = oPList.Style
oPListStyle.AddColumn(PropertyTypeEnum.kFileProperty, oPropSetID, oTitleId, "Detail Name")
oPListStyle.AddColumn(PropertyTypeEnum.kFileProperty, oDTPId, oVendorId, "MAT'L",,HorizontalTextAlignmentEnum.kAlignTextCenter)
oPListStyle.AddColumn(PropertyTypeEnum.kFileProperty, oDTPId, oDescId, "Finish Size")

Dim oColumns As PartsListColumns = oPList.PartsListColumns
Try
	Dim oPos1 As Integer
	Dim oPos2 As Integer
	Dim oPos3 As Integer
	'Reposition
	For i As Integer = 1 To oColumns.Count
		If oColumns.Item(i).Title = "Part Number" Then
			oColumns.Item(i).Remove
		End If
		If oColumns.Item(i).Title = "Title" Then
			oPos1 = i
		ElseIf oColumns.Item(i).Title = "Description" Then
			oPos2 = i
		ElseIf oColumns.Item(i).Title = "Vendor" Then
			oPos3 = i
		End If
	Next
	oColumns.Item(oPos1).Reposition(oPos2, True)
	oColumns.Item(oPos3).Reposition(oPos2, True)
Catch oEx As Exception
	MsgBox("Something went wrong while attempting to 'reposition' columns within the Parts List." & vbCrLf & _
	"The 'Error Message' is as follows:" & vbCrLf & _
	oEx.Message & vbCrLf & _
	"And the 'Source' is as follows:" & vbCrLf & _
	oEx.Source,vbOKOnly + vbExclamation,"Repositioning Failed")
End Try

Dim oView As DrawingView
If oSheet.DrawingViews.Count > 0 Then
	oView = oSheet.DrawingViews.Item(1)
End If
' Create the parts list.
oPList = oSheet.PartsLists.Add(oView, oPoint) 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 11 of 19

Anonymous
Not applicable

I found that I needed to have a Parts List already inserted (which is not my intent) and the added columns all have a width of 0, how do I specify the column widths for each?

 

Manually changing the widths in the Style Editor does not fix the issue.

 

oPList.PartsListColumn.Item(#).Width() = 1.49

Above is the code that I found and modified for column width but this does not specify which column.

 

0 Likes
Message 12 of 19

WCrihfield
Mentor
Mentor

If you need code to create a new Parts List, instead of just find an existing one, we can modify the code for that too.

Would you want the code to still check to see if there are any Parts Lists within the drawing first, before attempting to create a new one?

Perhaps specifying or retrieving the actual PartsListStyle you want to apply/use from the Styles Library, then using that to change the columns and column order (and similar) would work better for you than trying to do all the modifications individually?

Adjusting column width is still something that will have to be dealt with locally, instead of by Style, but specifying/applying a Style might do a lot of the work for you.

There are ways to make the column widths 'autofit' to the widest text within each column, but it isn't a very stable way, because it kind of depends on the font you're using within the title cells & data cells.  Some fonts have set character widths, and others are variable width.  The fonts with variable character widths, may not produce reliable results when attempting to measure the width of strings.

I can attempt to though, if you need it.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 13 of 19

Anonymous
Not applicable

If you need code to create a new Parts List, instead of just find an existing one, we can modify the code for that too.

Would you want the code to still check to see if there are any Parts Lists within the drawing first, before attempting to create a new one?

 

I would only need the code to create a new Parts List, even if there was an existing Parts List I would remove it before creating the new one.

 

Perhaps specifying or retrieving the actual PartsListStyle you want to apply/use from the Styles Library, then using that to change the columns and column order (and similar) would work better for you than trying to do all the modifications individually?

 

That is what I was intending to do, with my limited knowledge on this topic it seems I deviated from that.

 

Adjusting column width is still something that will have to be dealt with locally, instead of by Style, but specifying/applying a Style might do a lot of the work for you.

There are ways to make the column widths 'autofit' to the widest text within each column, but it isn't a very stable way, because it kind of depends on the font you're using within the title cells & data cells.  Some fonts have set character widths, and others are variable width.  The fonts with variable character widths, may not produce reliable results when attempting to measure the width of strings.

 

I think the autofit method would work best since the iProperty fields that are being used are filled in using iLogic to standardize the entries, also overall width doesn't matter as long as all rows have only one line of text (within reason).  For reference the column names & widths that are currently in use follow below:

 

DET. NO. (0.35)

NO. REQ. (0.35)

Detail Name (1.49)

MAT'L (0.59)

Finish Size (1.45)

SHT. NO. (0.35)

 

The columns widths usually resize a bit during the entry of data but not so much that it is an issue.

0 Likes
Message 14 of 19

WCrihfield
Mentor
Mentor
Accepted solution

OK. Try this.

You will need to change the name of the PartsListStyle to match one you have, as stated in the comments.

 

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kDrawingDocumentObject Then
	MsgBox("This rule '" & iLogicVb.RuleName & "' only works for Drawing Documents.",vbOKOnly, "WRONG DOCUMENT TYPE")
	Return
End If

Dim oDDoc As DrawingDocument = ThisApplication.ActiveDocument
Dim oSheet As Sheet = oDDoc.ActiveSheet
Dim oView As DrawingView
If oSheet.DrawingViews.Count > 0 Then
	oView = oSheet.DrawingViews.Item(1)
Else
	MsgBox("There was no view on the Active Sheet to base the Parts List on. Exiting.", vbOKOnly + vbExclamation, "No View")
	Return
End If

Dim oBorder As Border = oSheet.Border
Dim oPoint As Point2d
If oBorder IsNot Nothing Then
	' A border exists. The placement point
	' is the top-right corner of the border.
	oPoint = oBorder.RangeBox.MaxPoint
Else
	' There is no border. The placement point
	' is the top-right corner of the sheet.
	oPoint = ThisApplication.TransientGeometry.CreatePoint2d(oSheet.Width, oSheet.Height)
End If

'You will have to customise the name I'm using here to one that exists in your library, that you want to use.
Dim oPListStyle As PartsListStyle = oDDoc.StylesManager.PartsListStyles.Item("Detail List - A Size Sheet")
Dim oPList As PartsList = oSheet.PartsLists.Add(oView, oPoint, PartsListLevelEnum.kStructured)
oPList.Style = oPListStyle
'oPList.Title = "Detail List"
'oPList.ShowTitle = True

'Start going through the columns to set their widths
Dim oCols As PartsListColumns = oPList.PartsListColumns
Dim oCol As PartsListColumn
Dim oRows As PartsListRows = oPList.PartsListRows
Dim oRow As PartsListRow
Dim oFWidth As Double = oPList.DataTextStyle.FontSize * oPList.DataTextStyle.WidthScale
Dim oData As String
Dim oDWidths As List(Of Double)
For i As Integer = 1 To oCols.Count
	For Each oRow In oRows
		If oRow.Visible Then
			oDWidths.Add(Len(oRow.Item(i).Value))
		End If
	Next
	'You may need to add a little extra to each column width for left & right side padding from grid lines
	oCols.Item(i).Width = (oFWidth*(MaxOfMany(oDWidths.ToArray)))
Next

'This is for if you want to set specific widths
'I'm not sure if the values you provide will be interpreted as
'the default centimeters, or document units.
'For Each oCol In oCols
'	Select Case oCol.Title
'	Case "DET. NO."
'		oCol.Width = .35
'	Case "NO. REQ."
'		oCol.Width = .35
'	Case "Detail Name"
'		oCol.Width = 1.49
'	Case "MAT'L"
'		oCol.Width = .59
'	Case "Finish Size"
'		oCol.Width = 1.45
'	Case "SHT. NO."
'		oCol.Width = .35
'	End Select
'Next

 

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

Also, when you have time, please review & vote for these 'Ideas' I'd like to get implemented.

  • Add more capabilities to the 'Customize' dialog box (exe. Add Tab & Add Panel) Click Here
  • Constrain & Dimension Images In Assembly Sketches & Drawing Sketches (TitleBlocks & SketchedSymbols) Click Here
  • Save Section View Status In DesignViewRepresentation (So It Can Be Used In The Drawing) Click Here
  • Add SolidBodies Folder In iLogic Rule Editor Model Tab Click Here
  • Convert All Views To Raster Before Autosave Stores To 'OldVersions' Folder Click Here
  • SetDesignViewRepresentation - Fix limitations for DrawingView of a Part Click Here
  • Create DocumentSubTypeEnum Click Here
  • Add kRevisionTag or kDrawingRevisionTag to ObjectTypeEnum Click Here

Inventor 2020 Help | Inventor Forum | Inventor Customization Forum | Inventor Ideas Forum

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 15 of 19

Anonymous
Not applicable
Accepted solution

This is amazing thank you so much!

0 Likes
Message 16 of 19

WCrihfield
Mentor
Mentor

 Looks like I forgot to put some code in there to delete any existing PartsLists as you wanted in your answers to my earlier questions, so here the same code with that extra block of code in there right under defining the active sheet.

It doesn't iterate through all sheets, because i didn't think it was necessary, but you already know how do that now from my earlier post.

Here's the updated code.

If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kDrawingDocumentObject Then
	MsgBox("This rule '" & iLogicVb.RuleName & "' only works for Drawing Documents.",vbOKOnly, "WRONG DOCUMENT TYPE")
	Return
End If

Dim oDDoc As DrawingDocument = ThisApplication.ActiveDocument
Dim oSheet As Sheet = oDDoc.ActiveSheet
If oSheet.PartsLists.Count > 0 Then
	For Each oList As PartsList In oSheet.PartsLists
		oList.Delete
	Next
End If
Dim oView As DrawingView
If oSheet.DrawingViews.Count > 0 Then
	oView = oSheet.DrawingViews.Item(1)
Else
	MsgBox("There was no view on the Active Sheet to base the Parts List on. Exiting.", vbOKOnly + vbExclamation, "No View")
	Return
End If
Dim oPoint As Point2d
If oSheet.Border IsNot Nothing Then
	oPoint = oSheet.Border.RangeBox.MaxPoint
Else
	oPoint = ThisApplication.TransientGeometry.CreatePoint2d(oSheet.Width, oSheet.Height)
End If
Dim oPList As PartsList = oSheet.PartsLists.Add(oView, oPoint, PartsListLevelEnum.kStructured)


'Start going through the columns to set their widths
Dim oCols As PartsListColumns = oPList.PartsListColumns
Dim oCol As PartsListColumn
Dim oRows As PartsListRows = oPList.PartsListRows
Dim oRow As PartsListRow
Dim oFWidth As Double = oPList.DataTextStyle.FontSize * oPList.DataTextStyle.WidthScale
Dim oData As String
Dim oDWidths As List(Of Double)
For i As Integer = 1 To oCols.Count
	For Each oRow In oRows
		If oRow.Visible Then
			oDWidths.Add(Len(oRow.Item(i).Value))
		End If
	Next
	'You may need to add a little extra to each column width for left & right side padding from grid lines
	oCols.Item(i).Width = (oFWidth*(MaxOfMany(oDWidths.ToArray)))
Next

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 17 of 19

c.bloedorn
Enthusiast
Enthusiast

I know this post is a little older but the last code snippet posted returns and error in line 40:

"Object reference not set to an instance of an object."

Would anyone know a fix for this?

I'm using inventor Professional 2023

0 Likes
Message 18 of 19

A.Acheson
Mentor
Mentor

Perhaps it is this line. 

Dim oDWidths As List(Of Double)

The object hasn't been created so needs the word "New"

Dim oDWidths As New List(Of Double)

 

If this solved a problem, please click (accept) as solution.‌‌‌‌
Or if this helped you, please, click (like)‌‌
Regards
Alan
Message 19 of 19

c.bloedorn
Enthusiast
Enthusiast
That was it, thank you!
0 Likes