Element Parameter Filter

Learn how to use ElementParameterFilter class in Revit API To filter your elements with parameter values. P.S. This video is also published on YouTube. I wanted to make it for a long time for free as well.

Element Parameter Filter

Learn how to use ElementParameterFilter class in Revit API To filter your elements with parameter values. P.S. This video is also published on YouTube. I wanted to make it for a long time for free as well.

Summary

Element Parameter Filter

Have you Ever wanted to Get your elements in Revit API based on a specific parameter value? And if you did you might have come across ElementParameterFilter Class.

So in this lesson I will break down how to use ElementParameterFilter so you can filter your elements based on parameter values.

And we are going to make 2 functions

  • Get Elements by Type Name.

  • Get Elements by Family Name

Let's start by exploring Documentation

Revit API Docs: Element Parameter Filter

Once we start exploring this class in documentation you will notice that we have a C# Example

// Creates an ElementParameter filter to find rooms whose area is 
// greater than specified value
// Create filter by provider and evaluator 
// provider
ParameterValueProvider pvp = new ParameterValueProvider(new ElementId(BuiltInParameter.ROOM_AREA));
// evaluator
FilterNumericRuleEvaluator fnrv = new FilterNumericGreater();
// rule value    
double ruleValue = 100.0f; // filter room whose area is greater than 100 SF
// rule
FilterRule fRule = new FilterDoubleRule(pvp, fnrv, ruleValue, 1E-6);

// Create an ElementParameter filter
ElementParameterFilter filter = new ElementParameterFilter(fRule);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
IList<Element> rooms = collector.WherePasses(filter).ToElements();


// Find rooms whose area is less than or equal to 100: 
// Use inverted filter to match elements
ElementParameterFilter lessOrEqualFilter = new ElementParameterFilter(fRule, true); 
collector = new FilteredElementCollector(document);
IList<Element> lessOrEqualFounds = collector.WherePasses(lessOrEqualFilter).ToElements

And here is python translation of it:

# Creates an ElementParameter filter to find rooms whose area is 
# greater than specified value
# Create filter by provider and evaluator 
# provider
pvp = ParameterValueProvider(ElementId(BuiltInParameter.ROOM_AREA))
# evaluator
fnrv = FilterNumericGreater()
# rule value    
rule_value = 100.0  # filter room whose area is greater than 100 SF
# rule
fRule = FilterDoubleRule(pvp, fnrv, rule_value, 1E-6)

# Create an ElementParameter filter
filter = ElementParameterFilter(fRule)

# Apply the filter to the elements in the active document
collector = FilteredElementCollector(document)
rooms = collector.WherePasses(filter).ToElements()


# Find rooms whose area is less than or equal to 100: 
# Use inverted filter to match elements
less_or_equal_filter = ElementParameterFilter(fRule, True) 
collector = FilteredElementCollector(document)
less_or_equal_founds = collector.WherePasses(less_or_equal_filter).ToElements()

Based on that example we can see that we need to prepare a rule to create our filter. And while there are different classes for rules depending on StorageType, in this example they use FilterDoubleRule

To create this rule we need

There is also an option to invert the filter to get the opposite results. For that we just need to provide True boolean as a second argument when we create ElementParameterFilter

Let's start from the beginning and explore all required classes in more detail.

Filter Rules

When we look at ElementParameterFilter, we can see that it takes FilterRule as an argument. This is a base class for many other classes that we should use instead.

To choose correct one, we need to think of a StorageType of our parameter:

These Elements have very similar constructors, but also there might be differences like CaseSensetive / Tollerance.

Here are Constructors (You Can Scroll Through Carousell):

How do we create Rules?

Now let's look at rules in more detail to understand it better. Mainly they need the same arguments:

  • valueProvider

  • evaluator

  • ruleString

And there might be additional tollerance number or case-sensetivity boolean.

How do we create Rules?

Now let's look at rules in more detail to understand it better. Mainly they need the same arguments:

  • valueProvider

  • evaluator

  • ruleString

And there might be additional tollerance number or case-sensetivity boolean.

How do we create Rules?

Now let's look at rules in more detail to understand it better. Mainly they need the same arguments:

  • valueProvider

  • evaluator

  • ruleString

And there might be additional tollerance number or case-sensetivity boolean.

Compare these arguments to Revit UI

Before we are going to break down each argument, let's compare them to Revit UI so you get more comfortable.

Have a look at Filter Rules that we create for Views.

Usually we select the following:

  • Category

  • Parameter

  • Evaluator (Contains, Equals…)

  • Rule Value

Do you see similarities to what we need for creating Revit API Rules? Except for Category, this is done separately in FEC class.

ParameterValueProvider

First of all we need to choose a parameter we want to check, and we will use ParameterValueProvider class. It has very simple constructor:

We just need to provide ElementId of our parameter.

First of all we need to choose a parameter we want to check, and we will use ParameterValueProvider class. It has very simple constructor:

We just need to provide ElementId of our parameter.

#1️⃣ Parameter
p_id = ElementId(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM)
pvp  = ParameterValueProvider(p_id)
Evaluator

Next we need to select a class for evaluator. There are separate classes for Strings and Numeric, so make sure you choose the right one based on your parameter.

They all have no arguments, so we just select the one we want, and create an instance of it like this:

#2️⃣ Evaluator
evaluator = FilterStringContains()

I choose Contains evaluator, so I can partially provide Rule Value to match.

Rule Value

Rule value can be anything that you want. In my case I want to create a function to get elements by Type Name, so I will write that in here!

#3️⃣ Value
value = 'FE TÜR'
FilterStringRule

Now we can combine all these arguments to create FilterStringRule

⚠️ But before we do that I want to warn you!

