Creating Materials with Python

create materials python code.dyn (3.8 KB)
Hello all,

I am trying to use excel as a material database as we use various software etc so I need a central resource. I want to use Dynamo to add these materials to Revit, and be able to update them. Unfortunately the out of the box nodes are not sufficient so I am trying to use python as well. I am however getting tripped up in one of the first steps.

I can add materials to Revit, but if the script is re run or a materials is added to the list, it will not run as there is already a materia with that name present. Help appreciated!

This is the script

import clr
clr.AddReference(“RevitAPI”)
from Autodesk.Revit.DB import *
clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

names = IN[0]

newMaterials =
for mat_name in names:
TransactionManager.Instance.EnsureInTransaction(doc)
new_mat_id = Material.Create(doc, mat_name)
new_mat = doc.GetElement(new_mat_id)
TransactionManager.Instance.TransactionTaskDone()
newMaterials.append(new_mat)

OUT = newMaterials

add a try/except clause to ensure unique names…
https://docs.python.org/2/tutorial/errors.html

Thank you for your response!

When the script is complete i would like to be able to use it to update material data with new info etc, if i use unique name will it not just make make new materials each time?

So…
I was able to expand the script to include all of the data on the Identity Data page except for the Material Class has anyone any idea where in the Revit API this value is located? it is the only parameter left on this page that I can’t find.

i have also started looking at adding the thermal data. But have hit a stumbling block, see screenshot below, it is returning “AttributeError: ‘NoneType’ object has no attribute ‘Set’

#Create or Update Materials based on List inputs
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
#Inputs

names = IN[0]
thermalconductivity = IN[1]

#New materials OUT list
newMaterials = []
#Overwritten materials OUT list
ovwMaterials = []

	
#Avoid instance input problem
if isinstance(names, list):
	names = names
else: names = [names]

if isinstance(thermalconductivity, list):
	thermalconductivity = thermalconductivity
else: thermalconductivity = [thermalconductivity]

#Iterate through the input names list
for n, thmcd in zip(names,thermalconductivity):
	#Check if the material with the specified name already exists
	if Material.IsNameUnique(doc,n):
		#If name is unique, create material
		TransactionManager.Instance.EnsureInTransaction(doc)
		new_mat_id = Material.Create(doc, n)
		new_mat = doc.GetElement(new_mat_id)
		new_mat_ThermalConductivity = new_mat.get_Parameter(BuiltInParameter.PHY_MATERIAL_PARAM_THERMAL_CONDUCTIVITY).Set(thmcd)
		TransactionManager.Instance.TransactionTaskDone()
		newMaterials.append(n)
	else:
		#If it already exists, collect it and modify it
		TransactionManager.Instance.EnsureInTransaction(doc)
		namePar = ParameterValueProvider(ElementId(BuiltInParameter.MATERIAL_NAME))
		fRule = FilterStringRule(namePar,FilterStringEquals(),n, True)
		filter = ElementParameterFilter(fRule)
		exist_mat = FilteredElementCollector(doc).OfClass(Material).WherePasses(filter).ToElements()
		#Iteration is necessary because the output of exist_mat is invariably a list
		for em in exist_mat:
			#Modify the Material Properties and Parameters
			emThermalConductivity = em.get_Parameter(BuiltInParameter.PHY_MATERIAL_PARAM_THERMAL_CONDUCTIVITY).Set(thmcd)
			ovwMaterials.append(n)
		TransactionManager.Instance.TransactionTaskDone()
		
OUT = newMaterials, ovwMaterials

You can get and set the Class value via the MaterialClass property, or use the Built In Parameter name which appears to be “PHY_MATERIAL_PARAM_CLASS” Edit: that BIP is a read-only integer value associated with a material’s physical properties, not its identity data.

2 Likes

Did you managed to solve this? if you did could you please add the code? I am having the same issue where I want the material library to update from an excel sheet with both identity parameters and thermal parameters.

Thank you so much in advance!

hello I also have same issue if you have solustion please shar the code&physon strip.
I also string line 17 error i don’t know why is not work… sometimes it work but when i re work is not working.

thank to shar the coad and advance,!

Ive started using the Orchid package instead of Python code and its working well! I nearly have the script rebuilt and will post when complete

Have you looked into the genuis loci package?

1 Like

I hadn’t actually. There’s a few more nodes in the orchid package for doing both foreground and surface pattern which i useful depending on what you want. I think the genius loci package just does cut and surface patterns rather than background and foreground, I may be wrong though!

Hi Shane,

Background and foreground patterns are supported in Genius Loci package. That said, there are also many useful nodes for creating and editing materials in Orchid package :slightly_smiling_face: