Group Filtered Elements in different list from uidoc selection : pyrevit forms

Hello,

I am using ui.doc method to pick Elements from Revit and have a class customISelectionFilter
which selects the Elements by MultiCategory. I am looking to group them in a list based on their categories after selection. Can anyone help me with this

This line does the selection from pyrevit forms.
sel_filteredElements = uidoc.Selection.PickObjects(ObjectType.Element,sel_filters,“Select your objects”)

You’ll need to do the sorting after the selection.
You can use an if elif elif else to parse the list into different groups (lists) and then put them all in one list or as a list of tuples.

You can’t do the sorting during.g the selection. Revit pretty much adds them in the order picked.

1 Like

I also find it nicer for the end use if they follow the standard selection path of Revit
If there are already elements selected - use that.
I’d no objects are selected - wait for a user selection (as you are doing.)
The same grouping and filtering works for either method the user chooses.

For instance, if the user has text, dimensions and walls selected, and my app oy wants walls and dimensions, I’ll group the walls and dimensions and skip the text as I sort. Saves a bunch of time for the user in case they pick poorly.

1 Like

Can you please help me solve this? @GavinCrump I was following your tutorial on CustomISelection and I want to print the Element Categories and also generate a Schedule based on selection from uidoc in pyrevit forms . Let me know if you can help

My code is below:

	user_filters = CustomISelectionFilter(chosen)
		
        sel_filteredElements = uidoc.Selection.PickObjects(ObjectType.Element,user_filters,"Select your objects")
		
        forms.alert('Done with Selection?',ok = False, yes = True, no = True, exitscript = True)

        print("This prints the List of the PickedObjects from user UI selection ")
		
        print("\n")
        print(sel_filteredElements)
        print("\n")
		
        print("This prints the Category of the PickedObjects ")
		
		#Print the Category of the PickedObjects from the UI selection
        for elements in sel_filteredElements:
            print(elements.Element.Category.Name)

        # Sort the selected objects by their categories
        sort_sel_filteredElements = sorted(sel_filteredElements, key=lambda obj: obj.Element.Category.Name)

        #print(sort_sel_filteredElements)

        #print("Quantities of the Selected Objects is :{}".format(len(sel_filteredElements)))

        # Iterate over the sorted objects and count the quantities for each category
        for category_name in tochoose:
            category_count = sum(1 for obj in sorted_objects if obj.Element.Category.Name == category_name)
            quantities[category_name] = category_count

        # Print the quantities specific to categories
        for category_name, quantity in quantities.items():
            print("{}: {}".format(category_name, quantity))

and for ISelection the code is:

tochoose = ["Walls","Structural Foundations","Structural Framing","Roofs","Structural Columns"]
		
		chosen = forms.SelectFromList.show(tochoose,title = "Choose Categories for Schedule", width= 300,
                                         height = 500,button_name = "Make a Selection",multiselect = True)

@AshindeExd to get you started: Erik Frits on LinkedIn: #learnrevitapi #revitapi #revit #pyrevit
by @ErikFrits

1 Like

Just got pinged on this so assume I’ve been freshly tagged. Apologies if this is thread necromancy.

This is the code I use for mulit-category selection. In my case I use that as a filtering mechanism and only limit to common ones my firm uses, but you could use other methods such as asking your document for its categories using API.

# import pyrevit libraries
from pyrevit import forms,revit,DB,script
from Autodesk.Revit.UI.Selection import *

# Revit doc and UIdoc
doc = revit.doc
uidoc = revit.uidoc

# Custom selection filter class
class CustomISelectionFilter(ISelectionFilter):
    def __init__(self, nom_category):
        self.nom_category = nom_category
    def AllowElement(self, e):
        if e.Category.Name in self.nom_category:
            return True
        else:
            return False

# List of options
catOptions = ["Areas","Casework","Ceilings","Curtain Panels","Curtain Wall Grids",
			  "Curtain Wall Mullions","Doors","Floors","Furniture","Generic Models",
			  "Plumbing Fixtures","Roofs","Specialty Equipment","Walls","Windows"]

# Message for selection
selmsg = forms.SelectFromList.show(catOptions, title= "Select categories", width=500, button_name = "Choose categories", multiselect = True)

# Proceed if message accepted
if selmsg:
	sel = None
	with forms.WarningBar(title='Select objects, then press \'Finish\':'):
		try:
			selFil = CustomISelectionFilter(selmsg)
			sel = uidoc.Selection.PickObjects(ObjectType.Element,selFil,"Select elements")
		except:
			pass
else:
	script.exit()

if not sel:
	script.exit()

# Libraries for selection
import System
from System.Collections.Generic import List

# Empty ID list
elementIds = List[DB.ElementId]()

# Try to get elements for selection
for s in sel:
	try:
		id = s.ElementId
		el = doc.GetElement(id)
		elementIds.Add(id)
	except:
		pass

That would yield all prefiltered selected elements, from then which you can write a csv file for use in Excel by iterting over potentially. You can’t generate Revit schedules for this sort of output, schedules are limited to their own filtering/sorting etc.