From Dynamo to C# – All Elements of Category

I had a few comments in response to my post on using the API to clear out a problem line pattern, mostly that the API is over the average user’s head. While this may be the case, there are other users out there that have been using Dynamo for a while now and are looking to take their solutions to the next level.

So I thought it might be useful to show comparisons between what some basic tasks in Dynamo look like, and then what they look like in code. And as I myself am still learning, if you’re a more experienced coder, feel free to correct me if I’ve made any mistakes or if I have taken an around-about method that could be simplified.

It is worth noting that the code examples provided below are from macros, not loadable addins. There are slight differences between the requirements of macros and addins that you can read on Harry Mattison’s blog BoostYourBIM

The first example is getting all families of the mechanical equipment family category. In Dynamo, you would achieve this with the following nodes:

In C# there is a little bit of groundwork that is required first. You need to tell Revit to work with the active open document. To do this you use

//set the active document
Document doc = this.ActiveUIDocument.Document;

In this line, doc is a variable that you are setting and can use later throughout your code to call the active document.

The next step is to create a FilteredElementCollector to collect all the mechanical equipment families in the model.

//setup collector and filter
var collector = new FilteredElementCollector(doc);
var filter = new ElementCategoryFilter(BuiltInCategory.OST_MechanicalEquipment);
 
 
//collect all mechanical equipment
var allMechanicalEquipment = collector.WherePasses(filter).WhereElementIsNotElementType().Cast<FamilyInstance>();

We are filtering our families by the built in category OST_MechanicalEquipment. The variable fi represents every family in the model of the mechanical equipment category.

You can however filter any other family category, there is a list of built in categories in the Revit API documentation, the online version of this documentation is here.

But say you wanted to filter further? Selecting the mechanical equipment in the model is far too broad. What about filtering by the family type name? In Dynamo you would achieve this with the following nodes:

As you can see, I’m filtering the families to see if they contain the string “AHU”

In C# we need to take our allMechanicalEquipment variable and filter the list of mechanical equipment families by using a LINQ query to find elements that contain the word AHU.

//filter for ones containing AHU in the name
var ahuEquipment = from fi in allMechanicalEquipment
                   where fi.Symbol.FamilyName.ToUpper().Contains("AHU")
                   select fi;

You can read more about LINQ queries on the Microsoft website:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq

You will also notice here that when we take the family name using fi.Symbol.FamilyName we have added ToUpper(). The reason for this is that some families may have been named inconsistently such as Ahu or ahu. Converting the family name to uppercase means we catch everything with AHU in the name regardless of text case.

So now that we have all of our AHU families, what about replicating that watch node? In Revit we can use the TaskDialog to display information back to the user.

When we want to do something with each of the AHU families, such as getting their name and element id, we need to use a foreach loop which repeats the same process to each selected element.

//example foreach loop
foreach (FamilyInstance fi in ahuEquipment)
{
//do stuff here
}

So we are going to collect the names and element ids for each family instance fi in our list ahuEquipment

First we need to do a little groundwork by defining an empty stringbuilder to populate with information. We do this with the following code:

//setup string builder to store data
StringBuilder displayInfo = new StringBuilder();

Then inside the foreach loop, we need to collect the information on our families and add them to a variable (var) named elementinfo.

We build each line in our string with fi.Name which takes the name of our family instance as well as fi.Id which is the element id of our family.

//loop through, collect data
foreach (FamilyInstance fi in ahuEquipment)
{
    var elementinfo = string.Format("Family Name: {0} Element Id: {1}", fi.Name, fi.Id);
    displayInfo.AppendLine(elementinfo);
}

To display this information, we need to add the following line outside the foreach loop.

TaskDialog.Show("Watch",displayInfo);

The result is the following dialogue box displayed in Revit

Don’t forget to add spaces around your strings like I did

So to wrap everything up, our final code dropped into our macro looks like so:

//get current document
Document doc = this.ActiveUIDocument.Document;
 
//setup collector and filter
var collector = new FilteredElementCollector(doc);
var filter = new ElementCategoryFilter(BuiltInCategory.OST_MechanicalEquipment);
 
//collect all mechanical equipment
var allMechanicalEquipment = collector.WherePasses(filter).WhereElementIsNotElementType().Cast<FamilyInstance>();
 
//use LINQ to filter for familyInstances containing AHU in the family name
var ahuEquipment = from fi in allMechanicalEquipment
                   where fi.Symbol.FamilyName.ToUpper().Contains("AHU")
                   select fi;
 
//setup string builder to store data
StringBuilder displayInfo = new StringBuilder();
 
//loop through, collect data
foreach (FamilyInstance fi in ahuEquipment)
{
    var elementinfo = string.Format("Family Name: {0} Element Id: {1}", fi.Name, fi.Id);
    displayInfo.AppendLine(elementinfo);
}
 
//display results
TaskDialog.Show("Watch", displayInfo.ToString());

And yes, I admit coding is a big jump from stringing together some Dynamo nodes, but just like learning Dynamo the more you dive into it the simpler it becomes.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: