Help with custom pyRevit Extension

I’m reaching out for assistance with troubleshooting errors in a custom tool we’ve developed. We’ve begun creating our own tools, but several projects utilizing this specific tool are encountering an error. All projects are within ACC and configured identically. The error only occurs on some projects, and occasionally resolves itself.

The tool’s function is to hide all text, detail components, and symbols with “H4P” (Hide for Print) at the end of their type name. This enables us to include internal comments on construction documents that we can address during the project, while preventing these items from printing on external drawings.
Error is
“One if the elements cannot be hidden.
Parameter name: elementldSet”

Additionally, we have two separate tools: one to hide all “H4P” items and one to reveal them. Is it possible to combine these into a single tool with an indicator of its active state?

Thank you for your time and any guidance you can provide.

Here is the Hide4Print Script
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import TaskDialog
import clr
clr.AddReference(“System”)
from System.Collections.Generic import List

Access Revit document, UIDocument, and Application

doc = revit.ActiveUIDocument.Document
uidoc = revit.ActiveUIDocument
app = revit.Application

def get_elements_by_type_name(type_name):
“”"
Retrieves element IDs from the Revit document where the element type name matches type_name.
“”"
try:
# Parameter to filter by element type name
p_type_id = ElementId(BuiltInParameter.SYMBOL_NAME_PARAM)
f_param = ParameterValueProvider(p_type_id)
evaluator = FilterStringContains()
value = type_name

    # Handle version-specific differences in FilterStringRule
    rvt_year = int(app.VersionNumber)
    if rvt_year >= 2023:
        f_rule = FilterStringRule(f_param, evaluator, value)
    else:
        f_rule = FilterStringRule(f_param, evaluator, value, False)

    filter_type_name = ElementParameterFilter(f_rule)

    # Collect and return element IDs
    element_ids = FilteredElementCollector(doc).WherePasses(filter_type_name).WhereElementIsNotElementType().ToElementIds()
    return element_ids

except Exception as e:
    # Handle any errors that occur
    TaskDialog.Show("Error", str(e))
    return []

def hide_element_in_drafting_views(element_ids, doc_hide):
# Start a transaction to modify the document
t = Transaction(doc_hide, “Hide Elements in Drafting Views”)
t.Start()

try:
    # Collect all drafting views
    drafting_views = FilteredElementCollector(doc_hide).OfClass(ViewDrafting).ToElements()
    # Collect all Sheet views
    sheet_views = FilteredElementCollector(doc_hide).OfClass(ViewSheet).ToElements()
    # Collect all Sheet views
    plan_views = FilteredElementCollector(doc_hide).OfClass(ViewPlan).ToElements()
    # Collect all legend views
    legend_views = FilteredElementCollector(doc_hide).OfClass(View).ToElements()
    legend_views = [v for v in legend_views if v.ViewType == ViewType.Legend]

    # Iterate through each drafting view
    for view in drafting_views:
        # Hide the elements in the view
        view.HideElements(element_ids)

    # Iterate through each sheet view
    for view in sheet_views:
        # Hide the elements in the view
        view.HideElements(element_ids)

    # Iterate through each sheet view
    for view in plan_views:
        # Hide the elements in the view
        view.HideElements(element_ids)

     # Iterate through each sheet view
    for view in legend_views:
        # Hide the elements in the view
        view.HideElements(element_ids)

    t.Commit()  # Commit the transaction
except Exception as e:
    t.RollBack()  # Rollback if there's an error
    TaskDialog.Show("Error", str(e))

def select_elements(type_name):
# Get the current document and application
uiapp = revit.ActiveUIDocument.Application
doc_hide = uiapp.ActiveUIDocument.Document

# Get elements by type name
element_ids = get_elements_by_type_name(type_name)

# Call the function to hide the element
hide_element_in_drafting_views(element_ids, doc_hide)

Call function to select elements with specified type name

type_name = ‘H4P’
select_elements(type_name)

Here is the Unhide script

from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import TaskDialog
import clr
clr.AddReference(“System”)
from System.Collections.Generic import List

Access Revit document, UIDocument, and Application

doc = revit.ActiveUIDocument.Document
uidoc = revit.ActiveUIDocument
app = revit.Application

def get_elements_by_type_name(type_name):
“”"
Retrieves element IDs from the Revit document where the element type name matches type_name.
“”"
try:
# Parameter to filter by element type name
p_type_id = ElementId(BuiltInParameter.SYMBOL_NAME_PARAM)
f_param = ParameterValueProvider(p_type_id)
evaluator = FilterStringContains()
value = type_name

    # Handle version-specific differences in FilterStringRule
    rvt_year = int(app.VersionNumber)
    if rvt_year >= 2023:
        f_rule = FilterStringRule(f_param, evaluator, value)
    else:
        f_rule = FilterStringRule(f_param, evaluator, value, False)

    filter_type_name = ElementParameterFilter(f_rule)

    # Collect and return element IDs
    element_ids = FilteredElementCollector(doc).WherePasses(filter_type_name).WhereElementIsNotElementType().ToElementIds()
    return element_ids

