Get Area parameter and populate it to room Parameter

Hi all, I am trying to get Room that is inside the Area(rentable) to fill the Parameter of area"Color" to Room

# Add this import at the beginning of your script
from Autodesk.Revit.DB import ElementSet
from pyrevit import revit, DB

def get_rooms():
    return DB.FilteredElementCollector(revit.doc).OfCategory(DB.BuiltInCategory.OST_Rooms).ToElements()

def get_area():
    return DB.FilteredElementCollector(revit.doc).OfCategory(DB.BuiltInCategory.OST_Areas).ToElements()

def set_room_department(room, color_parameter_value):
    room.Parameter[DB.BuiltInParameter.ROOM_DEPARTMENT].Set(color_parameter_value)

def process_views():
    views = DB.FilteredElementCollector(revit.doc).OfClass(DB.View).ToElements()

    for view in views:
        # Execute the main logic for each view
        main()


def main():
    rooms = get_rooms()
    areas = get_area()

    for area in areas:
        # Access the Color parameter
        color_parameter = area.LookupParameter("Color")

        if color_parameter is not None:
            # Get the color information
            color_parameter_value = color_parameter.AsString()  # Assuming Color is an integer parameter

            for room in rooms:
                room_location = room.Location.Point

                # Check if the area has a valid bounding box
                area_bounding_box = area.get_BoundingBox(revit.doc.ActiveView)
                if area_bounding_box is not None:
                    # Check if the room location is inside the bounding box of the associated area plan
                    if area_bounding_box.IsInside(room_location):
                        # Set the department parameter of the room with the color information
                        set_room_department(room, color_parameter_value)


if __name__ == "__main__":
    process_views()

Resolved it

# Add this import at the beginning of your script
from Autodesk.Revit.DB import ElementSet
from pyrevit import revit, DB
from Autodesk.Revit.DB import Transaction

def get_rooms():
    return DB.FilteredElementCollector(revit.doc).OfCategory(DB.BuiltInCategory.OST_Rooms).ToElements()

def get_areas():
    return DB.FilteredElementCollector(revit.doc).OfCategory(DB.BuiltInCategory.OST_Areas).ToElements()

def set_room_department(room, color_parameter_value):
    # Start a new transaction
    transaction = Transaction(revit.doc, "Set Room Department")
    transaction.Start()

    try:
        value = color_parameter_value
        value_as_string = str(value)
        room.LookupParameter("Department").Set(value_as_string)

        # Commit the transaction if everything is successful
        transaction.Commit()
    except Exception as e:
        # Rollback the transaction if an exception occurs
        transaction.RollBack()
        raise e
      



        

def process_views():
    views = DB.FilteredElementCollector(revit.doc).OfClass(DB.View).ToElements()

    for view in views:
        # Execute the main logic for each view
        main()


def main():
    rooms = get_rooms()
    areas = get_areas()

    for area in areas:
        color_parameter = area.LookupParameter("Color")

        if color_parameter is not None:
            color_parameter_value = color_parameter.AsString()
            
            for room in rooms:
                room_location = room.Location.Point
                
                area_bounding_box = area.get_BoundingBox(revit.doc.ActiveView)
                
                if area_bounding_box is not None:
                    # Check if the room location is inside the bounding box of the associated area plan
                    if (area_bounding_box.Min.X <= room_location.X <= area_bounding_box.Max.X and
                        area_bounding_box.Min.Y <= room_location.Y <= area_bounding_box.Max.Y):
                        # Set the department parameter of the room with the color information
                        set_room_department(room, color_parameter_value)


if __name__ == "__main__":
    process_views()

Hi @saurabhsjha,
I’m glad you found out the problem.
I suggest you to take advantage of the pyrevit library functions and classes:

  • ger_elements_by_categories([category], doc=doc) is a shortcut for the FilteredElementCollector(doc).OfCategory(category).WhereElementIsNotElementType().ToElements()
  • get_elements_by_class is the shortcut for… well, you guessed it :wink:
  • pyrevit.revit.Transaction class is a context manager that handles the commit or rollback for you:
with Transaction(doc):
    value = color_parameter_value
    value_as_string = str(value)
    room.LookupParameter("Department").Set(value_as_string)

Also, it might be better to open only one transaction outside of the loop to avoid a potentially very long undo history! I would put the with Transaction inside the process_views just before the loop.

I see that you’re always using the ActiveView to get the bounding box, but shouldn’t you use the view which are you looping on (by passing it as parameters to the main function)?
On that note, I see from the revit api that the FilterElementCollector can also take the view Id to limit the search to the elements you need, it might remove the need to check id the bounding box is none. Of course, if you go that way you can’t use the first shortcut function I mentioned because it doesn’t support the view id parameter (yet).

1 Like

Thanks @sanzoghenzo thank you for the Suggestion you are correct i was going on Active view in each process. One thing that I was not able to get is this function get_elements_by_categories get_elements_by_categories([DB.BuiltInCategory.OST_Areas]) is in pyrevit or any other library

from pyrevit import revit, DB
from Autodesk.Revit.DB import Transaction

def get_rooms():
    return DB.FilteredElementCollector(revit.doc).OfCategory(DB.BuiltInCategory.OST_Rooms).ToElements()

def get_areas():
    return DB.FilteredElementCollector(revit.doc).OfCategory(DB.BuiltInCategory.OST_Areas).ToElements()


def set_room_parameter(room, area_area_value, area_unit_value):
    # Set Room Area_area & Area_unit in a single transaction
    with revit.Transaction("Set Room Area_area & Area_unit") as tr:
        try:
            value1 = area_area_value
            value2 = area_unit_value
            value_as_string = str(value2)
            value_as_float = float(value1)
            
            room.LookupParameter("Area_area").Set(value_as_float)

            # Check if area_unit_value is not None before setting it
            if value2 is not None:
                room.LookupParameter("Area_unit").Set(value_as_string)

        except Exception as e:
            # Exception will automatically rollback the transaction
            raise e


def get_area_plan_views():
    # Modify the area plan type filter based on your type
    area_plan_type = "AreaPlan"
    
    return [view for view in DB.FilteredElementCollector(revit.doc).OfClass(DB.ViewPlan).ToElements()
            if area_plan_type in view.ViewType.ToString()]

def process_area_plans():
    area_plan_views = get_area_plan_views()
    
    for area_plan_view in area_plan_views:
        # Execute the main logic for each Area Plan
        
        process_all_elements(area_plan_view)
        

def process_all_elements(area_plan_view):
    rooms = get_rooms()
    areas = get_areas()
    
    for area in areas:
        area_parameter = area.Area
        unit_parameter = area.LookupParameter("Unit Type")

        if area_parameter is not None and unit_parameter is not None:
            area_area_value = area_parameter
            area_unit_value = unit_parameter.AsString()  # Use AsString() to get the parameter value as a string

            for room in rooms:
                room_location = room.Location.Point

                area_bounding_box = area.get_BoundingBox(area_plan_view)

                if area_bounding_box is not None:
                    # Check if the room location is inside the bounding box of the associated area plan
                    if (area_bounding_box.Min.X <= room_location.X <= area_bounding_box.Max.X and
                            area_bounding_box.Min.Y <= room_location.Y <= area_bounding_box.Max.Y):
                        # Set the department parameter of the room with the color information
                        set_room_parameter(room, area_area_value, area_unit_value)

if __name__ == "__main__":
    process_area_plans()

Do you know that this forum has a search functionality :wink: ? You could have searched for the function name there to quickly discover that it is in the pyrevit.revit.query module.
Also, the pinned quick start post has a lot of links/references to documentation and tutorials tha should help you discover and unlock pyrevit capabilities.

2 Likes