Wait for user response

Hello,

I am trying to call the “Purge Unused” command via a script. As we all know this needs to run multiple times in order to purge all the unused elements. So I though i put it in a while loop to run it 5 times. But the script runs whitout waiting for the user’s response, ie clicking “OK” on the purge unused dialoge box


therefore I end up with this error

here is the code I have used

from pyrevit import UI, HOST_APP
uiapp = HOST_APP.uiapp

purge_count = 5
while purge_count > 0:
    uiapp.PostCommand(UI.RevitCommandId.LookupCommandId("ID_PURGE_UNUSED"))
    purge_count -= 1

I could be wrong, but I think I need to add a line in the while loop to wait for user to click on ok.
Thanks for your help in advance

Why don’t you use GetUnusedElement()?

It provide a decent C# example that you can easily translate with an LLM

Rough guess, you may have to wrap your while loop in a Transaction?

1 Like

Hi Hoss,

Here is a version that purges unused in either a quick or deep way (so recursive):

import clr
from System.Collections.Generic import List
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import FilteredElementCollector, PerformanceAdviser, PerformanceAdviserRuleId, Transaction, ElementId, BuiltInCategory, HostObjAttributes, Material, AppearanceAssetElement, PropertySetElement, View, ParameterFilterElement, LinePatternElement
import sys


doc = __revit__.ActiveUIDocument.Document
inputdoc = doc

from pyrevit import forms

# Set bool to True
bool = True

# Create a PyRevit form to ask the user to choose between a deep purge and a quick purge
deep_purge_option = "Deep Purge"
quick_purge_option = "Quick Purge"
selected_option = forms.CommandSwitchWindow.show(
    [deep_purge_option, quick_purge_option],
    message='Choose the type of purge you would like to perform:',
    title='Purge Options'
)

if selected_option == deep_purge_option:
    deeply = True
elif selected_option == quick_purge_option:
    deeply = False
else:
    # If the user cancels the form, exit the script without doing any purge
    sys.exit()
    
#GetPurgeableElements
def GetPurgeableElements(doc, rule_id_list):
	failure_messages = PerformanceAdviser.GetPerformanceAdviser().ExecuteRules(doc, rule_id_list)
	if failure_messages.Count > 0:
		purgeable_element_ids = failure_messages[0].GetFailingElements()
		return purgeable_element_ids

#A constant 
PURGE_GUID = "e8c63650-70b7-435a-9010-ec97660c1bda"

#A generic list of PerformanceAdviserRuleIds as required by the ExecuteRules method
rule_id_list = List[PerformanceAdviserRuleId]()

#Iterating through all PerformanceAdviser rules looking to find that which matches PURGE_GUID
for rule_id in PerformanceAdviser.GetPerformanceAdviser().GetAllRuleIds():
	if str(rule_id.Guid) == PURGE_GUID:
		rule_id_list.Add(rule_id)
		break

#Attempting to retrieve the elements which can be purged
purgeable_element_ids = GetPurgeableElements(doc, rule_id_list)

trans = Transaction(doc,'Purge')
trans.Start()

if bool and purgeable_element_ids != None:
	doc.Delete(purgeable_element_ids)

#Materials to delete
toKeep=[]
elements = FilteredElementCollector(doc).WhereElementIsElementType().ToElements()
for elem in elements:
	matlist=[]
	for matid in elem.GetMaterialIds(False):
		matlist.append(matid)
	toKeep.extend(matlist)

compound=FilteredElementCollector(doc).OfClass(HostObjAttributes).WhereElementIsElementType().ToElements()
compoundStructure = [comp.GetCompoundStructure() for comp in compound]
for compoundStr in compoundStructure:
	if compoundStr != None:
		layerCount=compoundStr.LayerCount
		for j in range (0, layerCount):
			if compoundStr.GetMaterialId(j) != ElementId(-1):
				toKeep.append(compoundStr.GetMaterialId(j))

materials = FilteredElementCollector(doc).OfClass(Material).ToElementIds()

#Assets to delete
appearanceAssetIds = FilteredElementCollector(doc).OfClass(AppearanceAssetElement).ToElementIds()
#The PropertySetElement contains either the Thermal or Structural Asset
propertySet = FilteredElementCollector(doc).OfClass(PropertySetElement).ToElementIds()

thermal=[doc.GetElement(id).ThermalAssetId for id in set(toKeep)]
structural=[doc.GetElement(id).StructuralAssetId for id in set(toKeep)]
appearanceAssets=[doc.GetElement(id).AppearanceAssetId for id in set(toKeep)]

propertySet2 = [e for e in propertySet if e not in thermal and e not in structural]
appearanceAssetIds2 = [e for e in appearanceAssetIds if e not in appearanceAssets]
matToDelete=[m for m in materials if not m in toKeep]

views = FilteredElementCollector(doc).OfClass(View).WhereElementIsNotElementType().ToElements()

#Unused filters to delete
filterIds = FilteredElementCollector(doc).OfClass(ParameterFilterElement).ToElementIds()

usedFilterIds = []
if not doc.IsFamilyDocument:
	for view in views:
		viewFilterIds = []
		if view.AreGraphicsOverridesAllowed():
			viewFilterIds = view.GetFilters()
		usedFilterIds.extend(viewFilterIds)
unusedFilterIds = [u for u in filterIds if u not in usedFilterIds]
	
#Unused view Templates to delete
appliedtemplates = [v.ViewTemplateId for v in views]
templates = [v.Id for v in views if v.IsTemplate == True]
templatesToDelete = [t for t in templates if t not in appliedtemplates]

#LinePatterns to delete
linePatterns = FilteredElementCollector(doc).OfClass(LinePatternElement).ToElements()
linesToDelete = [l.Id for l in linePatterns if l.Name.startswith("IMPORT")]

#"Imports in Families" Object Styles to delete
ImportCat = doc.Settings.Categories.get_Item(BuiltInCategory.OST_ImportObjectStyles)
importsInFamily=[c.Id for c in ImportCat.SubCategories]

if bool and matToDelete != None:
	[doc.Delete(m) for m in matToDelete]
if bool and appearanceAssetIds2 != None:
	for a in appearanceAssetIds2:
		try:doc.Delete(a)
		except:pass
if bool and propertySet2 != None:
	[doc.Delete(p) for p in propertySet2]
if deeply and unusedFilterIds != None:
	[doc.Delete(u) for u in unusedFilterIds]
if deeply and templatesToDelete != None:
	[doc.Delete(t) for t in templatesToDelete]
if deeply and linesToDelete != None:
	[doc.Delete(l) for l in linesToDelete]
if deeply and importsInFamily != None:
	[doc.Delete(i) for i in importsInFamily]

trans.Commit()
2 Likes