Try to write a script to match all loaded Families' filled region to Project filled region

Hi all,

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.
1 Like

hey @ja8on !

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 :slight_smile:

  • 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 :slight_smile:

    I used the OkPy assistant to help me out with this :laughing: !

  • 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! :slight_smile: Here it is in action :
FillTest

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)

FilledTest.okpy (4.7 KB)

Hi @m.elayoubi ,

thank you so much!!!> it works now!!.

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)
1 Like

Awesome ! :slight_smile: nice work @ja8on

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”.

You can remove that line and replace familyDoc with family everywhere (OkPy has ctrl+H to find replace all!). family is your iterator in the for loop.