12 Replies Latest reply on Feb 12, 2019 1:54 AM by Keith Rice

    Get Child Component

    Di Anne

      Hi SW Community,

       

      Im am currently working on a macro that will get all the components inside a sub-assembly..

      But I need to get them on how they are arranged in the assembly.

      So I used the Feature function, but when I get the component inside the sub assembly I cannot

      cast it to component even though I already check if its component or not.

       

      Here's my code.

      Feature swFeat = (Feature)swModel.FirstFeature();

       

      while((swFeat != null)\
      {
      Entity entity = (Entity)swFeat;
      // check if component
       if (entity.GetType() == (int)swSelectType_e.swSelCOMPONENTS)
      {
       Component2 comp = (Component2)swFeat.GetSpecificFeature2();
      if (!comp.ExcludeFromBOM & !comp.IsSuppressed())
       {
      Feature swSubFeat = (Feature)((ModelDoc2)comp.GetModelDoc2()).FirstFeature();
      
      while ((swSubFeat!= null))
      {
      if (((Entity)swSubFeat).GetType() == (int)swSelectType_e.swSelCOMPONENTS)
      {
      /// I have a problem in casting the swSubFeat into component
      Component2 subComp = (Component2)swSubFeat.GetSpecificFeature2();
      }
      swSubFeat= (Feature)swSubFeat.GetNextSubFeature();
      }
      }
      }
      
      swFeat = (Feature)swFeat.GetNextFeature();
      }
      

       

       

      Does anyone know why I cant cast the swSubFeat into component even though I already checked if the feature is component or not?

       

       

      Thanks in advance.

       

      Regards,

      DiAnne

        • Re: Get Child Component
          Simon Turner

          I don't think this line is right:

          if (((Entity)swSubFeat).GetType() == (int)swSelectType_e.swSelCOMPONENTS)

          I think you need to use swSubFeat.GetTypeName2 and check that instead.

           

          • Re: Get Child Component
            Jesse Seger

            You have to get the component from the Entity.  Try entity.GetComponent()

            • Re: Get Child Component
              Keith Rice

              You're running into the bug documented in SPR 853484, which has caused me a lot of problems in some of my projects. I ask that you please email apisupport@solidworks.com and ask that your name be added to the notification list for this bug. That will effectively act as a vote for getting it fixed.

               

              I have documented the bug in great depth here. You can use that information to try to write your own workaround, if you wish. For example, if you open the target sub-assembly in the background, the bug will not appear.

               

              In my Macro Library, paying customers can download a macro I wrote called "Traverse components in order" that demonstrates how to deal with this bug. It took a very long time to write, which is why do I not offer it for free. If you want to purchase it by itself without having to get a full membership to my site, please email me.

               

              The key function in the macro is called GetComponents.

               

              Arguments:

              • model as ModelDoc2 - The active ModelDoc2
              • targetAssembly as Component2 - The desired sub-assembly. If you pass in Nothing, it will use the top-level assembly.
              • topLevelOnly as Boolean - True to get all components or just the top-level ones. Using recursion to get sub-components.

               

              Return value is a variant array of Component2 objects.

               

              As you can see, this function mirrors IAssemblyDoc2::GetComponents except 1) it handles SPR 853484, 2) it returns components in the order they appear in the feature tree.

               

              Keith

              SolidWorks API Training and Services

              • Re: Get Child Component
                Jana Stahn

                Hi Di Anne,

                I ran into the problem myself and found a workaround:

                 

                Before you start traversing the features, just call IAssemblyDoc.GetComponents(true) once (need to cast the IModelDoc2 into IAssemblyDoc for that). You do not need to do anything with its return value. This seems to do some internal things making sure that the data is actually there.

                  • Re: Get Child Component
                    Jana Stahn

                    Turned out that the following method gives all components in order*:

                     

                    public static IComponent2[] GetChildComponentsOrdered(this IAssemblyDoc assyDoc)
                    {
                        object[] comps = assyDoc.GetComponents(true);
                        return comps.Select(c => (IComponent2)c).OrderBy(c => c.GetID()).ToArray();
                    }
                    

                     

                    *Note that this is the model definition order, i.e. the order in which objects (components) were put into the assembly. This does not reflect the feature tree order which can change over time (as the user reorders the items). If feature tree order is important, use IModelDoc.FeatureManager.GetFeatureTreeRootItem2((int)swFeatMgrPane_e.swFeatMgrPaneBottom) and the ITreeControlItem interface (GetFirstChild, GetNext, ObjectType to determine if component and Object to get IComponent2 or IFeature). But there are similar problems with non-active assemblies: GetFeatureTreeRootItem2 will return null, not allowing you to traverse. Check Get assembly top level components in correct feature tree order  and Traversing doesn't work when the file is not visible.