There was a change in Revit 2022 for this class, so we need to protect our script from breaking if we go below this version. And it's not complicated, as they just removed 4th argument for case-sensitivity.

It's also great to practice, how to make script for multiple Revit versions due to changes.

I will just get Revit version from app variable, and make 2 different code snippets for making this rule.

#4️⃣ Rule
rvt_year = int(app.VersionNumber)
if rvt_year >= 2022:
    f_rule = FilterStringRule(f_param, evaluator, value)
else:
    f_rule = FilterStringRule(f_param, evaluator, value, False)

Now we have created FilterStringRule.

Create ElementParameterFilter

Lastly, we can use this rule to create ElementParameterFilter.

#5️⃣ Filter
filter_fam_name = ElementParameterFilter(f_rule)

Let's also apply it to a collector to get ElementIds of Window Instances.

#6️⃣ Apply Filter to FEC
element_ids = FilteredElementCollector(doc)\
                .OfCategory(BuiltInCategory.OST_Windows)\
                .WherePasses(filter_fam_name)\
                .WhereElementIsNotElementType()\
                .ToElementIds()

#👉 Select Elements
uidoc.Selection.SetElementIds(element_ids)
ElementParameterFilter for String Parameters

Now, let's summarize it all together into 1 snippet for Strings.

#1️⃣ Parameter
p_fam_id = ElementId(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM)
f_param  = ParameterValueProvider(p_fam_id)

#2️⃣ Evaluator
evaluator = FilterStringContains()

#3️⃣ Value
value = 'FE TÜR'

#4️⃣ Rule
rvt_year = int(app.VersionNumber)
if rvt_year >= 2023:
    f_rule = FilterStringRule(f_param, evaluator, value)
else:
    f_rule = FilterStringRule(f_param, evaluator, value, False)


# #5️⃣ Filter
filter_fam_name = ElementParameterFilter(f_rule)

#6️⃣ Apply Filter to FEC
element_ids = FilteredElementCollector(doc)\
                .OfCategory(BuiltInCategory.OST_Windows)\
                .WherePasses(filter_fam_name)\
                .WhereElementIsNotElementType()\
                .ToElementIds()

#👉 Select Elements
uidoc.Selection.SetElementIds(element_ids)

💡 Now you know all the steps, and it doesn't look that complicated.

It does take quite a few lines of code, but overall it's very simple and similar to Revit View filters, as it needs same things.

ElementParameterFilter for Numeric Parameters

Now let's also create a snippet for a numeric parameter.

#1️⃣ Parameter
p_fam_id = ElementId(BuiltInParameter.WALL_USER_HEIGHT_PARAM)
f_param  = ParameterValueProvider(p_fam_id)

#2️⃣ Evaluator
evaluator = FilterNumericGreater()

#3️⃣ Value
value = 10 # Value in FEET!

#4️⃣ Rule
f_rule = FilterDoubleRule(f_param, evaluator, value, 0.0001)


# #5️⃣ Filter
filter_wall_height = ElementParameterFilter(f_rule)

#6️⃣ Apply Filter to FEC
walls_higher_10ft_ids = FilteredElementCollector(doc)\
                        .OfCategory(BuiltInCategory.OST_Walls)\
                        .WherePasses(filter_wall_height)\
                        .WhereElementIsNotElementType()\
                        .ToElementIds()

#👉 Select Elements
uidoc.Selection.SetElementIds(walls_higher_10ft_ids)

1️⃣ We will take WALL_USER_HEIGHT_PARAM, to check wall heights.

2️⃣ I will choose FilterNumericGreater to only get walls that are higher

3️⃣ We will provide 10ft height. Be sure to convert if you use metric units!

4️⃣ Combine these parameters into a rule, and don't forget 4th argument for tollerance

5️⃣ Lastly, we can create ElementParameterFilter

6️⃣ And same as before, we can apply it to a collector

💡 Now it becomes so much easier, as we just need to tweak a few things. Just like in Revit UI when you duplicate a filter and change parameter and its value!

Turn it into a function:

🎦 Lastly, I want to give you a snippet from the video so you can see how it can easily be turned into a reusable function

Here is the snippet to get elements by Type Name:

def get_elements_by_type_name(type_name):
    """Function to get Elements by Family Name"""
    #1️⃣ Parameter
    p_type_id = ElementId(BuiltInParameter.SYMBOL_NAME_PARAM)
    f_param  = ParameterValueProvider(p_type_id)

    #2️⃣ Evaluator
    evaluator = FilterStringEquals()

    #3️⃣ Value
    value = type_name

    #4️⃣ Rule
    rvt_year = int(app.VersionNumber)
    if rvt_year >= 2023:
        f_rule = FilterStringRule(f_param, evaluator, value)
    else:
        f_rule = FilterStringRule(f_param, evaluator, value, False)


    #5️⃣ Filter
    filter_fam_name = ElementParameterFilter(f_rule)

    #6️⃣ Apply Filter to FEC
    return FilteredElementCollector(doc)\
                    .WherePasses(filter_fam_name)\
                    .WhereElementIsNotElementType()\
                    .ToElements()

# MAIN
elements    = get_elements_by_type_name('2000 x 2250')
el_ids      = [el.Id for el in elements]
List_el_ids = List[ElementId](el_ids)

uidoc.Selection.SetElementIds(List_el_ids)

💡 You can extend the functionality by adding second argument for evaluator to make it even more versatile!

HomeWork

Try to create your own ElementParameterFilter.

Choose a parameter, evaluator and a value to check, and see if you can get your elements using it.

Feel free to copy my snippet and modify it, as it will save you a lot of time!

⌨️ Happy Coding!

Questions:

What Rule to use for Yes/No parameters?

What Rule to use for Yes/No parameters?

Discuss the lesson:

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API