I am trying to write a script to overwrite all filled region properties in the project to all loaded families, so that I do not have to open and change all the filled region with the same name in project from every families.
here is the code I have:
(with the help of OpenAI)
import clr
import System
from System import Guid, Array
from System.Collections.Generic import Dictionary
from System.IO import Path
from Autodesk.Revit import DB
from Autodesk.Revit.DB import FamilySource, Transaction
#doc = __currentdoc__
doc = __revit__.ActiveUIDocument.Document
class FamilyOption(DB.IFamilyLoadOptions):
def OnFamilyFound(self, familyInUse, overwriteParameterValues):
overwriteParameterValues = True
return True
def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
source = FamilySource.Family
overwriteParameterValues = True
return True
# Find all Filled Region Type, and create a dictionary with it
modelFilledRegionTypes = dict()
filledinFamily = DB.FilteredElementCollector(doc).OfClass(DB.FilledRegionType).ToElements()
for e in filledinFamily:
modelFilledRegionTypes[Element.Name.__get__(e)] = e
print(str(modelFilledRegionTypes))
# Find all loaded families
elements = DB.FilteredElementCollector(doc).OfClass(DB.Family).ToElements()
print(elements)
# Get Detail Item category id.
detailItemCategoryId = DB.Category.GetCategory(doc, DB.BuiltInCategory.OST_DetailComponents).Id
print(detailItemCategoryId)
# Initialize report list
report = []
# Loop on all loaded families
famdocs = []
for f in elements:
if f.IsEditable:
famdocs.append(doc.EditFamily(f))
for family in famdocs:
print("working on family:"+str(family))
familyDoc = family.EditFamily
print("Load family done" + str(familyDoc))
familyEdited = False
print("Editing family...." + str(family))
# Find all Filled Region Type in the family
filledinFamily = DB.FilteredElementCollector(familyDoc).OfClass(DB.FilledRegionType).ToElements()
print(str(filledinFamily))
with Transaction(familyDoc, "Edit Filled Region Type") as famTx:
famTx.Start()
for filledRegionType in filledinFamily:
if Element.Name.__get__(filledRegionType) in modelFilledRegionTypes:
refFilledRegion = modelFilledRegionTypes[Element.Name.__get__(filledRegionType)]
print(refFilledRegion)
# Change the foreground pattern color
filledRegionType.ForegroundPatternColor = refFilledRegion.ForegroundPatternColor
familyEdited = True
print("foreground pattern color_check is " + str(filledRegionType.ForegroundPatternColor))
# Change the Background
filledRegionType.BackgroundPatternColor = refFilledRegion.BackgroundPatternColor
familyEdited = True
print("background pattern color_check" + str(filledRegionType.BackgroundPatternColor))
# Change line weight
filledRegionType.LineWeight = refFilledRegion.LineWeight
familyEdited = True
print("lineweight_check" + str(filledRegionType.LineWeight))
# Change fill pattern
filledRegionType.BackgroundPatternId = refFilledRegion.BackgroundPatternId
familyEdited = True
print("filed pattern background_check" + str(filledRegionType.BackgroundPatternId))
# Change fill pattern
filledRegionType.ForegroundPatternId = refFilledRegion.ForegroundPatternId
familyEdited = True
print("fill pattern foreground_check" + str(filledRegionType.ForegroundPatternId))
famTx.Commit()
if familyEdited:
familyDoc.LoadFamily(doc, FamilyOption())
familyDoc.Close(False)
report.append("Changes made to family: " + family.Name)
else:
familyDoc.Close(False)
# Print report
for entry in report:
print(entry)
Can anyone help me? I had Element.Name not working but Gavin from AussiGuru helped me to use Element.Name.__get__(element)
unfortunately, it still has a lot of other issues as well. :(
https://drive.google.com/file/d/1AcChcDXqflGhw8tdxzXzxcWqTCOC60Qy/view?usp=share_link
since here cannot upload zip or revit file, so here is the test revit file.
Damn AI is getting pretty good! This is very close to working. There are some errors in the code,and a couple of PyRevit specific elements that would need replacing for it to work in OkPy. I’ll take you through them.
BTW : the OkPy assistant that will be available directly from within OkPy with Orkestra 1.7 will be context aware and will use the appropriate variables
Before you can use the Revit API namespaces, you need to reference it : clr.AddReference('RevitAPI')
the current document in OkPy is stored in the __current doc__ variable.
Getting a type name in IronPython is more complicated than it should be. This is not OkPy or PyRevit related… it’s just the way it is as far as I know. I believe they’ve improved it in IronPython 3. Here’s how I usually do it : e.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()
There is a redunduncy at line 42 where the code tries to get the family doc from what is already a family doc :
for family in famdocs:
print("working on family:"+str(family))
familyDoc = family.EditFamily
there’s no need for that. in here, familyDoc = family
When trying to set the foreground pattern, you’re using the ID from the project document to look for the pattern in the family document so, in many cases, this will fail. You can copy the pattern element into the family document when needed. You’ll probably need to do the same with background pattern just to make this more bulletproof
I used the OkPy assistant to help me out with this !
Line 92, there are two issues: a document doesn’t have a “Name” property, and even if it did have it, you’re trying to get it after the document is closed. I simply removed the line. It is a reporting line anyway so it’s not actually doing anything.
And with this it works! Here it is in action :
Here’s the full modified code, and the OkPy file.
import clr
clr.AddReference('RevitAPI')
import System
from System import Guid, Array
from System.Collections.Generic import *
from System.IO import Path
from Autodesk.Revit import DB
from Autodesk.Revit.DB import *
doc = __currentdoc__
class FamilyOption(DB.IFamilyLoadOptions):
def OnFamilyFound(self, familyInUse, overwriteParameterValues):
overwriteParameterValues = True
return True
def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
source = FamilySource.Family
overwriteParameterValues = True
return True
# Find all Filled Region Type, and create a dictionary with it
modelFilledRegionTypes = dict()
filledinFamily = DB.FilteredElementCollector(doc).OfClass(DB.FilledRegionType).ToElements()
for e in filledinFamily:
modelFilledRegionTypes[e.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()] = e
print(str(modelFilledRegionTypes))
# Find all loaded families
elements = DB.FilteredElementCollector(doc).OfClass(DB.Family).ToElements()
print(elements)
# Get Detail Item category id.
detailItemCategoryId = DB.Category.GetCategory(doc, DB.BuiltInCategory.OST_DetailComponents).Id
print(detailItemCategoryId)
# Initialize report list
report = []
# Loop on all loaded families
famdocs = []
for f in elements:
if f.IsEditable:
famdocs.append(doc.EditFamily(f))
for family in famdocs:
print("working on family:"+str(family))
familyDoc = family
print("Load family done" + str(familyDoc))
familyEdited = False
print("Editing family...." + str(family))
# Find all Filled Region Type in the family
filledinFamily = DB.FilteredElementCollector(familyDoc).OfClass(DB.FilledRegionType).ToElements()
print(str(filledinFamily))
with Transaction(familyDoc, "Edit Filled Region Type") as famTx:
famTx.Start()
for filledRegionType in filledinFamily:
if filledRegionType.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString() in modelFilledRegionTypes:
refFilledRegion = modelFilledRegionTypes[filledRegionType.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()]
print(refFilledRegion)
# Change the foreground pattern color
filledRegionType.ForegroundPatternColor = refFilledRegion.ForegroundPatternColor
familyEdited = True
print("foreground pattern color_check is " + str(filledRegionType.ForegroundPatternColor))
# Change the Background
filledRegionType.BackgroundPatternColor = refFilledRegion.BackgroundPatternColor
familyEdited = True
print("background pattern color_check" + str(filledRegionType.BackgroundPatternColor))
# Change line weight
filledRegionType.LineWeight = refFilledRegion.LineWeight
familyEdited = True
print("lineweight_check" + str(filledRegionType.LineWeight))
# Change fill pattern
filledRegionType.BackgroundPatternId = refFilledRegion.BackgroundPatternId
familyEdited = True
print("filed pattern background_check" + str(filledRegionType.BackgroundPatternId))
# Change fill pattern
try:
filledRegionType.ForegroundPatternId = refFilledRegion.ForegroundPatternId
except:
newPat = FillPatternElement.Create(familyDoc, doc.GetElement(refFilledRegion.ForegroundPatternId).GetFillPattern())
filledRegionType.ForegroundPatternId = newPat.Id
familyEdited = True
print("fill pattern foreground_check" + str(filledRegionType.ForegroundPatternId))
famTx.Commit()
if familyEdited:
familyDoc.LoadFamily(doc, FamilyOption())
familyDoc.Close(False)
else:
familyDoc.Close(False)
# Print report
for entry in report:
print(entry)
I fixed some errors and also replaced some of the elements in console for troubleshooting.
now it works seamless. Also, after days of troubleshooting, i realized I had the filled region in General Annotation family typed wrong. “corss hatch” instead of “cross hatch”. (stupid typo lol)
import clr
clr.AddReference('RevitAPI')
import System
from System import Guid, Array
from System.Collections.Generic import *
from System.IO import Path
from Autodesk.Revit import DB
from Autodesk.Revit.DB import *
doc = __currentdoc__
class FamilyOption(DB.IFamilyLoadOptions):
def OnFamilyFound(self, familyInUse, overwriteParameterValues):
overwriteParameterValues = True
return True
def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
source = FamilySource.Family
overwriteParameterValues = True
return True
# Find all Filled Region Type, and create a dictionary with it
modelFilledRegionTypes = dict()
filledinFamily = DB.FilteredElementCollector(doc).OfClass(DB.FilledRegionType).ToElements()
for e in filledinFamily:
modelFilledRegionTypes[e.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()] = e
print(str(modelFilledRegionTypes))
# Find all loaded families
elements = DB.FilteredElementCollector(doc).OfClass(DB.Family).ToElements()
elementName=[]
for en in elements:
eName= en.Name
elementName.append(eName)
print(elementName)
# Initialize report list
report = []
# Loop on all loaded families
famdocs = []
for f in elements:
if f.IsEditable:
fName=f.Name
famdocs.append(doc.EditFamily(f))
print(fName)
for family in famdocs:
#print("working on family:"+ family.Name)
familyDoc = family
familyEdited = False
print("--Editing family...." + familyDoc.Title)
# Find all Filled Region Type in the family
filledinFamily = DB.FilteredElementCollector(familyDoc).OfClass(DB.FilledRegionType).ToElements()
print(str(filledinFamily))
with Transaction(familyDoc, "Edit Filled Region Type") as famTx:
famTx.Start()
for filledRegionType in filledinFamily:
if filledRegionType.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString() in modelFilledRegionTypes:
refFilledRegion = modelFilledRegionTypes[filledRegionType.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString()]
print(refFilledRegion)
# Change the foreground pattern color
filledRegionType.ForegroundPatternColor = refFilledRegion.ForegroundPatternColor
familyEdited = True
print("foreground pattern color_checked")
# Change the Background
filledRegionType.BackgroundPatternColor = refFilledRegion.BackgroundPatternColor
familyEdited = True
print("background pattern color_checked" )
# Change line weight
filledRegionType.LineWeight = refFilledRegion.LineWeight
familyEdited = True
print("lineweight_checked")
# Change fill pattern
filledRegionType.BackgroundPatternId = refFilledRegion.BackgroundPatternId
familyEdited = True
print("filed pattern background_checked")
# Change fill pattern
try:
filledRegionType.ForegroundPatternId = refFilledRegion.ForegroundPatternId
except:
newPat = FillPatternElement.Create(familyDoc, doc.GetElement(refFilledRegion.ForegroundPatternId).GetFillPattern())
filledRegionType.ForegroundPatternId = newPat.Id
familyEdited = True
print("fill pattern foreground_check " + str(filledRegionType.ForegroundPatternId))
print("Current family"+ familyDoc.Title + " is done! ")
famTx.Commit()
if familyEdited:
familyDoc.LoadFamily(doc, FamilyOption())
familyDoc.Close(False)
else:
familyDoc.Close(False)
# Print report
for entry in report:
print(entry)
I do not know why I have to use this variable. familyDoc = family
but it works when its there ,and it does not work when i take it out,even though I changed all the variables from reading “familyDoc” to “family”.