How to create customized schedule including the nested family Instances in Revit.

How to create customized schedule including the nested family Instances in Revit.

theknownsilhouette
Enthusiast Enthusiast
916 Views
8 Replies
Message 1 of 9

How to create customized schedule including the nested family Instances in Revit.

theknownsilhouette
Enthusiast
Enthusiast

Hi Folks,

I've placed only one instance (a family of generic Models category) in my Revit project. Basically, this family is a window assembly made of some other families hence this Family has some nested families (all are of generic model category) in it.

Now using Revit API I want to create a customizes schedule in which I can display count of all the individual nested families (instances). I've attached the family as well. Though I tried but didn't succeed. Can you suggest something?

Thanks for your valuable time! 

0 Likes
Accepted solutions (1)
917 Views
8 Replies
Replies (8)
Message 2 of 9

theknownsilhouette
Enthusiast
Enthusiast

I've tried below code.

 

class ScheduleCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            Document doc = commandData.Application.ActiveUIDocument.Document;
                        FamilyInstance assemblyInstance = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).WhereElementIsNotElementType().Cast<FamilyInstance>().FirstOrDefault(x => x.Symbol.FamilyName.Equals("Sample Window Family"));

            if (assemblyInstance is FamilyInstance)
            {
                Dictionary<string, int> nestedFamilies = GetNestedFamilyNamesAndCounts(doc, assemblyInstance);

                string resultMsg = "The Family '" + assemblyInstance.Name + "' containsthe following families:\n";

                foreach (var item in nestedFamilies)
                {
                    resultMsg += $"- {item.Key}: {item.Value} instance(s)\n";
                }
                TaskDialog.Show("Nested Family Details", resultMsg);
            }
            return Result.Succeeded;
        }




        private Dictionary<string, int> GetNestedFamilyNamesAndCounts(Document doc, FamilyInstance assemblyInstance)
        {
            Dictionary<string, int> nestedFamilyCounts = new Dictionary<string, int>();

            ICollection<ElementId> nestedComponentIds = assemblyInstance.GetSubComponentIds();
            foreach (var nestedComponentId in nestedComponentIds)
            {
                FamilyInstance familyInstance = doc.GetElement(nestedComponentId) as FamilyInstance;

                if (familyInstance != null)
                {
                    string nestedFamilyName = familyInstance.Symbol.Name;
                    if (nestedFamilyCounts.ContainsKey(nestedFamilyName))
                    {
                        nestedFamilyCounts[nestedFamilyName]++;
                    }
                    else
                    {
                        nestedFamilyCounts[nestedFamilyName] = 1;
                    }
                }
            }
            return nestedFamilyCounts;
        }
    }

 

It didn't work as  the below line of code returned null.

ICollection<ElementId> nestedComponentIds = assemblyInstance.GetSubComponentIds(); 




Also I've tried this code as well:

 

Document doc = commandData.Application.ActiveUIDocument.Document;
           
            FilteredElementCollector familyCollector = new FilteredElementCollector(doc)
                .OfClass(typeof(FamilyInstance));

            foreach (FamilyInstance familyInstance in familyCollector)
            {
                if (familyInstance.Symbol.FamilyName == "Sample Window Family")
                {
                    Dictionary<string, int> nestedFamilies = GetVisibleNestedFamilyNamesAndCounts(doc, familyInstance);

                   
                    string resultMessage = "The family '" + familyInstance.Name + "' contains the following visible nested families:\n";
                    foreach (var family in nestedFamilies)
                    {
                        resultMessage += $"- {family.Key}: {family.Value} instance(s)\n";
                    }

                    TaskDialog.Show("Visible Nested Family Count", resultMessage);
                }
            }



 private Dictionary<string, int> GetVisibleNestedFamilyNamesAndCounts(Document doc, FamilyInstance parentFamilyInstance)
        {
            Dictionary<string, int> nestedFamilyCounts = new Dictionary<string, int>();

            FilteredElementCollector collector = new FilteredElementCollector(doc)
                .OfClass(typeof(FamilyInstance));

            foreach (FamilyInstance instance in collector)
            {if (instance.Host != null && instance.Host.Id == parentFamilyInstance.Id)
                {
                    if (IsFamilyInstanceVisible(instance))
                    {
                        string nestedFamilyName = instance.Symbol.FamilyName;

                        if (nestedFamilyCounts.ContainsKey(nestedFamilyName))
                        {
                            nestedFamilyCounts[nestedFamilyName]++;
                        }
                        else
                        {
                            nestedFamilyCounts[nestedFamilyName] = 1;
                        }
                    }
                }
            }

            return nestedFamilyCounts;
        }

 private bool IsFamilyInstanceVisible(FamilyInstance instance)
        {
            
            Parameter visibilityParam = instance.get_Parameter(BuiltInParameter.IS_VISIBLE_PARAM);
            if (visibilityParam != null && visibilityParam.AsInteger() == 0)
            {
                return false; 
            }
            return true; 
        }

 

