Let us continue to talk about the particular slow filter in Revit API, ElementParameterFilter.
Let’s look at how to use the FilterStringRule filter rule to filter text (string) type element parameters in this article. Supposing we’d like to find all rooms with room numbers greater than or equal to a number and less than or equal to another, what shall we do?
The following code does so in C#:
public static ICollection<ElementId> GetRoomsNumberInRange(RvtDocument doc, string low, string high)
{
ParameterValueProvider provider = new ParameterValueProvider(new ElementId((int)BuiltInParameter.ROOM_NUMBER)); //THE ELEM_ROOM_NUMBER IS NOT THE RITHT PARAMETER!!!
FilterStringRule rule1 = new FilterStringRule(provider, new FilterStringGreaterOrEqual(), low, false);
FilterStringRule rule2 = new FilterStringRule(provider, new FilterStringLessOrEqual(), high, true);
ElementParameterFilter filter1 = new ElementParameterFilter(rule1);
ElementParameterFilter filter2 = new ElementParameterFilter(rule2);
return
(new FilteredElementCollector(doc))
//.OfClass(typeof(Room)) //THE ROOM CLASS DOES NOT WORK!!
.OfCategory(BuiltInCategory.OST_Rooms)
.WherePasses(filter1)
.WherePasses(filter2)
.ToElementIds();
}
A few highlights about the code:
• An ElementParameterFilter needs a filter rule, the FilterStringRule in this case.
• The FilterStringRule needs a parameter value provider (ParameterValueProvider) and a filter rule evaluator (FilterStringRuleEvaluator), specifically the FilterStringGreaterOrEqual and the FilterStringLessOrEqual here.
• The FilterStringRule also needs a value and a flag to indicate whether the string operation is case sensitive or not.
• The ParameterValueProvider needs an argument of parameter, as the room number parameter BuiltInParameter. ROOM_NUMBER in this case.
• NOTE: THE ELEM_ROOM_NUMBER IS NOT THE RITHT PARAMETER!!!
• The parameter is represented by an ElementId, which is the numeric value of the BuiltInParameter enumerator value.
• The ElementClassFilter fast filter (by its shortcut, the OfClass method of the class FilteredElementCollector) does not work with the Room API class as it is not a Revit native class in the product.
• So another fast filter instead, ElementCategoryFilter (by its shortcut, the OfCategory method of the class FilteredElementCollector), is used to narrow down the huge amount of elements and speeds up the search.
• Please be careful of using the OfCategory method or the ElementCategoryFilter filter as the OfCategory(BuiltInCategory.OST_Rooms) will not return exactly those Room elements that we are interested in. It may also include some symbols. But in our case, we do not have to bother adding one more filter to exclude those symbols as it is unlikely that room symbols have the ROOM_NUMBER parameter.
Curious people may ask: how did you figure out the ROOM_NUMBER of the BuiltInParameter enumerator is the right one to use as some similar ones are also there like the ELEM_ROOM_NUMBER mentioned earlier?
Good question! Though we still have to make some guess and do some experiment most of times to sort things like this out, a few RevitAddinCoder can help make the task a lot easier:
• Parameter Infoer Coder
• Parameter Categorizer Coder
• Parameter Retriever Coder
To use the method is very straightforward. Here is some test code in C#:
…
ICollection<ElementId> ids = GetRoomsNumberInRange(CachedDoc, "10", "20");
TaskDialog.Show("ElementParameterFilter Test", string.Format("{0} rooms are in the room number range [10, 20].", ids.Count));
…
The test is supposed to find all rooms with numbers in the range between 10 and 20. However, thoughtful readers may wonder: will the two FilterStringRuleEvaluator evaluators (FilterStringGreaterOrEqual and FilterStringLessOrEqual) really find out all and only those rooms with room numbers more than or equal than 10 and less than or equal to 20? What about room number 2, 1A, 155, or similar if any in the same Revit model since Room Number can be any string instead of numeric values only?
Great question! The two evaluators will not exclude those room numbers if they do exist. Performing one more evaluator like FilterStringNumericOnly seems to be necessary, but it is not possible as there is not such a filter string rule in the Revit API:
Autodesk.Revit.DB.FilterStringRuleEvaluator
Autodesk.Revit.DB.FilterStringBeginsWith
Autodesk.Revit.DB.FilterStringContains
Autodesk.Revit.DB.FilterStringEndsWith
Autodesk.Revit.DB.FilterStringEquals
Autodesk.Revit.DB.FilterStringGreater
Autodesk.Revit.DB.FilterStringGreaterOrEqual
Autodesk.Revit.DB.FilterStringLess
Autodesk.Revit.DB.FilterStringLessOrEqual
So, it is not really convenient or even possible to filter string parameters for some complex situations like this using the ElementParameterFilter and the existing FilterStringRuleEvaluator unless some more custom string evaluators can be created. In the next post, we are going to talk about this matter.
ElementParameterFilter Creator of RevitAddinCoder can create the code automatically in no time.
Recent Comments