31 Replies Latest reply on Jul 27, 2018 1:09 AM by Artem Taturevych

    How to get a part's Item Number in a View?

    Matt Peneguy

      So, here's the TL:DR: I need the part Item Number from the BOM in a View Title for that part.  I have many parts.  So, I want to do this with a macro.

       

      Here's the long story: I have long BOMs and it would be very handy to have an automatic way of adding that "linked" number to the views for each of these parts.  I figured out a way to manually do this, but it is very time and labor intensive.  I am not looking for a complete solution, just some guidance.  I have kludged macros together before, but I'm stuck on how to grab the part in the view and extract the Item Number from the BOM for that part in the view. 

      I really thought this was something that should be implemented as an option within SW, and submitted an ER stating the following:

      When dealing with parts or items in a cut list or BOM the item number should be displayed

      next to or under the part in the drawing.  However item numbers not available in the same

      manner as custom properties.  The new ability in 2017 doesn't solve this problem.

      If the BOM or Cut List has many parts it is very difficult to identify where the part is in the

      BOM, especially if the BOM spans multiple sheets.

      However, nothing came of it.  The ER was marked closed and nothing was done with it.  So, I'm asking y'all for help.

        • Re: How to get a part's Item Number in a View?
          Josh Brady

          First question:

          Are the part/item drawing views within the same .slddrw document as the BOM?

          Second question:

          Do you ever use the same part file in multiple different assemblies (BOMs)?

            • Re: How to get a part's Item Number in a View?
              Matt Peneguy

              Thanks Josh. I should have been more specific.

              Are the part/item drawing views within the same .slddrw document as the BOM?

              Yes.

              Do you ever use the same part file in multiple different assemblies (BOMs)?

              No.  But, would this be a problem?  (This may have something to do with the above question?)

               

              Basically, if I have a part in a view that is linked to a BOM.  I want to "grab" the part's Item Number from the BOM and add it to the View Title to make it easier to cross reference in a long BOM.  Where I'm stuck is how I "grab" the Item Number.  I know it'll break if I have subassembly views because they won't have BOM Item Numbers.  But, I can deal with that with an If Then statement. But I'm stuck at grabbing the Item Number.

                • Re: How to get a part's Item Number in a View?
                  Josh Brady

                  If the part view is linked to the main BOM, all you have to do is add a balloon.  If you don't want the leader or the circle, those are easy enough to remove, either by using a style/favorite/[whatever they call it these days] or with code.  The advantage of this is that item number will stay linked to the BOM, so you never have to update it again (you don't have to worry about forgetting to run the macro again).  If you have other info in your view labels, you can group the balloon to the view label, as long as both actually "belong" to the same view.  You can verify belongingnesses by dragging the view on the sheet.  If the annotation moves, it belongs to the view.  If not, it belongs to another view or to the sheet.  If the balloon text really needs to be in the middle of the label, you can add a reference to the balloon by clicking on the balloon while editing the note text and then move the balloon off the printable area.

                   

                  The approach related to the second question would be to have your macro iterate through the BOM and read the item number, then write that number to a custom property of the part.  Then all your views just need to have their label linked to that custom property.  The reason for the question is that if your part is used in multiple different assemblies/BOMs then the item number needed varies with the assembly.  Running the macro in one assembly would overwrite the item number in an older assembly.  The other disadvantage of this method is that if the BOM changes you need to remember to run the macro again. 

                    • Re: How to get a part's Item Number in a View?
                      Matt Peneguy

                      Thanks for the suggestion.  Yes, you are absolutely correct.  It can be done manually.  And I have done it the way you suggest in the past.  But, it is tedious to add that number manually for a lot of views (balloon, hide arrow, change font, group number with view title text, rinse repeat).  I'm looking to make this easier by incorporating some code into a macro I already have to update my View Titles to show that number, too.

                       

                      Edit to Add: Josh, I'm sorry I didn't see your second paragraph. I'm not interested in the second approach at all. Though I agree it is a valid workaround, I see that it could cause some serious problems.  The first solution you offer is exactly what I want to do, but with a macro.  I'm just not smart enough or good enough to figure it out.  And I've tried the best I can and even submitted an ER on this.  So, that's why I'm reaching out to y'all.

                • Re: How to get a part's Item Number in a View?
                  John Stoltzfus

                  Matt Peneguy

                  There are probably some guy's I'm missing, but below are the elite API guys, that come to me at the moment.

                   

                  Josh Brady

                  Amen Allah Jlili

                  Keith Rice

                  Artem Taturevych

                  • Re: How to get a part's Item Number in a View?
                    Alex Burnett

                    I would agree that it's possible, however the best way to get started is to post an example document with a few views of different parts in the same manner as one of your proprietary prints. This way, we will be able to see any potential issues with some approaches early on.

                     

                    It doesn't seem too hard to iterate through all of the views in the drawing and to determine which part is pictured. I haven't programatically added a view label yet but it shouldn't be more difficult than adding a standard annotation. From there, you would just modify the text of the view label and move on to the next view.

                     

                    Josh Brady always has good questions and approaches to things like this.

                      • Re: How to get a part's Item Number in a View?
                        Matt Peneguy

                        Alex,

                        Thanks for the suggestion. The smallest subassembly is to large to attach. I posted it on Dropbox at Dropbox - Bom Number SW Example.zip, if it helps.

                        And I already have a macro that goes through and updates view titles.  I'd just need the snippet that grabs the Title and adds the BOM Item Number.

                          • Re: How to get a part's Item Number in a View?
                            Alex Burnett

                            I was able to get something working but it's not a linked variable and I don't know if there's a way to create a link.

                             

                            This macro checks each view in a drawing and sees if it is referencing a part document. If it is, then it gets the first note annotation. Typically the view label is the first note but if there isn't one then it picks the next one which may not be correct.

                             

                            If it finds this, then it gets the referenced BOM part number from the model and appends it to the note. Unfortunately, there isn't a way to check if it's already there.

                             

                            Maybe this helps and maybe it doesn't but here is the code:

                            Dim swApp As SldWorks.SldWorks
                            Dim swModel As SldWorks.ModelDoc2
                            Dim swDraw As DrawingDoc
                            Dim swRefModel As SldWorks.ModelDoc2
                            Dim swView As SldWorks.View
                            Dim lerr As Long
                            Dim bstatus As Boolean
                            Dim allSheetViewArrays As Variant
                            Dim sheetViews As Variant
                            Dim swNote As Note
                            Dim swConfig As Configuration
                            Dim BOM_PN As String
                            
                            
                            Sub main()
                            
                            
                                Set swApp = Application.SldWorks
                                Set swModel = swApp.ActiveDoc
                                
                                If swModel.GetType <> swDocDRAWING Then
                                    Msg = "Only Allowed on Drawings" ' Define message
                                    Style = vbOKOnly ' OK Button only
                                    Title = "Error" ' Define title
                                    Call MsgBox(Msg, Style, Title) ' Display error message
                                    Exit Sub ' Exit this program
                                End If
                                
                                Set swDraw = swModel
                                allSheetViewArrays = swDraw.GetViews
                                For i = 0 To UBound(allSheetViewArrays)
                                    sheetViews = allSheetViewArrays(i)
                                    For j = 0 To UBound(sheetViews)
                                        Set swView = sheetViews(j)
                                        Set swRefModel = swView.ReferencedDocument
                                        
                                        If Not swRefModel Is Nothing Then
                                            If Not swRefModel.GetType <> swDocPART Then
                                                Set swConfig = swRefModel.ConfigurationManager.ActiveConfiguration
                                                BOM_PN = BOMPartNumber(swConfig, swRefModel)
                                                Set swNote = swView.GetFirstNote
                                                If Not swNote Is Nothing Then
                                                    swNote.SetText (swNote.GetText & vbCrLf & BOM_PN)
                                                End If
                                            End If
                                        End If
                                        
                                        Set swView = swView.GetNextView
                                    Next j
                                    
                                Next i
                                
                                
                            End Sub
                            
                            
                            'Borrowed from forum post https://forum.solidworks.com/thread/205803
                            Function BOMPartNumber(config As SldWorks.Configuration, document As SldWorks.ModelDoc2) As String
                            
                            
                                Select Case config.BOMPartNoSource
                                Case SwConst.swBOMPartNumberSource_e.swBOMPartNumber_ConfigurationName
                                    BOMPartNumber = config.Name
                                Case SwConst.swBOMPartNumberSource_e.swBOMPartNumber_DocumentName
                                    BOMPartNumber = document.GetTitle
                                    BOMPartNumber = Replace(BOMPartNumber, ".SLDPRT", "") 'added to remove suffix if uppercase
                                    BOMPartNumber = Replace(BOMPartNumber, ".sldprt", "") 'added to remove suffix if lowercase
                                Case SwConst.swBOMPartNumberSource_e.swBOMPartNumber_UserSpecified
                                    BOMPartNumber = config.AlternateName
                                Case SwConst.swBOMPartNumberSource_e.swBOMPartNumber_ParentName
                                    Dim parentConfig As SldWorks.Configuration
                                    Set parentConfig = config.GetParent
                                    If parentConfig.BOMPartNoSource = SwConst.swBOMPartNumberSource_e.swBOMPartNumber_ParentName Then
                                        BOMPartNumber = BOMPartNumber(parentConfig, document)
                                    Else
                                        BOMPartNumber = parentConfig.Name
                                    End If
                                End Select
                            End Function
                            

                             

                            Edit: check if note is null before trying to use it & add a lowercase replace for the file extension in the function

                        • Re: How to get a part's Item Number in a View?
                          Amen Allah Jlili

                          Heard my name being called.

                           

                          Matt Peneguy feel free to contact me. I will leave you my e-mail privately!

                          • Re: How to get a part's Item Number in a View?
                            Artem Taturevych

                            You can also try to use technique similar to the one in the video: Capturing quantities into components - YouTube

                            The idea is to have another column in the BOM table which is linked to the custom property. To make it safe custom property can be specific to this assembly only, i.e. ItemNo_MyAssem. Now you can copy the values of item number column into this new custom property column and force push them into the properties of corresponding components (this is shown in the video). Now you can simply link the note to that value. This value won't automatically update, but it is easy to maintain as it is simple to compare the columns in the BOM and push the values. This is the solution which doesn't require any macro programming.

                             

                            To make it fully flexible you need to have custom macro feature which will take care about updating the value/view label as it changes.

                            • Re: How to get a part's Item Number in a View?
                              Nilesh Patel

                              Hi Matt,

                               

                              Have a look at the macro below. It creates a note for each view linking BOM item number means if you move the item up or down in BOM table, the note will update. Currently, the macro only works on active sheet but you can modify to suit your needs.

                               

                              Option Explicit
                              
                              
                              Dim swApp      As SldWorks.SldWorks
                              Dim swModel    As ModelDoc2
                              Dim swSelMgr    As SelectionMgr
                              
                              
                              Sub main()
                                     
                                  Dim swDraw          As DrawingDoc
                                  Dim swAssyView      As View
                                  Dim swView          As View
                                  Dim swViewModel    As ModelDoc2
                                  Dim swCompModel    As ModelDoc2
                                  Dim swAssy          As AssemblyDoc
                                  Dim swComp          As Component2
                                  Dim swBalOpt        As BalloonOptions
                                  Dim swBody          As Body2
                                  Dim swFace          As Face2
                                  Dim swEntity        As Entity
                                  Dim swNote          As Note
                                  Dim swAnn          As Annotation
                                  Dim vComp          As Variant
                                  Dim vViewPos        As Variant
                                  Dim sBalloonID      As Integer
                                  Dim i              As Integer
                              
                              
                                  Set swApp = Application.SldWorks
                                  Set swModel = swApp.ActiveDoc
                                  Set swDraw = swModel
                                  Set swSelMgr = swModel.SelectionManager
                                  Set swBalOpt = swModel.Extension.CreateBalloonOptions
                                  swBalOpt.Style = swBalloonStyle_e.swBS_None
                                  swBalOpt.UpperTextContent = swBalloonTextContent_e.swBalloonTextItemNumber
                                 
                                  Set swAssyView = swSelMgr.GetSelectedObject6(1, -1)
                                  If swAssyView Is Nothing Then Exit Sub
                                  swModel.ClearSelection2 True
                                 
                                  Set swViewModel = swAssyView.ReferencedDocument
                                  Set swAssy = swViewModel
                                  vComp = swAssy.GetComponents(False)
                                  If IsEmpty(vComp) Then Exit Sub
                                 
                                  Set swView = swDraw.GetFirstView
                                  Set swView = swView.GetNextView
                                 
                                  While Not swView Is Nothing
                                      'Debug.Print swView.Name
                                      vViewPos = swView.GetOutline
                                      Set swViewModel = swView.ReferencedDocument
                                      If Not swViewModel Is Nothing Then
                                          If swViewModel.GetType = swDocumentTypes_e.swDocPART Then
                                              'Debug.Print swView.Name
                                              For i = 0 To UBound(vComp)
                                                  Set swComp = vComp(i)
                                                  Set swCompModel = swComp.GetModelDoc2
                                                  If swCompModel Is Nothing Then Exit Sub
                                                 
                                                  If swViewModel.GetTitle = swCompModel.GetTitle Then
                                                      'Debug.Print "    " & swCompModel.GetTitle
                                                      Set swBody = swComp.GetBody
                                                      Set swFace = swBody.GetFirstFace
                                                      Set swEntity = swFace
                                                      swAssyView.SelectEntity swEntity, False
                                                      Set swNote = swModel.Extension.InsertBOMBalloon2(swBalOpt)
                                                      If swNote Is Nothing Then Exit Sub
                                                                         
                                                      Set swAnn = swNote.GetAnnotation
                                                      sBalloonID = swModel.Extension.GetObjectId(swAnn)
                                                      swModel.ClearSelection2 True
                                                     
                                                      swDraw.ActivateView (swView.Name)
                                                      Set swNote = swModel.InsertNote("Item No=<OBJECT ID=" & Chr(34) & sBalloonID & Chr(34) & ">")
                                                      If swNote Is Nothing Then Exit Sub
                                                      Set swAnn = swNote.GetAnnotation
                                                      swAnn.SetLeader3 swLeaderStyle_e.swNO_LEADER, swLeaderSide_e.swLS_SMART, False, False, False, False
                                                      swAnn.SetPosition vViewPos(0) + ((vViewPos(2) - vViewPos(0)) / 2) - 0.01, vViewPos(1), 0
                                                      swModel.ClearSelection2 True
                                                      Exit For
                                                  End If
                                              Next i
                                          End If
                                      End If
                                      Set swView = swView.GetNextView
                                  Wend
                              End Sub
                              

                               

                              This is how the macro works;

                               

                              1. Create a view for final assembly anywhere in the active sheet (it can be even outside the drawing area). You don't need to create a BOM table for it but you will have to set the view's balloon property to link to existing BOM table. Select this assembly view and run the macro.

                               

                              2. It will create a balloon for referenced parts for which you have drawing views. Macro then create a note for each view and links the balloon item number for that referenced part. Whatever text format you need for view note, you will have to set the same text format for the balloon text.

                               

                              3. Once the notes are created, you can hide the assembly view. Now if you move any of the part up or down in the BOM table, the note will update.

                               

                              4. You will also have to add some error handling.

                               

                              I have only tested this macro for a small assembly and as mentioned earlier, it only works for active sheet. Only drawback is that you will have to create the assembly view which will increase you file size but you can hide it later. Have a look at it. Hope this helps.

                               

                              Regards,

                              Nilesh

                                • Re: How to get a part's Item Number in a View?
                                  Josh Brady

                                  Nilesh,

                                  Good macro.  I had not noticed GetObjectID in the API before.  That's great!

                                  Not sure what version of SW you're running, but at least in 2017 you can link drawing views of components to a BOM that's driven by an assembly.  That BOM doesn't have to be on the same sheet.

                                   

                                  So, all you have to do with your macro is add the balloon to the component drawing view instead of finding it in the assembly view and adding it there.  The small downside is that you then need to move the balloon off the printable area of the drawing.  You can't just hide the balloon or move it to an invisible layer because the "<OBJECT..." link follows that display and the number disappears from the note.

                                  • Re: How to get a part's Item Number in a View?
                                    Matt Peneguy

                                    Nilesh,

                                    Thanks for posting this.  I'm about to test it out.

                                    • Re: How to get a part's Item Number in a View?
                                      Matt Peneguy

                                      Nilesh,

                                      It's hanging on the highlighted line:

                                      I'm looking through and seeing what's going on.

                                        • Re: How to get a part's Item Number in a View?
                                          Josh Brady

                                          You probably didn't make a view of the assembly and then select it.  But that's not necessary.  Here's a hacked-up version that doesn't need a view of the assembly.  Just requires all part drawing views to be linked to the main BOM (wherever it is)

                                           

                                          Option Explicit
                                            
                                            
                                          Dim swApp      As SldWorks.SldWorks
                                          Dim swModel    As ModelDoc2
                                          Dim swSelMgr    As SelectionMgr
                                            
                                            
                                          Sub main()
                                                   
                                              Dim swDraw          As DrawingDoc
                                              Dim swAssyView      As View
                                              Dim swView          As View
                                              Dim swViewModel    As ModelDoc2
                                              Dim swCompModel    As ModelDoc2
                                              Dim Pdoc            As SldWorks.PartDoc
                                              Dim swAssy          As AssemblyDoc
                                              Dim swComp          As Component2
                                              Dim swBalOpt        As BalloonOptions
                                              Dim swBody          As Body2
                                              Dim swFace          As Face2
                                              Dim swEntity        As Entity
                                              Dim swNote          As Note
                                              Dim swAnn          As Annotation
                                              Dim vComp          As Variant
                                              Dim vViewPos        As Variant
                                              Dim sBalloonID      As Integer
                                              Dim i              As Integer
                                            
                                            
                                              Set swApp = Application.SldWorks
                                              Set swModel = swApp.ActiveDoc
                                              Set swDraw = swModel
                                              Set swSelMgr = swModel.SelectionManager
                                              Set swBalOpt = swModel.Extension.CreateBalloonOptions
                                              swBalOpt.Style = swBalloonStyle_e.swBS_None
                                          
                                          
                                              swBalOpt.UpperTextContent = swBalloonTextContent_e.swBalloonTextItemNumber
                                               
                                               
                                              Set swView = swDraw.GetFirstView
                                              Set swView = swView.GetNextView
                                              Dim swBodys As Variant
                                              While Not swView Is Nothing
                                                  'Debug.Print swView.Name
                                                  vViewPos = swView.GetOutline
                                                  Set swViewModel = swView.ReferencedDocument
                                                  If Not swViewModel Is Nothing Then
                                                      If swViewModel.GetType = swDocumentTypes_e.swDocPART Then
                                                          'Debug.Print swView.Name
                                                              'Set swCompModel = swComp.GetModelDoc2
                                                              'if swCompModel Is Nothing Then Exit Sub
                                                               
                                                                  'Debug.Print "    " & swCompModel.GetTitle
                                                                  Set Pdoc = swViewModel
                                                                  swBodys = Pdoc.GetBodies(0)
                                                                  Set swFace = swBodys(0).GetFirstFace
                                                                  Set swEntity = swFace
                                                                  swView.SelectEntity swEntity, False
                                                                  Set swNote = swModel.Extension.InsertBOMBalloon2(swBalOpt)
                                                                  If swNote Is Nothing Then Exit Sub
                                                                                       
                                                                  Set swAnn = swNote.GetAnnotation
                                                                  swAnn.SetLeader3 0, 0, False, False, False, False
                                                                  swAnn.SetPosition2 -0.01, -0.01, 0
                                                                  sBalloonID = swModel.Extension.GetObjectId(swAnn)
                                                                  swModel.ClearSelection2 True
                                                                   
                                                                  swDraw.ActivateView (swView.Name)
                                                                  Set swNote = swModel.InsertNote("Item No=<OBJECT ID=""" & sBalloonID & """>")
                                                                  If swNote Is Nothing Then Exit Sub
                                                                  Set swAnn = swNote.GetAnnotation
                                                                  swAnn.SetLeader3 swLeaderStyle_e.swNO_LEADER, swLeaderSide_e.swLS_SMART, False, False, False, False
                                                                  swAnn.SetPosition vViewPos(0) + ((vViewPos(2) - vViewPos(0)) / 2) - 0.01, vViewPos(1), 0
                                                                  swModel.ClearSelection2 True
                                          
                                          
                                                      End If
                                                  End If
                                                  Set swView = swView.GetNextView
                                              Wend
                                          End Sub
                                          
                                        • Re: How to get a part's Item Number in a View?
                                          Artem Taturevych

                                          Excellent macro! I was always wondering how to get the object ID for the embedded annotation. now I know. Thanks for sharing.