☰
TEKLA二次开发图纸入门:从API到自动出图实战
2026/10/25 12:26:48 网站建设 项目流程

简介:这是一份面向钢结构详图设计人员与.NET开发者的TEKLA二次开发入门资料,聚焦图纸管理与数据提取方向,帮助读者理解如何借助API扩展TEKLA功能、实现图纸自动化处理。资源包共20个文件,约74KB,以C#源码文件为主,配合项目文件、解决方案文件、资源与配置文件等,构成一个可直接参考的WinForm工程结构,涵盖图纸列表载入、图纸选择、图纸打开及数值提取等典型环节的实现思路。内容围绕TEKLA数据库查询、UI交互绑定与几何属性读取展开,适合具备一定C#或VB.NET基础、希望切入TEKLA定制开发的读者对照学习。目前已有785人学习下载,可作为二次开发练手与工作流优化的起步参考。

1. TEKLA二次开发图纸入门:从看懂API到跑通第一段源代码

很多做钢结构详设的人第一次打开 TEKLA 的二次开发文档,都会卡在同一个地方:软件里明明能点出来的图纸,代码里却找不到对应对象。这不是你笨,而是 TEKLA 的图纸模型和模型空间是两套体系,图纸(Drawing)挂在模型对象下面,而不是独立存在。这篇笔记要解决的就是这件事——用源代码把「模型 → 图纸 → 视图 → 对象」这条链路打通,让你能自动批量出图、改图框、写标题栏,而不是每次手动点几十遍。适合已经会画 TEKLA 模型、想用 C# 或 Python 接管重复出图工作的结构工程师,也适合刚接触 Open API 的二次开发新手。下面所有代码都基于 TEKLA Structures 的 Open API,思路同样适用于其他版本,参数以你本机实际枚举为准。

2. 图纸对象模型:为什么你 new 不出一个 Drawing

2.1 模型空间和图纸空间是两棵树

TEKLA 的数据结构里,Model是根,ModelObject是模型里的梁、柱、板,而Drawing并不继承自ModelObject。图纸是通过DrawingHandler从模型对象上「取」出来的,不是凭空创建的。很多人翻车就翻在这里:写了一句new Drawing(),编译都过不去,因为构造函数根本不公开。

正确的取图路径是:先拿到Model,再通过DrawingHandler.GetDrawings()拿到当前模型下所有图纸,或者用GetDrawingByMark()按图号精确取。图纸下面再挂DrawingSheet,Sheet 里才是View,View 里才是DrawingObject。这条链路每一层都要用对应的 Handler 去查,不能跳级。

// 获取当前打开的模型 Model model = new Model(); // 拿到图纸处理器 DrawingHandler dh = new DrawingHandler(); // 取当前模型下所有图纸 Drawing[] drawings = dh.GetDrawings(); foreach (Drawing dwg in drawings) { // 图纸名和图号在这里 string mark = dwg.Mark; string name = dwg.Name; // 继续往下拿图纸下的视图 DrawingSheet sheet = dwg.GetSheet(); View[] views = sheet.GetViews(); }

逻辑说明:new Model()拿到的是当前已打开模型的引用,不是新建模型。GetDrawings()返回的是当前模型下所有图纸的数组,如果模型里没图纸,返回空数组而不是 null,所以不用先判 null 再遍历。参数方面,dwg.Mark是图号,dwg.Name是图纸名称,这两个在出图时最常用。注意GetSheet()对某些图纸类型可能返回 null,比如多件图,所以实际项目里要加一层判断。

2.2 图纸类型决定你能改什么

TEKLA 的图纸分好几种:单件图、构件图、组装图、多件图、浇筑体图。不同类型能拿到的视图和对象不一样。单件图通常只有一个视图,构件图可能有多个视图加一个材料表。如果你写了一段代码在单件图上跑得好好的,换到构件图上就报空引用,大概率是视图数量对不上。

我一般会先判断图纸类型再决定后续操作:

