SetParameterByName to wall object in Python


#1

Hi All,

I have a little question. I have this short Python that does 2 tasks:

  • Corrects the level name according to my criteria.
  • Assign a determined RebarCoverType to the wall elements collected.

The last task I can’t to get it done, I have this message:.

image

The Code:

import clr

clr.AddReference('RevitNodes')
import Revit

#importa el ToProtoType y ToRevitType
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference('ProtoGeometry')
import Autodesk.DesignScript.Geometry
from Autodesk.DesignScript.Geometry import *

#Importar el Docuement Manager y Transacciones
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference('System')
from System import *

#Importar la API de Revit
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference('DSCoreNodes')
from DSCore import *


# Datos de entrada
EntradaTonta = IN[0]		#Solo se deja para que funcione el Passthrough.

# Hacer referencia al documento activo.
doc = DocumentManager.Instance.CurrentDBDocument

# Crear un colector de los elementos para ciertas categorias (http://www.revitapidocs.com/2017.1/ba1c5b30-242f-5fdc-8ea9-ec3b61e6e722.htm)
collectorLevels = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels)
collectorWalls = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)
collectorRebarCover = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CoverType)

# Inicia la transaccion
TransactionManager.Instance.EnsureInTransaction(doc)

# Genera una lista con todos los
PisosRevit = []
for i in collectorLevels:
    if not ('LevelType' in str(i)):
        if 'FUNDACION' in i.Name:
            i.Name = 'PLANTA DE FUNDACIONES'
        elif ' ' in i.Name:
            i.Name = (i.Name).Replace(' ', '')

# Finaliza la transaccion
TransactionManager.Instance.TransactionTaskDone()

Muros = []
for i in collectorWalls:
    if not ('WallType' in str(i)):
        Muros.append(i)

RebarCover = []
for i in collectorRebarCover:
    RebarCover.append(i)

# Aplica recubrimientos en todos los elementos muro.
for wall in Muros:
    muro = wall
    muro.SetParameterByName("Rebar Cover - Exterior Face", RebarCover[8])
    muro.SetParameterByName("Rebar Cover - Interior Face", RebarCover[8])
    muro.SetParameterByName("Rebar Cover - Other Faces", RebarCover[8])

OUT = []

I know that I’m missing something here, Cold you help me with this please?

Thanks in advance for your time.

Cheers!


#2

try:
muro.LookupParameter(“Rebar Cover - Exterior Face”).Set(RebarCover[8])


#3

Thanks @Tomasz_Puchala. Tried what you recommended but this didn’t solve my problem.

Here is the same script, but using the collections trough Dynamo.

Seteo Inicial.dyn (17.9 KB)

This works just fine.

Thanks in advance!


#4

try to change

clr.AddReference('DSCoreNodes')
from DSCore import *

to

clr.AddReference('RevitNodes')


#5

I just tested you actually dont need to load anything, the below worked fine for me

elements = IN[0]
for element in elements:
    element.SetParameterByName('Comments', 'test')
OUT = 'done'

#6

I have just tested this

elements = IN[0]
for element in elements:
    level = element.GetParameterValueByName('Base Constraint')
    if '1' in level.Name:
        element.SetParameterByName('Comments', 'test')
OUT = 'done'

and without understanding Spanish, then I suppose something like this will work

elements = IN[0]
rebar_cover = IN[1]
rebar = rebar_cover[8]
for element in elements:
    level = element.GetParameterValueByName('Base Constraint')
    if 'FUNDACION' in level.Name:       
        element.SetParameterByName("Rebar Cover - Exterior Face", rebar)
        element.SetParameterByName("Rebar Cover - Interior Face", rebar)
        elementelement.SetParameterByName("Rebar Cover - Other Faces", rebar)
OUT = 'done'

#7

Thanks, @erfajo! It works like you said. But, I doing the collector to avoid putting the nodes “Categories” and “All Elements of Category”. I want to do this process in Python.
More similar to what I did in the first post.

Is it possible?

Thanks in advance!


#8

That should be doable. This example is the same as I have been testing on, just collecting the elements inside the python script.

# Common Language Runtime modules
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('RevitNodes')

# Revit and Dynamo modules
from Autodesk.Revit.DB import BuiltInCategory, FilteredElementCollector
from RevitServices.Persistence import DocumentManager
import Revit
clr.ImportExtensions(Revit.Elements)

