Challenge: Optimize NoPlot Hooks

I wrote a few hook scripts, doc-printing and file-exporting, that grab anything with the text “NPLT” in the name including lines, families, text, dimensions etc(?) and they also grab all the views in the project, then in each view they hide the NPLT elements. Then doc-printed and/or file-exported undo the above. So to the end-user, it looks like their NPLT just didn’t plot. It’s magic really. :magic_wand:

Lately these pairs of scripts seem to have been running very slow. It’s all my fault though, I couldn’t figure a way around the issue where the exec_param for getting printed views doesn’t seem to give a list of views if the user chooses to combine sheets into one pdf, so I just grab all views and brute force it.

So now to my question, do any of you kind, smart, caring, thoughtful, civic individuals out there have any ideas to fine-tune these scripts? :angel:

I am happy to post all four but they are long-ish. Here’s file-exporting:

__author__ = 'Stewart Cartmell'

from pyrevit import revit
from pyrevit import DB
from pyrevit import script
from pyrevit import EXEC_PARAMS
from System.Collections.Generic import * #use LIST

# determine if file export type is PDF
filetype = str(EXEC_PARAMS.event_args.Format)
if filetype != 'PDF':
    script.exit()

output = script.get_output()

# Close other output when launched several times
close_other_output = output.close_others(all_open_outputs=True)

npId = 'NPLT'

# shortcut for DB.BuiltInParameter
BIP = DB.BuiltInParameter

# current document from event handler
doc = EXEC_PARAMS.event_args.Document

# attempt to get all elements with a type name that contains "NPLT"
param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_TYPE_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId)
param_filter_other = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.BUILDING_CURVE_GSTYLE))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId)
param_filter_curve = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_FAMILY_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId)
param_filter_fam = DB.ElementParameterFilter(param_rule)

np_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_other).WhereElementIsNotElementType().ToElementIds()
#print('Collected {} Model Elements'.format(len(np_element_ids)))
curve_elem_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_curve).WhereElementIsNotElementType().ToElementIds()
#print('Collected {} Curve Elements'.format(len(curve_elem_ids)))
fam_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_fam).WhereElementIsNotElementType().ToElementIds()
#print('Collected {} Family Elements'.format(len(fam_element_ids)))
np_element_ids.AddRange(curve_elem_ids)
np_element_ids.AddRange(fam_element_ids)

#np_group_elems = DB.FilteredElementCollector(doc).OfClass(DB.Group).ToElementIds()
#try removing groups from main NPLT list
#for gId in np_group_elems:
#    np_element_ids.Remove(gId)
#print('Removed {} Group Elements'.format(len(np_group_elems)))
#print('TOTAL NPLT ELEMENTS COLLECTED: {}'.format(len(np_element_ids)))

if np_element_ids.Count > 0:
    #Note! Using EXEC_PARAMS to get printed views does not work
    # for views that are combined into a single pdf when printing
    # so we'll collect all sheets and unhide elements there:
    #Get all sheets in project, including placeholder sheets
    sheetsUnfiltered = DB.FilteredElementCollector(doc) \
                         .OfCategory(DB.BuiltInCategory.OST_Sheets) \
                         .WhereElementIsNotElementType() \
                         .ToElements()
    #print('Collected {} Sheets'.format(sheetsUnfiltered.Count))
    views = DB.FilteredElementCollector(doc) \
              .OfCategory(DB.BuiltInCategory.OST_Views) \
              .WhereElementIsNotElementType() \
              .ToElements()
    #print('Collected {} Views'.format(views.Count))
    #Create empty list to hold all sheets minus placeholder sheets
    all_views = []
    #Filter out placeholder sheets
    #print('Removing Placeholder Sheets')
    for s in sheetsUnfiltered:
        if not s.IsPlaceholder:
            all_views.append(s)
    for v in views:
        all_views.append(v)
    
    #print('TOTAL VIEWS-SHEETS COLLECTED: {}'.format(len(all_views)))
    #all_views = sheetlist.extend(views)
    #print(all_views)
    #print('Checking CanBeHidden...')
    npList = []
    for e in np_element_ids:
        elem = doc.GetElement(e)
        for a in all_views:
            if elem.CanBeHidden(a):
                npList.append(e)
                break
    
    npIds = List[DB.ElementId](npList)
    #print('{} OBJECTS CAN BE HIDDEN'.format(npIds.Count))
    
    # hide elements
    with revit.Transaction("Hide NPLT Elements",doc):
        for a in all_views:
            a.HideElements(npIds)

Here’s the partner to the above hook, file-exported. It unhides all the NPLT items:

