Reorder View Filters

Is it possible to change the order of these filters? Pass the SPK to the top so that it overlaps others?

@guilherme.woltmann To the best of my knowledge, it is not possible to reorder the filters in an autonomous way. There isn’t any API method which gives you the order of the filters. So you cannot rearrange it automatically.

A semi-autonomous way would be to manually define an order > copy overrides > remove existing ones > apply the new order.

It would look something like this: Reorder View Filters.dyn (34.4 KB)

I’ve made it more generalized by asking for an order. If you just care about SPK being at the top, you can find the index of SPK from x.Name and reorder such that SPK’s index is on top followed by the rest indices in the default order as returned by the API call.

Graph in action:
ReorderViewFilters

3 Likes

@AmolShah …great way :wink:

1 Like

a python solution by following this example

reorder

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

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

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

toList = lambda x : x if hasattr(x, '__iter__') else [x]

lstViews = toList(UnwrapElement(IN[0]))
serachFilter = IN[1]
TransactionManager.Instance.EnsureInTransaction(doc)
for v in lstViews:
	filterIds = v.GetFilters()
	datafilters = [[filId, doc.GetElement(filId).Name, v.GetFilterOverrides(filId)] for filId in filterIds]
	try:
		indexFilter = [i[1] for i in datafilters].index(serachFilter)
	except ValueError:
		indexFilter = None
	#
	if indexFilter is not None:
		for i in filterIds:
			v.RemoveFilter(i)
		#
		datafilters.insert(0, datafilters.pop(indexFilter))
		for fId, filterName, graphOver in datafilters:
			v.AddFilter(fId)
			v.SetFilterOverrides(fId, graphOver)

TransactionManager.Instance.TransactionTaskDone()

Important Note
View.GetFilters method don’t return Filters in the order they are applied to a view (in Revit versions prior to 2021)

4 Likes

@c.poupin Amazing, just how I imagined.
The only thing missing is the filter visibility (and IsFilterEnabled for 2021/2022).
Would it be possible for you to add the SetFilterVisibility method so that it’s a perfect solution?

try this
the method is a little different (encapsulation of properties in a Class instance)
Important Note
before Revit 2021, View.GetFilters method don’t return Filters in the order they are applied to a view

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

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

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

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
uidoc = uiapp.ActiveUIDocument
app = uiapp.Application
sdkNumber = int(app.VersionNumber)

class FilterUtils():
	def __init__(self, view):
		self._view = view
		
	@property
	def FilterIds(self):
		filterIds = self._view.GetFilters()
		return filterIds
		
	@property
	def FilterNames(self):
		return [doc.GetElement(x).Name for x in self.FilterIds]
		
	@property
	def FilterOverrides(self):
		return [self._view.GetFilterOverrides(x) for x in self.FilterIds]

	@property
	def FilterVisibity(self):
		return [self._view.GetFilterVisibility(x) for x in self.FilterIds]
		
	@property
	def FilterEnabled(self):
		if sdkNumber > 2020:
			return [self._view.GetIsFilterEnabled(x) for x in self.FilterIds]
		else:
			return [None] * len(self.FilterIds)
		
	def SetFilterOnTop(self, filterName):
		try:
			indexFilter = self.FilterNames.index(serachFilter)
		except ValueError:
			indexFilter = None
		#
		older = self.FilterNames[:]
		if indexFilter is not None and len(self.FilterIds) > 0:
			datafilters = zip(self.FilterIds, self.FilterOverrides, self.FilterVisibity, self.FilterEnabled)
			datafilters.insert(0, datafilters.pop(indexFilter))
			#
			for i in self.FilterIds:
				self._view.RemoveFilter(i)
			#
			for fId, overrideVG, visuVG, fiEnabled in datafilters:
				self._view.AddFilter(fId)
				self._view.SetFilterOverrides(fId, overrideVG)
				self._view.SetFilterVisibility(fId, visuVG)
				if fiEnabled is not None:
					self._view.SetIsFilterEnabled(fId, fiEnabled)
			return self.FilterNames


toList = lambda x : x if hasattr(x, '__iter__') else [x]

lstViews = toList(UnwrapElement(IN[0]))
serachFilter = IN[1]
TransactionManager.Instance.EnsureInTransaction(doc)
for v in lstViews:
	objFi = FilterUtils(v)
	newOrderFilters = objFi.SetFilterOnTop(serachFilter)
TransactionManager.Instance.TransactionTaskDone()	

OUT = newOrderFilters
4 Likes