I´m building a python node on top of Batch Upgader (Detach From Central) to open a number of files as detached, then SaveAsCentral with another name.
The issue from the original code I want to overcome is: all workset become editable with myself as owner.

To overrcome the issue I´m trying to:
- use a collector to get the list of worksets
-
convert the python list into an icollection of WorksetID
- finally make use of WorksharingUtils.CheckoutWorksets and toggle the workset editability
- all of the above in the loop that opens, detaches, renames, saves, closes.
Despite the script running without errors, worksets are still editable and owened by me.
Posting my code below (apologies for formatting…first time here). What am I doing wrong?
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
>#import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
>doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
>#Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
>clr.AddReference("System")
from System.Collections.Generic import List
>#collect inputs
if isinstance(IN[0], list):
files = IN[0]
else:
files = [IN[0]]
>pDir = IN[1]
nPrefix = IN[2]
Originator = IN[3]
>#define originator split
splitPath = 1 + len(pDir)
splitA = splitPath + nPrefix
splitB = splitA + len(Originator)
>#save&worksharing options
options = OpenOptions()
options.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets
>worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True
>SaveOptions = SaveAsOptions()
SaveOptions.SetWorksharingOptions(worksharingOptions)
>allPaths=[]
>#run through all files
for file in files:
#Detatch
modelpath = FilePath(file)
newdoc = app.OpenDocumentFile(modelpath,options)
#CloseWorksets
collector = FilteredWorksetCollector(newdoc).OfKind(WorksetKind.UserWorkset)
iDs = [c.Id for c in collector] #python list
wsIds = List[WorksetId](iDs) #convert to icollection
wsClose = WorksharingUtils.CheckoutWorksets(newdoc,wsIds)
#Rename
newfile = file[:splitA] + Originator + file[splitB:]
#SaveAsCentral
newdoc.SaveAs(newfile,SaveOptions)
newdoc.Close(False)
allPaths.append(newfile)
OUT = allPaths
1 Like
If you were to do this manually, you would have to sync after saving to relinquish the worksets. This is because you have to own each workset on initial creation in a central file. Just because you’re doing this programmatically doesn’t mean that Revit will perform things differently.
Try adding a Sync after saving, and note that you will need to set the options for relinquishing ownership as you do so.
A breadcrumb: SynchronizeWithCentralOptions Members
very much helpful Jacob, thanks!
As I do not know the “theory” behind, are you pointing out to relinquish all attributes - correct? or is it just the UserWorkset?
sth like
tOptions = TransactWithCentralOptions()
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
to then parse this line right before the close, as you say?
newdoc.SynchronizeWithCentral(tOptions,sOptions)
I think it would require relinquish all to be set to ‘true’. You don’t want to own anything when you’re done after all. 
2 Likes
amazing @jacob.small ! sync after save with relinquish all just did the trick
attached final script (with rationalized inputs)
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference("System")
from System.Collections.Generic import List
# collect inputs
if isinstance(IN[0], list):
files = IN[0]
filenames = IN[2]
else:
files = [IN[0]]
filenames = [IN[2]]
newPath = IN[1]
#shortings and options
options = OpenOptions()
options.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets
worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True
SaveOptions = SaveAsOptions()
SaveOptions.SetWorksharingOptions(worksharingOptions)
tOptions = TransactWithCentralOptions()
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
allPaths=[]
#run through all files
for file,filename in zip(files,filenames):
#Detatch
modelpath = FilePath(file)
newdoc = app.OpenDocumentFile(modelpath,options)
#CloseWorksets
collector = FilteredWorksetCollector(newdoc).OfKind(WorksetKind.UserWorkset)
#iDs = []
iDs = [c.Id for c in collector] #python list
wsIds = List[WorksetId](iDs) #convert to icollection
wsClose = WorksharingUtils.CheckoutWorksets(newdoc,wsIds)
#Rename
newfile = newPath +"\\"+ filename
# + version + ".rvt"
#SaveAsCentral
newdoc.SaveAs(newfile,SaveOptions)
newdoc.SynchronizeWithCentral(tOptions,sOptions)
newdoc.Close(False)
allPaths.append(newfile)
OUT = allPaths
Kudos to @stillgotme and @brunocassol as the breadcrumb lead me to the excellent opening&closing of multiple models in background while completeing a set of tasks
3 Likes
can you provide the final script plz