Setting element parameter of type float via python outputs incorrect values in revit

I want to set a parameter on a Revit element that is of type float.
When I use element.Set(value) it sets it to a float but multiplied with 28.32 for some reason.

I tried setting it using OOTB setParameterByName and it sets it right. Where is this multiplication with 28.32 coming from?

the inputs are element Id in 0, name in 1 and value in 2 as string

Here is the code

# The inputs to this node will be stored as a list in the IN variables.
ele=UnwrapElement(IN[0])
name=IN[1]
val1=IN[2]
val2=float(val1)
val3=val2/28.32
doc = DocumentManager.Instance.CurrentDBDocument
# Place your code below this line
TransactionManager.Instance.EnsureInTransaction(doc)
ele.LookupParameter(name).Set(val3)
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable.
OUT = val2,val3

It may be related to internal units. Are you able to provide more information about the parameter itself (e.g. its type)?

2 Likes

This.

1 Like

A guess: Cubic feet being returned as the prior method is pulling using the internal units instead of the display units or project units.

1 Like

After reading about it on the weekend , I think its the conversion to parameters own units.
I experimented with the element.setParameterValeByName node and it manages to set some value correctly and some not (flow and pressure was as in dynamo but temp. was converted ).
I’m going to try to get the unit type from the parameter and convert it somehow to what its supose to be before setting it. Il post my results.

So i found out that you can:

  • set fields that take in values of type double ( or float) by using param.SetValueString( string ).
    Here the string should be formatted like this “1234.5667”. If you use a , it won’t work.
    string.replace(",",".") can be used here to get the desired result. The value that is set in dynamo should hold in revit also, no conversion.

  • set fields that take in the value of type int by using param.Set( intNum )

  • set fields that take in the value of type string by using param.Set( string )

So a bit of context for why I needed this.
I wanted to make a script that will take the ids and parameter names and values from excel and set them in Revit but the OOTB element.SetParameterValueByName was not setting all the parameters, just the text, and int types.
In the end, I made it the excel table has the first row ElementId,para1,para2,… the second row has the types of parameters (int, float or string) written underneath para1,para2,… and values in rows bellow.
I then parse the element I, para names,para. types and values into separate lists and feed it to a python script that does the setting of parameters.

Here is the code:

#input1:
#list of ids of elements
#input2:
#list of parameters that are going to be set
#input 3:
#list of paramater types (float,int,string)
#input4:
#a list of list where:
#smaller lists contain values for the parameters in input 2 (their sizes have to match),
#Larger list is the size of the numbre of elements ,and conatins the smaller lists
# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#import revit nodes
clr.AddReference('RevitNodes')
import Revit
#import revit APi
clr.AddReference('RevitAPi')
import Autodesk
from Autodesk.Revit.DB import *
#import revit services (dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# The inputs to this node will be stored as a list in the IN variables.
elementIds=UnwrapElement(IN[0])
paraNames = IN[1]
paraTypes = IN[2]
paraVals = IN[3]
doc = DocumentManager.Instance.CurrentDBDocument
# Place your code below this line
TransactionManager.Instance.EnsureInTransaction(doc)
for i in range(len(elementIds)):
	for j in range(len(paraNames)):
		revPara=elementIds[i].LookupParameter(paraNames[j])
		if (paraTypes[j] == 'int'):
			revPara.Set(int(paraVals[i][j]))
		elif(paraTypes[j] == 'float'):
			revPara.SetValueString(paraVals[i][j].replace(",","."))
		elif (paraTypes[j] == 'string'):
			revPara.Set(paraVals[i][j])		
TransactionManager.Instance.TransactionTaskDone()
#Assign your output to the OUT variable.
OUT = list

If anybody has a better idea on how to achieve this please post a link a solution.

Certain parameter types in Revit use internal units for behind the scenes calculations and conversions. Temperature is one of them. Many parameter types use a ValueAsString property to show certain parameter values in a more user-friendly way. (A common example is parameters that utilize an element or element Id as their value. They show the element name but the value is the actual element/Id. This is also the case for these internal units.) By setting a parameter value via ValueAsString, you’re specifically telling Revit that the user-facing value should be x. This means that the value is already being converted to show the value you’re expecting, even though the actual internal value is being set as y.

You can either learn the internal units (and their conversions) or use custom nodes to avoid this. MEPover has Get/Set nodes for ParameterAsProjectUnits specifically for cases like this. That should make things much simpler.

2 Likes

So if want to pass 11 deg. C from dynamo and have it be 11 deg.C in revit, how should i go about it? UnitUtils class?

Yes, UnitUtils would be your best bet. For example:

# 11 Celsius
deg_visible = 11
# 511.47 Rankine
deg_internal = UnitUtils.ConvertToInternalUnits(deg_visible, DisplayUnitType.DUT_CELSIUS)
1 Like

Success!
Arigato Kozaimas

So it goes like this
1.Get the parameter with element.LookupParameter(“name”)
2.Get external unit type with element.LookupParameter(“name”).DisplayUnitType
3.Convert unit UnitUtils via UnitUtils.ConvertToInternalUnits(value,extUnitType)
4.Now use parameter.Set(Converted Value)
Example parameter p1 and i want it to get 11.05 deg
Code:

ele=UnwrapElement(IN[0])
extUnType=ele.LookupParameter("p1").DisplayUnitType
convUnit =UnitUtils.ConvertToInternalUnits(11.05,extUnType)
ele.LookupParameter("p1").Set(convUnit)
2 Likes