Hello 大家好!我是九哥~
前几天群里有个小伙伴,咨询了我一个问题:如何批量修改多个 Revit 文件的项目基点?
本来是想帮忙改改程序,奈何打开以后,我看到了无数的节点和连线,而且这个问题,主要是因为 Transaction 的问题,代码应该更容易一些~
那么我们就来一起解决下这个,本次教程呢,主要是讲解如何完全通过代码来解决这个事,最后你会发现,用代码解决这个事,就会变得超级简单了~
一、获取 Revit 项目文件
第一步比较简单,用自带的几个节点一连就好,如下图,我这里为了便于多次测试,把带 “000” 的文件过滤了一下:
二、后台打开 Revit 文件
我们打开 API 手册,搜索 Application,能够找到如下三种方法,我们选择按路径和选项打开文件:
大意呢,就是需要一个模型路径和打开选项,我们分别看下。
(1)字符串路径转换为 ModelPath
首先我们需要将字符串的文件路径转化为 ModelPath,在 API 手册里搜索 ModelPathUtils,就能找到相关的转换方法,我们选择
ConvertUserVisiblePathToModelPath() 方法:
基本代码如下:
#获取文件路径,并后台打开文件,获取document
modelPath = ModelPathUtils.ConvertUserVisiblePathToModelPath(i)
d = app.OpenDocumentFile(modelPath, options)
(2)打开选项
在第二步的 Application 方法下,直接点击 OpenOptions 即可跳转相关页面:
这里重点关注下面这个选项,是否分离中心文件:
继续点进去,可以看到DetachFromCentralOption 的枚举:
这里我就简单选择第二个,打开并分离中心文件,实际按需选择即可。代码如下:
#打开文件的选项
options = OpenOptions()
options.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets
三、获取项目基点
这里用到 System.Enum.ToObject 方法,大家记住即可,就不过多讲解了,用此方法将输入的 Category 转换为 BuiltInCategory。
然后就可以用过滤器,过滤出所需的图元了,代码如下:
#将Category转换为BuiltInCategory,并获取项目基点
bic = System.Enum.ToObject(BuiltInCategory, cat.Id)
element = FilteredElementCollector(d).WhereElementIsNotElementType().OfCategory(bic).ToElements()[0]
四、开启和关闭时事务
由于我们要更改项目基点的参数,开启事务是必须的,很多小伙伴都会用网上万能模板里提供的 Dynamo 开启和关闭事务方法,这里呢,我就直接调用 API 的方法了,可以参考之前的文章《如何让撤销栏显示 Dynamo 的具体操作内容》,介绍了 Transaction 相关内容。
#尝试开启事务
t = Transaction(d,'设置项目基点参数')
t.Start()
#关闭事务
t.Commit()
五、解锁和锁定项目基点
大多数情况下,Revit 默认的项目基点都是锁定状态的,这样如果我们用 Dynamo 设置项目基点参数,是无法完成的,会提示你图元被锁定。
在 API 手册中直接搜索 Pinned 就能找到图元锁定的方法,可 get 可 set,如下图:
那么我们就可以先解除锁定,在设置完参数以后再给他锁上,代码如下:
#解锁项目基点
element.Pinned = False
#锁定项目基点
element.Pinned = True
六、设置项目基点参数
这里呢,我也就简单写了,直接采用 LookupParameter 的方法,毕竟也不涉及多语言版本等问题,就是演示下思路,只需要写一个循环即可,代码如下:
#循环参数名称,并设置项目基点参数
r = []
for p,v in zip(parameter_names,values):
data = element.LookupParameter(p).Set(v)
七、关闭和保存
直接在 API 手册里搜索 Document,就能看到 Close 的方法,如下图:
到这里我们的程序基本就完成了,如果你想让程序更完美,可以再加一个 try...except...,来更好的输出错误报告,代码如下:
#返回错误报告
import traceback
errorReport = traceback.format_exc()
这样我们本次教程的代码就写完了,最后附上完整的代码和节点截图,如下:
import clr
from System.Collections.Generic import *
import System
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
doc = DocumentManager.Instance.CurrentDBDocument
app = doc.Application
def tolist(x):
if hasattr(x,'__iter__'): return x
else : return [x]
filePath = tolist(IN[0])
cat= IN[1]
parameter_names = tolist(IN[2])
values = tolist(IN[3])
options = OpenOptions()
options.DetachFromCentralOption = DetachFromCentralOption.DetachAndPreserveWorksets
docOnDisk = []
items = []
result = []
for i in filePath:
modelPath = ModelPathUtils.ConvertUserVisiblePathToModelPath(i)
d = app.OpenDocumentFile(modelPath, options)
bic = System.Enum.ToObject(BuiltInCategory, cat.Id)
element = FilteredElementCollector(d).WhereElementIsNotElementType().OfCategory(bic).ToElements()[0]
try:
t = Transaction(d,'设置项目基点参数')
t.Start()
element.Pinned = False
r = []
for p,v in zip(parameter_names,values):
data = element.LookupParameter(p).Set(v)
r.append(data)
element.Pinned = True
t.Commit()
result.append(r)
except:
import traceback
errorReport = traceback.format_exc()
result.append(errorReport)
d.Close(True)
OUT = result
tips:
注意,由于我这里用的 LookupParameter 方法设置的参数,所以就涉及 Revit 内部单位问题,这里我就没做处理,直接用 Dynamo 的单位转换节点了,如下图:
好了,今天的教程就到这里了,小伙伴们快去尝试吧~