if (dwg is SinglePartDrawing) { // 单件图逻辑 } else if (dwg is AssemblyDrawing) { // 构件图逻辑,视图可能不止一个 View[] views = dwg.GetSheet().GetViews(); foreach (View v in views) { // 每个视图单独处理 } }

这里用is做类型判断比看字符串靠谱,因为图纸类型是强类型枚举出来的。参数上,SinglePartDrawing和AssemblyDrawing都是Drawing的子类,可以直接用父类引用接住再判断。实际项目里我习惯先写一个GetDrawingType()辅助方法,把类型转成可读字符串,方便日志排查。

2.3 视图坐标系和模型坐标系不是一回事

图纸视图里的对象坐标是图纸坐标,不是模型坐标。你在模型里量出来梁长 6000,在图纸视图里拿到的可能是缩放后的值。这个坑我在第一次做自动标注时踩得很深:按模型坐标算的标注位置,画到图纸上全偏了。

解决办法是拿视图的ViewCoordinateSystem,把模型坐标转成视图坐标:

View view = sheet.GetViews()[0]; TransformationPlane plane = view.ViewCoordinateSystem; // 把模型点转到视图坐标 Point modelPoint = new Point(1000, 2000, 0); Point viewPoint = plane.TransformationToLocal(modelPoint);

TransformationToLocal把全局坐标转到视图局部坐标,反过来用TransformationToGlobal。参数上,ViewCoordinateSystem返回的是一个TransformationPlane,包含原点和三个轴方向。实际用的时候要注意视图可能被旋转过,所以不能简单加减偏移量,必须走这个转换。

3. 用源代码跑通第一张自动出图

3.1 环境准备和最小可运行工程

TEKLA Open API 分两种:一种是 .NET API,用 C# 写,功能最全;另一种是 Python 通过tekla-python包调用,适合快速脚本。我建议新手先从 C# 入手,因为官方示例和社区代码基本都是 C#,遇到问题好搜。

最小工程需要引用两个 DLL:Tekla.Structures.Model.dll和Tekla.Structures.Drawing.dll。这两个文件在 TEKLA 安装目录下的nt\bin\plugins里。新建一个 C# 控制台项目,把这两个引用加进去,目标框架选 .NET Framework 4.8,因为 TEKLA 目前对 .NET Core 支持还不完整。

using Tekla.Structures.Model; using Tekla.Structures.Drawing; class Program { static void Main(string[] args) { // 连接当前打开的 TEKLA 模型 Model model = new Model(); if (!model.GetConnectionStatus()) { Console.WriteLine("没连上 TEKLA,检查软件是否打开"); return; } DrawingHandler dh = new DrawingHandler(); Drawing[] drawings = dh.GetDrawings(); Console.WriteLine($"当前模型共有 {drawings.Length} 张图纸"); } }

逻辑说明:GetConnectionStatus()返回 bool,用来确认代码进程和 TEKLA 进程是否握手成功。这一步很多人忽略,结果代码跑起来没报错但也没输出,其实是根本没连上。参数上不需要额外配置,只要 TEKLA 开着且模型已打开就行。注意如果 TEKLA 是以管理员权限运行的,你的代码也要用管理员权限跑,否则连不上。

3.2 批量改图框和标题栏字段

图纸入门最实用的功能就是批量改标题栏。比如项目后期业主要求把所有图纸的设计人改成同一个名字,手动改一百张图能改到怀疑人生。用代码就是遍历图纸,找到标题栏对象,改字段。

foreach (Drawing dwg in drawings) { // 拿图纸下的所有对象 DrawingObjectEnumerator objects = dwg.GetSheet().GetObjects(); while (objects.MoveNext()) { DrawingObject obj = objects.Current; // 标题栏在 TEKLA 里通常是 Text 或 Rectangle 组合 if (obj is Text textObj) { // 按内容匹配要改的字段 if (textObj.TextString.Contains("设计人")) { textObj.TextString = "设计人:张三"; textObj.Modify(); } } } }

逻辑说明:GetObjects()返回的是枚举器,用MoveNext()遍历,不是 foreach 直接遍历,这是 TEKLA API 的老式写法。Text对象改完必须调Modify(),否则只改内存不写回图纸。参数上,TextString是文本内容,匹配时建议用Contains而不是==,因为标题栏文本可能带前后空格。实际项目里我会先把所有文本打出来看一遍,确认字段格式再写匹配逻辑。

3.3 自动创建图纸视图并插入对象

比改图更进一步的是自动创建视图。比如模型里有一批梁,你想每根梁自动出一张单件图,视图方向固定。这需要用到DrawingHandler.CreateDrawings()或者更细的View创建方法。

// 假设已经拿到一根梁的 ModelObject Beam beam = ...; DrawingHandler dh = new DrawingHandler(); // 创建单件图 Drawing drawing = dh.CreateDrawings( new ArrayList { beam }, new ArrayList(), new ArrayList() )[0] as SinglePartDrawing; // 拿默认视图 View view = drawing.GetSheet().GetViews()[0]; // 在视图里插入一个文本 Text text = new Text( view, new Point(100, 100, 0), "自动生成" ); text.Insert();

逻辑说明:CreateDrawings第一个参数是要出图的模型对象列表,第二个是图纸属性,第三个是图纸设置,传空数组就用默认。返回的是Drawing数组,取第一个转成SinglePartDrawing。Text构造函数第一个参数是所属视图,第二个是插入点,第三个是内容,最后必须Insert()才真正画上去。参数上,插入点坐标是视图坐标,不是模型坐标,所以要先做坐标转换。实际用的时候建议先手动出一张图,用代码把视图和对象信息打出来,照着抄参数。

4. 避坑排查:图纸开发最容易翻车的 5 个地方

4.1 现象:代码编译通过但运行报「未将对象引用设置到对象的实例」

原因:最常见的是GetSheet()返回 null。多件图或者某些特殊图纸类型没有 Sheet,直接往下取视图就炸了。

解决:每次取 Sheet 和 View 之前都判空,并且用GetViews().Length > 0确认有视图再操作。我习惯写一个SafeGetFirstView(Drawing dwg)方法,内部做完整判空,返回 null 就跳过这张图。

4.2 现象:改了图纸对象但图纸上没变化

原因:TEKLA 的图纸对象修改后需要显式调Modify(),而且有些对象在视图里是只读的,比如自动标注生成的尺寸。

解决:改完立刻调Modify(),如果还不行,检查对象是不是IsReadOnly。对于只读对象,只能删了重建,不能直接改属性。

4.3 现象:批量出图跑到一半卡死

原因:在循环里频繁调CreateDrawings且没有释放资源,TEKLA 进程内存涨得很快。另外如果模型很大,每次GetDrawings()都全量拉一遍也慢。

解决:批量操作时把模型对象先收集到一个列表,一次性调CreateDrawings传整个列表,而不是循环里一张一张建。每处理完一批调一次GC.Collect()虽然不优雅但管用。

4.4 现象:图纸坐标转换后位置还是偏

原因:视图可能被旋转或镜像过,只做平移转换不够。

解决:用ViewCoordinateSystem的TransformationToLocal做完整转换,不要自己算偏移。如果还偏,检查视图的ViewRotation属性,有些视图默认带 90 度旋转。

4.5 现象:代码在开发机上跑得好,换台机器就报找不到 DLL

原因:TEKLA 版本不一致,或者目标框架不对。开发机装的是 2023,现场装的是 2021,API 接口有差异。

解决:在项目里把 TEKLA 的 DLL 设为「复制本地」为 false,运行时从 TEKLA 安装目录加载。同时代码里用反射或者条件编译兼容不同版本,别硬编码版本号。

5. 进阶技巧:用源代码做图纸批量校验和版本对比

图纸开发做到后面,最有价值的不是出图,而是校验。比如项目要交付了,业主要求所有图纸的图号不能重复、标题栏不能为空、视图比例必须是 1:10。这些用代码扫一遍比人工翻快得多。

我一般会写一个校验脚本,把图纸信息导成表格,然后用 Python 做二次分析。C# 端只负责把数据吐出来:

// 导出图纸信息到 CSV using (StreamWriter sw = new StreamWriter("drawing_check.csv")) { sw.WriteLine("图号,图纸名,视图数,比例,标题栏设计人"); foreach (Drawing dwg in drawings) { DrawingSheet sheet = dwg.GetSheet(); if (sheet == null) continue; View[] views = sheet.GetViews(); string designer = ""; // 从文本对象里找设计人字段 DrawingObjectEnumerator objs = sheet.GetObjects(); while (objs.MoveNext()) { if (objs.Current is Text t && t.TextString.Contains("设计人")) { designer = t.TextString; } } sw.WriteLine($"{dwg.Mark},{dwg.Name},{views.Length},{views[0].ViewScale},{designer}"); } }

逻辑说明:这段代码把每张图的图号、名称、视图数、第一个视图的比例、设计人字段导成 CSV。参数上ViewScale是 double 类型,直接输出就行。导出的 CSV 可以用 Excel 打开做筛选,也可以用 Python 的 pandas 做重复图号检测。实际项目里我会再加一列「最后修改时间」,用来对比两次导出的差异,快速定位哪些图被改过。

另一个实用技巧是图纸版本对比。把两次导出的 CSV 做 diff,图号相同但比例或设计人变了的,就是需要重点检查的图。这个思路比人工翻图纸靠谱得多,尤其是几百张图的交付项目。

最后说个血泪经验:图纸开发的代码一定要加日志,每处理一张图就写一行「已处理图号 XXX」,不然跑到一半崩了,你根本不知道崩在哪张图上。我现在的习惯是日志和 CSV 同时输出,日志看进度,CSV 看结果。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询