Script causing revit to bug out with blue spinning circle

I have the following code below. It allows the user to select a first element’s selected parameter (example: comment) and push it to a second element’s selected parameter (example: mark).

the code works as I expect it to, however, after it has been executed, Revit will show the blue spinning circle like it’s still thinking or something. it goes on and off every few seconds. I hit escape but it still happens.

Any suggestions on what might be causing this?

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI.Selection import *
from pyrevit import revit, forms

# Function to get parameter names from an element
def get_parameter_names(element):
    parameter_names = []
    parameters = element.Parameters
    for parameter in parameters:
        parameter_names.append(parameter.Definition.Name)
    return sorted(parameter_names)  # Sort the parameter names alphabetically

# Function to select an element
def select_element(prompt):
    uidoc = __revit__.ActiveUIDocument
    reference = uidoc.Selection.PickObject(ObjectType.Element, prompt)
    return uidoc.Document.GetElement(reference.ElementId)

# Get the active UIDocument
uidoc = __revit__.ActiveUIDocument

# Prompt user to select the first element
first_selected_element = select_element("Select the first element")

if first_selected_element:
    # Get parameter names from the first selected element
    parameter_names_first = get_parameter_names(first_selected_element)

    # Allow the user to select a parameter from the dropdown list for the first element
    selected_parameter_name_first = forms.SelectFromList.show(parameter_names_first, 
                                                        title="Select Parameter for the first element", 
                                                        multiselect=False)

    if selected_parameter_name_first:
        # Get the parameter object for the selected parameter for the first element
        parameter_first = first_selected_element.LookupParameter(selected_parameter_name_first)
        if parameter_first:
            # Get the parameter value of the first element
            parameter_value_first = parameter_first.AsString()

            # Prompt user to select the second element
            second_selected_element = select_element("Select the second element")

            if second_selected_element:
                # Get parameter names from the second selected element
                parameter_names_second = get_parameter_names(second_selected_element)

                # Allow the user to select a parameter from the dropdown list for the second element
                selected_parameter_name_second = forms.SelectFromList.show(parameter_names_second, 
                                                            title="Select Parameter for the second element", 
                                                            multiselect=False)

                if selected_parameter_name_second:
                    # Get the parameter object for the selected parameter for the second element
                    parameter_second = second_selected_element.LookupParameter(selected_parameter_name_second)
                    if parameter_second:
                        # Set the parameter value of the second element to be the same as the first element
                        t = Transaction(uidoc.Document, "Replace Parameter Value")
                        t.Start()
                        parameter_second.Set(parameter_value_first)
                        t.Commit()
                        print("Parameter value of the second element replaced with the value of the first element.")
                    else:
                        print("Parameter not found for the second element.")
                else:
                    print("No parameter selected for the second element.")
            else:
                print("No second element selected.")
        else:
            print("Parameter not found for the first element.")
    else:
        print("No parameter selected for the first element.")
else:
    print("No first element selected.")
1 Like

@Ralph1024 ,

there are a concept of set a parameter, i use regulary try statements like this:

# 🔓 SET PARAMETER
t = Transaction(doc, "set room bounding")
t.Start()

for d in selected_walls:
    try:
        door_out_param = d.get_Parameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING).Set(False)
    except:
        print("not possible")

t.Commit()
# 🔒 Done

Hi @Ralph1024, I honestly don’t know what happens to you, but I can give you some unsolicited advices:

  • use pyrevit’s pick_element in place you your select_element function
  • use pyrevit’sTransaction which will automatically start and commit (or rollback) if used as a context manager (with Transaction: ...)
  • avoid all that nesting by enclosing the code in a main function, invert all the ifs and return after printing the error messages. You will notice that you have repeated code that can be turned into a function with the order as parameter (“first” or “second”) that returns the parameter of the element.
def pick_element_parameter(order):
    selected_element = pick_element("Select the {} element".format(order))
    if not selected_element:
        print("No {} element selected.".format(order))
        return
    # Get parameter names from the selected element
    parameter_names = get_parameter_names(selected_element)
    # Allow the user to select a parameter from the dropdown list for the element
    selected_parameter_name = forms.SelectFromList.show(
        parameter_names,
        title="Select Parameter for the {} element".format(order), 
        multiselect=False,
    )
    if not selected_parameter_name:
        print("No parameter selected for the {} element.".format(order))
        return
    # Get the parameter object for the selected parameter for the first element
    return selected_element.LookupParameter(selected_parameter_name)

def main():
    parameter_first = pick_element_parameter("first")
    if not parameter_first:
        print("Parameter not found for the first element.")
        return
    parameter_second = pick_element_parameter("second")
    if not parameter_second:
        print("Parameter not found for the second element.")
        return
   # Set the parameter value of the second element to be the same as the first element
   with Transaction("Replace Parameter Value"):
        parameter_second.Set(parameter_first.AsString())
        print("Parameter value of the second element replaced with the value of the first element.")

Note that the checks in the main function are redundant, since the parameter is chosen from the list of available parameters of the element.

Thank you for the advice @andreasd811 and @sanzoghenzo, I am always looking for ways to improve. I will definitely implement some of these techniques.

I am also looking into finding ways to auto update parameters. so as i mentioned in the original post, a parameter from the first element is pushed into the second element. but now i’d like to include some auto updating function so that if the parameter of the first element changes, the parameter of the second element also changes, without me having to run the script again.

You can use the userconfig module to store the selected elements (Id or even better UniqueId) and parameters (or maybe you’ll be fine with just the parameters); then use an hook to trigger the update. I would use the doc closing or doc saving hook because triggering it for each document change would be overkill.