Need help editing nested sub-assembly component design view

Need help editing nested sub-assembly component design view

CamperUnhappy
Advocate Advocate
1,461 Views
14 Replies
Message 1 of 15

Need help editing nested sub-assembly component design view

CamperUnhappy
Advocate
Advocate

I've been trying to figure this out on my own for 3 days now and still not having much luck.  Most of the examples that I've found don't go into enough detail or use iLogic which doesn't help me to understand how to actually do what I need to do in my Add-In using VB.NET.

 

 

I have a tool where would like to set all parts and sub-assemblies (and their sub-components) to a specific design view that matches the name of the top level assy Design View Rep name.  First I look through all the LeafOccurrences to make sure all the parts have a specific DVR that matches the top level DVR name.  If not, it opens the part and creates it, then closes it.  Then comes the issue where if a sub-assembly doesn't have the specific DVR with the matching name, I get how to create an Assy DVR, but I don't understand how to create the Sub-Assembly DVR and that actually contains the sub-components with THEIR appropriate DVR.    When I try SetDesignViewRepresentation on the sub-assembly, the sub-components change the "Master"   When I change a suboccurrence to it's appropriate DVR, the assembly changes.  I've tried creating proxies and changing proxies, substituting proxies.  Nothing seems to behave like right clicking on the browser and clicking "Representation..."   <===  this is exactly the functionality I want to mimic but the API behaves much differently.

 

 

I mostly have a good grasp on the concept of ComponentOccurrences and ComponentOccurrentProxies.  The issue that I'm struggling to nail down is how to actually properly create a DVR for a sub-assembly which contains the appropriate part DVRs.

 

 

Here's an example to try and clarify:

 

Change Parent Assy DVR to "BRANDNEW" (whether existing or new)

Go through all sub-assemblies and parts to make sure all Parts are set to "BRANDNEW" and Sub-Assemblies are set to "BRANDNEW"

Check through all sub-assemblies to make sure all their parts are set to "BRANDNEW"  (if not do so)

If any of the parts or assemblies do not contain a DVR named "BRANDNEW" create them.

 

Before Running tool:

BRANDNEW (Top Level Assy)

---Default (Sub Assy)

     ---Master (Part)

     ---Editing (Sub Assy)

           ---Master (Part)

           ---Master (Part)

          ---Default (Part)

    ---BRANDNEW (Part)

After Running tool:

BRANDNEW (Top Level Assy)

---BRANDNEW (Sub Assy)

     ---BRANDNEW (Part)

     ---BRANDNEW (Sub Assy)

           ---BRANDNEW (Part)

           ---BRANDNEW (Part)

           ---BRANDNEW (Part)

     ---BRANDNEW (Part)

1,462 Views
14 Replies
Replies (14)
Message 2 of 15

WCrihfield
Mentor
Mentor

It sounds to me like you need to dig down to your deepest level part files and set their DVR's first, then work your way back up through the levels, to make this scenario work.

