I keep receiving the subject error message, also indicating a failure. Honestly I’ve been chasing this a bit and I’m at a loss, though it’s likely something very simple. It’s worth noting all the tasks successfully complete but there is no output due to this error. The second time the script runs on the same project, there is no error (probably because the tasks do not need to execute).
My solution is basically: 1) checking/creating a shared parameter in a project’s families, 2) checking/applying the same shared parameter to the project, 3) validating other properties in the applied families and inserting a value into the parameter inserted in stage 1.
Here are the parts of python that are tripping on the error:
this function:
def _CheckIN0(families):
for f1 in families:
famdoc = doc.EditFamily(f1)
load1 = False
load2 = False
#get category for later
cats.append(f1.FamilyCategory)
try:
param = famdoc.FamilyManager.get_Parameter(sParam)
load1 = _AddParameter(famdoc, f1)
_FilterNonBlankIN0(famdoc, f1)
#results.append(sParam)
except Exception, e:
errors.append("112: "%e)
#if load1 == True:
if famdoc.FamilyManager.get_Parameter(sParam):
results.append(famdoc.FamilyManager.get_Parameter(sParam))
trans = Transaction(famdoc, "LoadFamily")
trans.Start()
try:
famdoc.LoadFamily(doc, FamilyOption())
except Exception,e:
famdoc.LoadFamily(doc, True)
errors.append("124: "%e)
trans.Commit()
famdoc.Close(False)
Thank you again for the tip! The effect of that would be an instruction for Revit to save the family files upon reloading into the project. If you think about the process of opening a project, choosing Edit Family, editing the family and then reloading the family into the project, that Family.Close(bool) step would indicate to Revit if the user would like to save the family file, which in this case, I do not. The second class in my OP automates the dialog upon family reentry into the project (no change, overwrite (including bool parameter values), and overwrite a nested (“Shared”) family that is hosted into another family.
I have been able to eliminate the following possibilities:
• Nested issues
• Category-based reload limits
• Transactions
It may be a flaw in the IFamilyLoadOptions method that could generate a fail no matter the outcome.
So here is code that I use to do some cleaning of families. I think something to note here is that I don’t believe you have to be IN a transaction to load families into the model.
import System
import clr
clr.AddReference("RevitNodes")
import Revit
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("RevitAPI")
clr.AddReference('DSCoreNodes')
from DSCore import *
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
ProjectDoc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
families = IN[0]
if not isinstance(paths, list): paths = [paths]
cats = List.Flatten([IN[1]],1)
save = IN[2]
load = IN[3]
class FamilyOption(IFamilyLoadOptions):
def OnFamilyFound(self, familyInUse, overwriteParameterValues):
overwriteParameterValues = True
return True
def OnSharedFamilyFound(
self, sharedFamily, familyInUse, source, overwriteParameterValues):
source = FamilySource.Family
overwriteParameterValues = True
return True
delIds = []
errorReport = None
try:
for fam in families:
trans = Transaction(doc,'del')
trans.Start()
famDoc = ProjectDoc.EditFamily(fam)
#Do your work here for your parameters
trans.Commit()
trans.Dispose()
if load:
famDoc.LoadFamily(ProjectDoc,FamilyOption())
if save:
opt = SaveAsOptions()
opt.OverwriteExistingFile = True
opt.Compact = True
opt.MaximumBackups = 1
doc.SaveAs(path,opt)
doc.Close(False)
else:
doc.Close(False)
except:
import traceback
errorReport = traceback.format_exc()
if errorReport is None:
OUT = delIds
else:
OUT = errorReport
It took some time comparing the two and considering/applying the differences. At the end of it, I removed 2 of the functions the original called, and restructured when the transaction and load family should be called. The other 2 functions didn’t end up as robust as originally intended. So you’ll see fragments of them in the final result that I will be cleaning out. Also, you’re absolutely right in that the load family does not need to be in a transaction.
Here’s what I ended up with:
def _CheckIN0(families):
trans1 = TransactionManager.Instance
trans1.ForceCloseTransaction() #just to make sure everything is closed down
for f1 in families:
_paramType = ParameterType.Text
_paramGroup = BuiltInParameterGroup.PG_IDENTITY_DATA
_paramName = cParam
_groupName = "Assets"
cc = ""
value = ""
famdoc = doc.EditFamily(f1)
famMan = famdoc.FamilyManager
trans1.EnsureInTransaction(famdoc)
#get category for later
cats.append(f1.FamilyCategory)
#add shared parameter to families
try:
file = app.OpenSharedParameterFile()
except Exception,e:
errors.append("83: "%e)
pass
try:
param = famMan.get_Parameter(sParam)
params = famMan.Parameters
eDef = DefFile(file, _groupName, cParam)
famdoc.FamilyManager.AddParameter(eDef,_paramGroup, False)
for p1 in params:
if p1.Definition.Name == sParam:
ac = p1
for p2 in params:
if p2.Definition.Name == cParam:
cc = p2
familyTypesItor = famMan.Types.ForwardIterator()
familyTypesItor.Reset()
while (familyTypesItor.MoveNext()):
ft = familyTypesItor.Current
value = ft.AsString(ac)
custom = ft.AsString(cc)
if value > "":
typeinfo = []
typeinfo.append(f)
typeinfo.append(ft.Name)
typeinfo.append(custom)
typeinfo.append(value)
listings.Add(typeinfo)
trans1.ForceCloseTransaction()
except Exception, e:
errors.append(e)
trans1.ForceCloseTransaction()
famdoc.LoadFamily(doc, FamilyOption())
famdoc.Close(False)