How to set a series Filter Rules using "OR (Any rule may be ture)" instead of "AND (All rules must be true)"?

Dear All, I am new to the forum and trying to set up Filter Rules using FilterRule.ByRuleType and ParameterFilterElement.ByRules. However, the list of the rules I created is using “AND” by default. How to change to “OR”? Please see the attached images.

I am also looking for a way to do this. Anyone know a way?

Maybe take a look at:
ParameterFilterElement.SetRules() → ParameterFilterElement.SetElementFilter() – The new function sets the ParameterFilterElement to contain an ElementFilter representing the combination of filter rules.

I don’t think any packages have this yet, so you may need python?

There is also this. (I’m currently testing this out)

  • ParameterFilterElement.Create(Document, String, ICollection, IList) → ParameterFilterElement.Create(Document, String, ICollection, ElementFilter) – The ElementFilter input now specifies the filtering rules. This allows combinations of filter rules using logical AND and OR operations. The ElementFilter must be either an ElementParameterFilter or an ElementLogicalFilter containing only ElementParameterFilters and other ElementLogicalFilters.

@Matt_Fleming Thanks, I will look into this as well.

@erfajo I wonder if this could possibly be something that you could roll into Orchid if you have time. :slight_smile:

I’ve done this using Python in Dynamo.

To create a Revit Filter (Parameter Filter Element) you need an ICollection of the categories the filter will apply to and an ElementParameterFilter. The Construction of the Element Parameter Filter is the most confusing part because you can construct ElementParameterFilters our of other previously constructed ElementParameterFilters.

To try to show this I’ll make a filter that works on Framing and Columns and test for either Comments Equals “Magnum” OR (Family Name Begins With “Blue” AND Comments Equals “Steel”)

import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
import System
from System.Collections.Generic import *
from System.Collections.Generic import List

doc=DocumentManager.Instance.CurrentDBDocument
app=DocumentManager.Instance.CurrentUIApplication.Application

First construct an ICollection of StructuralFraming and Structural Column Categories:

beamcolumncatlist=[]
beamcolumncatlist.Add(ElementId(BuiltInCategory.OST_StructuralFraming))
beamcolumncatlist.Add(ElementId(BuiltInCategory.OST_StructuralColumns))
iCollBeamColumnCats=List[ElementId](beamcolumncatlist)

Next get the parameters you will be testing on (in this case the Comments parameter and the Family Name):

pComment=ParameterValueProvider(ElementId(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS))
pFamName=ParameterValueProvider(ElementId(BuiltInParameter.ALL_MODEL_FAMILY_NAME))

Next construct the Filter Rules/Tests on those parameters:

xFamName=FilterStringRule(pFamName,FilterStringBeginsWith(),"Blue",False)
xCommSteel=FilterStringRule(pComment,FilterStringEquals(),"Steel",False)
xCommMagnum=FilterStringRule(pComment,FilterStringEquals(),"Magnum",False)

Now construct the actual filter (ParameterFilterElement) - note that this must occur inside a transaction:

TransactionManager.Instance.EnsureInTransaction(doc)

##Make an ICollection of the “Blue” and “Steel” filter tests, then use that ICollection to construct an AND filter set.

beamcolumnfilt1=[]
beamcolumnfilt1.Add(ElementParameterFilter(xFamName))
beamcolumnfilt1.Add(ElementParameterFilter(xCommSteel))
icolbeamcolumnfilt1=List[ElementFilter](beamcolumnfilt1)
andbeamcolumnfilt1=LogicalAndFilter(icolbeamcolumnfilt1)

##Now make an ICollection of the “Magnum” tests and the previous AND of “Blue”+“Steel”, then use that ICollection to construct an OR filter set.

beamcolumnfilt2=[]
beamcolumnfilt2.Add(ElementParameterFilter(xCommMagnum))
beamcolumnfilt2.Add(andbeamcolumnfilt1)
icolbeamcolumnfilt2=List[ElementFilter](beamcolumnfilt2)
orbeamcolumnfilt2=LogicalOrFilter(icolbeamcolumnfilt2)

##Now construct a ParameterFilterElement called “ZoolanderBeamsColumns” using the previously defined beam and column category ICollection and the OR ElementParameterFilter.

pfebeamcolelem=ParameterFilterElement.Create(doc,"ZoolanderBeamsColumns",iCollBeamColumnCats,orbeamcolumnfilt2)
TransactionManager.Instance.TransactionTaskDone()

Hope this helps.

10 Likes

Hi all, Read the below, unfortunately am not yet at Python stage of my learning.
I have the opposite issue which is strange, When I use “FilterFule.ByRuleType” in Revit 2020 all Filters Default to “OR (Any rule may be true)” instead of “AND(All rules must be true)”

Of course the below does not work, (Put it in as a joke :blush: ) but I’m just hoping the “FilterRule.ByRuleType” gets updated as this is a super handy Node. We use it to auto-generate loads filters based on Parameters in the model.

