I’ve written the code below to iterate over all materials within the document. I grabbed the material named Béton, coulé sur place with the ID 183853 , which I’m trying to use as a layer material in my new wall type. However, I’m encountering the following error related to the MaterialId ."
import math
from Autodesk.Revit.DB import *
from System.Collections.Generic import IList, List
uidoc = __revit__.ActiveUIDocument
doc = uidoc.Document
t = Transaction(doc, 'create New wall type')
# getting the first wall type within the document
first_wall_type = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsElementType().FirstElement()
# looking for the material named "Béton, coulé sur place " in the document
mat_Ids = FilteredElementCollector(doc).OfClass(Material).ToElementIds()
for m in mat_Ids:
mat = doc.GetElement(m)
if mat.Name == "Béton, coulé sur place":
mid = m
c = 1/0.3048
# Starting transaction
t.Start()
voile_BA_15 = first_wall_type.Duplicate('voile-BA_15')
cs = voile_BA_15.GetCompoundStructure()
Thick_wall = 0.20*c
mat = doc.GetElement(mid)
cl = CompoundStructureLayer()
cl.Width = Thick_wall
cl.MaterialId = mat.Id
cs.SetLayeres.LIST[CompoundStructureLayer](cl)
voile_BA_15.SetCompoundStructure(cs)
t.Commit()
This code generally works in my pyRevit build. There were some errors in code like: cs.SetLayeres.LIST[CompoundStructureLayer](cl) or other bugs like retrieving Curtain Wall as first element from FilteredElementCollector.
As I’m not using Revit Python Shell (just regular pyRevit ) it’s hard for me to pinpoint the issue but my guess would be that for some reason you are getting integer values of element ids instead references. To make sure, you should debug your code by simply printing types of suspicious elements and solving issues step by step. You can also try to convert integer values to element id by using DB.ElementId(integer_value).
hopefully correctly setting the CompoundStructureLayer of the wall type I made some changes in this part of code :
voile_BA_15 = first_wall_type.Duplicate('voile-BA_15')
cs = voile_BA_15.GetCompoundStructure()
Thick_wall = 0.20*c
for structLayer in cs.GetLayers():
cs.SetMaterialId(structLayer.LayerId, mat.Id)
structLayer.Width = Thick_wall
voile_BA_15.SetCompoundStructure(cs)
However, after debugging the code, I received the following error:
Exception : System.MissingMemberException: ‘NoneType’ object has no attribute ‘GetLayers’
I discovered that the first_wall_type is a curtain wall, which does not seem to have a CompoundStructureLayer. In this case, I need to apply a filter that selects only the Basic Wall kind, but I’m struggling with how to do that.
I tried this syntax for the filter but it does not work!!
^^^yes like he said you should print all your variables while you are debugging
and you are mixing C# linq with ironpython. Python could use next() function
You will have to translate to python, but Jeremy Tammik has some good examples in the Revit SDK for working with walls and materials. Revit SDK example
The message is quite explicit and when you go through the members of the filteredElementCollector class in the revit API, quickly you find the right attribute
I know that, to get the first element in FilteredElementCollector I should use the syntax: FirstElement() and I’ve used it in my first script above, but as I said in my previous post, I was unable to GetLayers for the CompoundStructureLayer because the first Wall Type in the FilteredElementCollector is a Curtain Wall, for that I should use another filter to get Basic Wall Kind in my filtered elements, for that I used a sample code I found in dynamobim forum which look for a specific wall type name, but I dont know why id doesn’t work!! (Maybe I should import its module or function)
@MarcinTalipski
I finally solved my issue and tested my code by creating walls, and it works as shown in the image below. However, I want to change the material’s physical characteristics as described in the image. Can you guide me on how to do that?
For declaring material properties for structural analysis, you will need to access material’s StructuralAssetId property. From there you will be able modify each parameter or assign new structural asset
To enhance my code I should use a concrete structural material named (Béton - Coulé sur place - Béton20) which I can use its properties such as (concrete compression , yong modulus)…I notice That I’m working with an architecture template, and the material I’m looking for is listed in the structural template, I attempted to retrieve this material using the following code, but I encountered the following error (I’m sure that this material is not listed in the architecture template):
Exception : Autodesk.Revit.Exceptions.ArgumentException: The given value for name is already in use as a material element name.
Parameter name: name
materials = FilteredElementCollector(doc).WherePasses(ElementCategoryFilter(BuiltInCategory.OST_Materials))
t = Transaction(doc, 'create material')
t.Start()
for m in materials:
if m.Name == "Béton - Coulé sur place - Béton20":
mat = m
mat_id = mat.Id
else:
mat_id = Material.Create(doc, "Béton - Coulé sur place - Béton20")
mat = doc.GetElement(mat_id)
t.Commit()
I finaly create the material, but I can’t set the “concrete compression” property to be equal to (20 MPa); it remains unchanged at (0.1 MPa) as shown in the image below
As far as I know, the internal unit for pressure in Revit is N/ft² . I used a formula to convert the unit to MPa , but I don’t know what’s wrong with my code
Here my code:
import math
from Autodesk.Revit.DB import *
from System.Collections.Generic import IList, List
uidoc = __revit__.ActiveUIDocument
doc = uidoc.Document
materials = FilteredElementCollector(doc).WherePasses(ElementCategoryFilter(BuiltInCategory.OST_Materials))
material = [i for i in materials if i.Name == "Béton - Coulé sur place - Béton20"]
# converting unit from **`N/ft²`** to MPA
c = 1/92903.04
if len(material) > 0:
mat = m
m_Id = mat.Id
else:
t = Transaction(doc, 'Get/create concrete material')
t.Start()
m_Id = Material.Create(doc, "Béton - Coulé sur place - Béton20")
mat = doc.GetElement(m_Id)
mat.MaterialClass = "Concrete"
asset = StructuralAsset("b", StructuralAssetClass.Concrete)
asset.ConcreteCompression = 20*c
struc = PropertySetElement.Create(doc, asset)
mat.SetMaterialAspectByPropertySet(MaterialAspect.Structural, struc.Id)
t.Commit()