import clr
# Add reference to necessary Revit API libraries
clr.AddReference("RevitAPI")
clr.AddReference("RevitServices")
# Import necessary Revit namespaces
from Autodesk.Revit.DB import *
from Autodesk.Revit.ApplicationServices import Application
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# Get the current document
uidoc = __revit__.ActiveUIDocument
if uidoc is None:
revit.output.print_warning("No active document detected. Open a Revit project and try again.")
else:
doc = uidoc.Document
# Start a transaction
t = Transaction(doc, "Transfer Level to Shared Parameter")
t.Start()
shared_param_name = "Level" # Ensure this matches the shared parameter you want to use
try:
# Collect rooms in the project
collector = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).WhereElementIsNotElementType()
for room in collector:
# Access the Level parameter (built-in)
room_level_param = room.LookupParameter("Level")
if room_level_param and room_level_param.HasValue:
# Get the Level element from the Level parameter
level = doc.GetElement(room_level_param.AsElementId())
if level:
level_name = level.Name # Extract the name of the Level
# Check if the shared parameter exists on the room element
shared_param = room.LookupParameter(shared_param_name) # Ensure shared param name matches
if shared_param:
if not shared_param.IsReadOnly:
# Set the shared parameter value to the Level name
shared_param.Set(level_name)
# Commit the transaction if all went well
t.Commit()
print("Transaction committed successfully.") # Debugging: log transaction success
except Exception as e:
t.RollBack()
print("Transaction rolled back.") # Debugging: log transaction rollback
Welcome
What is your question @pari2105 ?
Hello@ Jean-Marc
I am novice to Pyrevit.
Trying to copy parameter value from Built-in parameter “Level” to the shared parameter named as “Level” for all rooms.
I am getting message as “Transactions committed successfully”
But level value does not get copied.
Need help on this.
Thanks
Here is a quick and dirty refactor, simplified, pyrevited, pythoned but still needs some love
Have a look at the comments in the code
from pyrevit import HOST, revit, DB
doc = HOST.doc
shared_param_name = "Level_SP" # Should use a different Name from the BuiltIn one!!! and I set it outside the collector loop
# Start a transaction
with revit.Transaction(doc, "Transfer Level to Shared Parameter"):
rooms = DB.FilteredElementCollector(doc).OfCategory(DB.BuiltInCategory.OST_Rooms).WhereElementIsNotElementType()
count_rooms_with_level = 0
for room in rooms:
# Access the Level parameter (built-in)
room_level_param = room.LookupParameter("Level") # the lookupParameter method does not differentiate between builtin or shared parameter when they have the same name, it just takes the first one it finds in the revit DB, always better to use getParameter method whenever possible
if room_level_param and room_level_param.HasValue:
# Get the Level element from the Level parameter
level = doc.GetElement(room_level_param.AsElementId())
if level:
level_name = level.Name # Extract the name of the Level
shared_param = room.LookupParameter(shared_param_name) # Ensure shared param name matches
if shared_param:
if not shared_param.IsReadOnly:
# Set the shared parameter value to the Level name
shared_param.Set(level_name)
count += 1
print("{} rooms levels transfered to the shared parameter".format(count_rooms_with_level))
Thanks a lot @Jean-Marc for you help. It worked perfectly!
May I suggest an improvement?
since there are many rooms in a single level, you could first create a mapping, or lookup table, or in python terms a dictionary, of levels ids and names
from pyrevit.revit import query
# using pyrevit convenience function to get elements of a category
all_levels = query.get_elements_by_categories(
[DB.BuiltInCategory.OST_Levels], doc=doc
)
levels_lookup = {l.Id: l.Name for l in all_levels}
so that when you’re looping through the rooms you only have to read the room_level_param
and obtain the level name.
# using pyrevit convenience function to get elements of a category
all_rooms = query.get_elements_by_categories(
[DB.BuiltInCategory.OST_Rooms], doc=doc
)
for room in all_rooms:
# using pyrevit convenience functions to get the Level value
level_id = query.get_param_value(query.get_param("Level"))
# inverting the if condition to reduce indentation
if not level_id:
continue
# the level name now is one call away
level_name = levels_lookup[level_id]
shared_param = query.get_param(shared_param_name)
# if you have 2 if conditions one next to each other, merge them with an "and"
if not shared_param or not shared_param.IsReadOnly:
continue
# go on with your thing