Opening & closing of multiple models in background while completing a set of tasks

yes you can do that by including more opening option.

incase you havent worked it out yet, just input the following codes accordingly into the lines
image

openConfig = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
oOptions.SetOpenWorksetsConfiguration(openConfig)

@stillgotme firstly thank you for sharing it, very useful. I am getting the message: unsupported operand type(s) for +: ‘list’ and ‘str’. and the file is not saving.

I barely know python, however, I am guessing it is related to this line:
newfilepath = newpath + “\” + filenames

If I change to
newfilepath = newpath + “\” + str(filenames)

It works however I get a file name with [’ '] E.g. [‘actualfilename.rvt’]
Also if I have more than one file, it will be [‘actualfilename.rvt’, ‘actualfilename2.rvt’, ‘actualfilename3.rvt’] saved as 1 file, instead of 3 separated files.

How to proceed from there?

Thanks

You should try to comment out some of the lines and create a list for debugging which you will assign to your OUT variable. I would append newpath and filenames to this list so you can understand what they actually look like in the loop. The variable names are actually a bit confusing (file is actually a list of files and files is actually a single file), but if you append filenames to your list and find that it is indeed a list, that would explain the TypeError.

Do you mind showing me your current workflow?? and which script did you use?

Revit 2018.3.2.7
Dynamo Core 2.0.2.6826
Dynamo Revit 2.0.2.6833

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.Attributes import*

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

from System.Collections.Generic import *

# Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

# Import python library
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os

tOptions = TransactWithCentralOptions()

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc =     DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

def flatten(*args):
for x in args:
    if hasattr(x, '__iter__'):
        for y in flatten(*x): yield y
    else: yield x


#Credits Archi-lab
def checkParameter(param):
for p in param:
	internal = p.Definition
	if internal.BuiltInParameter != BuiltInParameter.INVALID:
		return p
return param[0]

def GetParaValue(params):
paravalue = []
p = checkParameter(params)
if p.StorageType == StorageType.String:
	paravalue.append(p.AsString())
elif p.StorageType == StorageType.ElementId:
	paravalue.append(p.AsValueString())
elif p.StorageType == StorageType.Integer:
	paravalue.append(p.AsValueString())
else:
	paravalue.append(None)
return paravalue

if isinstance(IN[0], list):
file = IN[0]
filename = IN[2]
else:
file = [IN[0]]
filename = [IN[2]]

newpath = IN[1]
LinkNames, newdocpath, results, unloadstatus, linkParas = [], [], [], [], []

openConfig =     WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
oOptions = OpenOptions()
oOptions.DetachFromCentralOption =     DetachFromCentralOption.DetachAndPreserveWorksets
oOptions.Audit = True
oOptions.SetOpenWorksetsConfiguration(openConfig)

worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True

SaveOptions = SaveAsOptions()
SaveOptions.MaximumBackups = 50
SaveOptions.SetWorksharingOptions(worksharingOptions)
SaveOptions.OverwriteExistingFile = True

rOptions = RelinquishOptions(False)
rOptions.StandardWorksets = True
rOptions.ViewWorksets = True
rOptions.FamilyWorksets = True
rOptions.UserWorksets = True
rOptions.CheckedOutElements = True

sOptions = SynchronizeWithCentralOptions()
sOptions.SetRelinquishOptions(rOptions)
sOptions.Compact = True
sOptions.SaveLocalBefore = True
sOptions.SaveLocalAfter = True

TransactionManager.Instance.ForceCloseTransaction()

try:
for files,filenames in zip(file,filename):
	modelpath = FilePath(files)
	newdoc = app.OpenDocumentFile(modelpath,oOptions)
	collector = Autodesk.Revit.DB.FilteredElementCollector(newdoc)
	linkTypes = UnwrapElement(collector.OfClass(Autodesk.Revit.DB.RevitLinkType))
	for linkType in flatten(linkTypes):
		linkPara = linkType.GetParameters("Type Name")
		linkParavalue = GetParaValue(linkPara)
		try:
			linkType.Unload(None)
			unloadstatus.append(True)
		except:
			unloadstatus.append(False)
		results = [unloadstatus]		
	newfilepath = newpath + "\\" + filenames
	newdoc.SaveAs(newfilepath,SaveOptions)			
	newdoc.SynchronizeWithCentral(tOptions,sOptions)
	newdoc.Close(True)
	newdocpath.append(newfilepath) 
	OUT = newdocpath 	
except Exception,e:
OUT = str(e)

Getting this warning and the RVT file does not save.

try changing from this:

if isinstance(IN[0], list):
    file = IN[0]
    filename = IN[2]
else:
    file = [IN[0]]
    filename = [IN[2]]

to this:

if isinstance(IN[0], list):
    file = IN[0]
else:
    file = [IN[0]]
if isinstance(IN[2],list): 
    filename = IN[2]
else:
    filename = [IN[2]]

Unfortunately, same message: unsupported operand type(s) for +: ‘list’ and ‘str’

Thanks for the feedback. I do not know how to do that yet, I am now trying to learn python as I have never learned any coding language. Guess will need some time to get it going :slight_smile:

I did some changes and it is working now!

I set the line:

	newfilepath = newpath + "\\" + filenames

To:

	newfilepath = newpath + "\\" + str(filenames)

And removed two flatten nodes, leaving as this:

However, it seems that the files are not being closed, even with the line

	newdoc.Close(True)

As I can see them in the worksharing monitor and the memory is still in use.

The current script is now:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.Attributes import*

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

from System.Collections.Generic import *

# Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

# Import python library
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os

tOptions = TransactWithCentralOptions()

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

def flatten(*args):
for x in args:
    if hasattr(x, '__iter__'):
        for y in flatten(*x): yield y
    else: yield x


#Credits Archi-lab
def checkParameter(param):
for p in param:
	internal = p.Definition
	if internal.BuiltInParameter != BuiltInParameter.INVALID:
		return p
return param[0]

def GetParaValue(params):
paravalue = []
p = checkParameter(params)
if p.StorageType == StorageType.String:
	paravalue.append(p.AsString())
elif p.StorageType == StorageType.ElementId:
	paravalue.append(p.AsValueString())
elif p.StorageType == StorageType.Integer:
	paravalue.append(p.AsValueString())
else:
	paravalue.append(None)
return paravalue

if isinstance(IN[0], list):
file = IN[0]
filename = IN[2]
else:
file = [IN[0]]
filename = [IN[2]]

newpath = IN[1]
LinkNames, newdocpath, results, unloadstatus, linkParas = [], [], [], [], []

openConfig = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
oOptions = OpenOptions()
oOptions.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets
oOptions.Audit = True
oOptions.SetOpenWorksetsConfiguration(openConfig)

worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True

SaveOptions = SaveAsOptions()
SaveOptions.MaximumBackups = 50
SaveOptions.SetWorksharingOptions(worksharingOptions)
SaveOptions.OverwriteExistingFile = True

rOptions = RelinquishOptions(False)
rOptions.StandardWorksets = True
rOptions.ViewWorksets = True
rOptions.FamilyWorksets = True
rOptions.UserWorksets = True
rOptions.CheckedOutElements = True

sOptions = SynchronizeWithCentralOptions()
sOptions.SetRelinquishOptions(rOptions)
sOptions.Compact = True
sOptions.SaveLocalBefore = True
sOptions.SaveLocalAfter = True

TransactionManager.Instance.ForceCloseTransaction()

try:
for files,filenames in zip(file,filename):
	modelpath = FilePath(files)
	newdoc = app.OpenDocumentFile(modelpath,oOptions)
	collector = Autodesk.Revit.DB.FilteredElementCollector(newdoc)
	linkTypes = UnwrapElement(collector.OfClass(Autodesk.Revit.DB.RevitLinkType))
	for linkType in flatten(linkTypes):
		linkPara = linkType.GetParameters("Type Name")
		linkParavalue = GetParaValue(linkPara)
		try:
			linkType.Unload(None)
			unloadstatus.append(True)
		except:
			unloadstatus.append(False)
		results = [unloadstatus]		
	newfilepath = newpath + "\\" + str(filenames)
	newdoc.SaveAs(newfilepath,SaveOptions)			
	newdoc.SynchronizeWithCentral(tOptions,sOptions)
	newdoc.Close(True)
	newdocpath.append(newfilepath) 
	OUT = newdocpath 	
except Exception,e:
OUT = str(e)

well i dont know whats wrong with your code, maybe can upload your sample files? and show me the inputs?? here is what i have now:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.Attributes import*

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

# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

from System.Collections.Generic import *

# Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

# Import python library
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)
import os

