Looking For An Easy Way To Select & Hide Components Within An Assembly Drawing

Looking For An Easy Way To Select & Hide Components Within An Assembly Drawing

V_L_F
Enthusiast Enthusiast
3,220 Views
7 Replies
Message 1 of 8

Looking For An Easy Way To Select & Hide Components Within An Assembly Drawing

V_L_F
Enthusiast
Enthusiast

Good morning all,

 

I've got another challenge for you all.  I'm currently developing a form that'll allow the user to name a particular component in the displayed assembly model of an assembly drawing; the rules & macros behind the form will then search through all of the present views on the assembly drawing and hide (i.e. visibility turned off) all instances of the specified component.  I've been successful in developing such a feature via a VB macro, which is awesome. I've even been able to extend the search function's reach so that it can search for components within a subassembly.

 

However, there are some cases where the user will want to specify a folder name within the assembly's model tree, and have all of the components contained within this folder be turned invisible.  This would be much easier to do than naming all of the individual components whenever one of these folders happens to contain a large number of components.

Assembly Folder Image.png

 

Given what I've come to expect from Inventor's VBA Editor, I'm imagining that these folders are probably some kind of an object collection or an array that I'd probably be able to iterate through via a For-Each loop.  I just need to know how to create a representation of the folder in my VB macro.

 

Does anyone know how to refer to a folder within an assembly model when creating a VB macro for an assembly drawing?  I've been digging through the various help files in search for the keywords that I need to do this, but I haven't come across anything useful (at least, nothing that I've recognized as what I'm looking for, exactly).  If anyone happens to know if & how this may be possible, I'd greatly appreciate some pointers on this matter.

 

Thanks in advance for giving this post a look-over, and I hope to hear from you soon.  =D

 

- Sincerely,

Vinny

0 Likes
Accepted solutions (1)
3,221 Views
7 Replies
Replies (7)
Message 2 of 8

V_L_F
Enthusiast
Enthusiast

Alrighty, I've figured out a bunch about hunting down and finding components based on whether or not they're nested inside of a folder.  However, I've run into a bit of a brick wall in regard to trying to set the visibility of these nested components in the drawing itself.

 

Below is my code block thus far for sifting through and locating the components contained within a folder that's been specified by name by the user:

Sub FindAndHideFolders(sFolderName As String)
' This sub-routine will seek out and hide any components that are contained within a Browser Folder that's 
' specified by the user. ' This variable is used for testing purposes ONLY. Dim sFolderName As String sFolderName = "Folder1" ' Set a reference to the drawing document. Dim oDrawDoc As Inventor.DrawingDocument Set oDrawDoc = ThisApplication.ActiveDocument ' Set a reference to the active sheet. Dim oSheet As Inventor.sheet Set oSheet = oDrawDoc.ActiveSheet ' This variable keeps track of which drawing view that this sub-routine is currently working on. It starts on VIEW2 and will count through to VIEW5 on the shop drawing. Dim lViewCounter As Long lViewCounter = 2 ' Set a reference to the drawing view (defaults to VIEW2). Dim oView As Inventor.DrawingView Set oView = oSheet.DrawingViews.Item(lViewCounter) ' Set a reference to all drawing views. Dim oViews As DrawingViews Set oViews = oSheet.DrawingViews '------------------------------------------------------------------------------------- ' Set a reference to the FileManager Object. Dim oFileManager As FileManager Set oFileManager = ThisApplication.FileManager Dim sFullFileName As String sFullFileName = oDrawDoc.FullDocumentName Dim sLastActiveLOD As String sLastActiveLOD = "iLogic" ' Get the full document name using the full file name & LOD name. Dim sFullDocName As String sFullDocName = oFileManager.GetFullDocumentName(sFullFileName, sLastActiveLOD) ' Set a reference to the assembly document. Dim oRefDoc As AssemblyDocument Set oRefDoc = oView.ReferencedDocumentDescriptor.ReferencedDocument Dim oAssyDef As AssemblyComponentDefinition Set oAssyDef = oRefDoc.ComponentDefinition Dim oCompOcc As ComponentOccurrence Dim oSubCompOcc As ComponentOccurrence Dim oCompDef As AssemblyComponentDefinition Set oCompDef = oRefDoc.ComponentDefinition Dim oPane As BrowserPane Set oPane = oRefDoc.BrowserPanes.ActivePane '------------------------------------------------------------------------------------- ' This While-Wend loop will scan VIEW2 thru VIEW5 for the specified component, and then hide it if it's found. While lViewCounter <= 5 Set oView = oSheet.DrawingViews.Item(lViewCounter) ' This variable will reference the collection of components in the assembly model's Browser window. Dim oTopNodes As BrowserNodesEnumerator Set oTopNodes = oPane.TopNode.BrowserNodes ' This variable will reference the BrowserFolder collection (if any) within each TopNode. Dim oBrowserFolders As BrowserFoldersEnumerator Dim oTopNode As BrowserNode For Each oTopNode In oTopNodes Set oBrowserFolders = oTopNode.BrowserFolders ' If there are any browser folders within the current TopNode object, then we'll scan through them to
' find a folder name that matches the user's input. If oBrowserFolders.Count > 0 Then Dim oBrowserFolder As BrowserFolder For Each oBrowserFolder In oBrowserFolders ' If the current oBrowserFolder name is the same as the folder name provided by the user, then we'll proceed to ' turn off the visibility for every component within the current oBrowserFolder. We'll skip over any suppressed ' components to avoid any odd errors or such. If oBrowserFolder.Name = sFolderName Then 'MsgBox ("Found it!") Dim oBrowserNodes As BrowserNodesEnumerator Set oBrowserNodes = oBrowserFolder.BrowserNode.BrowserNodes
' This variable will reference each component found within the current oBrowserFolder. Dim oBrowserNode As BrowserNode For Each oBrowserNode In oBrowserNodes If oBrowserNode.NativeObject.Suppressed = False Then '====================================================================================== ' Insert code block that selects & hides the oBrowserNode object on the drawing HERE!!! '====================================================================================== End If Next End If Next End If Next
Wend
'...
End Sub

 

