Merge python code,Create pipe connectors,family

I’m allowed to merge two python scripts, both of which run independently in dynamo, but I won’t merge them.
1:
import clr
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *
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
import System

def tolist(x):
if hasattr(x,‘iter’): return x
else : return

获取当前文档

doc = DocumentManager.Instance.CurrentDBDocument

定义要查找的类别 ID

category_id = -2000196

通过类别 ID 尝试找到对应的类别

target_category = doc.Settings.Categories.get_Item(category_id)

如果没有找到指定的类别,抛出异常

if target_category is None:
raise ValueError(f"Category with ID {category_id} not found.")

收集指定类别下的非元素类型的元素

collector = FilteredElementCollector(doc).OfCategoryId(target_category.Id).WhereElementIsNotElementType().ToElements()

将 collector 包装成列表

collector = [collector] if not isinstance(collector, list) else collector

OUT = collector

2:
代码2:
import clr
clr.AddReference(‘ProtoGeometry’)
from Autodesk.DesignScript.Geometry import *
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
import System

elements = IN[0]
mepSystemTypes = IN[1] if len(IN) > 1 else None
desired_diameter = IN[2] if len(IN) > 2 else None

def get_element_faces(element):
if isinstance(element, list):
faces =
for e in element:
try:
element_faces = e.Faces
faces.extend(element_faces)
except AttributeError:
pass
return faces
else:
try:
return element.Faces
except AttributeError:
return None

faces = get_element_faces(elements)

circular_faces =
for face in faces:
try:
curves = face.PerimeterCurves()
surface_curves =
for curve in curves:
surface_curves.append(curve)
if any(isinstance(curve, Circle) for curve in surface_curves):
circular_faces.append(face)
except AttributeError:
pass

references =
for face in circular_faces:
try:
reference = face.Tags.LookupTag(“RevitFaceReference”)
references.append(reference)
except:
references.append(None)

确保处理的是族文档

doc = DocumentManager.Instance.CurrentDBDocument
if not doc.IsFamilyDocument:
raise ValueError(“The document is not a family document.”)

connector =
TransactionManager.Instance.ForceCloseTransaction()
TransactionManager.Instance.EnsureInTransaction(doc)

检查并处理 mepSystemTypes 的类型

if not isinstance(mepSystemTypes, list):
mepSystemTypes = [mepSystemTypes]

for ref in references:
if ref is not None:
for mepSystemType in mepSystemTypes:
if isinstance(mepSystemType, Autodesk.Revit.DB.Plumbing.PipeSystemType):
mepSys = mepSystemType
else:
# 如果 mepSystemType 是整数,先转换为字符串再进行解析
if isinstance(mepSystemType, int):
mepSystemType = str(mepSystemType)
mepSys = System.Enum.Parse(Autodesk.Revit.DB.Plumbing.PipeSystemType, mepSystemType)
created_connector = ConnectorElement.CreatePipeConnector(doc, mepSys, ref)
if desired_diameter is not None:
radius_param = created_connector.get_Parameter(BuiltInParameter.CONNECTOR_RADIUS)
radius_param.Set(desired_diameter / 2)
connector.append(created_connector)

TransactionManager.Instance.TransactionTaskDone()

OUT = connector

I’m trying to:

  1. Generate the sat file family file in batches.
  2. Obtain the location, direction and diameter of the connector from the table and export it as an sat file.
  3. Create a family document, import the corresponding sat file and the sat file generated by the connector into the document, obtain the sat file generated by the imported connector, and obtain the size of the reference and surface. Place the connector and set the eating size.

Can you please edit the first post to format the code

You can use the code format in the edit menu </>

or you can use triple back-ticks ``` at the start and finish of code

Include the language without a space at the start for formatting like this ```python

import clr

# This is python

This will make your code readable and will assist in getting a response

代码1:
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
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
import System

def tolist(x):
    if hasattr(x,'__iter__'): return x
    else : return [x]

# 获取当前文档
doc = DocumentManager.Instance.CurrentDBDocument

# 定义要查找的类别 ID
category_id = -2000196

# 通过类别 ID 尝试找到对应的类别
target_category = doc.Settings.Categories.get_Item(category_id)

# 如果没有找到指定的类别,抛出异常
if target_category is None:
    raise ValueError(f"Category with ID {category_id} not found.")

# 收集指定类别下的非元素类型的元素
collector = FilteredElementCollector(doc).OfCategoryId(target_category.Id).WhereElementIsNotElementType().ToElements()

# 将 collector 包装成列表
collector = [collector] if not isinstance(collector, list) else collector

OUT = collector

