多人协作的Revit项目都是基于工作共享(Worksharing)的模式,运用中心模型(Central model)来进行协作工作。
一个正确的中心文件的备份程序应该是这样的:
- 以从中心分离的方式打开一个中心文件 (open one central file as Detached)
- 将打开的文件另存为一个中心文件 (save the file as a detached central file)
- 放弃所有工作集并关闭 (relinquish all worksets and close)
在大型多人协作的Revit项目中,一般会将项目分割成多个中心文件,这给周期性的备份工作带来了一定的时间成本。当然,我们可以粗暴地拷贝粘贴中心文件到某个备份文件夹。但风险是,这个备份文件并不是与中心文件分离的(detached),所以有可能一段时间后有人用备份文件将中心文件错误地同步了(我也不幸经历过)。所以,我做了一个Dynamo脚本来自动化这项工作。
同样,这里我使用到了 DATA|SAHAPES 的UI Node:

使用者首先选择中心文件所在的文件夹以及项目名称,之后脚本会在这个文件夹下自动新建一个备份文件夹(使用项目名称),然后遵循刚提到的备份程序将备份文件保存在此。最后生成一个结果报告。
Dynamo 脚本如下:
下面我解释一下红色区域的Python脚本的部分:
# Coded by kj.luo # kj-luo.com # 2021.01.05 ########## IMPORT ########## import clr import sys sys.path.append('C:\Program Files (x86)\IronPython 2.7\Lib') clr.AddReference("RevitAPI") import Autodesk from Autodesk.Revit.DB import * clr.AddReference("RevitServices") import RevitServices from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager from datetime import datetime import System import os doc = DocumentManager.Instance.CurrentDBDocument uiapp = DocumentManager.Instance.CurrentUIApplication app = uiapp.Application # date for the new folder name # 取得给文件夹命名的日期 now = datetime.now() namedate = now.strftime("%y%m%d") ########## INPUT ########## projektname = IN[0] directory = IN[1] filepaths = [FilePath(x) for x in IN[2]] ########## OUTPUT ########## out = [] ########## SCRIPT ########## # create open options. It must be detached # 新打开文件必须的 open option openoptions = OpenOptions() openoptions.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets # Worksets from the file should be all closed to speed up the loading # 为了节省载入时间,所有的工作集在打开过程中应该是关闭的 openConfig = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets) openoptions.SetOpenWorksetsConfiguration(openConfig) # Create two save options, for two types of revit file: worksharing and not worksharing # 两种 save options,分别给中心文件和普通文件 saveoptions_sharing = SaveAsOptions() saveoptions_notsharing = SaveAsOptions() saveoptions_sharing.OverwriteExistingFile = False saveoptions_notsharing.OverwriteExistingFile = False # As well two worksharing save options for each type wsOptions_sharing = WorksharingSaveAsOptions() wsOptions_notsharing = WorksharingSaveAsOptions() wsOptions_sharing.SaveAsCentral = True wsOptions_notsharing.SaveAsCentral = False saveoptions_sharing.SetWorksharingOptions(wsOptions_sharing) saveoptions_notsharing.SetWorksharingOptions(wsOptions_notsharing) # Relinquish option to relinquish the file # 放弃工作集的设定 relinoptions = RelinquishOptions(True) transoptions = TransactWithCentralOptions() # Create Archiv-folder and Backup+date-folder # 新建备份文件夹 archivdirectory = directory + "\\Archiv" if not os.path.exists(archivdirectory): os.makedirs(archivdirectory) backupfolder = archivdirectory+ "\\" + projektname + "_" + namedate +"_AutoBACKUP" if not os.path.exists(backupfolder): os.makedirs(backupfolder) TransactionManager.Instance.EnsureInTransaction(doc) # Each file path stands for a revit file. # 每个路径代表了一个revit文件 for filepath in filepaths: filedocu = app.OpenDocumentFile(filepath, openoptions) filetitle = filedocu.Title savepath = FilePath(backupfolder +"\\"+ filetitle + "_autobackup_" + ".rvt") try: # If it is a worksharing file if filedocu.IsWorkshared: filedocu.SaveAs(savepath,saveoptions_sharing) out.append(filetitle + ": saved") WorksharingUtils.RelinquishOwnership(filedocu,relinoptions,transoptions) # If it is not a worksharing file else: filedocu.SaveAs(savepath,saveoptions_notsharing) out.append(filetitle + ": saved") except: out.append(filetitle + ": not saved") # at last, the file must be closed to free up space # 最后必须得关闭文件,以释放硬盘空间 filedocu.Close(False) TransactionManager.Instance.TransactionTaskDone() OUT = out
脚本运行完成后:


2021年1月5日