Wednesday 20 September 2017

Total Quantity in the Assembly BOM

Hey all.
Lately there have been a few Autodesk forum posts looking to set a total quantity value in the BOM (Bill Of Materials)

I have cobbled some code together from various snippets found on the forum and in the help files to create just that. Unfortunately I cannot give credit to the original author of the file counter.


It is based on the Inventor "iProperties, Project, Project Number" field. This allows duplicates and common parts to be used in multiple assemblies without the total quantity being affected.  Though, on the other hand, if your typical workflow does not involve a new project number, then this will not work for you.



Read only and Content Center parts will not be updated.
The code will also check the Project number field before running, and change it, if so desired.

It is advised that this is run from the GA, and preferably at the end of the build. You can run it as many times as you wish, but it is still a manual process, so if your assembly changes, you need to run the code again to refresh the total QTY field.

A Custom field of #projectnumber_QTY is created and the total quantity of all sub assemblies and parts are counted and the value added to the field. this is then written to each part and assembly.

I did have to manually add a value for the GA, as the lack of the field was causing some issues in the detail drawings.

example:
Clip of a small assembly:

a clip of the same part Custom iProps:






As you can see, the total quantity has been added to the part as a custom field. The same goes for any Sub-Assemblies as well.

This field can now be used wherever and however you wish.

Anyway, till the next time, enjoy.
Don't forget the golden rule, if you use it and improve on it, share it.




***Start of the iLogic code ***
-----------------------------------------
'09/2017
'Reg Hasell.
'This iLogic rule will run though all the items in an assembly and add a QTY field to it.
'The QTY field is based on a programmable project number. (project_QTY)
'Any Content Center items are ignored. (Read Only)
'There is an option to set the project number.
'
'Some of this code has originated from the forum, but I cannot
'remember where I got it from, so I am unable To give credit To the original author.

Sub Main ()
    'Check to see if this document is an assembly.
    oDoc = ThisApplication.ActiveDocument
        If oDoc.DocumentType <> kAssemblyDocumentObject Then
        MessageBox.Show("This rule can only be run in an Assembly file - exiting rule...", "iLogic")
        Return
        End If
    If iProperties.Value("Project", "Project")=""
        oProj = InputBox("Change Project Name", "Project Name", iProperties.Value("Project", "Project"))
        iProperties.Value("Project", "Project")=oProj
    End If

'get the project number of this assembly and use it to build the name of a custom property, i.e. "4100_QTY"
oBOMQTY = CStr(iProperties.Value("Project", "Project")) & "_QTY"

    oQ=MessageBox.Show(oBOMQTY, "Project Number",MessageBoxButtons.YesNoCancel,MessageBoxIcon.Question)
        If oQ=vbYes
        oDone() 'next Sub Routine
        ElseIf oQ=vbNo
        Call oProject 'Option to change the project Number for the GA
        ElseIf oQ=vbCancel
        MessageBox.Show("Cancelled", "iLogic", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1)
        Return
    End If
End Sub

