I’m trying to create new materials with Python script. I have used @Scott_Crichton script from this topic but Im getting an error “expected an indented block”. I know that @mimp had the same problem, but this has not been resolved.
Have you any ideas what might be wrong with that script?
I’m just a total beginner
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
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
def ToRevitColor(dynamoColor):
return Color(dynamoColor.Red, dynamoColor.Green, dynamoColor.Blue)
def ToDynamoObject(revitObject, isRevitOwned=False): # isRevitOwned should be False if Dynamo script created the object.
return revitObject.ToDSType(isRevitOwned)
doc = DocumentManager.Instance.CurrentDBDocument
names = IN[0]
transparencies = IN[1]
colors = IN[2]
newMaterials = []
for mat_name, transparency, color in zip(names, transparencies, colors):
TransactionManager.Instance.EnsureInTransaction(doc)
new_mat_id = Material.Create(doc, mat_name)
new_mat = doc.GetElement(new_mat_id)
new_mat.Color = ToRevitColor(color)
new_mat.Transparency = transparency
TransactionManager.Instance.TransactionTaskDone()
newMaterials.append(ToDynamoObject(new_mat))
OUT = newMaterials
Traceback (most recent call last):
File “”, line 29, in
Exception: The given value for name is already in use as a material element name.
Parameter name: name
At this moment my script looks like this:
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
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
def ToRevitColor(dynamoColor):
return Color(dynamoColor.Red, dynamoColor.Green, dynamoColor.Blue)
def ToDynamoObject(revitObject, isRevitOwned=False): # isRevitOwned should be False if Dynamo script created the object.
return revitObject.ToDSType(isRevitOwned)
doc = DocumentManager.Instance.CurrentDBDocument
names = IN[0]
transparencies = IN[1]
colors = IN[2]
newMaterials = []
for mat_name, transparency, color in zip(names, transparencies, colors):
TransactionManager.Instance.EnsureInTransaction(doc)
new_mat_id = Material.Create(doc, mat_name)
new_mat = doc.GetElement(new_mat_id)
new_mat.Color = ToRevitColor(color)
new_mat.Transparency = transparency
TransactionManager.Instance.TransactionTaskDone()
newMaterials.append(ToDynamoObject(new_mat))
OUT = newMaterials
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
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
def ToRevitColor(dynamoColor):
return Color(dynamoColor.Red, dynamoColor.Green, dynamoColor.Blue)
def ToDynamoObject(revitObject, isRevitOwned=False): # isRevitOwned should be False if Dynamo script created the object.
return revitObject.ToDSType(isRevitOwned)
doc = DocumentManager.Instance.CurrentDBDocument
names = IN[0]
transparencies = IN[1]
colors = IN[2]
newMaterials = []
for mat_name, transparency, color in zip(names, transparencies, colors):
try:
TransactionManager.Instance.EnsureInTransaction(doc)
new_mat_id = Material.Create(doc, mat_name)
new_mat = doc.GetElement(new_mat_id)
new_mat.Color = ToRevitColor(color)
new_mat.Transparency = transparency
TransactionManager.Instance.TransactionTaskDone()
newMaterials.append(ToDynamoObject(new_mat))
except:
newMaterials.append(None)
OUT = newMaterials
I have added Try/Except. It should pass now, but it will return a null if there was an error (for instance if you have a material with that name already in the project).
Hang on, I edited this in the forum and Python gets a little funny with mixed tabs and spaces and failed when i ran it. I have also pulled the transaction out of the loop…
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
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
def ToRevitColor(dynamoColor):
return Color(dynamoColor.Red, dynamoColor.Green, dynamoColor.Blue)
def ToDynamoObject(revitObject, isRevitOwned=False): # isRevitOwned should be False if Dynamo script created the object.
return revitObject.ToDSType(isRevitOwned)
doc = DocumentManager.Instance.CurrentDBDocument
names = IN[0]
transparencies = IN[1]
colors = IN[2]
newMaterials = []
TransactionManager.Instance.EnsureInTransaction(doc)
for mat_name, transparency, color in zip(names, transparencies, colors):
try:
new_mat_id = Material.Create(doc, mat_name)
new_mat = doc.GetElement(new_mat_id)
new_mat.Color = ToRevitColor(color)
new_mat.Transparency = transparency
newMaterials.append(ToDynamoObject(new_mat))
except:
newMaterials.append(None)
TransactionManager.Instance.TransactionTaskDone()
OUT = newMaterials
This should now override any materials with the same name.
I have also added an option to disable whether the Material is Owned by Dynamo (this feature can be annoying sometimes as Dynamo keeps track of which Elements it made and always remembers these for modification, now you have a choice of whether you want to do this. I prefer to disable this personally, particularly on a generic script that I will use many times in different situations on the same document).
I have also made sure that even if you are passing in one one item (not in a list), that this will still work and I have added a new OUT variable for errors that will give you a description of the error it encountered.
Additionally, I have commented on what’s going on to make it forum friendly so people new to python can understand step by step.
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
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
################ Definitions ################
# Convert DSCore Colour to Revit Colour...
def ToRevitColor(dynamoColor):
return Color(dynamoColor.Red, dynamoColor.Green, dynamoColor.Blue)
# Add Dynamo Ownership to Element...
def ToDynamoObject(revitObject, isRevitOwned=False): # isRevitOwned should be False if Dynamo script created the object.
return revitObject.ToDSType(isRevitOwned)
# Gets the Material Id by name from a list of Materials ...
def GetMaterialIdByName(mat_Name, mats):
return next((m.Id for m in mats if m.Name == mat_Name), None)
# Used to Ensure that object is in a list...
def tolist(obj1):
if hasattr(obj1,"__iter__"): return obj1
else: return [obj1]
################ IN Variables ################
names = tolist(IN[0])
transparencies = tolist(IN[1])
colors = tolist(IN[2])
toDynObj = tolist(IN[3])[0]
################ OUT Variables ################
newMaterials = []
err = []
################ Main Body ################
# Get all the Materials that are currently created in the Revit doc...
mats = FilteredElementCollector(doc).OfClass(Material).ToElements()
TransactionManager.Instance.EnsureInTransaction(doc)
for mat_name, transparency, color in zip(names, transparencies, colors):
try:
# Check if material exists already...
new_mat_id = GetMaterialIdByName(mat_name, mats)
# Create one if it doesn't...
if not new_mat_id:
new_mat_id = Material.Create(doc, mat_name)
# Get Material from Revit doc...
new_mat = doc.GetElement(new_mat_id)
# Set Material colour...
new_mat.Color = ToRevitColor(color)
# Set Material Transparency...
new_mat.Transparency = transparency
# If toDynObj is true, Dynamo will own the Elements it creates and overwrite those...
if toDynObj:
newMaterials.append(ToDynamoObject(new_mat))
# if toDynObj is false, Dynamo will not own this Element...
else:
newMaterials.append(new_mat)
err.append(None)
except Exception, ex:
newMaterials.append(None)
err.append(ex.message)
TransactionManager.Instance.TransactionTaskDone()
################ OUT ################
OUT = newMaterials, err
You’re welcome @Jacko! Glad this is now working for you!
Ah, it might seem like black magic now, but I’m sure soon enough, you’ll be up and running with python and this will look simple! It’s scarier than it looks!
Indentation means the space from margin to the begin of characters in a line. Python language is a very sensitive language for indentation, it has caused confusion for many beginners. Putting in an extra space or leaving one out where it is needed will surely generate an error message . Some common causes of this error include:
Forgetting to indent the statements within a compound statement.
Forgetting to indent the statements of a user-defined function.
The error message IndentationError: expected an indented block would seem to indicate that you have an indentation error. It is probably caused by a mix of tabs and spaces .