代码2:
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
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
import System

elements = IN[0]
mepSystemTypes = IN[1] if len(IN) > 1 else None
desired_diameter = IN[2] if len(IN) > 2 else None

def get_element_faces(element):
    if isinstance(element, list):
        faces = []
        for e in element:
            try:
                element_faces = e.Faces
                faces.extend(element_faces)
            except AttributeError:
                pass
        return faces
    else:
        try:
            return element.Faces
        except AttributeError:
            return None

faces = get_element_faces(elements)

circular_faces = []
for face in faces:
    try:
        curves = face.PerimeterCurves()
        surface_curves = []
        for curve in curves:
            surface_curves.append(curve)
        if any(isinstance(curve, Circle) for curve in surface_curves):
            circular_faces.append(face)
    except AttributeError:
        pass

references = []
for face in circular_faces:
    try:
        reference = face.Tags.LookupTag("RevitFaceReference")
        references.append(reference)
    except:
        references.append(None)

# 确保处理的是族文档
doc = DocumentManager.Instance.CurrentDBDocument
if not doc.IsFamilyDocument:
    raise ValueError("The document is not a family document.")

connector = []
TransactionManager.Instance.ForceCloseTransaction()
TransactionManager.Instance.EnsureInTransaction(doc)

# 检查并处理 mepSystemTypes 的类型
if not isinstance(mepSystemTypes, list):
    mepSystemTypes = [mepSystemTypes]

for ref in references:
    if ref is not None:
        for mepSystemType in mepSystemTypes:
            if isinstance(mepSystemType, Autodesk.Revit.DB.Plumbing.PipeSystemType):
                mepSys = mepSystemType
            else:
                # 如果 mepSystemType 是整数,先转换为字符串再进行解析
                if isinstance(mepSystemType, int):
                    mepSystemType = str(mepSystemType)
                mepSys = System.Enum.Parse(Autodesk.Revit.DB.Plumbing.PipeSystemType, mepSystemType)
            created_connector = ConnectorElement.CreatePipeConnector(doc, mepSys, ref)
            if desired_diameter is not None:
                radius_param = created_connector.get_Parameter(BuiltInParameter.CONNECTOR_RADIUS)
                radius_param.Set(desired_diameter / 2)
            connector.append(created_connector)

TransactionManager.Instance.TransactionTaskDone()

OUT = connector

代码3:
import clr  
import System  
import os  
import traceback  

# 引用必要的程序集和库  
clr.AddReference('ProtoGeometry')  
from Autodesk.DesignScript.Geometry import *  
clr.AddReference('RevitAPI')  
from Autodesk.Revit.DB import *  
clr.AddReference('RevitServices')  
from RevitServices.Persistence import DocumentManager  
from RevitServices.Transactions import TransactionManager  

# 输入路径  
sat_path = IN[0]  # .sat 文件所在目录  
yangban_path = IN[1]  # Revit 族样板文件路径  
save_path = IN[2]  # 保存族文件的路径  
elements = IN[3]  # 要处理的元素列表  
mepSystemTypes = IN[4] if len(IN) > 4 else None  # 管道系统类型  

# 获取当前文档和应用程序实例  
doc = DocumentManager.Instance.CurrentDBDocument  
app = doc.Application  

# 文件路径遍历  
sat_files = [f for f in os.listdir(sat_path) if f.endswith('.sat')]  
result = []  

# 用于存储已处理的文件名,避免重复导入  
processed_names = []  

def get_element_faces(element):  
    if isinstance(element, list):  
        faces = []  
        for e in element:  
            try:  
                element_faces = e.Faces  
                faces.extend(element_faces)  
            except AttributeError:  
                pass  
        return faces  
    else:  
        try:  
            return element.Faces  
        except AttributeError:  
            return None  

