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..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 @@ -1,46 +1,83 @@ __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): - with revit.Transaction("Delete unplaced Views"): - try: - unplaced_names = [] # Get sheet names + 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) + 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 unplaced_views: - name = doc.GetElement(view).Name - doc.Delete(view) # Delete the sheets - unplaced_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 unplaced_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 d520eba..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 @@ -1,35 +1,94 @@ __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: - forms.alert("No empty Sheets, well done!") -else: - if forms.alert(message, ok=False, yes=True, no=True, 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 - # 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).") +# 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: + 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) + 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).")