From bb7723f1b3a87528f5003a7b343904671c630367 Mon Sep 17 00:00:00 2001 From: dariaivanciucova Date: Tue, 27 May 2025 16:17:35 +0100 Subject: [PATCH 1/3] update Purge unused sheets - sheets with schedules (but no viewports) are preserved - option to choose sheets to keep (for Splash Screens) --- .../Purge unused sheets.pushbutton/script.py | 84 ++++++++++++++++--- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py index d520eba..c3d2ca5 100644 --- a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py +++ b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py @@ -1,35 +1,93 @@ __title__ = "Purge unused sheets" -__doc__ = "Delete all the Sheets without Viewports on them." +__doc__ = "Delete all the Sheets without Viewports or schedules on them." from pyrevit import forms from pyrevit import revit, DB from pyrevit.framework import List +from pyrevit.forms import SheetOption, SelectFromList, TemplateListItem uidoc = __revit__.ActiveUIDocument doc = __revit__.ActiveUIDocument.Document -cl = DB.FilteredElementCollector(doc) +FEC = DB.FilteredElementCollector +BIP = DB.BuiltInParameter -sheets = List[DB.ElementId]\ - ([i.Id for i in cl.OfClass(DB.ViewSheet).WhereElementIsNotElementType() if len(i.GetAllViewports()) == 0]) -message = 'There are {} empty Sheets in the current model. Are you sure you want to delete them?'.format(str(len(sheets))) +def get_sheet_nr(sheet_element): + return sheet_element.get_Parameter(BIP.SHEET_NUMBER).AsValueString() -if len(sheets) == 0: + +# custom ViewOption wrapper to display Sheet Number + Name +class SheetViewOption(TemplateListItem): + def __init__(self, view_element): + super(SheetViewOption, self).__init__(view_element) + + @property + def name(self): + """Sheet Number + name""" + return '{} - {}'.format(get_sheet_nr(self.item), revit.query.get_name(self.item)) + + +# custom form to select from a specific list of sheets instead of all sheets in the project +def select_sheets_preserve(title='Select Sheets to preserve', + button_name='Select', + width=600, + multiple=True, + sheets_to_keep=None + ): + selected_sheets = SelectFromList.show( + sorted([SheetViewOption(x) for x in sheets_to_keep], + key=lambda x: x.name), + title=title, + group_selector_title='Sheet Sets:', + button_name=button_name, + width=width, + multiselect=multiple, + checked_only=True + ) + + return selected_sheets + + +# get the sheets with no viewports - this does not pick up sheets with schedules +sheets_with_no_views = [i for i in FEC(doc).OfClass(DB.ViewSheet).WhereElementIsNotElementType() if + len(i.GetAllPlacedViews()) == 0] + +# get the schedules and sheets that they are placed on +schedules = FEC(doc).OfClass(DB.ScheduleSheetInstance).ToElements() +sheets_with_schedules = set() +for sch in schedules: + if sch.IsTitleblockRevisionSchedule: # Skip revision schedules + continue + owner_id = sch.OwnerViewId + if owner_id != DB.ElementId.InvalidElementId: + sheet = doc.GetElement(owner_id) + if isinstance(sheet, DB.ViewSheet): + sheets_with_schedules.add(sheet.Id) # use Id to be able to compare lists + +sheets_with_no_views = [i for i in FEC(doc).OfClass(DB.ViewSheet).WhereElementIsNotElementType() if + len(i.GetAllPlacedViews()) == 0] + +# subtract sheets with schedules from the list of sheets with no viewports +unused_sheets = [i for i in sheets_with_no_views if i.Id not in sheets_with_schedules] + +if len(unused_sheets) == 0: forms.alert("No empty Sheets, well done!") else: - if forms.alert(message, ok=False, yes=True, no=True, exitscript=True): + message = 'There are {} empty Sheets in the current model. Do you choose to proceed?'.format( + str(len(unused_sheets))) + if forms.alert(message, sub_msg="You can select the sheets to keep", ok=False, yes=True, no=True, exitscript=True): + excluded_sheets = select_sheets_preserve(sheets_to_keep=unused_sheets) + sheets_to_purge = List[DB.ElementId]([sh.Id for sh in unused_sheets if sh not in excluded_sheets]) + if not sheets_to_purge: + forms.alert("No Sheets deleted.", exitscript=True) with revit.Transaction(__title__): try: - s_names = [doc.GetElement(s).Title for s in sheets] # Get sheet names - doc.Delete(sheets) # Delete the sheets + s_names = [doc.GetElement(s).Title for s in sheets_to_purge] # Get sheet names + doc.Delete(sheets_to_purge) # Delete the sheets # print result print("SHEETS DELETED:\n") for s in s_names: print("{}".format(s)) except: forms.alert("Could not execute the script (make sure there are no active empty Sheets).") - - - - From e7ebb4196e17762497b260171c51e1846885cfdb Mon Sep 17 00:00:00 2001 From: dariaivanciucova Date: Wed, 28 May 2025 17:54:53 +0100 Subject: [PATCH 2/3] Update purge views - removed the View Templates from the list of views to purge - added option to keep the views from purging --- .../Purge unplaced views.pushbutton/script.py | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py index 4530767..49ec147 100644 --- a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py +++ b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py @@ -1,46 +1,82 @@ __title__ = "Purge unplaced Views" __doc__ = "Delete all Views which have not been placed onto Sheets." +import sys + from pyrevit import forms from pyrevit import revit, DB from pyrevit.framework import List +from pyrevit.forms import SheetOption, SelectFromList, TemplateListItem uidoc = __revit__.ActiveUIDocument doc = __revit__.ActiveUIDocument.Document cl = DB.FilteredElementCollector(doc) -viewports = List[DB.ElementId]\ + +# name wrapper for forms +class ViewOption(TemplateListItem): + def __init__(self, view_element): + super(ViewOption, self).__init__(view_element) + + @property + def name(self): + """View Name""" + return '{}'.format(revit.query.get_name(doc.GetElement(self.item))) + + +# custom form to select from a specific list of sheets instead of all sheets in the project +def select_views_to_preserve(title='Select Sheets to preserve', + button_name='Select Views to Keep', + width=600, + multiple=True, + sheets_to_keep=None + ): + selected_sheets = SelectFromList.show( + sorted([ViewOption(x) for x in sheets_to_keep], + key=lambda x: x.name), + title=title, + button_name=button_name, + width=width, + multiselect=multiple, + checked_only=True + ) + + return selected_sheets + + +viewports = List[DB.ElementId] \ ([i.ViewId for i in cl.OfCategory(DB.BuiltInCategory.OST_Viewports).WhereElementIsNotElementType()]) -views = List[DB.ElementId]\ - ([i.Id for i in DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Views).WhereElementIsNotElementType()]) +views = List[DB.ElementId] \ + ([i.Id for i in + DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Views).WhereElementIsNotElementType() if + not i.IsTemplate]) unplaced_views = List[DB.ElementId]([v for v in views if v not in viewports]) -message = 'There are {} unplaced Views in the current model. Are you sure you want to delete them?'.format(str(len(unplaced_views))) +message = 'There are {} unplaced Views in the current model. Are you sure you want to delete them?'.format( + str(len(unplaced_views))) if len(unplaced_views) == 0: - forms.alert("No unpolaced Views, well done!") + forms.alert("No unplaced Views, well done!") else: - if forms.alert(message, ok=False, yes=True, no=True, exitscript=True): + if forms.alert(message, sub_msg="You can select the views to keep. If you select none, all views will be purged.", ok=False, yes=True, no=True, exitscript=True): + excluded_views = select_views_to_preserve(sheets_to_keep=unplaced_views) + views_to_purge = List[DB.ElementId]([v for v in unplaced_views if v not in excluded_views]) with revit.Transaction("Delete unplaced Views"): try: - unplaced_names = [] # Get sheet names + purged_names = [] # Get sheet names try: - for view in unplaced_views: + for view in views_to_purge: name = doc.GetElement(view).Name doc.Delete(view) # Delete the sheets - unplaced_names.append(name) + purged_names.append(name) except: pass # print result print("VIEWS DELETED:\n") - for s in unplaced_names: + for s in purged_names: print("{}".format(s)) except: forms.alert("Could not execute the script.") - - - - From 2186cee1fc110c946299e3a41d32289bd32f38e0 Mon Sep 17 00:00:00 2001 From: dariaivanciucova Date: Wed, 28 May 2025 18:03:14 +0100 Subject: [PATCH 3/3] avoid error when closing Forms window --- .../Purge unplaced views.pushbutton/script.py | 31 ++++++++++--------- .../Purge unused sheets.pushbutton/script.py | 27 ++++++++-------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py index 49ec147..ecd3504 100644 --- a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py +++ b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unplaced views.pushbutton/script.py @@ -63,20 +63,21 @@ def select_views_to_preserve(title='Select Sheets to preserve', else: if forms.alert(message, sub_msg="You can select the views to keep. If you select none, all views will be purged.", ok=False, yes=True, no=True, exitscript=True): excluded_views = select_views_to_preserve(sheets_to_keep=unplaced_views) - views_to_purge = List[DB.ElementId]([v for v in unplaced_views if v not in excluded_views]) - with revit.Transaction("Delete unplaced Views"): - try: - purged_names = [] # Get sheet names + if excluded_views is not None: + views_to_purge = List[DB.ElementId]([v for v in unplaced_views if v not in excluded_views]) + with revit.Transaction("Delete unplaced Views"): try: - for view in views_to_purge: - name = doc.GetElement(view).Name - doc.Delete(view) # Delete the sheets - purged_names.append(name) + purged_names = [] # Get sheet names + try: + for view in views_to_purge: + name = doc.GetElement(view).Name + doc.Delete(view) # Delete the sheets + purged_names.append(name) + except: + pass + # print result + print("VIEWS DELETED:\n") + for s in purged_names: + print("{}".format(s)) except: - pass - # print result - print("VIEWS DELETED:\n") - for s in purged_names: - print("{}".format(s)) - except: - forms.alert("Could not execute the script.") + forms.alert("Could not execute the script.") diff --git a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py index c3d2ca5..5c77e21 100644 --- a/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py +++ b/pyChilizer.tab/Project.panel/Purge +.pulldown/Purge unused sheets.pushbutton/script.py @@ -78,16 +78,17 @@ def select_sheets_preserve(title='Select Sheets to preserve', str(len(unused_sheets))) if forms.alert(message, sub_msg="You can select the sheets to keep", ok=False, yes=True, no=True, exitscript=True): excluded_sheets = select_sheets_preserve(sheets_to_keep=unused_sheets) - sheets_to_purge = List[DB.ElementId]([sh.Id for sh in unused_sheets if sh not in excluded_sheets]) - if not sheets_to_purge: - forms.alert("No Sheets deleted.", exitscript=True) - with revit.Transaction(__title__): - try: - s_names = [doc.GetElement(s).Title for s in sheets_to_purge] # Get sheet names - doc.Delete(sheets_to_purge) # Delete the sheets - # print result - print("SHEETS DELETED:\n") - for s in s_names: - print("{}".format(s)) - except: - forms.alert("Could not execute the script (make sure there are no active empty Sheets).") + if excluded_sheets is not None: + sheets_to_purge = List[DB.ElementId]([sh.Id for sh in unused_sheets if sh not in excluded_sheets]) + if not sheets_to_purge: + forms.alert("No Sheets deleted.", exitscript=True) + with revit.Transaction(__title__): + try: + s_names = [doc.GetElement(s).Title for s in sheets_to_purge] # Get sheet names + doc.Delete(sheets_to_purge) # Delete the sheets + # print result + print("SHEETS DELETED:\n") + for s in s_names: + print("{}".format(s)) + except: + forms.alert("Could not execute the script (make sure there are no active empty Sheets).")