This approach didn't work as the collector didn't collect the nested familyInstances actually.

I'd appreciate any potential suggestions that will help to achieve the goal.

0 Likes
Message 3 of 9

MarryTookMyCoffe
Collaborator
Collaborator

you had error in cration of famiy you need to make families nested in order to get them in

GetSubComponentIds()

 

MarryTookMyCoffe_0-1725616875383.png

You can see in revit lookup that when I set inner family as nested list have elements

-------------------------------------------------------------
--------------------------------|\/\/|------------------------
do not worry it only gonna take Autodesk 5 years to fix bug
0 Likes
Message 4 of 9

theknownsilhouette
Enthusiast
Enthusiast

Sorry @MarryTookMyCoffe,  I didn't get it. This is a family (rfa) which already has instances of other families (rfa files).
Are you saying that somehow, I need to make these families (or define these families) as a nested family using the API? 

0 Likes
Message 5 of 9

jeremy_tammik
Alumni
Alumni

Can you achieve the desired result manually in the end user interface? What do you do there in order to achieve that? If it is not possible in the UI, the API will not be able to help you either. It just wraps and reproduces the UI functionality.

  

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

theknownsilhouette
Enthusiast
Enthusiast

Yes @jeremy_tammik  
If I check the option "shared" as below, I can see the particular nested instance in the project schedule.

theknownsilhouette_0-1725872402601.png


In this particular context, we can use "IFamilyOptions" interface to check if a family is shared or not but I'm not getting how to make a family "shared" using the API? If I can make the family shared and load it back to the project, it can be done.

0 Likes
Message 7 of 9

theknownsilhouette
Enthusiast
Enthusiast
Accepted solution

Below line worked for me:

bool a = NestedFamily.get_Parameter(BuiltInParameter.FAMILY_SHARED).Set(1);

complete code can be referred below.

 UIApplication uiApp = commandData.Application;
            UIDocument uiDoc = uiApp.ActiveUIDocument;
            Document doc = commandData.Application.ActiveUIDocument.Document;
            string FolderLocation = Path.GetDirectoryName(doc.PathName);

            
            FamilyInstance assemblyInstance = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).WhereElementIsNotElementType().Cast<FamilyInstance>().FirstOrDefault(x => x.Symbol.FamilyName.Equals("Sample Window Family"));

            Family placedFamily = assemblyInstance.Symbol.Family;
            Document familyDoc = doc.EditFamily(placedFamily);

            IEnumerable<FamilyInstance> nestedFamilies = new FilteredElementCollector(familyDoc).OfClass(typeof(FamilyInstance)).Cast<FamilyInstance>();


            familyLoadOption famLoadOptions = new familyLoadOption();
            foreach (var item in nestedFamilies)
            {
                Transaction nestedTrans = new Transaction(familyDoc, "make Shared");
                nestedTrans.Start();
                Family NestedFamily = item.Symbol.Family;
                Document nestedFamilyDoc = doc.EditFamily(NestedFamily);
                
                bool a = NestedFamily.get_Parameter(BuiltInParameter.FAMILY_SHARED).Set(1);
                nestedFamilyDoc.LoadFamily(doc, famLoadOptions);
                nestedTrans.Commit();
            }



            Transaction Trans = new Transaction(familyDoc, "make current Shared");
            Trans.Start();
            familyDoc.LoadFamily(doc, famLoadOptions);
            Trans.Commit();
            return Result.Succeeded;


My schedule before this implementation:

theknownsilhouette_0-1725889414113.png

 

My schedule after making the families shared:

theknownsilhouette_1-1725889497165.png

 




 

0 Likes
Message 8 of 9

MarryTookMyCoffe
Collaborator
Collaborator

I see you made it, good job

 

-------------------------------------------------------------
--------------------------------|\/\/|------------------------
do not worry it only gonna take Autodesk 5 years to fix bug
Message 9 of 9

MarryTookMyCoffe
Collaborator
Collaborator

I had revit in difrent language so I didn't know that they call it shared in english UI

-------------------------------------------------------------
--------------------------------|\/\/|------------------------
do not worry it only gonna take Autodesk 5 years to fix bug
0 Likes