Bulk Save as Central

I need a way to open multiple files and save them as central worksharing models. I am able to create a list of file paths in excel for all the files I want to do this with.

The reason: We are moving to a different file storage system which means all the workshared Revit files will still point to the old location. This means that I would have to open all the Revit files individually and save as central model and close them.
It seems like this is something that could be done with a python script, but I am not skilled enough to make it happen.

1 Like

You’ll need access to the API through Python. This is the API you’ll probably need to start with – http://www.revitapidocs.com/2016/5db03f57-b7fa-a1fa-e8b2-289c80678e75.htm

Find a Python node that opens files and modify it from there. You gotta start somewhere!

1 Like

Did you manage this? I have the same issue and I’d love to stand on the shoulders of giants rather than start from scratch.

Thanks!

well, i believe this will do the trick. i personally used it for model migration and model upgrades.

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
from System.IO import *

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

worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True

SaveOptions = SaveAsOptions()
SaveOptions.MaximumBackups = 50
SaveOptions.SetWorksharingOptions(worksharingOptions)
SaveOptions.OverwriteExistingFile = True
SaveOptions.Compact = 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

tOptions = TransactWithCentralOptions()

TransactionManager.Instance.ForceCloseTransaction()    
filepaths = IN[0]

RVer = "R" + app.VersionNumber[-2:]

docpath = []

if IN[1] == True:
	try:
		for filepath in filepaths:
			file = FileInfo(filepath)
			filein = file.FullName
			modelpath = FilePath(filein)
			filename = filepath.Split("\\")[-1].Replace(".rvt","")
			newdoc = app.OpenDocumentFile(filepath)			
			if RVer not in filename:
				if "Central" in filename:
					x = filepath.split("_")
					x.insert(len(filepath.split("_"))-1,RVer)
					y = "_".join(x)
				else:
					x = filepath[:-4]
					y = x + "_" + RVer + ".rvt"
			else:
				y = filepath
			newdoc.SaveAs(y,SaveOptions)			
			newdoc.SynchronizeWithCentral(tOptions,sOptions)
			newdoc.Close(True)
			docpath.append(y)	
		OUT = [filepaths,docpath]
	except Exception,e:
		OUT = str(e)
else:
	OUT = "Please set it to true"
8 Likes

Hi !
Can you explain what are the inputs for this Python script ?

Hello, IN[0] will be the list of filepaths you wanna open, and IN[1] is just a boolean (true or false)

Thank you !

Here is what I add to the script to make it works !

it does not work fo me, it says something like the file path does not exist, but there is already a file in there
image

I guess because script is editing the file path name, splitting string by “_” and something more, and my file name contains that symbol.

ilename = filepath.Split("\\")[-1].Replace(".rvt","")
			newdoc = app.OpenDocumentFile(filepath)			
			if RVer not in filename:
				if "Central" in filename:
					x = filepath.split("_")
					x.insert(len(filepath.split("_"))-1,RVer)
					y = "_".join(x)
				else:
					x = filepath[:-4]
					y = x + "_" + RVer + ".rvt"
			else:
				y = filepath
			newdoc.SaveAs(y,SaveOptions)			

yea it does that, the script’s intention was to also change the name to the respective version. you can comment away the if statement to make it work as you need.

Hi everyone,

stumbled upon this thread when looking for answers to custom node packages (genuis loci & clockwork?) not working or using the current document to run the save as rather than the model I specified.

I modified stillgotme’s code using a custom GPT model called Copilot to work with a string input for the filepath of the model you are wanting to save and also allows for a string input on what you are wanting to save the new model as. Ive included the code below for others to use.

So essentially you can run this in a blank revit file to upgrade models , archive models e.t.c

I just want to extend my thanks to stillgotme for providing that code which formed the foundation of the revised script I used AI to write

Script below feel free to use but make sure to credit stillgotme if you do end up using this i barely did anything other than chat with the Ai to get it to work which required some understanding of python and revit workings but still that is no where near the efforts of stillgotme :smiley:

Set up can be done however you want so long as IN[0] & IN[2] is in string format and IN[1] is a bool input format. example below:

For some reason when I try upload the code it does something weird with the formatting so ive attached a .dyn file which will help you with set up

save as test.dyn (9.9 KB)

This will only work for Central Model Revit file, right?
Else it comes back with :

Error: The document is not workshared, so no WorksharingSaveAsOptions are allowed to be set for SaveAs.
Parameter name: options
at Autodesk.Revit.DB.Document.SaveAs(String filepath, SaveAsOptions options)

Is there a way to just save the elements into a newly created workset directly?

are you wanting to run a save as for a none central model model? or are you wanting it to open and run a save as for the model which isnt a central and during the save as make it a central?

run a save as for the model which isnt a central and during the save as make it a central

Think you’d need to enable worksharing first. Best to start a new topic if this looks unfamilar to you, including the .dyn you’re currently using and the formatted Python script.

I have asked GPT to modify it for your needs but it may not work without further modification. I havent tested this either so it may not work at all but worth trying. IF this doesnt work perhaps copy the code and start another forum post to ask for help from others as im working currently and dont really have a need for a node with this function just yet therefor I wont be spending time getting it to work as other areas require my attention.

Best of luck with it and if you do get it to work make sure you credit the person I creditted in my response as he did a lot of the leg work for this.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitAPI")
clr.AddReference("RevitAPIUI")
clr.AddReference("RevitServices")
clr.AddReference("RevitNodes")

import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

import sys
import os
from System.IO import *

# Inputs
file_to_open = IN[0]  # String path of the file to open
run_save_as = IN[1]  # Boolean flag to execute the SaveAs operation
save_as_path = IN[2]  # Specific full file path for saving the Revit model (string)

# Setup Revit application variables
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

# Setup options for saving and synchronizing
worksharingOptions = WorksharingSaveAsOptions()
worksharingOptions.SaveAsCentral = True  # Setting SaveAsCentral to true
saveOptions = SaveAsOptions()
saveOptions.MaximumBackups = 50
saveOptions.SetWorksharingOptions(worksharingOptions)
saveOptions.OverwriteExistingFile = True
saveOptions.Compact = True

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

syncOptions = SynchronizeWithCentralOptions()
syncOptions.SetRelinquishOptions(relinquishOptions)
syncOptions.Compact = True
syncOptions.SaveLocalBefore = True
syncOptions.SaveLocalAfter = True

transactOptions = TransactWithCentralOptions()

# Process the files
docpath = []

if run_save_as:
    try:
        # Validate that file_to_open is a valid string path
        if not isinstance(file_to_open, str) or not os.path.exists(file_to_open):
            raise ValueError(f"Invalid file path to open: {file_to_open}")

        # Validate the save_as_path to ensure it's a valid full file path
        save_directory = os.path.dirname(save_as_path)
        if not os.path.exists(save_directory):
            raise ValueError(f"Invalid directory in save path: {save_as_path}")

        # Open the document using the file path
        newdoc = app.OpenDocumentFile(file_to_open)

        # Use the full file path provided in IN[2] for saving as central
        newdoc.SaveAs(save_as_path, saveOptions)

        # Synchronize with central after save as central
        newdoc.SynchronizeWithCentral(transactOptions, syncOptions)

        # Close the document
        newdoc.Close(True)

        # Record the saved file path
        docpath.append(save_as_path)
        OUT = [file_to_open, docpath]

    except Exception as e:
        # Output the error message with detailed information
        OUT = f"Error: {str(e)}\nFile: {file_to_open}"

else:
    OUT = "Please set the 'run_save_as' flag to true"