My problem at this point is that there's no way to direct way to create a proxy for the components' occurrences so that I can hide them in the current view via something like the oView.SetVisibility() sub-routine.  Ugh!!!  So close, and yet so far away...

 

I'm trying to see if there's anything like regular expressions or such that I could use to extrapolate the names of the components via the BrowserNode.FullPath property.  I would then just run my other macro with the extrapolated component name and have it hide the component.

 

If anyone has any suggestions on what could help me close the gap between these user interface objects and their actual component occurrences, I'm all ears.  If I figure out some other way around it, I'll post it here for people to see.  Wish me good luck!  =P

 

- Vinny

 

0 Likes
Message 3 of 8

V_L_F
Enthusiast
Enthusiast
Accepted solution

Hello everyone,

 

So I've finally come up with a solution to my problem.  It took a while to figure out a solution, but I did it, and it works beautifully (at least, for my purposes, anyway).  And like I said I would do in my previous reply, here's the code that I came up with.

 

Disclaimer:  I apologize in advance if my code is messy or inefficient - I'm just getting my feet wet in Inventor's VBA, so I'm learning a LOT of things every day on how to program efficiently.

 

What Does This Gibberish Do?

Like the instructions in the screenshot below shows, this tool will scan through and turn off the visibility for individual component occurrences in DrawingViews 1 - 5 on the shop drawing.  It can also turn off all components that share the same "part number", which is the name that shows up in the Inventor drawing's Browser Window.  On top of that, you can enter multiple part numbers into the Find & Hide Components textbox; just separate each name with a comma, and the sub-routines will find & hide each of the components that you've listed.  Lastly, the Find & Hide Folders textbox will find & hide all of the contents of a specified Browser Folder.

 

..But Why?

Why not just do this all by hand?  Well, when you're working with a shop drawing template, there can be multiple DrawingViews used to illustrate an assembly model's details (my company uses 5 views to illustrate our packing crates).  When you swap out some unit assemblies that are contained within each crate assembly model, sometimes a lot of small components that you'd prefer to remain invisible become visible on the drawing.  I got sick and tired of having to go into each DrawingView and manually hiding the same components over and over again.  So now I won't have to, and it's frakkin' AWESOME.

 

Um, How You Do??

These sub-routines work in tandem with a couple simple User Parameters, iLogic rules & a simple form to perform their task.  They're currently a part of a shop drawing template file that I've been refining, so everything is tied locally to a single .IDW file.

 

The .IDW file has two simple User Parameters:  hide_this_component; and hide_this_folder.  These text parameters simply hold the value of whatever the user types into the UI Form (see below).  The iLogic rules that are tied to these User Parameters are simple, and look like the following:

 

find_and_hide_components_rule:

' This rule will seek out a specified component, and will run the FindAndHideComponents(sCompName) macro to hide it.
InventorVb.RunMacro("DocumentProject", "Module1", "FindAndHideComponents", hide_this_component)

find_and_hide_folders_rule:

SyntaxEditor Code Snippet

' This rule will run a few macros to locate a folder in the Browser window that has the same name as hide_this_folder.' It will then hide all of the components within the specified folder.
InventorVb.RunMacro("DocumentProject", "Module1", "FindAndHideFolders", hide_this_folder)

 

I threw together a simple User Interface Form for this "Find & Hide Components" tool, complete with instructions on how to enter the component names into the textboxes:

 Find And Hide Components Form.png

 Last, but certainly not least, here be my source code:

Sub FindAndHideFolders(sFolderName As String)
' This sub-routine will seek out and hide any components that are contained within a Browser Folder 
' that's specified by the user.

    ' Set a reference to the drawing document.
    Dim oDrawDoc As Inventor.DrawingDocument
    Set oDrawDoc = ThisApplication.ActiveDocument
       
    ' Set a reference to the active sheet.
    Dim oSheet As Inventor.sheet
    Set oSheet = oDrawDoc.ActiveSheet
       
    ' Set a reference to the drawing view (defaults to VIEW1).
    Dim oView As Inventor.DrawingView
    Set oView = oSheet.DrawingViews.Item(1)
    
    ' Set a reference to all drawing views.
    Dim oViews As DrawingViews
    Set oViews = oSheet.DrawingViews
'-------------------------------------------------------------------------------------

' Set a reference to the FileManager Object.
    Dim oFileManager As FileManager
    Set oFileManager = ThisApplication.FileManager
    
    ' Set the full file name of the drawing document.
    Dim sFullFileName As String
    sFullFileName = oDrawDoc.FullDocumentName
    
    ' Set the name of the desired LOD representation.
    Dim sLODName As String
    sLODName = "iLogic"
    
    ' Get the full document name using the full file name & LOD name.
    Dim sFullDocName As String
    sFullDocName = oFileManager.GetFullDocumentName(sFullFileName, sLODName)

    ' Set a reference to the assembly document.
    Dim oRefDoc As AssemblyDocument
    Set oRefDoc = oView.ReferencedDocumentDescriptor.ReferencedDocument
    
    ' Set a reference to the assembly component definition.
    Dim oSub1AssyCompDef As AssemblyComponentDefinition
    Set oSub1AssyCompDef = oRefDoc.ComponentDefinition
    
    ' Set a reference to the component & sub-component occurrences.
    Dim oSub1AssyCompOcc As ComponentOccurrence
    Dim oSub2AssyCompOcc As ComponentOccurrence
    
    ' Set a reference to the Browser Pane.
    Dim oPane As BrowserPane
    Set oPane = oRefDoc.BrowserPanes.ActivePane