Sub oDone
oCompDef = ThisDoc.Document.ComponentDefinition ' Don't need this, but I left it in for reference when looking for code snippets.
openDoc = ThisDoc.Document
oBOMQTY = CStr(iProperties.Value("Project", "Project")) & "_QTY"
'Open the document that inventor has in focus right now
    For Each docFile In openDoc.AllReferencedDocuments

    'FNamePos is getting the number of spaces that it takes to get to the
    'very last back slash in the full file name of our document.        
        FNamePos = InStrRev(docFile.FullFileName, "\", -1)       
    
    'We can then take that number (position) and use it to cut off all of the
    'file path that we don't need. In this case, it's the front of the path
    'that we're getting rid of, leaving us with just the file name.
        docFName = Mid(docFile.FullFileName, FNamePos + 1, Len(docFile.FullFileName) - FNamePos)
       
        'Let's make sure that we can even change this part. If we can, then we'll continue.
        If docFile.IsModifiable = True Then
           
            'Because you can only grab the occurrences from an assembly document
            'we need to fill up that empty AssemblyDocument container with an object
            'that we know is definitely an assembly document. Because that was one
            'of the first checks we made up there on this open document, we can safely
            'declare that assemblyDoc (Which is an AssemblyDocument) is equal to
            ' openDoc (Which is just a regular old Document)            
            assemblyDoc = openDoc
           
            'While we're at it, let's go on and define the empty ComponentDefinition container
            '(we named ours assemblyDef) with some sort of content.
            assemblyDef = assemblyDoc.ComponentDefinition
           
            'Now we need to collect every instance of the document against
            'our open assembly and put them all inside of partQty.
            partQty = assemblyDef.Occurrences.AllReferencedOccurrences(docFile)
           
                'Now that we have our collection of instances, we need to populate
                'our target iproperty with the total amount.
               
                'Instead of just throwing that amount in there, let's make sure that
                'the value inside of the target iProperty isn't already equal to our count.
                'If it is equal, then we don't have to change anything (which saves us time!),
                'but if it isn't equal then we will need to change it.
               
                'The Try statement is here because of the next if statement ---
              
                'If we just compare the two values, there is a small chance that our target
                'iProperty is already set to something that is NOT a number, which would create
                'an error (as you can't compare numbers against things that aren't numbers).
                'So, we TRY to complete that if statement, and if there is an error (The CATCH)
                'we just force that target to equal our part qty total.
                Try
                        If partQty.Count <>  iProperties.Value(docFName, "Custom", oBOMQTY) Then               
                        iProperties.Value(docFName, "Custom", oBOMQTY) = partQty.Count
                        '
                       End If                     
                    Catch
                    iProperties.Value(docFName, "Custom", oBOMQTY) = partQty.Count
                End Try
        End If
    Next
'29/01/2016
'I Added the following line to add the value to the GA
' As the lack thereof was causing issues in the detailing environment.
            Try
                oASSYParam= iProperties.Value("Custom",oBOMQTY)
              Catch
                iProperties.Value("Custom",oBOMQTY) = "1"
                    End Try
iLogicVb.UpdateWhenDone = True
MessageBox.Show("Completed" & vbNewLine & "Champion" & vbNewLine & ":-)", "Completed", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1)
End Sub

Sub oProject
    oProj = InputBox("Change Project Name", "Project Name", iProperties.Value("Project", "Project"))
    iProperties.Value("Project", "Project")=oProj
    Main () 'Loop Back
End Sub


Friday 21 July 2017

Updated - Align Drawing Views

Hi

So I was actually using the code, and I discovered a small error.
The Horizontal "Top" and "Bottom" alignments were swapped around.

This has been fixed below. (Note, I have also amended the previous post as well.)

I have also added the ability to align the drawing view labels. There is one small addition though, there is a prompt to change the default location of the labels, the values concerned are really small, so work carefully. Naturally you can remove it from the code if it bugs you. (I personally have a need to move the labels around a bit)

Anyway the updated code:



'Reg Hasell
'18/07/2017
'This will align the selected views on the drawings sheet
'A minimum of two views must be selected.
'The first view selected will be the Anchor. (Base View)
'A section of the code was taken from the forum
'Thanks to Adrian Salariu, I stole the First view Co-Ordinates from him.
'I then changed everything to suit my personal needs.
'Revisions:
'Rev 1.1
'20/07/2017
'The Horizontal alignement was reversed
'Added the ability to align the view labels.


Sub Main()
Dim oSSet As SelectSet = ThisDoc.Document.SelectSet
If oSSet.count <2 Then
    MessageBox.Show("A Minimum of two views must be seleted first", "iLogic")
    Return
End If
oMenu()
End Sub

'--------------------------------------------------------------------------------

Sub oMenu()
Dim oResu1t As String="Result"
Dim oLst As New ArrayList
oLst.Add("Vert - Left")
oLst.Add("Vert - Right")
oLst.Add("Vert - CL")
oLst.Add("")
oLst.Add("Hor - Top")
oLst.Add("Hor - Bottom")
oLst.Add("Hor - CL")
oLst.Add("")
oLst.Add("Align Labels")

'Display table and get the selection
oResu1t=InputListBox("Select Alignment", oLst, oResu1t, _
Title := "View Alignment", ListName := "View Alignment")

'Set iProperties based on the selection.
If oResu1t="Vert - Left" Then
Call oVert_Left()
ElseIf oResu1t="Vert - Right" Then
Call oVert_Right()
ElseIf oResu1t="Vert - CL" Then
Call oVert_CL()
ElseIf oResu1t="Hor - Top" Then
Call oHor_Top()
ElseIf oResu1t="Hor - Bottom" Then
Call oHor_Bott()
ElseIf oResu1t="Hor - CL" Then
Call oHor_CL()
ElseIf oResu1t="Align Labels" Then
Call Align_Labels()
End If
End Sub

'--------------------------------------------------------------------------------

Sub oVert_Left()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'For Each oView In oSSet
        Dim oFirstView As DrawingView = TryCast(oSSet.item(1), DrawingView)
       'views are processed by center so we need to get center X and substract half view
        Dim XPos As Double
        XPos = oFirstView.Position.X - (oFirstView.Width/2)
        Dim oPoint2D As Inventor.Point2D
        'view position Is XPos + half Of Each view
 For Each oView In oSSet
    'For Each oView In oSheet.DrawingViews
           oPoint2D = ThisApplication.TransientGeometry.CreatePoint2D(XPos + (oView.Width/2),oView.Position.Y)
           oView.Position = oPoint2D
        Next
       
'finish the transaction
trans.End
End Sub

'--------------------------------------------------------------------------------

Sub oVert_Right()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'For Each oView In oSSet
        Dim oFirstView As DrawingView = TryCast(oSSet.item(1), DrawingView)
        'views are processed by center so we need to get center X and substract half view
        Dim XPos As Double
        XPos = oFirstView.Position.X + (oFirstView.Width/2)
        Dim oPoint2D As Inventor.Point2D
        'view position Is XPos + half Of Each view
 For Each oView In oSSet
    'For Each oView In oSheet.DrawingViews
        oPoint2D = ThisApplication.TransientGeometry.CreatePoint2D(XPos - (oView.Width/2),oView.Position.Y)
           oView.Position = oPoint2D
        Next
       
'finish the transaction
trans.End
End Sub

'--------------------------------------------------------------------------------

Sub oVert_CL()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'For Each oView In oSSet
        Dim oFirstView As DrawingView = TryCast(oSSet.item(1), DrawingView)
        'views are processed by center so we need to get center X and substract half view
        Dim XPos As Double
        XPos = oFirstView.Position.X
        Dim oPoint2D As Inventor.Point2D

         For Each oView In oSSet
    'For Each oView In oSheet.DrawingViews
            oPoint2D = ThisApplication.TransientGeometry.CreatePoint2D(XPos,oView.Position.Y)
            oView.Position = oPoint2D
        Next
       
'finish the transaction
trans.End
End Sub

'--------------------------------------------------------------------------------

Sub oHor_Top()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'For Each oView In oSSet
        Dim oFirstView As DrawingView = TryCast(oSSet.item(1), DrawingView)
        'views are processed by center so we need to get center X and substract half view
        'Dim XPos As Double
        Dim YPos As Double
        'XPos = oFirstView.Position.X + (oFirstView.Width/2)
        YPos = oFirstView.Position.Y + (oFirstView.Height/2)
        Dim oPoint2D As Inventor.Point2D

         For Each oView In oSSet
    'For Each oView In oSheet.DrawingViews
            oPoint2D = ThisApplication.TransientGeometry.CreatePoint2D(oView.Position.X,YPos - (oView.Height/2))
            oView.Position = oPoint2D
        Next
       
'finish the transaction
trans.End
End Sub

'--------------------------------------------------------------------------------

Sub oHor_Bott()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'For Each oView In oSSet
        Dim oFirstView As DrawingView = TryCast(oSSet.item(1), DrawingView)
       'views are processed by center so we need to get center X and substract half view

        'Dim XPos As Double
        Dim YPos As Double
        'XPos = oFirstView.Position.X - (oFirstView.Width/2)
        YPos = oFirstView.Position.Y - (oFirstView.Height/2)
        Dim oPoint2D As Inventor.Point2D

         For Each oView In oSSet
    'For Each oView In oSheet.DrawingViews
            oPoint2D = ThisApplication.TransientGeometry.CreatePoint2D(oView.Position.X,YPos + (oView.Height/2))
           oView.Position = oPoint2D
        Next
       
'finish the transaction
trans.End
End Sub

'--------------------------------------------------------------------------------

Sub oHor_CL()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'For Each oView In oSSet
        Dim oFirstView As DrawingView = TryCast(oSSet.item(1), DrawingView)
        'views are processed by center so we need to get center X and substract half view
        Dim XPos As Double
        Dim YPos As Double
            XPos = oFirstView.Position.X + (oFirstView.Width)
            YPos = oFirstView.Position.Y
        Dim oPoint2D As Inventor.Point2D

         For Each oView In oSSet
    'For Each oView In oSheet.DrawingViews
            oPoint2D = ThisApplication.TransientGeometry.CreatePoint2D(oView.Position.X,YPos)
           oView.Position = oPoint2D
        Next
       
'finish the transaction
trans.End
End Sub

'--------------------------------------------------------------------------------

Sub Align_Labels()
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
Dim oView As DrawingView
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet
Dim trans As Transaction
trans = ThisApplication.TransactionManager.StartTransaction(oDrawDoc, "Align Views")
Dim oSSet As SelectSet = oDrawDoc.SelectSet
'
        Dim oNewPosition As Point2d
        oNewPOS = InputBox("Add Offset?", "Title", 1)
        oNewPOS /= 10

         For Each oView In oSSet
          'oNewPosition = oView.Label.Position
          oNewPosition = ThisApplication.TransientGeometry.CreatePoint2d(oView.Center.X, oView.Center.Y - (oView.Height / 2)-( 1+oNewPOS))
          ' oNewPosition = ThisApplication.TransientGeometry.CreatePoint2d(oView.Center.X, oView.Center.Y - (oView.Height / 2)-1)
           oView.Label.Position = oNewPosition
        Next
       
'finish the transaction
trans.End
End Sub