doc = DocumentManager.Instance.CurrentDBDocument

# collect walls
walls = (
    FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)
    .WhereElementIsNotElementType().ToElements())

# turn into dynamo type
elements = []
for wall in walls:
    elements.append(wall.ToDSType(True))

for element in elements:
    level = element.GetParameterValueByName('Base Constraint')
    if '1' in level.Name:
        element.SetParameterByName('Comments', 'test')

OUT = 'done'

#9

…or joined in one loop

elements = (
    FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)
    .WhereElementIsNotElementType().ToElements())

for element in elements:
    element = element.ToDSType(True)
    level = element.GetParameterValueByName('Base Constraint')
    if '1' in level.Name:
        element.SetParameterByName('Comments', 'test')

#10

WOW! Great! Thanks a lot @erfajo . I didn’t know about the “WhereElementIsNotElementType()” method. Also, I think the “ToElements()” was the stumbling rock here. I’ll adjust my script using your recommendations.

Thanks a lot.


#11

Hi @erfajo:

I managed to adjust my code using you directions:

import clr

clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('RevitNodes')

#Importar el Docuement Manager y Transacciones
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Revit and Dynamo modules
from Autodesk.Revit.DB import BuiltInCategory, FilteredElementCollector
from RevitServices.Persistence import DocumentManager
import Revit
clr.ImportExtensions(Revit.Elements)

# Datos de entrada
EntradaTonta = IN[0]		#Solo se deja para que funcione el Passthrough.

# Hacer referencia al documento activo.
doc = DocumentManager.Instance.CurrentDBDocument

# Crear un colector de los elementos para ciertas categorias (http://www.revitapidocs.com/2017.1/ba1c5b30-242f-5fdc-8ea9-ec3b61e6e722.htm)
Niveles = (FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType().ToElements())
Muros = (FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements())
RebarCover = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CoverType).ToElements()

# Inicia la transaccion
TransactionManager.Instance.EnsureInTransaction(doc)

# Corrige el nombre de los niveles de acuerdo al criterio indicado en el manual.
for i in Niveles:
    if 'FUNDACION' in i.Name:
        i.Name = 'PLANTA DE FUNDACIONES'
    elif ' ' in i.Name:
        i.Name = (i.Name).Replace(' ', '')



# Finaliza la transaccion
TransactionManager.Instance.TransactionTaskDone()

# Aplica recubrimientos en todos los elementos muro.

for wall in Muros:
    muro = wall.ToDSType(True)
    muro.SetParameterByName('Rebar Cover - Exterior Face', RebarCover[8])
    muro.SetParameterByName('Rebar Cover - Interior Face', RebarCover[8])
    muro.SetParameterByName('Rebar Cover - Other Faces', RebarCover[8])

OUT = 'Nombres de pisos corregidos y parametros asignados correctamente.'

But now, if I want to assign a RebarCover Type to the corresponding parameter, the error says: “No parameter found by that name”.

This is weird, because If I look for Element.Parameters, I get the desired Parameter.

Any thoughts?

Thanks in advance for your time.


#12

do you have a sample file?
Your previously uploaded graph contained other elements/nodes I do not have, so I cant really use that as it is. What I have done is creating “clean” scenario for my tests.

Do you think it looks like this Subcategory problem, where the problems were to find the subcategory to a category? just a thought


#13

Hi,

I don’t think it is a SubCategory issue.

Here I made a simple example. I couldn’t replicate the exact error that I’m witnessing:

https://drive.google.com/open?id=1orXqYYt8SvyzkWArdRys_4h5k80NEOHb

Now, I’m getting this error:

Thanks in advance!


#14

I found your problem, remember that everything you collect is Revit elements, not dynamo elements.
change this line so it fits to your purpose -> cover_type_ds = cover_types_ds[1]

# Common Language Runtime modules
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('RevitNodes')

# Revit and Dynamo modules
from Autodesk.Revit.DB import BuiltInCategory, FilteredElementCollector
from RevitServices.Persistence import DocumentManager
import Revit
clr.ImportExtensions(Revit.Elements)

doc = DocumentManager.Instance.CurrentDBDocument