'-------------------------------------------------------------------------------------

    ' This variable will reference the collection of components in the assembly model's Browser window.
    Dim oTopNodes As BrowserNodesEnumerator
    Set oTopNodes = oPane.TopNode.BrowserNodes
    
    ' This variable will reference the BrowserFolder collection (if any) within each TopNode.
    Dim oBrowserFolders As BrowserFoldersEnumerator
    
    Dim oTopNode As BrowserNode
    For Each oTopNode In oTopNodes
        Set oBrowserFolders = oTopNode.BrowserFolders
        ' If there are any browser folders within the current TopNode object, then we'll scan through them 
        ' to find a folder name that matches the user's input.
        If oBrowserFolders.Count > 0 Then
            Dim oBrowserFolder As BrowserFolder
            For Each oBrowserFolder In oBrowserFolders
                ' If the current oBrowserFolder name is the same as the folder name provided by the user, 
                ' then we'll proceed to turn off the visibility for every component within the current 
                ' oBrowserFolder.  We'll skip over any suppressed components to avoid any odd errors or such.
                If oBrowserFolder.Name = sFolderName Then
                    ' This variable will reference the collection of Browser Nodes in the current 
                    ' oBrowserFolder.
                    Dim oBrowserNodes As BrowserNodesEnumerator
                    Set oBrowserNodes = oBrowserFolder.BrowserNode.BrowserNodes
                    ' This For-Each loop will iterate through each Browser Node in the current oBrowserFolder 
                    ' to find & extract the name of each component found within the user-specified folder.
                    Dim oBrowserNode As BrowserNode
                    For Each oBrowserNode In oBrowserNodes
                        ' We want to ignore any components that are already suppressed, so this If-Then block 
                        ' will ensure that such is the case.
                        If oBrowserNode.NativeObject.Suppressed = False Then
                            ' This variable will contain the FullPath of the current oBrowserNode.  We'll 
                    	    ' split the FullPath into a string array and extract the part number & occurrence 
                    	    ' number from it.
                            Dim sNodeName As String
                            sNodeName = oBrowserNode.FullPath
                            Dim S() As String
                    	    ' Produces S(0) thru S(5); S(4) has the component name that we want!
                            S() = Split(sNodeName, ":")
                            ' Now we'll put the extracted part number & occurrence number back together with 
                    	    ' a colon separator, and then store it within this variable.
                            Dim sPartNumber As String
                            sPartNumber = S(4) & ":" & S(5)
                            ' We'll use the FindAndHideComponents() sub-routine to handle the task of hiding 
                    	    ' the component that's associated with the current oBrowserNode.
                            Call FindAndHideComponents(sPartNumber)
                        End If
                    Next
                End If
            Next
        End If
    Next
    MsgBox ("Find & Hide Folder Components Process Complete.")
End Sub


Sub FindAndHideComponents(sCompName As String)
' This sub-routine will seek out and hide any unit assembly components that are specified by the user.
    ' Set a reference to the drawing document.
    Dim oDrawDoc As Inventor.DrawingDocument
    Set oDrawDoc = ThisApplication.ActiveDocument
       
    ' Set a reference to the active sheet.
    Dim oSheet As Inventor.sheet
    Set oSheet = oDrawDoc.ActiveSheet
    
    ' This variable keeps track of which drawing view that this sub-routine is currently working on.
    Dim lViewCounter As Long
    lViewCounter = 1
       
    ' Set a reference to the drawing view (defaults to VIEW1).
    Dim oView As Inventor.DrawingView
    Set oView = oSheet.DrawingViews.Item(lViewCounter)
    
    ' Set a reference to all drawing views.
    Dim oViews As DrawingViews
    Set oViews = oSheet.DrawingViews
'-------------------------------------------------------------------------------------

' Set a reference to the FileManager Object.
    Dim oFileManager As FileManager
    Set oFileManager = ThisApplication.FileManager
    
    ' Set the full file name of the drawing document.
    Dim sFullFileName As String
    sFullFileName = oDrawDoc.FullDocumentName
    
    ' Set the name of the desired LOD representation.
    Dim sLODName As String
    sLODName = "iLogic"
    
    ' Get the full document name using the full file name & LOD name.
    Dim sFullDocName As String
    sFullDocName = oFileManager.GetFullDocumentName(sFullFileName, sLODName)

    ' Set a reference to the assembly document.
    Dim oRefDoc As AssemblyDocument
    Set oRefDoc = oView.ReferencedDocumentDescriptor.ReferencedDocument
    
    ' Set a reference to the assembly component's definition.
    Dim oSub1AssyCompDef As AssemblyComponentDefinition
    Set oSub1AssyCompDef = oRefDoc.ComponentDefinition
    
    Dim oSub1AssyCompOcc As ComponentOccurrence
    Dim oSub2AssyCompOcc As ComponentOccurrence
