Filter Rule non String

So I’m struggling to get my filter rule by rule type working…

I want to filter by Level, so I believe I need to feed both the Level Parameter (ie. a parameter) from the floor and the Level Parameter value (ie. a string).

My attempts at retrieving the parameter by name don’t seem to be working (I create a rule but the value is blank) so I’m trying python… But I don’t seem able to return a parameter?

import clr
import sys

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

import System

elem = UnwrapElement(IN[0])
pName = IN[1]

outPut = []

p = elem.Parameters
for n in p:
	pvp = ParameterValueProvider(n.Id)
	#if pvp.IsElementIdValueSupported(elem):
	if n.Definition.Name == pName:	
		outPut.append([n.Definition.Name, pvp.GetElementIdValue(elem), doc.GetElement(pvp.Parameter)])
	
OUT = outPut 

Any thoughts welcome…

Cheers,

Mark

View Filter Set Create Add Check.dyn (104.6 KB)

1 Like

I don’t think GetElement works for parameter elements. You could probably use something like GetParameters or LookupParameter instead.

Thanks Nick,

I’m wondering if I’m looking at the wrong problem… I think the filter rule should work if i put the level in, but it only returns a filter if i put in a string (the level name)…

I’m seeing if i can doctor this code…

Correct. The input is actually a string here, which is backwards from how the Level parameter would normally work. It’s working on my end.
image

I find it makes a rule, but when i go look at that in Revit, it’s empty?

[Hopes it’s just me]

You’re right. Blank for me as well. I’m guessing it’s because the FilterRule node expects a string but the value for Level is an element. I’m guessing this will have to be fixed in an update.

Thanks!

I don’t think i have that node!

I’ll go update my package now…

I have Archilab 2019.2.11 are you on a more recent version?

No I’m on an older version. It doesn’t seem to work either. The rule gets created but the filter doesn’t.

Hum… It’s not there,

I’m messing around with the Python but getting this message, probably because I’m using a string equals filter…

But I can’t see a create method for a filter rule that isn’t a string?
https://www.revitapidocs.com/2020/c8c02bc8-5318-812c-e0f2-bc5dd5d2ad64.htm

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

# Import RevitAPI
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import ToProtoType, ToRevitType geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)

# Import DSCore nodes in Dynamo
clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

# Import python library
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os
import shutil
import math
# Import math library
from math import *

#Import Data and Time
from datetime import datetime
now = datetime.now()

#Import System Library
import System
from System.Collections.Generic import *
from System.IO import Directory, Path

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
def ToList(x):
	if isinstance(x,list): return UnwrapElement(x)
	else: return [UnwrapElement(x)]
	
#Preparing input from dynamo to revit
pName = IN[0]
elem = UnwrapElement(IN[1])
filtNames = IN[2]
cats = ToList(IN[3])

catids = List[ElementId]()
catids.Clear()
for cc in cats:
	catids.Add(cc.Id)

test = []
p = elem.Parameters
for n in p:
	test.append(n.Definition.Name)
	pvp = ParameterValueProvider(n.Id)
	#if pvp.IsElementIdValueSupported(elem):
	if n.Definition.Name == pName:	
		ePvp = pvp
		break

#define subset of element filters
sfilters = List[ElementFilter]()
sfilters.Add(ElementParameterFilter(FilterStringRule(ePvp,FilterStringEquals(),pName,False)))

#define final set of element filters
fRule = LogicalAndFilter(sfilters)

#Do some action in a Transaction #
TransactionManager.Instance.EnsureInTransaction(doc)
for name,cat in zip(filtNames,cats):
	paraele = ParameterFilterElement.Create(doc,name,catids)
	paraele.SetElementFilter(fRule)
	Parafilele.append(paraele)
TransactionManager.Instance.TransactionTaskDone()

OUT = Parafilele

View Filter Set Create Add Check.dyn (115.4 KB)

maybe you can should your final desired output of the filter rules and i will try and help you to code with it?

Note that in R18 and above, it uses different approach as compared to R17 and below. And the sample code you got is for R18 and above

1 Like

And also, i dont think you need to feed in an element to retrieve the parameter Id, you can either use parametermap for project or sharedparameter element and filter by name to retrieve its Id

Thank you for offer, I am trying to achieve this…

I want to make a filter rule which uses Elements (Levels)…

Right now I can only make a filter rule which uses Strings.

Cheers :slight_smile:

Mark

may i know on which categories you wanna apply that filter to?

Floors :slight_smile:

EDIT:

There doesn’t seem to be an… if value.GetType() ==typeof(element)

Just ints, doubles and strings…