__author__ = 'Stewart Cartmell'

from pyrevit import revit
from pyrevit import DB
from pyrevit import script
from pyrevit import HOST_APP, EXEC_PARAMS

# determine if file export type is PDF
filetype = str(EXEC_PARAMS.event_args.Format)
if filetype != 'PDF':
    script.exit()

npId = 'NPLT'

# shortcut for DB.BuiltInParameter
BIP = DB.BuiltInParameter
# importing doc-printing to gain access to it's sheet list

# current document from event handler
doc = EXEC_PARAMS.event_args.Document

# attempt to get all elements with a type name that contains "NPLT"
param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_TYPE_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId)
param_filter_other = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.BUILDING_CURVE_GSTYLE))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId)
param_filter_curve = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_FAMILY_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId)
param_filter_fam = DB.ElementParameterFilter(param_rule)

np_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_other).WhereElementIsNotElementType().ToElementIds()
curve_elem_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_curve).WhereElementIsNotElementType().ToElementIds()
fam_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_fam).WhereElementIsNotElementType().ToElementIds()
np_element_ids.AddRange(curve_elem_ids)
np_element_ids.AddRange(fam_element_ids)

np_group_elems = DB.FilteredElementCollector(doc).OfClass(DB.Group).ToElementIds()
for g in np_group_elems:
    gElem = doc.GetElement(g)
    if npId in gElem.Name:
        np_element_ids.AddRange(gElem.GetMemberIds())

#try removing groups from main NPLT list
for gId in np_group_elems:
    np_element_ids.Remove(gId)

if np_element_ids.Count > 0:
    #Note! Using EXEC_PARAMS to get printed views does not work
    # for views that are combined into a single pdf when printing
    # so we'll collect all sheets and unhide elements there:
    #Get all sheets in project, including placeholder sheets
    sheetsUnfiltered = DB.FilteredElementCollector(doc) \
                         .OfCategory(DB.BuiltInCategory.OST_Sheets) \
                         .WhereElementIsNotElementType() \
                         .ToElements()

    views = DB.FilteredElementCollector(doc) \
              .OfCategory(DB.BuiltInCategory.OST_Views) \
              .WhereElementIsNotElementType() \
              .ToElements()

    #Create empty list to hold all sheets minus placeholder sheets
    sheetlist = []
    #Filter out placeholder sheets
    for s in sheetsUnfiltered:
        if not s.IsPlaceholder:
            sheetlist.append(s)
    
    # unhide elements
    with revit.Transaction("Unhide NPLT Elements",doc):
        for s in sheetlist:
            s.UnhideElements(np_element_ids)
        for v in views:
            v.UnhideElements(np_element_ids)

And here are doc-printing.py and doc-printed.py hooks.

doc-printing first:

__author__ = 'Stewart Cartmell'

from pyrevit import revit
from pyrevit import DB
from pyrevit import EXEC_PARAMS
from pyrevit import script
from System.Collections.Generic import * #use LIST

output = script.get_output()

# Close other output when launched several times
close_other_output = output.close_others(all_open_outputs=True)

npId = 'NPLT'

# shortcut for DB.BuiltInParameter
BIP = DB.BuiltInParameter

# current document from event handler
doc = EXEC_PARAMS.event_args.Document

# attempt to get all elements with a type name that contains "NPLT"
param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_TYPE_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId,False)
param_filter_other = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.BUILDING_CURVE_GSTYLE))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId,False)
param_filter_curve = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_FAMILY_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId,False)
param_filter_fam = DB.ElementParameterFilter(param_rule)

np_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_other).WhereElementIsNotElementType().ToElementIds()
#print('Collected {} Model Elements'.format(len(np_element_ids)))
curve_elem_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_curve).WhereElementIsNotElementType().ToElementIds()
#print('Collected {} Curve Elements'.format(len(curve_elem_ids)))
fam_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_fam).WhereElementIsNotElementType().ToElementIds()
#print('Collected {} Family Elements'.format(len(fam_element_ids)))
np_element_ids.AddRange(curve_elem_ids)
np_element_ids.AddRange(fam_element_ids)

#np_group_elems = DB.FilteredElementCollector(doc).OfClass(DB.Group).ToElementIds()
#try removing groups from main NPLT list
#for gId in np_group_elems:
#    np_element_ids.Remove(gId)
#print('Removed {} Group Elements'.format(len(np_group_elems)))
#print('TOTAL NPLT ELEMENTS COLLECTED: {}'.format(len(np_element_ids)))