'-------------------------------------------------------------------------------------
    
    ' This string array will split up the value of sCompName so that multiple parts can be hidden at a time.
    ' The user will need to separate each component name up by placing a comma in between each component name.
    Dim sCompNameArray() As String
    sCompNameArray() = Split(sCompName, ",")
    
    Dim vCurrentCompName As Variant
    For Each vCurrentCompName In sCompNameArray()
        ' We reset our lViewCounter to 1.
        lViewCounter = 1
        
        ' The following variable will determine whether or not vCurrentCompName contains a colon (":") in its 
	' string value.
        ' - If a colon is present, bIsCompName1Occ will be set to False.
        ' - If a colon is NOT present, bIsCompName1Occ will be set to True.
        Dim bIsCompName1Occ As Boolean
        If InStr(vCurrentCompName, ":") > 0 Then
            bIsCompName1Occ = True
        ElseIf InStr(vCurrentCompName, ":") = 0 Then
            bIsCompName1Occ = False
        Else
            MsgBox ("ERROR:  Invalid value for vCurrentCompName variable.")
        End If
        
        ' This While-Wend loop will scan VIEW2 thru VIEW5 for the specified component, and then hide it if 
	' it's found.
        While lViewCounter <= 5
            Set oView = oSheet.DrawingViews.Item(lViewCounter)
            ' This variable will keep count of which assembly component item our specified component is 
	' located within.
            Dim AssyOccItemNumber As Long
            AssyOccItemNumber = 1
            
            ' We'll check every component under master assembly level to see if any of these components' names 
	    ' match the specified component.
            For Each oSub1AssyCompOcc In oSub1AssyCompDef.Occurrences
                ' We check to ensure that we're not looking at a suppressed component, as that can cause errors 
                ' to occur.
                If oSub1AssyCompOcc.Suppressed = False Then
        '====================================
        ' Single Component Hiding Block Begin
        '====================================
                    ' If a colon is present in sCompName's value, then we presume that we're only hiding a 
	            ' single occurrence of the specified component.  We'll run this If-Then code block to find 
            	    ' & hide the specified component.
                    If bIsCompName1Occ = True Then
                        If oSub1AssyCompOcc.Name = vCurrentCompName Then
                            If oView.GetVisibility(oSub1AssyCompOcc) = True Then
                                Call oView.SetVisibility(oSub1AssyCompOcc, False)
                            End If
                        End If
                        
                        ' If the current oSub1AssyCompOcc's name doesn't match the specified component, and it's 
                        ' an assembly component that is not suppressed, then we dive deeper to search the 
                        ' components within oSub1AssyCompOcc.
                        If oSub1AssyCompOcc.Definition.Type = kAssemblyComponentDefinitionObject Then
                            ' This variable gets the assembly component definition of the current 
	                    ' oSub1AssyCompOcc object.
                            Dim oSub2AssyCompDef As AssemblyComponentDefinition
                            Set oSub2AssyCompDef = oSub1AssyCompOcc.Definition
                            
                            ' This variable will keep count of which sub-assembly component item our specified 
                            ' component is located within.
                            Dim SubAssyOccItemNumber As Long
                            SubAssyOccItemNumber = 1
                            
                            ' Now we'll go down one level into the current sub-assembly component and check its 
                            ' sub-components for a matching component name.
                            For Each oSub2AssyCompOcc In oSub2AssyCompDef.Occurrences
                                If oSub2AssyCompOcc.Name = vCurrentCompName Then
                                    ' If the current oSub2AssyCompOcc's definition document type is that of an 
                                    ' assembly document, we'll check its contents to ensure that it contains 
                                    ' components that can actually be made invisible before proceeding.  This is 
                                    ' done to avoid the run-time error that we get when we attempt to hide a 
                                    ' sub-assembly component that's simply an empty placeholder component.
                                    ' These placeholder components are in the assembly component solely to have 
                                    ' its iProperties included on the B.O.M., so we're not to be concerned with 
                                    ' hiding them.
                                    If oSub2AssyCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
                                        Dim oSub3AssyCompDef As AssemblyComponentDefinition
                                        Set oSub3AssyCompDef = oSub2AssyCompOcc.Definition
                                        ' We'll pass all of the necessary info on to our CheckAndHideSubAssyComps() 
                                        ' sub-routine to recursively scan the rest of the sub-assembly layers to 
                                        ' find & hide the user-specified component.
                                        Call CheckAndHideSubAssyComps(oView, oSub3AssyCompDef, oSub1AssyCompDef, AssyOccItemNumber, SubAssyOccItemNumber)
                                    ' If the current oSub2AssyCompOcc is NOT an assembly document object, then we 
                                    ' just hide it; it's likely just a part component.
                                    ElseIf oSub2AssyCompOcc.DefinitionDocumentType <> kAssemblyDocumentObject Then
                                        ' We'll create a proxy of our component so that we can properly tell oView 
                                        ' to hide it.
                                        Dim oSubCompProxy As ComponentOccurrenceProxy
                                        Set oSubCompProxy = oSub1AssyCompDef.Occurrences.Item(AssyOccItemNumber).SubOccurrences.Item(SubAssyOccItemNumber)
                                        ' Toggle visibility of components in subassembly.
                                        If oView.GetVisibility(oSubCompProxy) = True Then
                                            Call oView.SetVisibility(oSubCompProxy, False)
                                        End If
                                    End If
                                End If
                                SubAssyOccItemNumber = SubAssyOccItemNumber + 1
                            Next
                        End If
        '==================================
        ' Single Component Hiding Block End
        '==================================
        
        '===================================
        ' Batch Component Hiding Block Begin
        '===================================
                    ' If a colon is NOT present in sCompName's value, then we run this ElseIf-Then code block to 
		    ' find & hide all occurrences of the specified component part number.
                    ElseIf bIsCompName1Occ = False Then
                        ' First, we need to take the current oSub1AssyCompOcc's name and split it into an array.
                        ' - sCompOccName(0) will contain the oSub1AssyCompOcc's part number.
                        ' - sCompOccName(1) will contain the oSub1AssyCompOcc's occurrence number.
                        Dim sCompOccName() As String
                        sCompOccName() = Split(oSub1AssyCompOcc.Name, ":") ' sCompOccName(0) = "1003UA30055-WT"; sCompOccName(1) = "1"
                        ' If the current oSub1AssyCompOcc's part number matches the user-specified component, 
                        ' then we proceed as normal and hide the current oSub1AssyCompOcc.
                        If sCompOccName(0) = vCurrentCompName Then ' Returns True
                            If oView.GetVisibility(oSub1AssyCompOcc) = True Then
                                Call oView.SetVisibility(oSub1AssyCompOcc, False)
                            End If
                        End If
                        
                        ' If the current oSub1AssyCompOcc's name doesn't match the user-specified component AND 
                        ' it's an assembly component that is not suppressed, then we dive deeper to search the 
                        ' components within oSub1AssyCompOcc.
                        If oSub1AssyCompOcc.Definition.Type = kAssemblyComponentDefinitionObject Then
                            ' This variable gets the assembly component definition of the current oSub1AssyCompOcc
                            ' object.
                            Set oSub2AssyCompDef = oSub1AssyCompOcc.Definition
                            
                            ' This variable will keep count of which sub-assembly component item our specified
                            ' component is located within.
                            SubAssyOccItemNumber = 1
                            
                            For Each oSub2AssyCompOcc In oSub2AssyCompDef.Occurrences
                                Dim sSubCompOccName() As String
                                sSubCompOccName() = Split(oSub2AssyCompOcc.Name, ":") ' sSubCompOccName(0) = "1003EG031"; sSubCompOccName(1) = "1"
                                If sSubCompOccName(0) = vCurrentCompName Then
                                    ' If the current oSub2AssyCompOcc's definition document type is that of an 
	                            ' assembly document, we'll check its contents to ensure that it contains 
	                            ' components that can actually be made invisible before proceeding.  This is 
	                            ' done to avoid the run-time error that we get when we attempt to hide a 
	                            ' sub-assembly component that's simply an empty placeholder component.
                                    ' These placeholder components are in the assembly component solely to have 
	                            ' its iProperties included on the B.O.M., so we're not to be concerned with 
	                            ' hiding them.
                                    If oSub2AssyCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
                                        Set oSub3AssyCompDef = oSub2AssyCompOcc.Definition
                                        ' We'll pass all of the necessary info on to our CheckAndHideSubAssyComps() 
	                                ' sub-routine to recursively scan the rest of the sub-assembly layers to 
	                                ' find & hide the user-specified component.
                                        Call CheckAndHideSubAssyComps(oView, oSub3AssyCompDef, oSub1AssyCompDef, AssyOccItemNumber, SubAssyOccItemNumber)

                                    ' If the current oSub2AssyCompOcc is NOT an assembly document object, then we 
	                            ' just hide it; it's likely just a part component.
                                    ElseIf oSub2AssyCompOcc.DefinitionDocumentType <> kAssemblyDocumentObject Then
                                        ' We'll create a proxy of our component so that we can properly tell oView 
	                                ' to hide it.
                                        Set oSubCompProxy = oSub1AssyCompDef.Occurrences.Item(AssyOccItemNumber).SubOccurrences.Item(SubAssyOccItemNumber)
                                        ' Toggle visibility of components in subassembly.
                                        If oView.GetVisibility(oSubCompProxy) = True Then
                                            Call oView.SetVisibility(oSubCompProxy, False)
                                        End If
                                    End If
                                End If
                                SubAssyOccItemNumber = SubAssyOccItemNumber + 1
                            Next
                        End If
                    Else
                        MsgBox ("ERROR:  Invalid value for bIsCompName1Occ variable.")
                    End If
        '=================================
        ' Batch Component Hiding Block End
        '=================================
                End If
                AssyOccItemNumber = AssyOccItemNumber + 1
            Next
            lViewCounter = lViewCounter + 1
        Wend
    Next