if (value.GetType() == typeof(int))
                {
                    System.Reflection.MethodInfo methodInfo = typeof(ParameterFilterRuleFactory).GetMethod(methodname, new[] { typeof(ElementId), typeof(int) });
                    if (methodInfo != null)
                    {
                        return new FilterRule((Autodesk.Revit.DB.FilterRule)methodInfo.Invoke(null, new object[] { parameterId, (int)value }));
                    }

EDIT EDIT:

Seems I need to go right back to create the parameter filter with a different method?

ParameterFilterElement Class
https://www.revitapidocs.com/2020/b231dc85-516a-5e75-c634-c6cd81b43fc5.htm
CreateEqualsRule Method (ElementId, ElementId)
https://www.revitapidocs.com/2020/13332eda-1822-237d-51a6-d09df09b5234.htm

EditEditEdit:
Doesn’t like it…

This seems relevant…https://forum.dynamobim.com/t/python-custom-rules-for-filteredelementcollector/21135*

And another fail :slight_smile:

Bit of progress…

Gotcha!

The first BIP LEVEL_PARAM didn’t work, it needs the 2nd… I’ll have to run some kind of check…

pId = ElementId(BuiltInParameter.SCHEDULE_LEVEL_PARAM)

sRule = ParameterFilterRuleFactory.CreateEqualsRule(pId, level.Id)
fRule = ElementParameterFilter(sRule)

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
for name,cat in zip(filtNames,cats):
	paraele = ParameterFilterElement.Create(doc,name,catids)
	paraele.SetElementFilter(fRule)
	Parafilele.append(paraele)
TransactionManager.Instance.TransactionTaskDone()

OUT = Parafilele
4 Likes

Sorry for the late reply but it seems that you had already figured out. Good for you! but since i already sort of did it already, here is another way to achieve what you want for R19 and above(my above reply is wrong)!

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


#Preparing input from dynamo to revit
pvp1 = ParameterValueProvider(ElementId(BuiltInParameter.SCHEDULE_LEVEL_PARAM))

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

#Empty list of Element Filter
sRule1 = List[ElementFilter]()

#Get all levelids in project
lvlids = FilteredElementCollector(doc).OfClass(Level).ToElementIds()
#You can use this loop to retrieve desired level, just change to ToElements() and search by name
#We can filter by element Id and since element id is numeric, we will use FilterNumericEquals()
for lvlid in lvlids:
	sRule1.Add(ElementParameterFilter(FilterElementIdRule(pvp1,FilterNumericEquals(),lvlid)))

#Can use LogicalAndFilter
fRule = LogicalOrFilter(sRule1)

#Get a list to cat ids to be used by the filter
catids = List[ElementId]()
catids.Add(Category.GetCategory(doc,BuiltInCategory.OST_Floors).Id)

#Create the ParameterFilterElement
pfe1 = ParameterFilterElement.Create(doc,"Example view filter1",catids,fRule)

TransactionManager.Instance.TransactionTaskDone()
#Final output
OUT = pfe1

And for R18 and below:

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


#Preparing input from dynamo to revit
pvp1 = ParameterValueProvider(ElementId(BuiltInParameter.SCHEDULE_LEVEL_PARAM))

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

#Empty list of FilterRule
sRule1 = List[FilterRule]()

#Get all levelids in project
lvlids = FilteredElementCollector(doc).OfClass(Level).ToElementIds()
#You can use this loop to retrieve desired level, just change to ToElements() and search by name
#We can filter by element Id and since element id is numeric, we will use FilterNumericEquals()
for lvlid in lvlids:
	sRule1.Add(FilterElementIdRule(pvp1,FilterNumericEquals(),lvlid))

#Get a list to cat ids to be used by the filter
catids = List[ElementId]()
catids.Add(Category.GetCategory(doc,BuiltInCategory.OST_Floors).Id)

#Create the ParameterFilterElement
pfe1 = ParameterFilterElement.Create(doc,"Example view filter1",catids,sRule1)

TransactionManager.Instance.TransactionTaskDone()
#Final output
OUT = pfe1

1 Like

This is to just check, if the value provided is int or string or double, you will notice they use sort of different methods for different type

Thanks for posting the code.

Yes, they check for int string or double, but they don’t check for element… Perhaps I’ll drop that on the github as a request.

One thing I found was that while SCHEDULE_LEVEL_PARAM works, LEVEL_PARAM didn’t… i need a filter :slight_smile:
Cheers,

Mark

Final Graph…


View Filter Set Create Add Check.dyn (98.5 KB)

3 Likes

Well… for this i do not have control over it as it is determined by the Autodesk team. If you use revit lookup, you will be able to find which builtin parameter the level is tied to. hahaha

1 Like