if np_element_ids.Count > 0:
    #Note! Using EXEC_PARAMS to get printed views does not work
    # for views that are combined into a single pdf when printing
    # so we'll collect all sheets and unhide elements there:
    #Get all sheets in project, including placeholder sheets
    sheetsUnfiltered = DB.FilteredElementCollector(doc) \
                         .OfCategory(DB.BuiltInCategory.OST_Sheets) \
                         .WhereElementIsNotElementType() \
                         .ToElements()
    #print('Collected {} Sheets'.format(sheetsUnfiltered.Count))
    views = DB.FilteredElementCollector(doc) \
              .OfCategory(DB.BuiltInCategory.OST_Views) \
              .WhereElementIsNotElementType() \
              .ToElements()
    #print('Collected {} Views'.format(views.Count))
    #Create empty list to hold all sheets minus placeholder sheets
    all_views = []
    #Filter out placeholder sheets
    #print('Removing Placeholder Sheets')
    for s in sheetsUnfiltered:
        if not s.IsPlaceholder:
            all_views.append(s)
    for v in views:
        all_views.append(v)
    
    #print('TOTAL VIEWS-SHEETS COLLECTED: {}'.format(len(all_views)))
    #all_views = sheetlist.extend(views)
    #print(all_views)
    #print('Checking CanBeHidden...')
    npList = []
    for e in np_element_ids:
        elem = doc.GetElement(e)
        for a in all_views:
            if elem.CanBeHidden(a):
                npList.append(e)
                break
    
    npIds = List[DB.ElementId](npList)
    #print('{} OBJECTS CAN BE HIDDEN'.format(npIds.Count))
    
    # hide elements
    with revit.Transaction("Hide NPLT Elements",doc):
        for a in all_views:
            a.HideElements(npIds)

And doc-printed to unhide the No-Plot items:

__author__ = 'Stewart Cartmell'

from pyrevit import revit
from pyrevit import DB
from pyrevit import EXEC_PARAMS

npId = 'NPLT'

# shortcut for DB.BuiltInParameter
BIP = DB.BuiltInParameter
# importing doc-printing to gain access to it's sheet list

# current document from event handler
doc = EXEC_PARAMS.event_args.Document

# attempt to get all elements with a type name that contains "NPLT"
param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_TYPE_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId,True)
param_filter_other = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.BUILDING_CURVE_GSTYLE))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId,False)
param_filter_curve = DB.ElementParameterFilter(param_rule)

param_provider = DB.ParameterValueProvider(DB.ElementId(BIP.ALL_MODEL_FAMILY_NAME))
param_rule = DB.FilterStringRule(param_provider,DB.FilterStringContains(),npId,False)
param_filter_fam = DB.ElementParameterFilter(param_rule)

np_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_other).WhereElementIsNotElementType().ToElementIds()
curve_elem_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_curve).WhereElementIsNotElementType().ToElementIds()
fam_element_ids = DB.FilteredElementCollector(doc).WherePasses(param_filter_fam).WhereElementIsNotElementType().ToElementIds()
np_element_ids.AddRange(curve_elem_ids)
np_element_ids.AddRange(fam_element_ids)

np_group_elems = DB.FilteredElementCollector(doc).OfClass(DB.Group).ToElementIds()
for g in np_group_elems:
    gElem = doc.GetElement(g)
    if npId in gElem.Name:
        np_element_ids.AddRange(gElem.GetMemberIds())

#try removing groups from main NPLT list
for gId in np_group_elems:
    np_element_ids.Remove(gId)

if np_element_ids.Count > 0:
    #Note! Using EXEC_PARAMS to get printed views does not work
    # for views that are combined into a single pdf when printing
    # so we'll collect all sheets and unhide elements there:
    #Get all sheets in project, including placeholder sheets
    sheetsUnfiltered = DB.FilteredElementCollector(doc) \
                         .OfCategory(DB.BuiltInCategory.OST_Sheets) \
                         .WhereElementIsNotElementType() \
                         .ToElements()

    views = DB.FilteredElementCollector(doc) \
              .OfCategory(DB.BuiltInCategory.OST_Views) \
              .WhereElementIsNotElementType() \
              .ToElements()

    #Create empty list to hold all sheets minus placeholder sheets
    sheetlist = []
    #Filter out placeholder sheets
    for s in sheetsUnfiltered:
        if not s.IsPlaceholder:
            sheetlist.append(s)
    
    # unhide elements
    with revit.Transaction("Unhide NPLT Elements",doc):
        for s in sheetlist:
            s.UnhideElements(np_element_ids)
        for v in views:
            v.UnhideElements(np_element_ids)