End Sub


Public Sub CheckAndHideSubAssyComps(oView, oCurrentSubAssyCompDef, oSub1AssyCompDef, AssyOccItemNumber, SubAssyOccItemNumber)
' This sub-routine will handle the sometimes recursive activity of hiding a sub-assembly by checking each of its 
' components for SurfaceBodies to hide.  Attempting to hide a sub-component that doesn't have any SurfaceBodies 
' (i.e. trying to hide the empty placeholder sub-components that are used only for their iProperties) causes an 
' error to occur, so in such a scenario it's easier to cherry-pick through a sub-assembly's components in order 
' to hide the components with actual 3D models in them.

' This sub-routine takes in a number of variables and checks if the given sub-assembly's components have 
' SurfaceBodies.  If they do, they get hidden.  If another sub-sub-assembly is found within the given sub-assembly, 
' this sub-routine will call upon itself again and pass along the sub-sub-assembly for processing.
    Dim oCurrentSubAssyCompOcc As ComponentOccurrence
    For Each oCurrentSubAssyCompOcc In oCurrentSubAssyCompDef.Occurrences
        If oCurrentSubAssyCompOcc.SurfaceBodies.Count > 0 Then
            ' We'll create a proxy of our component so that we can properly tell oView to hide it.
            Dim oCurrentSubAssyCompProxy As ComponentOccurrenceProxy
            Set oCurrentSubAssyCompProxy = oSub1AssyCompDef.Occurrences.Item(AssyOccItemNumber).SubOccurrences.Item(SubAssyOccItemNumber)
            ' Toggle visibility of components in subassembly.
            If oView.GetVisibility(oCurrentSubAssyCompProxy) = True Then
                Call oView.SetVisibility(oCurrentSubAssyCompProxy, False)
            End If
        ' If it turns out that the current sub-assembly component is ALSO an kAssemblyDocumentObject, then we create a new AssemblyComponentDefinition
        ' and recursively call upon this sub-routine to check the current sub-assembly component's sub-components.
        ElseIf oCurrentSubAssyCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
            ' This variable will be the AssemblyComponentDefinition that gets passed on to CheckAndHideSubAssyComps().
            Dim oInternalSubAssyCompDef As AssemblyComponentDefinition
            Set oInternalSubAssyCompDef = oCurrentSubAssyCompOcc.Definition
            Call CheckAndHideSubAssyComps(oView, oInternalSubAssyCompDef, oSub1AssyCompDef, AssyOccItemNumber, SubAssyOccItemNumber)
        End If
    Next
End Sub

There's a couple of interesting things that I've learned while figuring out this tool.  First, Inventor gets angry and throws errors at you if you attempt to hide a component that doesn't contain any 3D models.  The engineering team at my company sometimes create these empty placeholder components in their assembly models solely to make some additional unmodeled components appear on the assembly's B.O.M.  I found that checking each sub-component's SurfaceBodies property helped to determine if it was something that's safe to hide.

 

Another interesting thing that I've learned was that the BrowserNodes in the Browser Window don't seem to have any direct connection to their counterparts within the assembly document.  My need for a tool that could hide a specified folder in each DrawingView required that I dig through the BrowserNodes to find the components listed within a BrowserFolder.  But since there's no BrowserNode property that directly links it to its component counterpart within the assembly model, I had to create a work-around method to solve my problem.

 