tOptions = TransactWithCentralOptions()

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument

def flatten(*args):
    for x in args:
        if hasattr(x, '__iter__'):
            for y in flatten(*x): yield y
        else: yield x
	

#Credits Archi-lab
def checkParameter(param):
	for p in param:
		internal = p.Definition
		if internal.BuiltInParameter != BuiltInParameter.INVALID:
			return p
	return param[0]

def GetParaValue(params):
	paravalue = []
	p = checkParameter(params)
	if p.StorageType == StorageType.String:
		paravalue.append(p.AsString())
	elif p.StorageType == StorageType.ElementId:
		paravalue.append(p.AsValueString())
	elif p.StorageType == StorageType.Integer:
		paravalue.append(p.AsValueString())
	else:
		paravalue.append(None)
	return paravalue
	
if isinstance(IN[0], list):
	file = IN[0]
	filename = IN[2]
else:
	file = [IN[0]]
	filename = [IN[2]]

newpath = IN[1]
LinkNames, newdocpath, results, unloadstatus, linkParas = [], [], [], [], []

openConfig = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
oOptions = OpenOptions()
oOptions.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets
oOptions.Audit = True
oOptions.SetOpenWorksetsConfiguration(openConfig)

worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True

SaveOptions = SaveAsOptions()
SaveOptions.MaximumBackups = 50
SaveOptions.SetWorksharingOptions(worksharingOptions)
SaveOptions.OverwriteExistingFile = True

