资讯动态

Tekla二次开发如何读取零件信息:模型到清单的自动化方案

发布时间:2026/10/14 22:31:28 来源:尧图企业网站定制
简介Tekla Structures作为建筑、桥梁与工业领域广泛使用的三维结构建模软件其模型、图纸和零件数据往往需要高效管理。围绕该软件的二次开发场景这份C#示例工程专门解决读取图纸列表并显示零件信息的需求面向需要批量提取构件属性、生成图纸清单的BIM工程师、结构设计师及Tekla二次开发初学者。工程基于Tekla Open API实现采用Windows窗体构建演示了遍历模型Part对象、获取零件ID、名称、材料、尺寸、位置等属性的完整流程代码中涉及ModelObject.GetAttributes()、Drawing.GetDrawings()等常用API调用并以工具类形式对部分逻辑做了封装。Tekla模型以对象树方式组织数据零件是查询的基本单元图纸清单则需要从文档集合中遍历获取示例将这些操作集中在可视化窗口中便于对比界面结果与源码理解API返回值处理。资源共47个文件压缩包约778KB主要文件类型包括C#源码、Tekla.Structures系列DLL引用、编译生成的exe与pdb调试文件以及少量配置和资源文件目录结构清晰便于对照窗体设计、启动逻辑、辅助工具和项目设置学习。目前已有2010人学习下载。读者既可以从头学习API调用方式也可以直接借鉴其窗体与数据分离的组织思路进一步扩展零件筛选、图纸导出、Excel报表等功能对完成自动化数据提取与结构分析报告有一定参考价值。1. 从模型到清单Tekla二次开发读取零件信息到底解决了什么问题做过钢结构深化或者混凝土深化的人都有过这种经历模型快交付时业主或下游加工厂突然要一份按零件归组的材料清单于是你打开Tekla模型一个个选中零件看属性、抄表格或者靠着报告模板反复折腾模板字段一个几百根零件的模型能磨掉半天。某天一个近千根零件的门刚模型摆在我面前供应商要按零件号、材质、截面、单重分类统计那一刻我意识到手工在模型里翻零件信息这件事翻的不只是零件是时间和耐心。Tekla二次开发读取零件信息说白了就是通过Tekla开放的API让程序自己进入当前模型把零件的基础属性、位置信息和工程量数据批量取出来再按你的规则落到表格或者写回模型里。它能解决的是三类问题批量整理零件清单、给零件批量打标记或写自定义属性、为后续的工艺和交付流程提供数据源。适合谁用如果你是Tekla管理员、BIM工程师或者做模型数据交付的人下面的思路和代码可以直接拿去做工具。2. 零件数据藏在哪搞清Tekla模型里的三层信息结构2.1 零件信息的三个来源属性、位置、工程量Tekla里的一个零件其实承载了三类数据读之前必须先分清。第一类是基础属性包括零件名称、型材截面、材质、等级、抛丸/油漆这些写在对象属性面板里的内容它们大多挂在零件的标准属性字段上。第二类是位置信息说的是零件在哪根构件下、属于哪个装配体这在Tekla的数据结构里是父子关系零件Part挂在装配体Assembly下面。第三类是工程量信息比如净重、毛重、体积、表面积这些不是手工填的是Tekla根据几何和材质实时算出来的。我见过很多刚开始做二次开发的人一上来就想着遍历模型取所有对象然后取属性结果发现重量取不到、零件重复出现、分类怎么都对不上根因就是没搞清楚数据分了三层。你读模型的时候API面对的是一个对象化的世界Model对象代表当前模型装配体对象代表构件零件对象代表单个件。属性要从零件对象上取位置要从装配关系里推工程量则要调用计算类的方法三者完全不是一回事。2.2 为什么从“当前模型取对象”比“遍历数据库”更实用Tekla二次开发读取零件信息最常见的模型对象连接方式是GetObject()。这个方法打开的是“当前打开的模型”不是让你去解析某个文件或数据库。它的好处是和你屏幕上看到的模型完全一致包括了当前的视图过滤、选择过滤状态。这一点既是便利也是坑后面章节会专门讲视图过滤带来的数据缺失问题。2.3 装配层级读零件必须面对的父子结构Tekla的数据模型里装配体是顶层的逻辑单元一个装配体里可以有主零件、次零件也可以嵌套子装配体。零件信息读取最常见的需求是“按构件输出零件清单”这时你必须先枚举装配体再遍历装配体里的零件而不能直接全局遍历所有零件对象。直接全局遍历的问题在于你会在装配体层级和零件层级各看到同一根型钢一次因为API列表里它既是装配体的对象成员也是一个独立的零件对象。我的习惯是先按装配体走取装配体标记和名称然后遍历装配体里的零件只有需要全模型材料汇总时才做全局零件遍历并且先判断对象的类型再处理。这样输出的清单逻辑和图纸报表是一致的别人拿去对图号时不会对不上。3. Tekla二次开发读取零件信息环境搭建与最小读取代码3.1 环境准备与引用配置做Tekla二次开发语言基本选C#IDE用Visual Studio。第一步是在引用里加入Tekla的API程序集常见的做法是引用Tekla.Structures.dll和Tekla.Structures.Model.dll。如果你的机器装的是Tekla Structures某个常见版本这两个DLL通常位于安装目录下的nt\bin\或nt\bin\plugins\里。还有两个容易翻车的细节需要提前说。第一个是目标框架老版本Tekla的API面向.NET Framework新版虽然开始兼容.NET Core但为了省事新项目我一般直接选.NET Framework 4.8或4.7.2。第二个是平台目标很多人在x64系统上编译x86程序一运行就报“BadImageFormatException”所以项目平台的首选一定要改成x64。3.2 最小读取代码按类型过滤零件using Tekla.Structures; using Tekla.Structures.Model; class PartInfoReader { public void Run() { // 连接当前打开的Tekla模型 Model model new Model(); if (!model.GetConnectionStatus()) { System.Windows.Forms.MessageBox.Show(请先打开一个Tekla模型); return; } // 遍历装配体层级再进入零件层级 ModelObjectEnumerator assemblyEnum model.GetModelObjectSelector().GetAllObjectsWithType(new Assembly().GetType()); while (assemblyEnum.MoveNext()) { Assembly assembly assemblyEnum.Current as Assembly; if (assembly null) continue; // 取装配体主零件作为构件级别的标识 Part mainPart assembly.GetMainPart() as Part; if (mainPart null) continue; // 遍历装配体下的全部子零件 ModelObjectEnumerator partEnum assembly.GetSecondaries(); while (partEnum.MoveNext()) { Part part partEnum.Current as Part; if (part ! null) { // 这里就是读取零件信息并输出的位置 string name part.Name; string profile part.Profile.ProfileString; string material part.Material.MaterialString; System.Console.WriteLine(零件号: part.PartNumber.PartNumberString); System.Console.WriteLine(名称: name 截面: profile 材质: material); } } } } }这段代码做的事情是连接当前打开的Tekla模型枚举所有装配体再取每个装配体里的次零件最终拿到零件号、名称、截面、材质四个基础字段。选择器的GetAllObjectsWithType会返回符合条件的模型对象枚举器这里指定了装配体类型避免把螺栓、焊缝这类非零件对象混进来。我一般会先跑这样一段最小代码验证环境通不通再往上加字段和统计逻辑。如果只需要取零件号、截面这类字段上面的代码已经够用。但如果你在写完这个Demo后发现某些零件总是读不到或者读到的数量和模型视图里看到的不一致多半不是代码问题而是装配体遍历时漏掉了“没有装配关系的独立零件”后面避坑章节里会专门展开。3.3 从零件对象拿到属性字段GetValue与GetUserProperty的差别基础字段可以直接从对象的属性上取但像重量、体积这种计算属性以及你自己在零件上写的自定义属性需要用不同的方式读取。Tekla二次开发里标准属性直接用对象的属性成员比如part.Weight自定义属性要用GetUserProperty()方法。// 取零件重量、体积与自定义属性 double weight 0, volume 0; part.GetReportProperty(WEIGHT, ref weight); part.GetReportProperty(VOLUME, ref volume); string mark ; part.GetUserProperty(MY_MARK, ref mark); string moreInfo ; part.GetUserProperty(PART_COMMENT, ref moreInfo); System.Console.WriteLine(净重: weight kg 体积: volume m3 自定义标记: mark);这里把重量体积的读取方式写出来是因为很多人会试图直接用part.Weight这个属性但它在某些场景下返回的是0尤其是零件没有保存或者重量尚未计算时。用GetReportProperty是让Tekla按报告引擎去计算重量结果和图纸报告里看到的一致。GetUserProperty是读取用户在属性面板或通过API写入的扩展字段。注意自定义属性的名称必须和模型里定义的完全一致包括大小写否则会静默失败返回空字符串。这一点不少有经验的人也踩过属性名在界面里看起来是“My_Mark”代码里写“my_mark”读出来就为空。4. 让读到的零件信息能直接用数据落表和写回零件4.1 落表按零件归组输出清单的常见做法读取零件信息的最终目的八成是为了输出Excel或CSV清单。很多人第一反应是用Office的COM组件直接生成Excel但我建议在Tekla二次开发场景里尽量避免。原因有三服务器或设计院环境不一定装了ExcelCOM调用在批量循环里容易内存泄漏Tekla运行时会话里频繁创建Excel进程容易导致模型卡顿。常见做法是把零部件数据先装进DataTable再统一写成CSV用户用Excel直接打开CSV就能筛选排序。如果团队确实需要xlsx格式再单独写一步把CSV转成xlsx或者只在本地安装了Excel的机器上用COM。下面给一段CSV导出的核心代码System.Data.DataTable dt new System.Data.DataTable(); dt.Columns.Add(构件号); dt.Columns.Add(零件号); dt.Columns.Add(名称); dt.Columns.Add(截面); dt.Columns.Add(材质); dt.Columns.Add(净重(kg)); // 假设前面已经遍历了装配体和零件这里填充数据行 foreach (Part part in partList) { double weight 0; part.GetReportProperty(WEIGHT, ref weight); dt.Rows.Add(assemblyMark, part.PartNumber.PartNumberString, part.Name, part.Profile.ProfileString, part.Material.MaterialString, weight); } // 写CSV文件UTF-8编码保证中文不乱码 using (var sw new System.IO.StreamWriter(C:\part_list.csv, false, System.Text.Encoding.UTF8)) { foreach (System.Data.DataRow row in dt.Rows) { sw.WriteLine(string.Join(,, row.ItemArray)); } }这段代码的重点是先把数据收集到内存表里再一次性写出不要在遍历模型的过程中直接操作文件。数据量不大时可以边遍历边写但零件上千时频繁打开文件流的性能损耗明显。CSV使用UTF-8带BOM编码是比较稳妥的选择用Excel打开才不乱码记事本打开也不乱。4.2 落图按零件信息批量写回模型做标记比导出清单更进一步的做法是把读取到的信息处理后写回零件最常见的是批量标记“校验结果”“加工批次号”或“下料顺序号”。写回要用SetUserProperty或SetProperty然后在模型里用模板或过滤器读取这些字段。下面这段代码演示怎么给零件批量写批次string batchAttribute BATCH_NO; foreach (Part part in partList) { string currentOrder ; part.GetUserProperty(batchAttribute, ref currentOrder); if (string.IsNullOrEmpty(currentOrder)) { // 只给没有批次号的零件分配新批次 string newBatch P batchCounter.ToString(D3); part.SetUserProperty(batchAttribute, newBatch); part.Modify(); } }这种做法的核心价值在于把数据处理的结果留在模型里后续出图、提料、数控加工都能共享。许多人做钢结构深化管理时会用这个套路先读取每个零件的重量和板厚按阈值打上“需探伤”“需热处理”的标记再让下游用过滤器筛选这些零件生成工艺单。SetUserProperty写完后必须调用Modify()否则修改不会真正写入模型界面里刷新也不一定看得见。这是个很典型且代价不小的坑。4.3 增量更新只读“变化过的零件”以提升效率随着模型迭代每次刷新清单都要重跑全量读取零件多了以后耗时明显。有个务实技巧是利用Tekla的模型修改标记机制记录上一次遍历时零件对象的Identifier.ID下次只处理新增或ID列表之外变更过的零件。常见做法是给零件写一个“上次读取版本”的自定义属性每次读取时对比版本标记。比如第一次读取时给零件写入LAST_READ 2024-06-01第二次运行时先取该字段等于“2024-06-01”的就跳过。这种基于自定义属性的增量方案实现简单不需要依赖事件回调在模型不大但迭代频繁的场景里够用。5. Tekla二次开发读取零件信息的5个常见坑与排查5.1 属性读取返回空值字段名拼写与大小写现象代码运行不报错但读取出来的截面、材质或自定义属性是空字符串。 原因Tekla的属性名是大小写敏感且固定的常见的有PROFILE和MATERIAL。自定义属性名如果带了空格、中文或大小写差异读取会静默失败。 解决先用Tekla的“属性面板”和“报告”功能确认字段准确名称再在代码里硬编码或做成配置项。排查时可以在读取后立即判断IsEmpty并输出一条警告不要等到输出清单时才发现一堆空列。5.2 读到的零件比模型里少了视图或选择过滤生效了现象代码遍历模型的零件数量和模型文件夹里看到的零件数对不上少了半截。 原因GetModelObjectSelector()返回的对象受当前模型视图“选择过滤”的影响。如果某个视图中过滤掉了某些对象类型枚举器可能直接不返回它们。 解决读数据前先检查当前视图的过滤状态或者在代码里显式创建自己的选择过滤器只按类型筛选。我的做法是在工具启动时记录当前过滤状态执行读取前临时关闭过滤读完再恢复避免影响用户正在使用的视图设置。5.3 零件数量翻倍或统计重复装配线遍历导致重复计数现象输出清单总行数比模型里Part对象多同一根零件出现两次。 原因直接全局遍历零件对象时装配线Assembly作为参数对象和零件对象存在一对多关系有些装配体对象本身也参与枚举导致同一零件的不同引用形式被重复读到。 解决统一以装配体为主线只通过GetMainPart()和GetSecondaries()取零件如果确实要做全局零件汇总每次读取都先判断对象是否属于Part类型并且用一个包含零件标识ID的哈希集合去重。5.4 重量和模型报告对不上单位系统与属性取值方式现象代码取出的重量与模型自带报告里的差了几百倍。 原因Tekla的模型单位支持公制和英制API读取的重量值在公制下是kg如果模型设置成了英制或其他单位体系数值含义完全不同另外重量有净重、毛重、组立件重之分字段选择不同结果也不同。 解决读取前统一设置单位。最简单的方式是通过Tekla.Structures.ModelInternal工具或者使用GetReportProperty按报告字段取它在内部会返回当前单位体系下的显示值。如果代码取数和报表分别用不同方式取数值不一致就要优先检查单位设置。5.5 程序运行后模型卡死或莫名崩溃对象修改后未调用Modify现象批量写回时程序跑到中途就异常终止或者模型出现未保存的诡异状态。 原因只调用了SetUserProperty而没调用Modify()或者修改对象后没有重新插入模型导致内部缓存状态不一致更常见的是在一次无限循环里反复读取同一个枚举器造成API内部锁等待。 解决每次写回属性后立即调用part.Modify()并且对枚举器的循环增加最大迭代次数保护。遍历期间不要手动在Tekla界面里切换视图或选择对象等程序跑完再操作模型。6. 从“能用”到“顺手”把零件读取脚本做成团队工具的三个进阶技巧6.1 做成宏按钮一键导出零件清单把上面的逻辑封装成一个类库生成DLL后放到Tekla的宏目录里在菜单里挂一个按钮用户点一下就能导出当前模型的零件清单。关键在于程序的入口尽量避免弹窗参数可以从配置文件读取这样对不熟悉代码的同事也友好。6.2 校验零件信息完整性缺失属性自动预警零件信息读取的用途不止是导出也可以反向校验模型质量。我习惯在工具里加一步遍历零件凡是没有材质、截面值或自定义批次号为空的单独输出一个“待处理零件清单”。这个做法在模型交付前的自检环节非常有效能一次性揪出所有漏填属性的零件。6.3 把读取逻辑接入交付流程从模型到清单的自动化更进一步的做法是把读取工具嵌入到项目交付的标准流程里模型保存后自动运行读取输出CSV并比对前一次输出把差异部分生成变更说明。虽然自动化需要额外处理Tekla启动时的运行环境但实现后节省的时间相当可观。做这套工具下来我最大的教训就是不要把属性字段名硬编码得到处都是维护一套字段配置表会省很多事也不要信任一次读取的返回值关键字段做二次校验。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