To solve my problem, I went about grabbing each BrowserNodes' FullPath property, Split()ing them up into a Variant array, and then extracting the part numbers & occurrence numbers of each component from the Variant array's last two elements.  I then used my FindAndHideComponents() sub-routine to seek out & hide all applicable components whose Name property matched the extracted part numbers & occurrence numbers.

 

I can bet that this really long-winded post might be about a topic that a lot of you may have already figured out a loooooooong time ago.  But with all of the google & forum-searching that I've done, none of them really had the solution to this problem that I was looking for.  I'd be happy to let this post collect a lot of dust digitally in the back of a server hard drive somewhere for the rest of human existence for one single reason - that some other beginner like me may come along looking for this same exact answer, and will rejoice in finding all of this info in a single spot on the internet.

 

So I'll just make this post, pat myself on the back, and give myself a Kudo for solving my problem and sharing with everyone else.  Enjoy!

 

- Vinny

Message 4 of 8

Jesper_S
Collaborator
Collaborator

Hi @V_L_F

 

Really nice piece of work. Been looking for something like this but my codingskills sucks.

 

Got a few questions.

 

Is it possible to somehow reverse it, like a Show Components function?

 

As it works now, it hides all Occurrances of what you type in the parameter in all drawingviews, can it be done for only selected views?

I often hide bolt, nuts and washer in some specific detailviews but dont watn to hide them in all views.

 

//Jesper


//Jesper

Did you find this reply helpful ? If so please use the Accept as Solution or Kudos button below.
0 Likes
Message 5 of 8

V_L_F
Enthusiast
Enthusiast

Greetings Jesper,

 

It most certainly should be easy to make things visible again.  I would make a copy of both the Sub FindAndHideComponents() & Sub CheckAndHideSubAssyComps() sub-routinea, rename them to something like Sub FindAndUnhideComponents()Sub CheckAndUnhideSubAssyComps(), and then change the following lines of code wherever they occur:

 

Here's the original If-Then statement that checks & turns off the visibility of the named component:

 

' Toggle visibility of components in subassembly.
If oView.GetVisibility(oCurrentSubAssyCompProxy) = True Then
    Call oView.SetVisibility(oCurrentSubAssyCompProxy, False)
End If

 

 

To unhide the named component, change the If-Then statement to this:

 

' Toggle visibility of components in subassembly.
If oView.GetVisibility(oCurrentSubAssyCompProxy) = False Then
    Call oView.SetVisibility(oCurrentSubAssyCompProxy, True)
End If

 

 

On that note, I'd like to mention that I've made a slight revision to my Sub FindAndHideComponents() sub-routine.  I found that when my sub-routine is looking at a level 2 sub-component (which are referenced by the oSub2AssyCompOcc variable), I ran into an issue when that sub-component was NOT an AssemblyDocumentObject.  Essentially, I forgot to have my sub-routine check to see if the oSub2AssyCompOcc sub-component had a SurfaceBodies.Count of greater than 0.  If the current oSub2AssyCompOcc sub-component is an empty placeholder component (i.e. has no 3D model in it, and is only used for something like using its iProperties to populate a B.O.M.), the Sub FindAndHideComponents() sub-routine kicks up a run-time error.

 

Here's the revised sub-routine:

 

Sub FindAndHideComponents(sCompName As String)
' This sub-routine will seek out and hide any unit assembly components that are specified by the user.
    ' Set a reference to the drawing document.
    Dim oDrawDoc As Inventor.DrawingDocument
    Set oDrawDoc = ThisApplication.ActiveDocument
       
    ' Set a reference to the active sheet.
    Dim oSheet As Inventor.sheet
    Set oSheet = oDrawDoc.ActiveSheet
    
    ' This variable keeps track of which drawing view that this sub-routine is currently working on.
    Dim lViewCounter As Long
    lViewCounter = 1
       
    ' Set a reference to the drawing view (defaults to VIEW1).
    Dim oView As Inventor.DrawingView
    Set oView = oSheet.DrawingViews.Item(lViewCounter)
    
    ' Set a reference to all drawing views.
    Dim oViews As DrawingViews
    Set oViews = oSheet.DrawingViews
'-------------------------------------------------------------------------------------

' Set a reference to the FileManager Object.
    Dim oFileManager As FileManager
    Set oFileManager = ThisApplication.FileManager
    
    ' Set the full file name of the drawing document.
    Dim sFullFileName As String
    sFullFileName = oDrawDoc.FullDocumentName
    
    ' Set the name of the desired LOD representation.
    Dim sLODName As String
    sLODName = "iLogic"
    
    ' Get the full document name using the full file name & LOD name.
    Dim sFullDocName As String
    sFullDocName = oFileManager.GetFullDocumentName(sFullFileName, sLODName)

    ' Set a reference to the assembly document.
    Dim oRefDoc As AssemblyDocument
    Set oRefDoc = oView.ReferencedDocumentDescriptor.ReferencedDocument
    
    ' Set a reference to the assembly component's definition.
    Dim oSub1AssyCompDef As AssemblyComponentDefinition
    Set oSub1AssyCompDef = oRefDoc.ComponentDefinition
    
    Dim oSub1AssyCompOcc As ComponentOccurrence
    Dim oSub2AssyCompOcc As ComponentOccurrence