# collect walls
walls = (
    FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)
    .WhereElementIsNotElementType().ToElements())

# turn into dynamo type
walls_ds = []
for wall in walls:
    walls_ds.append(wall.ToDSType(True))

# get rebar cover types
cover_types = (
    FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CoverType)
    .ToElements())

# turn into dynamo type
cover_types_ds = []
for cover_type in cover_types:
    cover_types_ds.append(cover_type.ToDSType(True))

cover_type_ds = cover_types_ds[1]

for wall in walls_ds:
    level = wall.GetParameterValueByName('Base Constraint')
    if '1' in level.Name:
        wall.SetParameterByName('Rebar Cover - Exterior Face', cover_type_ds)
        wall.SetParameterByName('Rebar Cover - Interior Face', cover_type_ds)
        wall.SetParameterByName('Rebar Cover - Other Faces', cover_type_ds)

OUT = 'done'

#15

@erfajo I found the missing piece for the “No parameter found by that name” error. The model had some architectural walls which I couldn’t see in my Structural view. This walls didn’t have the “Structural” option enabled, therefore, they didn’t have Rebar Cover parameters.

The solution you recommended was accurate. So, the problem now is the one explained in my previous post. Is the one from the example provided.

image

Thanks in advance for your time!


#16

That is what i solved with the previous post…

# turn into dynamo type
cover_types_ds = []
for cover_type in cover_types:
    cover_types_ds.append(cover_type.ToDSType(True))

#17

Thanks @erfajo! I really appreciate your help. For me was very illustrative this thread!


#18

you are welcome, remember to post what you end up doing, others might be able to reuse it :slight_smile:


#19

My final code is like this:

import clr

clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
clr.AddReference('RevitNodes')
clr.AddReference('RevitAPIUI')

from Autodesk.Revit.UI import TaskDialog

#Importar el Docuement Manager y Transacciones
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Revit and Dynamo modules
from Autodesk.Revit.DB import BuiltInCategory, FilteredElementCollector
from RevitServices.Persistence import DocumentManager
import Revit
clr.ImportExtensions(Revit.Elements)

# Hacer referencia al documento activo.
doc = DocumentManager.Instance.CurrentDBDocument

# Crear un colector de los elementos para ciertas categorias (http://www.revitapidocs.com/2017.1/ba1c5b30-242f-5fdc-8ea9-ec3b61e6e722.htm)
Niveles = (FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType().ToElements())
Muros = (FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements())
RebarCover = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CoverType).ToElements()

# Inicia la transaccion
TransactionManager.Instance.EnsureInTransaction(doc)

# Corrige el nombre de los niveles de acuerdo al criterio indicado en el manual.
for i in Niveles:
    if 'FUNDACION' in i.Name:
        i.Name = 'PLANTA DE FUNDACIONES'
    elif ' ' in i.Name:
        i.Name = (i.Name).Replace(' ', '')

# Finaliza la transaccion
TransactionManager.Instance.TransactionTaskDone()

# Aplica recubrimientos en todos los elementos muro.

# transformar a elementos de Dynamo
coverTypes = []
for cover in RebarCover:
    coverTypes.append(cover.ToDSType(True))

indice = []
for i in range(len(Muros)):
    muro = Muros[i].ToDSType(True)
    if muro.GetParameterValueByName('Structural') == 1:
        muro.SetParameterByName('Rebar Cover - Exterior Face', coverTypes[8])
        muro.SetParameterByName('Rebar Cover - Interior Face', coverTypes[8])
        muro.SetParameterByName('Rebar Cover - Other Faces', coverTypes[8])
    else:
        indice.append(i)

if indice:
    contador = str(len(indice))
else:
    contador = str(0)

OUT = 'Nombres de pisos corregidos y parametros asignados correctamente. Hay ' + contador + ' muros arquitectonicos! Revisar!'
# OUT = indice

Hope it will be useful!


#20

just to explain a bit more about the code

this is not good coding style

Muros = (FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements())

this is more readable, and according to PEP8 (the python style)

Muros = (
    FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls)
    .WhereElementIsNotElementType().ToElements())

when you split a long line of code, then you add parenthesis -> Muros = ( xx )
if you dont split it, but gives a very long line (do never do that) then -> Muros = xx

you can verify you code on http://pep8online.com