except Exception as e:
    # Handle any errors that occur
    TaskDialog.Show("Error", str(e))
    return []

def hide_element_in_drafting_views(element_ids, doc_hide):
# Start a transaction to modify the document
t = Transaction(doc_hide, “Hide Elements in Drafting Views”)
t.Start()

try:
    # Collect all drafting views
    drafting_views = FilteredElementCollector(doc_hide).OfClass(ViewDrafting).ToElements()
    # Collect all Sheet views
    sheet_views = FilteredElementCollector(doc_hide).OfClass(ViewSheet).ToElements()
    # Collect all Sheet views
    plan_views = FilteredElementCollector(doc_hide).OfClass(ViewPlan).ToElements()
    # Collect all legend views
    legend_views = FilteredElementCollector(doc_hide).OfClass(View).ToElements()
    legend_views = [v for v in legend_views if v.ViewType == ViewType.Legend]

    # Iterate through each drafting view
    for view in drafting_views:
        # Hide the elements in the view
        view.UnhideElements(element_ids)

    # Iterate through each sheet view
    for view in sheet_views:
        # Hide the elements in the view
        view.UnhideElements(element_ids)

    # Iterate through each sheet view
    for view in plan_views:
        # Hide the elements in the view
        view.UnhideElements(element_ids)

     # Iterate through each sheet view
    for view in legend_views:
        # Hide the elements in the view
        view.UnhideElements(element_ids)

    t.Commit()  # Commit the transaction
except Exception as e:
    t.RollBack()  # Rollback if there's an error
    TaskDialog.Show("Error", str(e))

def select_elements(type_name):
# Get the current document and application
uiapp = revit.ActiveUIDocument.Application
doc_hide = uiapp.ActiveUIDocument.Document

# Get elements by type name
element_ids = get_elements_by_type_name(type_name)

# Call the function to hide the element
hide_element_in_drafting_views(element_ids, doc_hide)

Call function to select elements with specified type name

type_name = ‘H4P’
select_elements(type_name)

Sincerely,

Matthew

A lot of possibilities. I’d suggest returning the element id in your error trapping. Then you can see what is causing the issue.
Could be that the element is part of a group.
Could be that the element is not editable. Maybe checked out or otherwise not available.
Could be the element isn’t already visible, hidden by some other operation.

You are filtering elements at the document level. So not all of those elements are present in each of the views. You can’t hide it in that view if it doesn’t exist in that view. You could run the filter at the view level (FilteredElementCollector(doc, myViewId). This would limit the number of elements you are iterating to only those in each view. Might run faster or not. Sometimes you have to check the performance on getting everything once and then using that over and over. Or getting things in smaller chunks, but more often.

Revit also has a habit of orphaning elements when a view is radically changed. Rare, but I’ve seen this with filled regions on a section that was later rotated. The element exists but is no longer visible in any view.

Thank you for your assistance. I have found that the issues is that the code is not hiding dimension styles. I will just have to figure out what code I need to add to accomplish this.

Hmmm pretty cluttered coding (not trying to be rude, but it feels not logical to me :slight_smile: )

Assuming you want IF h4p hidden to unhide it, ELSE hide them.
Below my attempt (quick n dirty, could be improved). You can call the function H4P of any number of views.

from pyrevit import revit, DB
from pyrevit.framework import List


def getviewdependentelements(elements):
    return [element for element in elements if element.ViewSpecific]

KEYWORD = "H4P"

def H4P(elements, view):
    keywordelements = []
    keywordishidden = []

    for c in getviewdependentelements(elements):
        if not hasattr(c, "Name"):
            continue
        if KEYWORD not in c.Name:
            continue
        keywordelements.append(c.Id)           
        keywordishidden.append(True) if c.IsHidden(view) else False        

    if not keywordelements:
        print "no items with keyword '{}' found".format(KEYWORD)
        return
    
    with revit.Transaction("PA_unhidelements"):
        if any(keywordishidden):
            view.UnhideElements(List[DB.ElementId](keywordelements))
        else:        
            view.HideElements(List[DB.ElementId](keywordelements))

if __name__ == "__main__":		
    collector = DB.FilteredElementCollector(revit.doc).WhereElementIsNotElementType().ToElements()
    testview = revit.active_view
    H4P(collector, testview)

Yes, I agree that the coding appears quite cluttered. I’m currently working on improving code that was written by another member of our team. I’ll certainly give your suggestion a try. Thanks for your input.