'-------------------------------------------------------------------------------------
    
    ' This string array will split up the value of sCompName so that multiple parts can be hidden at a time.
    ' The user will need to separate each component name up by placing a comma in between each component name.
    Dim sCompNameArray() As String
    sCompNameArray() = Split(sCompName, ",")
    
    Dim vCurrentCompName As Variant
    For Each vCurrentCompName In sCompNameArray()
        ' We reset our lViewCounter to 1.
        lViewCounter = 1
        
        ' The following variable will determine whether or not vCurrentCompName contains a colon (":") in its 
	' string value.
        ' - If a colon is present, bIsCompName1Occ will be set to False.
        ' - If a colon is NOT present, bIsCompName1Occ will be set to True.
        Dim bIsCompName1Occ As Boolean
        If InStr(vCurrentCompName, ":") > 0 Then
            bIsCompName1Occ = True
        ElseIf InStr(vCurrentCompName, ":") = 0 Then
            bIsCompName1Occ = False
        Else
            MsgBox ("ERROR:  Invalid value for vCurrentCompName variable.")
        End If
        
        ' This While-Wend loop will scan VIEW2 thru VIEW5 for the specified component, and then hide it if 
	' it's found.
        While lViewCounter <= 5
            Set oView = oSheet.DrawingViews.Item(lViewCounter)
            ' This variable will keep count of which assembly component item our specified component is 
	' located within.
            Dim AssyOccItemNumber As Long
            AssyOccItemNumber = 1
            
            ' We'll check every component under master assembly level to see if any of these components' names 
	    ' match the specified component.
            For Each oSub1AssyCompOcc In oSub1AssyCompDef.Occurrences
                ' We check to ensure that we're not looking at a suppressed component, as that can cause errors 
                ' to occur.
                If oSub1AssyCompOcc.Suppressed = False Then
        '====================================
        ' Single Component Hiding Block Begin
        '====================================
                    ' If a colon is present in sCompName's value, then we presume that we're only hiding a 
	            ' single occurrence of the specified component.  We'll run this If-Then code block to find 
            	    ' & hide the specified component.
                    If bIsCompName1Occ = True Then
                        If oSub1AssyCompOcc.Name = vCurrentCompName Then
                            If oView.GetVisibility(oSub1AssyCompOcc) = True Then
                                Call oView.SetVisibility(oSub1AssyCompOcc, False)
                            End If
                        End If
                        
                        ' If the current oSub1AssyCompOcc's name doesn't match the specified component, and it's 
                        ' an assembly component that is not suppressed, then we dive deeper to search the 
                        ' components within oSub1AssyCompOcc.
                        If oSub1AssyCompOcc.Definition.Type = kAssemblyComponentDefinitionObject Then
                            ' This variable gets the assembly component definition of the current 
	                    ' oSub1AssyCompOcc object.
                            Dim oSub2AssyCompDef As AssemblyComponentDefinition
                            Set oSub2AssyCompDef = oSub1AssyCompOcc.Definition
                            
                            ' This variable will keep count of which sub-assembly component item our specified 
                            ' component is located within.
                            Dim SubAssyOccItemNumber As Long
                            SubAssyOccItemNumber = 1
                            
                            ' Now we'll go down one level into the current sub-assembly component and check its 
                            ' sub-components for a matching component name.
                            For Each oSub2AssyCompOcc In oSub2AssyCompDef.Occurrences
                                If oSub2AssyCompOcc.Name = vCurrentCompName Then
                                    ' If the current oSub2AssyCompOcc's definition document type is that of an 
                                    ' assembly document, we'll check its contents to ensure that it contains 
                                    ' components that can actually be made invisible before proceeding.  This is 
                                    ' done to avoid the run-time error that we get when we attempt to hide a 
                                    ' sub-assembly component that's simply an empty placeholder component.
                                    ' These placeholder components are in the assembly component solely to have 
                                    ' its iProperties included on the B.O.M., so we're not to be concerned with 
                                    ' hiding them.
                                    If oSub2AssyCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then
                                        Dim oSub3AssyCompDef As AssemblyComponentDefinition
                                        Set oSub3AssyCompDef = oSub2AssyCompOcc.Definition
                                        ' We'll pass all of the necessary info on to our CheckAndHideSubAssyComps() 
                                        ' sub-routine to recursively scan the rest of the sub-assembly layers to 
                                        ' find & hide the user-specified component.
                                        Call CheckAndHideSubAssyComps(oView, oSub3AssyCompDef, oSub1AssyCompDef, AssyOccItemNumber, SubAssyOccItemNumber)
                                    ' If the current oSub2AssyCompOcc is NOT an assembly document object, then we 
                                    ' just hide it; it's likely just a part component.
                                    ElseIf oSub2AssyCompOcc.DefinitionDocumentType <> kAssemblyDocumentObject Then