rOptions = RelinquishOptions(False)
rOptions.StandardWorksets = True
rOptions.ViewWorksets = True
rOptions.FamilyWorksets = True
rOptions.UserWorksets = True
rOptions.CheckedOutElements = True

sOptions = SynchronizeWithCentralOptions()
sOptions.SetRelinquishOptions(rOptions)
sOptions.Compact = True
sOptions.SaveLocalBefore = True
sOptions.SaveLocalAfter = True

TransactionManager.Instance.ForceCloseTransaction()

if IN[3]:
	try:
		for files,filenames in zip(file,filename):
			modelpath = FilePath(files)
			newdoc = app.OpenDocumentFile(modelpath,oOptions)
			collector = Autodesk.Revit.DB.FilteredElementCollector(newdoc)
			linkTypes = UnwrapElement(collector.OfClass(Autodesk.Revit.DB.RevitLinkType))
			for linkType in flatten(linkTypes):
				linkPara = linkType.GetParameters("Type Name")
				linkParavalue = GetParaValue(linkPara)
				try:
					linkType.Unload(None)
					unloadstatus.append(True)
				except:
					unloadstatus.append(False)
				results = [unloadstatus]		
			newfilepath = newpath + "\\" + filenames
			newdoc.SaveAs(newfilepath,SaveOptions)			
			newdoc.SynchronizeWithCentral(tOptions,sOptions)
			newdoc.Close(True)
			newdocpath.append(newfilepath) 
			OUT = newdocpath 	
	except Exception,e:
		OUT = str(e)
else: OUT = "Please set IN[3] to true"

with IN[3] being a boolean input

EDIT: it works fine for all cases i used.

1 Like

Thanks, it is working as well, however it does not close the files, and keep consuming memory. They will only go if I close Revit. Which is not a big deal, I am messing with this because I am willing to batch run this on 300 rvt files within a average of 300mb each.

The files I am using to test it are just blank ones.

I realized that because I had worksharing monitor open and I could still see them there.
123%20s

ah i know what is your issue. you will need to open a blank project for this application. Do not use it at a current project.

EDIT: by blank i mean a new empty project

I believe I was in a blank file, will check and try again, thanks!

Can the working dyn be posted? I’m trying to get this work but having trouble.

Thanks!

here is the latest one, RevitModel_DetachUnloadSave_v1.3.dyn (48.1 KB)

1 Like

Hi guys,
I’m looking for an automatization to detach and save as new central the files come in BIM360 in a server’s folder… This amazing script can help me?

Hi there, BIM360 documents might be alittle bit more tricky, but the script should do the trick as well. Maybe you could test it out and let us know?

Hi @stillgotme,
of course, I’m trying it right these days and I’ll let you know soon

It seems doesn’t work… Maybe in the dicrectory folder there must to be only rvt file and no other folders?
The script run and complete but the lists are empty