2 Likes

This is already asked here:

Hello @Ben_Osborne

i have tried to follow your outline for 2020 and have run into one issues.

I cant really work out how to set the rules, I have attached the script, but basically I try and create a rule that sets a typename- but it just doesnt want to work.

Blockquoteimport clr
clr.AddReference(‘System.Core’)
clr.AddReference(‘RhinoInside.Revit’)
clr.AddReference(‘RevitAPI’)
clr.AddReference(‘RevitAPIUI’)

from System import Enum

clr.AddReference(‘System’)
from System.Collections.Generic import List

clr.AddReference(‘RevitNodes’)
import Revit
clr.ImportExtensions(Revit.Elements)

import rhinoscriptsyntax as rs
import Rhino
import RhinoInside
import Grasshopper
from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML
from RhinoInside.Revit import Revit, Convert
from Autodesk.Revit import DB
#from Autodesk.Revit.DB import *

DB is the data base module

clr.AddReference(‘RevitServices’)
import RevitServices
from RevitServices.Persistence import DocumentManager

clr.ImportExtensions(RhinoInside.Revit.Convert.Geometry)
from RhinoInside.Revit.Convert.Geometry import UnitConverter

active Revit verison

REVIT_VERSION = Revit.ActiveUIApplication.Application.VersionNumber

access the active document object

doc = Revit.ActiveDBDocument

def show_warning(msg):
ghenv.Component.AddRuntimeMessage(RML.Warning, msg)

def show_error(msg):
ghenv.Component.AddRuntimeMessage(RML.Error, msg)

def show_remark(msg):
ghenv.Component.AddRuntimeMessage(RML.Remark, msg)

We want to get the element ID of the category

Get the built in type name paramter from curtain panels category

FINDNG CATEGR TYPES

CategoryFilter = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_CurtainWallPanels)

BuiltInCategory Enumeration

Create a list with one element of the category

Category_Elements =
for count, category in enumerate(CategoryFilter):
if count == 1:
break
Category_Elements.append(category)

Create a list

Category_ElementID_List2 =

get data from the category element

CategoryElement = Category_Elements[0]

Get the Element Id of the category

Category_ID = (CategoryElement.Id)
print (Category_ID)

Get tge element from the Category ID

Element = doc.GetElement(Category_ID)
Parameter_ElementID2= Element.get_Parameter(DB.BuiltInParameter.ALL_MODEL_TYPE_NAME).AsElementId()
print (Parameter_ElementID2)
Category_ElementID_List2.append(Parameter_ElementID2)
print (Category_ElementID_List2)

LOOKING ONLY AT CATEGORIES

Get element ID from curtain wall panels for the category and add it to a .net list

Category_ElementID_List =
Parameter_ElementID = DB.ElementId(DB.BuiltInCategory.OST_CurtainWallPanels)
print (Parameter_ElementID)
Category_ElementID_List.append(Parameter_ElementID)
print (Parameter_ElementID)

#cat_ids = [cat.Id for cat in category_set]

Convert Python list to .NET List

Stuck with List[ElementId](ids) - #4 by Yien

https://forums.autodesk.com/t5/revit-api-forum/view-filter-by-elementids/td-p/5531477

FilterRule.ByRuleType input issues - #12 by crapai

col1 = ListDB.ElementId
cat_ids_valid = DB.ParameterFilterUtilities.RemoveUnfilterableCategories(col1)

print (cat_ids_valid)

Find type name (just to add)

Type_Name = CategoryElement.get_Parameter(DB.BuiltInParameter.ALL_MODEL_TYPE_NAME).AsString()

Set the rules

Rules_List =

ParameterFilterRuleFactory Class

rule_01 = DB.ParameterFilterRuleFactory.CreateContainsRule(Parameter_ElementID, “Yes”, False)
Rules_List.append(rule_01)

Convert single FitlerRule to List

rules = ListDB.FilterRule

HOW DO I MAKE THE RULES?

FilterRule.ByRuleType input issues - #17 by crapai

How to set a series Filter Rules using "OR (Any rule may be ture)" instead of "AND (All rules must be true)"? - #6 by Ben_Osborne

How to set a series Filter Rules using "OR (Any rule may be ture)" instead of "AND (All rules must be true)"? - #6 by Ben_Osborne

xFamName=DB.FilterStringRule(Parameter_ElementID2,DB.FilterStringBeginsWith(),“Blue”,False)

test=
test.Add(ElementParameterFilter(xFamName))
testlist=ListElementFilter
logical=LogicalAndFilter(testlist)

Redo this bit

t = DB.Transaction(doc, ‘update top constraint’)
t.Start()

#try:

ParameterFilterElement Class

fitler = DB.ParameterFilterElement.Create(doc, “Test Filter”, cat_ids_valid, logical)
#except:
#pass

t.Commit()

1 Like