It would likely be a lengthy code, checking each level for document type (to see if you're at the part level yet), or if its an assembly.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 15

tdant
Collaborator
Collaborator

Firstly, kudos to you for crafting a well-explained question. That's increasingly rare on these forums lately.

 

When you edit a subassembly's DVR, are you explicitly opening the assembly document? The way to make changes to an assembly's DVR is to open that assembly file, activate the DVR you want to change, make the changes, then save before changing the assembly's active DVR.

 

Any chance you're able to post your code so far?

0 Likes
Message 4 of 15

CamperUnhappy
Advocate
Advocate

@WCrihfield wrote:

It sounds to me like you need to dig down to your deepest level part files and set their DVR's first, then work your way back up through the levels, to make this scenario work.

It would likely be a lengthy code, checking each level for document type (to see if you're at the part level yet), or if its an assembly.

I've definitely tried this and it does not work as intuitively as you'd think.   If I open a sub-assy and set it to a BRANDNEW DVR, all of the components could be set to DVR, but then when I try to set the DVR of this sub-assy in a parent assembly, the sub-components don't match what the assembly shows despite the DVR being set as "associative"

 

The length of the code doesn't scare me, I just need to figure out how to make it work and I've tried many many things.

 

 

@tdant  wrote:

Firstly, kudos to you for crafting a well-explained question. That's increasingly rare on these forums lately.

 

When you edit a subassembly's DVR, are you explicitly opening the assembly document? The way to make changes to an assembly's DVR is to open that assembly file, activate the DVR you want to change, make the changes, then save before changing the assembly's active DVR.

 

Any chance you're able to post your code so far?


Thanks very much, it's a bit of a convoluted task, so I wanted to be sure I was explaining it clearly.

 

Yes, I've tried editing the sub-assy DVR by opening it explicitly and changing it in there.  The issue is, the sub-assy DVR isn't the same as the DVR in the Parent Assembly and I have a feeling it has to do with proxies and context of how ComponentOccurrence's are being created.

 

I can't really post my code at the moment because it's a disaster from trying so many different things.

 

 

0 Likes
Message 5 of 15

tdant
Collaborator
Collaborator

Hey, messy code is just inherent to programming, don't be afraid to show your work.

 

Here's a proof of concept I whipped up. This code...

 

Sub DVRs()
    Dim topAsm As AssemblyDocument
    Set topAsm = ThisApplication.ActiveDocument
    
    Call topAsm.ComponentDefinition.RepresentationsManager.DesignViewRepresentations.Add("NoAs").Activate
    
    Dim newDVRAsms() As String
    ReDim newDVRAsms(0)
    
    Dim gDoc As Document
    Dim gOcc As ComponentOccurrence
    For Each gDoc In topAsm.AllReferencedDocuments
        If gDoc.DocumentType <> kAssemblyDocumentObject Then GoTo NextgDoc
        
        Dim subAsm As AssemblyDocument
        Set subAsm = gDoc
        
        ReDim Preserve newDVRAsms(UBound(newDVRAsms) + 1)
        newDVRAsms(UBound(newDVRAsms)) = subAsm.FullFileName
        
        Call subAsm.ComponentDefinition.RepresentationsManager.DesignViewRepresentations.Add("NoAs").Activate
        
        For Each gOcc In subAsm.ComponentDefinition.Occurrences
            If InStr(gOcc.Name, "A") Then
                gOcc.Visible = False
            End If
        Next
NextgDoc:
    Next
    
    For Each gOcc In topAsm.ComponentDefinition.Occurrences
        If InArray(gOcc.Definition.Document.DisplayName, newDVRAsms) Then
            Call gOcc.SetDesignViewRepresentation("NoAs", Associative:=True)
        End If
    Next
End Sub

Function InArray(targetText As String, searchArray() As String) As Boolean
    For i = 0 To UBound(searchArray)
        If InStr(searchArray(i), targetText) Then
            InArray = True
            Exit Function
        End If
    Next
End Function

 

 ...turns this...

Before.PNG

...into this...

After.PNG

 

Granted, this is all VBA, but anything that can be done in VBA can be done better in VB.Net.

 

I think you may have gone a little too far down the rabbit hole when you got into proxies and whatnot.

0 Likes
Message 6 of 15

CamperUnhappy
Advocate
Advocate

Thanks so much for putting that together.  I'll give it a try today and see if it's going to do what I want.

 

 

I went down the rabbit hole because I've written and re-written this piece of code at least 3-4 times after thinking I had it working properly.  But in practice (out of the sandbox) it wasn't working.  The assemblies would change to the correct DVR, but all sub-components in them would change to Master.  However, when I opened the sub-assembly separately, all components had their DVR match the opened sub-assy DVR.

 

 

I'll report back on whether this is going to work or not.

Message 7 of 15

CamperUnhappy
Advocate
Advocate

@tdant 

 

I tried out your code and it's not quite doing what I explained in the first post.  I ended up taking what you had and using a few ideas to write some new code.  Even with this new piece, it's STILL not doing what you'd expect.....  It must have something to do with proxies or context.

 

 

keep in mind, this is very rough. It was just a skeleton to be used as a proof-of-concept.

Public Sub DVRMatch()

Dim assyDoc As AssemblyDocument
Set assyDoc = ThisApplication.ActiveDocument

Dim assyDef As AssemblyComponentDefinition
Set assyDef = assyDoc.ComponentDefinition

Dim assyRepMan As RepresentationsManager
Set assyRepMan = assyDef.RepresentationsManager

Dim assyDvrName As String
Let assyDvrName = assyDef.RepresentationsManager.ActiveDesignViewRepresentation.Name

Dim assyOccs As ComponentOccurrences
Set assyOccs = assyDef.Occurrences

Dim assyLeafs As ComponentOccurrencesEnumerator
Set assyLeafs = assyOccs.AllLeafOccurrences

Dim leafOcc As ComponentOccurrence
For Each leafOcc In assyLeafs
    Dim openPart As PartDocument
    Set openPart = ThisApplication.Documents.Open(leafOcc.Definition.Document.FullFileName, False)
    
    Dim partRepMan As RepresentationsManager
    Set partRepMan = openPart.ComponentDefinition.RepresentationsManager
    
        Dim dvrFound As Boolean
        Let dvrFound = False
        
        Dim dvr As DesignViewRepresentation
        For Each dvr In partRepMan.DesignViewRepresentations
            If dvr.Name = assyDvrName Then
                Let dvrFound = True
                Exit For
            End If
        Next

        If Not dvrFound Then
            Dim newDvr As DesignViewRepresentation
            Set newDvr = openPart.ComponentDefinition.RepresentationsManager.DesignViewRepresentations.Add(assyDvrName)
        Else
            openPart.ComponentDefinition.RepresentationsManager.DesignViewRepresentations(assyDvrName).Activate
        End If

    Call openPart.Update2(True)
    Call openPart.Close(True)
Next

Dim occ As ComponentOccurrence
For Each occ In assyOccs

    Dim assyOccDoc As AssemblyDocument
    Set assyOccDoc = ThisApplication.Documents.Open(occ.Definition.Document.FullFileName, False)
    
    Dim subAssyDvrFound As Boolean
    Let subAssyDvrFound = False
    
    Dim subDvr As DesignViewRepresentation
    For Each subDvr In assyOccDoc.ComponentDefinition.RepresentationsManager.DesignViewRepresentations
        If subDvr.Name = assyDvrName Then
            Let subAssyDvrFound = True
            Exit For
        End If
    Next
    
    If Not subAssyDvrFound Then
        Call assyOccDoc.ComponentDefinition.RepresentationsManager.DesignViewRepresentations.Add(assyDvrName)
    Else
        Call assyOccDoc.ComponentDefinition.RepresentationsManager.DesignViewRepresentations(assyDvrName).Activate
    End If
    
    Dim subOcc As ComponentOccurrence
    For Each subOcc In assyOccDoc.ComponentDefinition.Occurrences
        Call subOcc.SetDesignViewRepresentation(assyDvrName, , True)
    Next
    
    assyOccDoc.Update2 (True)
    assyOccDoc.Close (True)
Next


Dim topLevelOcc As ComponentOccurrence
For Each topLevelOcc In assyOccs
    Call topLevelOcc.SetDesignViewRepresentation(assyDvrName, , True)
Next

End Sub

 

 

So it goes and opens up ALL leaf occurrences and adds a DVR.  Then opens up all sub-assemblies and sets the component DVRs to match the name of the DVR in the highest level assy.  Then creates a DVR for the assembly that matches the top level DVR.  Then sets each sub-assembly occurrence DVR to match the top level DVR name.

 

 

The result.....  (The Sub-assy components still do not match the DVR of the sub-assy if opened independantly)

 

BRANDNEW

      BRANDNEW

            Master

            Master

            Master

      BRANDNEW

            Master

            Master

            Master

      BRANDNEW

            Master

            Master

            Master

 

 

When I open up each Sub-Assembly  (Looks how you'd expect and how I want)

BRANDNEW

      BRANDNEW

      BRANDNEW

      BRANDNEW

 

 

 

0 Likes
Message 8 of 15

WCrihfield
Mentor
Mentor

Just letting you know I saw a few places within your latest posted code where you used "Let" instead of "Set".

I assume those are just typing errors, as I don't recall any use for that term.

  • the line setting the value of "assyDvrName"
  • line setting "dvrFound = False"
  • line setting "dvrFound = True"
  •   line setting "subAssyDvrFound = False"
  • line setting "subAssyDvrFound = True"

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 9 of 15

tdant
Collaborator
Collaborator

@WCrihfield, "Let" is a leftover VB6 artifact. It used to be required, but isn't anymore. It works fine, but is unnecessary. Basically, it was "Set", but for non-object variables (strings, longs, doubles, etc.).

 

@CamperUnhappy, I tried your code as-is on my ABC assembly, and it worked like a charm! It's not very efficient, as I'm sure you know, but it gets the job done. However, it's hard to tell it actually worked on the level of sub-assembly component parts from the top assembly file. After running your code, when you open a sub-assembly, you should have the new DVR activated, and each component should have its own new DVR active. Is that the case for you? If so, try making a visible change to the component part DVR (like hide the solid body) and then see if that affects the top assembly. Here are my screenshots after running your code:

Top Level.PNGSub-Assembly.PNGPart.PNG

0 Likes
Message 10 of 15

CamperUnhappy
Advocate
Advocate

@tdant   yes that code is pretty rough.  It was basically just to test the proof of concept out.

 

The code does everything I want it to......except at the top-level assembly.  In the Top-Level, the Sub-Assy DVR is being set to match (as intended), but it's not changing any of the sub-occurrences to match how the DVR looks if that Sub-Assembly was opened on it's own.

 

 

I tried to explain this to my co-worker the other day when asked what I was doing and here's the analogy I chucked out on the spot:

 

Think of my top level assembly as a clear shopping bag and all of the sub-assemblies as bags of chips.

 

I want to label the clear bag "Salt & Vinegar" and go through and make sure all the bags of chips inside are S&V and also make sure that all of the chips inside of the bags are S&V.   So far, I'm able to make all the individual chips S&V, and I'm able to look at the bags individually as S&V with all the chips inside being S&V.......  But for some reason in my main grocery bag that is labelled S&V.........the chip bags say S&V but the chips inside are BBQ.   Not the desired result.

 

 

From what I can tell, this operation in the API falls apart when I get to the ComponentOccurrenceProxy level inside of the top level assembly.  So this is why I think it has to do with Proxies or Context.  The thing is, there are no examples of anything similar to what I'm trying to accomplish.  In fact most of the information regarding proxies at all has to do with geometry and bodies.   I fear that to make this work I'm going to have to try and traverse the browser (which is a lot of work) and then interact with the selections using Inventor user commands so it was as-if I was right-clicking on the selection and changing the representation from there.

0 Likes
Message 11 of 15

tdant
Collaborator
Collaborator

So my assembly is behaving differently than yours when the same code runs over it? Check out my first screenshot in the previous post. The top assembly, called "ABCs" is the clear shopping bag, and the first subassembly occurrence, "ABC:1", is the first S&V chip bag. In my case, both were set to the new DVR, called "DVRText".

 

Are you able to upload the files you're working on?

0 Likes
Message 12 of 15

CamperUnhappy
Advocate
Advocate

You're still not following me on where the problem is coming in.

 

I can always get the immediate occurrences in a top level assembly to match the top level assembly.  That's never been the problem.  The problem is that the salt&vinegar bags that are opened while still inside of the grocery bag are NOT S&V..........but if I took that bag out of the grocery bag and opened it, they would be S&V.

 

Grocery Bag (Labeled Salt & Vinegar)

        Loose chip (Salt & Vinegar)

        Whole Bag of chips (Bag says Salt & Vinegar)  --------> Out of Grocery Bag:     Whole Bag (Salt & Vinegar)

              chip from bag (Barbeque)                                                                                                 chip from bag (Salt & Vinegar)

              chip from bag (All-Dressed)                                                                                             chip from bag (Salt & Vinegar)

              chip from bag (Ripple)                                                                                                       chip from bag (Salt & Vinegar)

 

 

0 Likes
Message 13 of 15

tdant
Collaborator
Collaborator

You're right, I don't think I understand the problem you're having. I'm afraid I've gone as far as I can go without seeing your problem more directly. Hopefully something here has helped.

0 Likes
Message 14 of 15

CamperUnhappy
Advocate
Advocate

@tdant   I appreciate the help.  Thank you.

 

The issue is, if the chip bag on it's own says Salt & Vinegar and all the chips inside ARE Salt & Vinegar.........then why does the same bag inside of the grocery bag not contain Salt & Vinegar?   Why should the assembly be any different inside of a parent assembly than it is on it's own if all of the occurrences in it are set to "associative" ??

 

 

Would you not be confused if a thing that you specifically set to one thing was then suddenly different all because you put it inside of a container?

 

 

Going back to your ABC Example.....    If you right click on an A, B, or C inside of a sub-assembly in the top-level ABCs assembly,  then go "Representation..."  the current representation that shows up is "Master"......which does NOT match the sub-assembly that it's in, nor does it match the top level.   Yet if you open the ABC, BAC, or CBA sub-assembly on it's own, all of the A, B, C representations would match it's parent DVR.

0 Likes
Message 15 of 15

WCrihfield
Mentor
Mentor

Hi @CamperUnhappy.  In response to your last post, where you said when you right click on the sub-assembly, then Representations, it was still showing "Master".  It sounds like you need to either set that associative check box manually for each Occurrence within the main assembly, or you need to have it set up so that they are already associative when you insert them.

There is a setting under Application Options / File tab, at the bottom [File Open] Options, where you can specify this behavior.

As far as automating this after the fact, I'm pretty sure its not possible right now.  I was in another post a while back where an Autodesk employee joined in the discussion where they were talking about the Associative setting.

He said you can turn off the Associative setting, within the code, but can't turn it back on right yet, because it gets pretty complicated to accomplish this reassociate task.

Another post by an Autodesk employee said that "in theory" when you call ActiveDesignViewRepresentation, and it is not associative, it will return an emply or null string.  And that setting ActiveDesignViewRepresentation to a null string should uncheck the associative box.  So sending a non-null string to the ActiveDesignViewRepresentation should check the box.  But I never heard any conclusions as to if this works, and I've never tried it.

But its worth a shot.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes