How to find all deeply nested components in the given family instance?

How to find all deeply nested components in the given family instance?

Anonymous
Not applicable
5,224 Views
14 Replies
Message 1 of 15

How to find all deeply nested components in the given family instance?

Anonymous
Not applicable

Hello!
I'm a beginner and I have a problem with retrieving nested families.
I have family instance that contains 7 subcomponents. I'm trying familyInstance.GetSubComponentsIds(), but as a result I have only 5 subcomponents. All "Shared" parameters in checked state.
What I'm doing wrong and how to find all components inside family instance? I will be grateful for any advice!

0 Likes
Accepted solutions (1)
5,225 Views
14 Replies
Replies (14)
Message 2 of 15

RPTHOMAS108
Mentor
Mentor

Are the two shared items you don't find subcomponents to a subcomponent and not the root?

0 Likes
Message 3 of 15

Anonymous
Not applicable

I'm not sure, but in the given family for example I'm retrieving everything except Nord-Lock Rings.

image.png

0 Likes
Message 4 of 15

RPTHOMAS108
Mentor
Mentor

Those family instances within the family have visibility assigned from instance parameters '1st Nord-Lock Ring' & '2nd Nord-Lock Ring' in turn those are driven by formulas with a default no value.

 

Invisible objects are not subcomponents I suspect.

 

If you need to find all seven then they are within the FamilyDocument as FamilyInstance objects, there is no nesting in this example (just visibility/scheduling project document functionality).

0 Likes
Message 5 of 15

jeremytammik
Autodesk
Autodesk
0 Likes
Message 6 of 15

Kevin.Lawson.PE
Advocate
Advocate

Post some code so we can see what you're doing.  It could be the elements you are missing are subcomponents of subcomponents.  If that's the case you'll need to create a queue to continue to search subcomponents for subcomponents until you find them all. 

-Kevin Lawson, PE
www.rippleengineeringsoftware.com
Revit heating and cooling load calculations in one click!
0 Likes
Message 7 of 15

Anonymous
Not applicable

It's my code. I just pick object and try to call GetSubComponentsIds().

public class Command : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string 
        message, ElementSet elements)
    {
        UIApplication uiapp = commandData.Application;
        UIDocument uidoc = uiapp.ActiveUIDocument;
        Application app = uiapp.Application;
        Document doc = uidoc.Document;
        try
        {
            Reference pickedObj = 
  uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
            if (pickedObj != null)
            {
                ElementId elementId = pickedObj.ElementId;
                Element element = doc.GetElement(elementId);
                FamilyInstance familyInstance = element as FamilyInstance;
                ICollection<ElementId> subElementsSet = 
 familyInstance.GetSubComponentIds();

                using (Transaction tx = new Transaction(doc))
                { 
                    tx.Start("Get subcomponents name");
                    foreach (ElementId eId in subElementsSet)
                    {
                        Element elem = doc.GetElement(eId);
                        FamilyInstance f = 
 familyInstance.Document.GetElement(eId) as FamilyInstance;
                        TaskDialog.Show("Info", string.Format("{0} - name", 
 f.Name));
                    }
                    tx.Commit();
                }
           }
        }
        catch
        {
             TaskDialog.Show("Error!", "smth was wrong");
        }
        return Result.Succeeded;
    }
}

 

0 Likes
Message 8 of 15

Kevin.Lawson.PE
Advocate
Advocate

Search for nested subcomponents using a queue like this:

 

Queue<FamilyInstance> fQueue = new Queue<FamilyInstance>();
while (fQueue.Count > 0)
{
    FamilyInstance currentQueueFamilyInstance = fQueue.Dequeue();
    ICollection<ElementId> subElementsSet = currentQueueFamilyInstance.GetSubComponentIds();
    foreach(ElementId elementId in subElementsSet)
    {
        fQueue.Enqueue(doc.GetElement(elementId) as FamilyInstance);
    }

    askDialog.Show("Info", string.Format("{0} - name", currentQueueFamilyInstance.Name));

}
-Kevin Lawson, PE
www.rippleengineeringsoftware.com
Revit heating and cooling load calculations in one click!
0 Likes
Message 9 of 15

Anonymous
Not applicable

Thank you for help, but it doesn't find all components anyway 😞 

0 Likes
Message 10 of 15

RPTHOMAS108
Mentor
Mentor
Accepted solution

You find the ones that are visible i.e. in the project the shared nested families only exist as subcomponents if they are visible. This is logical otherwise how could you rely on that method for determining how many of something you have?

 

If you want to find all seven as stated they exist as FamilyInstances in the family document, edit family and inspect (Document.EditFamily). Getting nested elements on the other hand (which these are not) is just a matter of forming a recursive function.

0 Likes
Message 11 of 15

Anonymous
Not applicable

I've tested this sample. It returns 5 instances. 

Reference pickedObj = uidoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
                if (pickedObj != null)
                {
                    ElementId elementId = pickedObj.ElementId;
                    Element element = doc.GetElement(elementId);
                    FamilyInstance familyInstance = element as FamilyInstance;

                    IList<Element> nested = new List<Element>();

                    Family family = familyInstance.Symbol.Family;
                    Document familyDoc = doc.EditFamily(family);
                    if(familyDoc != null && familyDoc.IsFamilyDocument == true)
                    {
                        FilteredElementCollector coll = new FilteredElementCollector(doc);
                        ICollection<Element> collection = coll.OfClass(typeof(FamilyInstance)).ToElements();

                        //TaskDialog.Show("count", string.Format("{0}", collection.Count));
                        foreach (Element ele in collection)
                        {
                            FamilyInstance fi = ele as FamilyInstance;
                            if(fi.Name.Contains(familyInstance.Name))
                            {
                                nested.Add(ele);
                            }
                            //TaskDialog.Show("names", string.Format("{0}", fi.Name));
                        }
                    }
                    TaskDialog.Show("count", string.Format("{0}", nested.Count));
                }

 

0 Likes
Message 12 of 15

RPTHOMAS108
Mentor
Mentor

Yes, that is because you are filtering the project document {FilteredElementCollector(doc)} not the family document {FilteredElementCollector(familyDoc)}.

 

You can review in RevitLookup, it's a quite useful add-in.

Message 13 of 15

Anonymous
Not applicable

Thank you so much! 

0 Likes
Message 14 of 15

Dronov.Dmitry
Advocate
Advocate

So if family inside family is not shared we dont have any possibility to find it?

DronovDmitry_0-1672780027062.png

 

0 Likes
Message 15 of 15

jeremy_tammik
Alumni
Alumni

I think you can retrieve all nested families by recursively opening their family definition using EditFamily and retrieving the nested families as embedded family definitions and instances within the upper-level family definition:

  

https://thebuildingcoder.typepad.com/blog/2009/05/nested-instance-geometry.html

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes