Hello @Draxl_Andreas,
I´d recommend to print the results after every step to investigate whats going on.
I´d recommend, keep it simple, don´t overuse list comprehensions (use them for heavy tasks to speed them up only) and ziping, etc. This helps in making the code readable and understandable. And don´t create such a small function that is only called a single time and is much more complicated then just making a “+”.
If I understood correct this should satisfy you needs, have a look at my comments:
Edit: looking at it again, i think you don´t need the offset parameter, just "level_elevation + elevation_from_level "?! I commented it out.
import clr
# RevitAPI
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory, BuiltInParameter
# RevitAPIUI
clr.AddReference('RevitAPIUI')
# System
clr.AddReference('System')
from System.Collections.Generic import List
# RevitNodes
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)
# RevitServices
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from Autodesk.Revit.UI import TaskDialog
doc = DocumentManager.Instance.CurrentDBDocument
try:
# Collecting all generic model elements
collector = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericModel)
all_elements = collector.WhereElementIsNotElementType().ToElements()
# Filtering for specific family name
openings = [elem for elem in all_elements if "Allg_WD_rechteckig" in elem.Symbol.FamilyName]
for opening in openings:
elevation_from_level_para = opening.get_Parameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM)
#offset_para = opening.LookupParameter("UK über Ebene")
target_para = opening.LookupParameter("EbenenHöhe über 00")
# Get values only if parameter exist or .AsDouble() will throw an error
if elevation_from_level_para and target_para:
elevation_from_level = elevation_from_level_para.AsDouble()
#offset = offset_para.AsDouble()
target = target_para.AsDouble
# Getting the elevation of the level associated with the opening
level = doc.GetElement(opening.LevelId)
level_elevation = level.Elevation
total_elevation = level_elevation + elevation_from_level # + offset
# Update the target parameter only if it does not already have the right value
if target != total_elevation:
TransactionManager.Instance.EnsureInTransaction(doc)
target_para.Set(total_elevation)
TransactionManager.Instance.TransactionTaskDone()
# Catch any error and display it with a taskdialog
except Exception as e:
TaskDialog.Show("Error", str(e))
This is by the way the perfect use case for a dynamic model updater, I have things like that running in the background to auto calculate those parameters. Triggered by family placement or geometry change. PyRevit script looks like that:
# -*- coding: utf-8 -*-
from System import Guid
from Autodesk.Revit.DB import (
IUpdater, UpdaterId, ElementId, UpdaterRegistry, Element,
ElementCategoryFilter, BuiltInCategory, ChangePriority, FamilyInstance,
)
from Autodesk.Revit.UI import TaskDialog, TaskDialogCommonButtons, TaskDialogResult
class SimpleUpdater(IUpdater):
def __init__(self, doc):
self._doc = doc
def Execute(self, data):
element_ids = list(data.GetAddedElementIds()) + list(data.GetModifiedElementIds())
for id in element_ids:
element = self._doc.GetElement(id)
# If element is of specific family type, update parameters
if self.is_specific_family_instance(element):
self.handle_wandoeffnung(element)
else:
self.handle_doors(element)
@staticmethod
def is_specific_family_instance(element):
from Autodesk.Revit.DB import FamilyInstance,BuiltInParameter
return (isinstance(element, FamilyInstance) and
hasattr(element, 'Symbol') and element.Symbol is not None and
element.Symbol.Family.Name == "Wandöffnung rechteckig" and
element.Name == "WD")
def handle_wandoeffnung(self, element):
from Autodesk.Revit.DB import FamilyInstance,BuiltInParameter
elevation_from_level = element.get_Parameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM).AsDouble()
height = element.LookupParameter("Höhe Aussparung").AsDouble()
top_edge_level = element.LookupParameter("Top Edge Elevation ")
level = self._doc.GetElement(element.LevelId)
level_elevation = level.Elevation
elevation = level_elevation + elevation_from_level + height
if top_edge_level and top_edge_level.AsDouble() != elevation:
top_edge_level.Set(elevation)
def handle_doors(self, element):
from Autodesk.Revit.DB import FamilyInstance,BuiltInParameter
top_edge_para = element.LookupParameter("Top Edge Elevation")
head_height_para = element.get_Parameter(BuiltInParameter.INSTANCE_HEAD_HEIGHT_PARAM)
if not top_edge_para or not head_height_para:
return
level = self._doc.GetElement(element.LevelId)
if not level_elevation_para:
return
height = head_height_para.AsDouble()
level_elevation = level.Elevation
elevation = level_elevation + height
if elevation != top_edge_para.AsDouble():
top_edge_para.Set(elevation)
def GetUpdaterId(self):
# Return the unique identifier for this updater
return self.updater_id
def GetUpdaterName(self):
return 'SimpleUpdaterName'
def GetAdditionalInformation(self):
return 'A simple updater for testing purposes'
def GetChangePriority(self):
return ChangePriority.Annotations
def Initialize(self):
# This is where you can add trigger conditions for the updater
pass
def Uninitialize(self):
pass
# Get the current document and application
doc = __revit__.ActiveUIDocument.Document
app = __revit__.Application
# Create an instance of the updater
updater = SimpleUpdater(doc)
# Create a unique Guid for the updater
guid_string = "145a0f8c-0ada-4526-a36c-85a079463414"
guid = Guid(guid_string)
# Create an UpdaterId using the AddInId of the current application and the unique Guid
updater_id = UpdaterId(app.ActiveAddInId, guid)
updater.updater_id = updater_id
# If the updater is already registered, ask the user if they want to unregister it
if UpdaterRegistry.IsUpdaterRegistered(updater_id, doc):
dialog_result = TaskDialog.Show("Updater Options",
"The updater is already registered. Do you want to unregister it?",
TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No)
# Depending on the user's choice, unregister the updater
if dialog_result == TaskDialogResult.Yes:
# User chose to unregister the updater
UpdaterRegistry.UnregisterUpdater(updater_id, doc)
TaskDialog.Show('Success', 'Updater has been unregistered!')
else:
UpdaterRegistry.RegisterUpdater(updater, doc, True)
# Create a filter for wall elements
door_filter = ElementCategoryFilter(BuiltInCategory.OST_Doors)
family_instance_filter = ElementCategoryFilter(BuiltInCategory.OST_GenericModel)
# Assign the trigger to the updater for element updates
UpdaterRegistry.AddTrigger(updater_id, door_filter, Element.GetChangeTypeElementAddition())
UpdaterRegistry.AddTrigger(updater_id, door_filter, Element.GetChangeTypeGeometry())
UpdaterRegistry.AddTrigger(updater_id, family_instance_filter, Element.GetChangeTypeElementAddition())
UpdaterRegistry.AddTrigger(updater_id, family_instance_filter, Element.GetChangeTypeGeometry())
TaskDialog.Show('Success', 'Updater has been registered and trigger has been set!')