' HERE is my fix. This'll keep us from getting an error if the current oSub2AssyCompOcc is an empty placeholder component. If oSub2AssyCompOcc.SurfaceBodies.Count > 0 Then
' We'll create a proxy of our component so that we can properly tell oView ' to hide it. Dim oSubCompProxy As ComponentOccurrenceProxy Set oSubCompProxy = oSub1AssyCompDef.Occurrences.Item(AssyOccItemNumber).SubOccurrences.Item(SubAssyOccItemNumber) ' Toggle visibility of components in subassembly. If oView.GetVisibility(oSubCompProxy) = True Then Call oView.SetVisibility(oSubCompProxy, False) End If End If
End If End If SubAssyOccItemNumber = SubAssyOccItemNumber + 1 Next End If '================================== ' Single Component Hiding Block End '================================== '=================================== ' Batch Component Hiding Block Begin '=================================== ' If a colon is NOT present in sCompName's value, then we run this ElseIf-Then code block to ' find & hide all occurrences of the specified component part number. ElseIf bIsCompName1Occ = False Then ' First, we need to take the current oSub1AssyCompOcc's name and split it into an array. ' - sCompOccName(0) will contain the oSub1AssyCompOcc's part number. ' - sCompOccName(1) will contain the oSub1AssyCompOcc's occurrence number. Dim sCompOccName() As String sCompOccName() = Split(oSub1AssyCompOcc.Name, ":") ' sCompOccName(0) = "1003UA30055-WT"; sCompOccName(1) = "1" ' If the current oSub1AssyCompOcc's part number matches the user-specified component, ' then we proceed as normal and hide the current oSub1AssyCompOcc. If sCompOccName(0) = vCurrentCompName Then ' Returns True If oView.GetVisibility(oSub1AssyCompOcc) = True Then Call oView.SetVisibility(oSub1AssyCompOcc, False) End If End If ' If the current oSub1AssyCompOcc's name doesn't match the user-specified component AND ' it's an assembly component that is not suppressed, then we dive deeper to search the ' components within oSub1AssyCompOcc. If oSub1AssyCompOcc.Definition.Type = kAssemblyComponentDefinitionObject Then ' This variable gets the assembly component definition of the current oSub1AssyCompOcc ' object. Set oSub2AssyCompDef = oSub1AssyCompOcc.Definition ' This variable will keep count of which sub-assembly component item our specified ' component is located within. SubAssyOccItemNumber = 1 For Each oSub2AssyCompOcc In oSub2AssyCompDef.Occurrences Dim sSubCompOccName() As String sSubCompOccName() = Split(oSub2AssyCompOcc.Name, ":") ' sSubCompOccName(0) = "1003EG031"; sSubCompOccName(1) = "1" If sSubCompOccName(0) = vCurrentCompName Then ' If the current oSub2AssyCompOcc's definition document type is that of an ' assembly document, we'll check its contents to ensure that it contains ' components that can actually be made invisible before proceeding. This is ' done to avoid the run-time error that we get when we attempt to hide a ' sub-assembly component that's simply an empty placeholder component. ' These placeholder components are in the assembly component solely to have ' its iProperties included on the B.O.M., so we're not to be concerned with ' hiding them. If oSub2AssyCompOcc.DefinitionDocumentType = kAssemblyDocumentObject Then Set oSub3AssyCompDef = oSub2AssyCompOcc.Definition ' We'll pass all of the necessary info on to our CheckAndHideSubAssyComps() ' sub-routine to recursively scan the rest of the sub-assembly layers to ' find & hide the user-specified component. Call CheckAndHideSubAssyComps(oView, oSub3AssyCompDef, oSub1AssyCompDef, AssyOccItemNumber, SubAssyOccItemNumber) ' If the current oSub2AssyCompOcc is NOT an assembly document object, then we ' just hide it; it's likely just a part component. ElseIf oSub2AssyCompOcc.DefinitionDocumentType <> kAssemblyDocumentObject Then ' We'll create a proxy of our component so that we can properly tell oView ' to hide it. Set oSubCompProxy = oSub1AssyCompDef.Occurrences.Item(AssyOccItemNumber).SubOccurrences.Item(SubAssyOccItemNumber) ' Toggle visibility of components in subassembly. If oView.GetVisibility(oSubCompProxy) = True Then Call oView.SetVisibility(oSubCompProxy, False) End If End If End If SubAssyOccItemNumber = SubAssyOccItemNumber + 1 Next End If Else MsgBox ("ERROR: Invalid value for bIsCompName1Occ variable.") End If '================================= ' Batch Component Hiding Block End '================================= End If AssyOccItemNumber = AssyOccItemNumber + 1 Next lViewCounter = lViewCounter + 1 Wend Next End Sub

 

To answer your other question, yes you can control which views that the Sub FindAndHideComponents() sub-routine affects.  The lViewCounter variable is the key to controlling which views that the sub-routine will affect.  Currently, I have it set to a value of "1" when the sub-routine is executed; as the Sub FindAndHideComponents() sub-routine goes through its For Each vCurrentCompName In sCompNameArray()...Next loop, it resets the lViewCounter variable to a value of "1", and runs through Views 1-5 via its While lViewCounter <= 5...Wend loop.  You simply need to slightly alter these variables & loops to only affect the views you want to affect in your drawing.

 

For example, let's assume that your drawing actually has something like 7 views in it, and you only want to affect views 5-7.  You could simply alter the Sub FindAndHideComponents() sub-routine like so:

Sub FindAndHideComponents(sCompName As String)

'.....

    Dim vCurrentCompName As Variant
    For Each vCurrentCompName In sCompNameArray()
        ' We reset our lViewCounter to 5.
        lViewCounter = 5

'.....
        
        ' This While-Wend loop will scan VIEW5 thru VIEW7 for the specified component, and then hide it if it's found.
        While lViewCounter <= 7
            Set oView = oSheet.DrawingViews.Item(lViewCounter)

'.....

        Wend
    Next
End Sub

Of course, you can apply the same adjustment to your Sub FindAndUnhideComponents() sub-routine, as well.

 

I hope this helps you out.  If it works for you, do me a favor and click the Kudo button for me.  Thanks for giving me the opportunity to help you out!  😃

 

- Sincerely,

Vinny

 

0 Likes
Message 6 of 8

Anonymous
Not applicable

This is awesome! MY big question is if I want to dumb it down and just have iLogic or just have it hid everything not in a certain folder how would I do that??

0 Likes
Message 7 of 8

bert.maesBK6NX
Explorer
Explorer

Hello,

I am that noob from the future that is looking for somethink like this code but simpler, i think.

 

I need some vba code to hide certain parts (easy) but these parts are nested in subassemblies. 

If possible I want to create a custom button to hide certain parts (selection through name) in de 3D environnement. 

And code that runs along my autodrawing button that hides the parts i dont want to see in the 2D. 

 

What parts of the code do I need for only selection occurrences with some name and hide these?

 

Kind regards

 

Bert 

 

0 Likes
Message 8 of 8

WCrihfield
Mentor
Mentor

Hi @bert.maesBK6NX.  You may need to explain your situation in much more detail, and what you want the code to do in much more detail, so we can better understand, and offer better solutions.  You mentioned "selection through name"...what do you mean by that?  Do want the code to examine your active assembly, then create a list of all top level component names, then show you that list, so you can choose a name from the list?  Or do you want something like an InputBox (an extremely simple dialog for typing in data) so you can enter a component name?

 

The other things to be aware of in this type of situation are Design View Representations (DVRs) and Level Of Detail Representations (LODs) (or ModelStates in 2022) settings, which may be set-up (and enforced), not only in the main assembly, but also at each sub-assembly level.  The DVRs record visual aspects like color/appearance and visibility, while LODs record suppression (and ModelStates record component suppression, feature suppression, parameters, iProperties, and more).  It can get complicated if you are using these things heavily and want to maintain their accuracy.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes