[Revit] Change fittings reference level without moving it

A common pain in Revit is to manage object’s reference level :

  • If you change a duct/pipe reference level. It stays at the same location which is great.
  • If you change any fitting/accessory reference level. It move at the same offset on the defined level. It generates many errors when you change a level elevation during a project…
from Autodesk.Revit.DB import *

uidoc = __revit__.ActiveUIDocument
doc = __revit__.ActiveUIDocument.Document
getselection = uidoc.Selection.GetElementIds

#Get current selection and store it
selection = getselection()

#Ask user to pick an object which has the desired reference level
def pickobject():
    from Autodesk.Revit.UI.Selection import ObjectType
    picked = uidoc.Selection.PickObject(ObjectType.Element, "Sélectionnez la référence")
    return picked

#Retrieve needed information from reference object
ref_object = doc.GetElement(pickobject().ElementId)
ref_level = ref_object.ReferenceLevel 
ref_levelid = ref_level.Id

t = Transaction(doc, "Change reference level")


#Change reference level and relative offset for each selected object in order to change reference plane without moving the object
for e in selection:
	object = doc.GetElement(e)
	object_param_level = object.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM)
	object_Level = doc.GetElement(object_param_level.AsElementId())
	object_param_offset = object.get_Parameter(BuiltInParameter.INSTANCE_FREE_HOST_OFFSET_PARAM)
	object_newoffset = object_param_offset.AsDouble() + object_Level.Elevation - ref_level.Elevation

I hope you’ll enjoy it as much as I do.


  1. Cyril,

    This used to work perfectly for me, but I think after Revit 2016 not anymore.

    I get:

    System.MissingMemberException: ‘FamilyInstance’ object has no attribute ‘ReferenceLevel’
    at IronPython.Runtime.Binding.PythonGetMemberBinder.FastErrorGet`1.GetError(CallSite site, TSelfType target, CodeContext context)
    at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
    at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
    at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
    at Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1)
    at IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx)
    at Microsoft.Scripting.Hosting.ScriptSource.Execute(ScriptScope scope)
    at RevitPythonShell.RpsRuntime.ScriptExecutor.ExecuteScript(String source, String sourcePath)

    Sorry to say I’m not into python very much. Any idea how to solve it?

  2. Cyril,

    Thanks for helping me out.

    I followed your video and installed pyPrevit and pyRevitMEP. I’ve got both tabs in Revit 2018 but still get the same error.

    I found script.py under “C:\PyRevit\pyRevitMEP.extension\pyRevitMEP.tab\Tools.panel\ElementChangeLevel.pushbutton” but it has the same line under record 44 “level = doc.GetElement(ref_object.LevelId)”

    Best regards,


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.