# 遍历 .sat 文件列表  
for sat_file in sat_files:  
    try:  
        sat_filename = sat_file.split('.')[0]  

        # 如果该文件名已处理过,则跳过  
        if sat_filename in processed_names:  
            continue  

        sat_file_path = os.path.join(sat_path, sat_file)  # 完整路径  

        # 打开样板文件  
        famdoc = app.NewFamilyDocument(yangban_path)  

        # 导入 SAT 文件  
        options = SATImportOptions()  
        options.Placement = ImportPlacement.Origin  
        options.Unit = ImportUnit.Millimeter  # 单位转换为毫米  

        # 执行导入操作  
        TransactionManager.Instance.EnsureInTransaction(famdoc)  
        satId = famdoc.Import(sat_file_path, options, None)  
        TransactionManager.Instance.ForceCloseTransaction()  

        # 获取导入的几何体  
        imported_elem = famdoc.GetElement(satId)  
        geom_options = Options()  # 使用选项  
        geom = imported_elem.get_Geometry(geom_options)  

        # 遍历剩余文件,查找相同名称的文件并导入  
        for other_file in sat_files:  
            if other_file != sat_file and other_file.split('.')[0] == sat_filename:  
                other_file_path = os.path.join(sat_path, other_file)  
                TransactionManager.Instance.EnsureInTransaction(famdoc)  
                other_satId = famdoc.Import(other_file_path, options, None)  
                TransactionManager.Instance.ForceCloseTransaction()  

        # 保存族文件  
        output_file_path = os.path.join(save_path, sat_filename + ".rfa")  # 保存路径  
        famdoc.SaveAs(output_file_path)  
        famdoc.Close(False)  # 关闭文档,不保存更改  
        result.append(f"成功导入 {sat_file} 及相关文件,文件保存为 {output_file_path}")  

        # 将文件名添加到已处理列表  
        processed_names.append(sat_filename)  

    except Exception as e:  
        # 捕获异常并记录错误  
        result.append(f"处理 {sat_file} 时出现错误: {str(e)}")  
        if famdoc is not None:  
            famdoc.Close(False)  # 确保在出现错误时关闭文档  

# 返回结果  
OUT = result

代码4:
import clr
import System
import os
import traceback
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# 输入路径
sat_path = IN[0]  #.sat 文件所在目录
yangban_path = IN[1]  # Revit 族样板文件路径
save_path = IN[2]  # 保存族文件的路径

# 获取当前文档
doc = DocumentManager.Instance.CurrentDBDocument
app = doc.Application

# 文件路径遍历
sat_files = [f for f in os.listdir(sat_path) if f.endswith('.sat')]
result = []

# 用于存储已处理的文件名,避免重复导入
processed_names = []

for sat_file in sat_files:
    try:
        # 修改 sat_filename,获取文件名(不带扩展名)文件名的每个字符串从"."字符开始删除后边所有的字符,保留"."字符前边的的字符
        sat_filename = sat_file.split('.')[0]

        # 如果该文件名已处理过,则跳过
        if sat_filename in processed_names:
            continue

        sat_file_path = os.path.join(sat_path, sat_file)  # 完整路径

        # 打开样板文件
        famdoc = app.NewFamilyDocument(yangban_path)

        # 导入 SAT 文件
        options = SATImportOptions()
        options.Placement = ImportPlacement.Origin
        options.Unit = ImportUnit.Millimeter  # 单位转换为毫米

        # 执行导入操作
        TransactionManager.Instance.EnsureInTransaction(famdoc)
        satId = famdoc.Import(sat_file_path, options, None)
        TransactionManager.Instance.ForceCloseTransaction()

        # 获取导入的几何体
        imported_elem = famdoc.GetElement(satId)
        geom_options = Options()  # 使用选项
        geom = imported_elem.get_Geometry(geom_options)

        # 遍历剩余文件,查找相同名称的文件并导入
        for other_file in sat_files:
            if other_file!= sat_file and other_file.split('.')[0] == sat_filename:
                other_file_path = os.path.join(sat_path, other_file)
                TransactionManager.Instance.EnsureInTransaction(famdoc)
                other_satId = famdoc.Import(other_file_path, options, None)
                TransactionManager.Instance.ForceCloseTransaction()

        # 保存族文件
        output_file_path = os.path.join(save_path, sat_filename + ".rfa")  # 保存路径
        famdoc.SaveAs(output_file_path)
        famdoc.Close(False)  # 关闭文档,不保存更改
        result.append(f"成功导入 {sat_file} 及相关文件,文件保存为 {output_file_path}")

        # 将文件名添加到已处理列表
        processed_names.append(sat_filename)

    except Exception as e:
        # 捕获异常并记录错误
        result.append(f"处理 {sat_file} 时出现错误: {str(e)}")
        if famdoc is not None:
            famdoc.Close(False)  # 确保在出现错误时关闭文档

# 返回结果
OUT = result

Thank you

Please take the time to read How to get help on the Dynamo forums

You cant just paste code together and expect a result - start by eliminating repeated imports and save them all at the top

If you’re looking to learn try this course Python Programming MOOC 2024

And if you have some coding experience go here Dynamo Python Primer

这里有一些关于脚本的想法,我刚刚开始使用python和思维导图,所以谢谢你的帮助。

Translated by moderator. See below the line for original post.


I have already started learning. Thank you very much for your advice


Original post below.


我已经开始学习了。非常感谢你的建议