Working on some code to load current (shared) family into a list of background opened family documents

Hey,

So, a couple of thoughts…

This is unfortunately quite a hard one to get yourself into using the API.

The big big issue here, is what happens if the code doesn’t finish executing… As it stands, you are background opening Every family in a folder.

Unless you successfully shut them after you use them, then you can quickly end up making your Revit fall over.

So, the sequence by which you do things, and the error catching you have in place is going to be critical…

Personally, I would organise your lists so that you run through 1 family doc at a time, try to open it, try to load it and try to close it. At each step, if there is a fail you need to deal with the errors you get.

I would have an extremely simple test setup because you’re likely to have to be shutting and opening Revit while you get it right.

Into the actual code, I’m curious to know why you benefit from background opening the files? Can you just load directly from a directory? Which I think is a quite simple adjustment to your code? :slight_smile: Untested unfortunately…

# Load the Python Standard and DesignScript Libraries
import clr

clr.AddReference('RevitAPI')
from Autodesk.Revit import DB
from Autodesk.Revit.DB.Structure import *

clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
uidoc=DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

#Preparing input from dynamo to revit
filepath_List = IN[0]

class FamilyLoaderOptionsHandler(DB.IFamilyLoadOptions):
    def OnFamilyFound(self, familyInUse, overwriteParameterValues):
        overwriteParameterValues = True
        return True

    def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
        source = DB.FamilySource.Family
        overwriteParameterValues = True
        return True

#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)
for filepath in filepath_List:
    fload_handler = FamilyLoaderOptionsHandler()
    OUT = doc.LoadFamily(filepath, fload_handler)

TransactionManager.Instance.TransactionTaskDone()

As to error catching, @c.poupin has posted an excellent piece which you might find interesting… [Dynamo =+ Python] Gestion des erreurs (context manager) ~ VoltaDynaBim

Personally, I look at the way that Archi-Lab is structured for most of mine, thanks Konrad :slight_smile: I think you might need to modify to nest a few Try statements…

if RunIt:
	try:
		errorReport = None
		# run checks
		checks = False
		if something:
			checks = True
		else:
			errorReport = "Some useful text for the user."
		TransactionManager.Instance.EnsureInTransaction(doc)
		if checks:
			output = something
		TransactionManager.Instance.TransactionTaskDone()
	except:
		# if error accurs anywhere in the process catch it
		import traceback
		errorReport = traceback.format_exc()
else:
	errorReport = "Please set RunIt to True."

#Assign your output to the OUT variable
if errorReport == None:
	OUT = output
else:
	OUT = errorReport #less useful for the user, but useful for you

Hope that is helpful :slight_smile:

Mark

2 Likes