Sort View Filters by input

Try this version

  • EDIT 29/04/2023 (code fixed for CPython3)
  • EDIT 29/04/2023 (code fixed for _alphanum_key)
import clr
import sys
import re
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 _alphanum_key(self): 
		convert = lambda text: int(text) if text.isdigit() else text.lower()
		# apply the function only at the 1st items
		alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key[0])]
		return alphanum_key
		
	def SetFilterOrder(self, lst_newOrder_Name = []):
		"""
		set order by input list filter Name -> lst_newOrder_Name
		if lst_newOrder_Name is empty -> set order by FilterName
		reurn new order filter name
		"""
		lst_datafilters = list(zip(self.FilterNames, self.FilterIds, self.FilterOverrides, self.FilterVisibity, self.FilterEnabled))
		if len(lst_newOrder_Name) == len(lst_datafilters):
			lst_datafilters.sort(key = lambda x : lst_newOrder_Name.index(x[0]))
		else:
			lst_datafilters.sort(key = self._alphanum_key())
		#
		# remove filters
		for i in self.FilterIds:
			self._view.RemoveFilter(i)
		#
		# set the new order
		for f_Name, fId, overrideVG, visuVG, fiEnabled in lst_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 [x[0] for x in lst_datafilters]

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

lstViews = toList(UnwrapElement(IN[0]))
try:
	lst_newOrder_Name = toList(IN[1])
except:
	lst_newOrder_Name = []

TransactionManager.Instance.EnsureInTransaction(doc)
for v in lstViews:
	objFi = FilterUtils(v)
	newOrderFilters = objFi.SetFilterOrder(lst_newOrder_Name)
TransactionManager.Instance.TransactionTaskDone()	

OUT = newOrderFilters
3 Likes