TEKLA二次开发图纸入门:自动标注与API对象模型实战
发布时间:2026/10/8 2:19:11 锦皓数字建站

简介这份资源面向钢结构详图设计与TEKLA二次开发初学者聚焦图纸模块的编程入门帮助读者理解如何通过API扩展TEKLA功能、实现图纸管理与数据提取的自动化。内容围绕载入模型图纸列表、选择模型图纸、打开模型图纸、取图纸数值四个核心环节展开涉及数据库查询、UI交互、视图控制与几何属性读取等知识点适合具备一定C#或VB.NET基础、希望提升工作效率的工程师参考。资源包共20个文件以cs源代码文件为主辅以resx资源文件、csproj项目文件、sln解决方案及config配置等整体约74KB结构紧凑可直接在Visual Studio中打开学习。目前已有785人学习下载。通过实际源码示例读者能掌握TEKLA图纸数据的读取与展示思路理解二次开发中界面绑定与事件处理的实现方式并借鉴几何数值提取的编程逻辑为后续定制化工作流打下基础。1. TEKLA二次开发图纸入门从一根梁的自动标注说起如果你正在用 TEKLA Structures 做钢结构深化每天重复着「打开图纸 → 手动标注构件 → 导出 → 改图 → 再导出」这套动作那你大概率已经想过这些活儿能不能让程序替我干TEKLA 二次开发图纸入门这件事核心就是回答这个问题——用代码去驱动图纸里的视图、标注、零件标记和图纸布局把重复劳动交给脚本。它适合两类人一类是深化设计出身、想把手上的重复操作自动化但没写过几行代码的工程师另一类是写过 C# 或 Python、但对 TEKLA 图纸对象模型不熟的程序员。源代码在这里不是让你抄一份就完事而是让你看懂「一根梁从模型到图纸再到标注」这条链路上哪些对象是可编程的、哪些参数是必须调的。我见过太多人卡在第一步不知道从哪打开 API也不知道图纸对象和模型对象根本是两套体系。这篇就把这条链路拆开讲透。2. 搞懂 TEKLA 图纸 API 的对象模型别把模型对象当图纸对象用2.1 模型对象和图纸对象是两套体系TEKLA 的 Open API 里模型侧和图纸侧是分开的。模型侧你操作的是ModelObject、Beam、Part、Connection这些图纸侧你操作的是Drawing、DrawingObject、ViewBase、PartMark、Dimension这些。很多人第一次写图纸脚本翻车就是因为拿着Beam对象去图纸里找结果发现图纸里根本没有Beam只有PartMark和Dimension。图纸的本质是模型的一个「快照 注释层」。模型里一根梁到了图纸里变成三样东西几何线Line、Arc等DrawingObject、零件标记PartMark、尺寸标注Dimension。你要改标注操作的是Dimension你要改标记内容操作的是PartMark你要改视图范围操作的是ViewBase的属性和View.ViewRectangle。所以入门第一件事是把下面这张对应关系记牢模型侧对象图纸侧对应对象典型用途Beam/PartPartMark读取/修改零件标记内容Beam的几何Line/Arc/Circle遍历图纸几何、判断位置Model的坐标ViewBase.ViewCoordinateSystem视图坐标系转换Part的尺寸Dimension自动标注、批量改标注Drawing本身DrawingSheet图纸布局、图框、导出2.2 打开图纸和遍历图纸对象的最小代码下面这段 C# 代码是入门必跑的最小闭环连接 TEKLA、拿到当前打开的图纸、遍历图纸里的所有对象并打印类型。跑通它你才算真正摸到了图纸 API 的门。using Tekla.Structures.Model; using Tekla.Structures.Drawing; using Tekla.Structures.Geometry3d; public class DrawingWalker { public void WalkCurrentDrawing() { // 拿到当前打开的图纸如果没有打开图纸会返回 null DrawingHandler drawingHandler new DrawingHandler(); Drawing currentDrawing drawingHandler.GetActiveDrawing(); if (currentDrawing null) { // 没有活动图纸直接退出别硬跑 return; } // 遍历图纸下的所有 Sheet通常一张图纸一个 Sheet DrawingObjectEnumerator sheets currentDrawing.GetSheetObjects(); while (sheets.MoveNext()) { DrawingObject obj sheets.Current as DrawingObject; if (obj null) continue; // 打印对象类型和 ID先看清楚图纸里到底有什么 System.Console.WriteLine( Type: obj.GetType().Name | ID: obj.GetIdentifier().ID ); // 如果是视图继续往里遍历视图内的对象 if (obj is ViewBase view) { DrawingObjectEnumerator viewObjs view.GetObjects(); while (viewObjs.MoveNext()) { DrawingObject inner viewObjs.Current as DrawingObject; if (inner null) continue; System.Console.WriteLine( ViewObj: inner.GetType().Name ); } } } } }逻辑说明DrawingHandler.GetActiveDrawing()是入口拿不到就说明当前没有活动图纸直接返回不要继续。GetSheetObjects()拿的是图纸页级别的对象通常是图框、视图、表格。ViewBase.GetObjects()才是视图内部的几何和标注。参数说明GetIdentifier().ID是 TEKLA 内部唯一 ID后面你要定位某个对象、做增量修改全靠它。注意DrawingObjectEnumerator是单向迭代器MoveNext()之后才能读Current不能随机访问。2.3 图纸坐标系和模型坐标系的转换这是第二个高频翻车点。模型里一根梁的起点坐标是(12000, 3000, 0)到了图纸视图里这个坐标可能变成(350, 200)因为视图有自己的坐标系和比例。你要在图纸上按模型位置放标注就必须做转换。常见做法是用ViewBase.ViewCoordinateSystem和ViewBase.ModelToView这类转换方法。我一般会先拿视图的坐标系原点再把模型点转成视图点最后用视图点去创建Dimension或PartMark。如果你跳过这一步直接拿模型坐标去图纸里画线结果就是标注飞到图纸外面找都找不回来。// 假设 view 是一个 ViewBase 对象modelPoint 是模型坐标 Point modelPoint new Point(12000, 3000, 0); // 模型坐标转视图坐标 Point viewPoint view.ModelToView(modelPoint); // 反过来视图坐标转模型坐标 Point backToModel view.ViewToModel(viewPoint);参数说明ModelToView返回的是视图内的二维点Z 通常为 0ViewToModel是逆变换。注意这两个方法依赖视图的当前坐标系如果视图被旋转过转换结果会跟着变。所以做自动标注前先确认视图没有被人手动旋转过否则你的标注位置会整体偏掉。3. 用源代码跑通第一个自动标注从零件标记到尺寸标注3.1 自动创建零件标记的完整流程零件标记PartMark是图纸里最常见的注释。自动创建它的流程是找到视图 → 找到视图里的零件几何 → 在几何附近插入PartMark→ 设置标记内容和位置。下面这段代码演示在视图里给每个零件插入一个零件标记using Tekla.Structures.Drawing; using Tekla.Structures.Geometry3d; public class AutoPartMark { public void InsertMarks(ViewBase view) { DrawingObjectEnumerator objs view.GetObjects(); while (objs.MoveNext()) { // 只处理零件几何通常是 Line 或 Arc DrawingObject obj objs.Current as DrawingObject; if (obj null) continue; // 拿对象的中点作为标记插入位置 Point insertPoint GetObjectCenter(obj); if (insertPoint null) continue; // 创建零件标记关联到当前对象 PartMark mark new PartMark(obj, insertPoint); // 设置标记内容这里用默认模板实际项目要换成自己的模板 mark.Attributes.Content PART_POS; mark.Insert(); } } private Point GetObjectCenter(DrawingObject obj) { // 简化处理实际项目里要根据对象类型取包围盒中心 if (obj is Line line) { return new Point( (line.StartPoint.X line.EndPoint.X) / 2, (line.StartPoint.Y line.EndPoint.Y) / 2, 0 ); } return null; } }逻辑说明PartMark的构造函数第一个参数是关联对象第二个是插入点。Attributes.Content决定标记显示什么内容常见值有PART_POS零件位置、PROFILE截面、MATERIAL材质。Insert()才是真正写入图纸不调用它什么都不会发生。参数说明插入点用视图坐标不是模型坐标所以如果你从模型坐标来先做ModelToView转换。注意PartMark插入后如果位置重叠TEKLA 不会自动避让需要你自己算偏移。3.2 自动创建尺寸标注的两种方式尺寸标注比零件标记复杂因为要指定标注的两个端点、标注方向、标注类型。TEKLA 图纸 API 里常用的有Dimension和DimensionSet。入门阶段先用Dimension单条创建跑通后再考虑批量。using Tekla.Structures.Drawing; using Tekla.Structures.Geometry3d; public class AutoDimension { public void CreateLinearDimension(ViewBase view, Point p1, Point p2) { // 把模型点转成视图点 Point v1 view.ModelToView(p1); Point v2 view.ModelToView(p2); // 创建线性尺寸方向为水平 Dimension dimension new Dimension( view, v1, v2, new Vector(1, 0, 0) // 水平方向 ); // 设置尺寸类型为线性 dimension.Attributes.Type DimensionType.LINEAR; dimension.Insert(); } }逻辑说明Dimension构造函数需要视图、两个端点、标注方向向量。方向向量决定标注是水平、垂直还是斜向。Attributes.Type设置标注类型常见有LINEAR、ANGULAR、RADIAL。参数说明两个端点必须是视图坐标方向向量是单位向量。注意如果两个端点太近TEKLA 可能拒绝创建实际项目里要加距离判断。3.3 批量标注的参数化思路单条标注跑通后批量标注的关键是「参数化」把标注位置、偏移量、标注类型做成可配置的参数而不是写死在代码里。我一般会用一个配置类来管理这些参数public class DimensionConfig { public double OffsetX { get; set; } 100; // 水平偏移 public double OffsetY { get; set; } 50; // 垂直偏移 public DimensionType Type { get; set; } DimensionType.LINEAR; public bool SkipShortEdges { get; set; } true; // 跳过太短的边 public double MinEdgeLength { get; set; } 200; // 最短标注边长 }参数说明OffsetX和OffsetY控制标注离几何的距离太小会重叠太大会跑出视图。MinEdgeLength是过滤短边的阈值避免给几毫米的倒角也标尺寸。这些参数没有万能值要根据你的图纸比例和视图大小调。我一般先在单张图纸上试调好了再批量跑。4. 避坑与排查图纸二次开发最常见的 5 个翻车现场4.1 现象脚本跑完图纸没变化但也没报错原因最常见的是忘了调用Insert()或Modify()。TEKLA 的图纸对象是「先创建、后提交」的模式你new了一个PartMark不调Insert()它只存在于内存里图纸上什么都不会出现。另一个原因是当前没有活动图纸GetActiveDrawing()返回 null后面所有操作都作用在 null 上但 C# 不会自动报错。解决在每个创建操作后强制调用Insert()并在入口处加 null 判断。我习惯在脚本开头写一句if (drawing null) throw new Exception(没有活动图纸);让问题尽早暴露。4.2 现象标注位置全部偏移整体飞到图纸外面原因模型坐标和视图坐标混用。你拿模型坐标去创建PartMark或DimensionTEKLA 把它当视图坐标处理结果就是位置完全不对。另一个原因是视图被旋转过ModelToView的结果和你预期不一致。解决所有进入图纸 API 的坐标先做ModelToView转换。如果视图可能被旋转先读ViewBase.ViewCoordinateSystem确认坐标系再决定要不要做额外变换。调试时先把转换后的坐标打印出来和图纸上手动量出来的位置对比。4.3 现象批量标注后图纸卡顿打开要几十秒原因一次性插入了大量Dimension和PartMark每个对象都触发一次图纸重绘。TEKLA 图纸对象越多重绘越慢。如果你在循环里每插一个就刷新一次性能会崩。解决把插入操作放在一个事务里或者先收集所有要插入的对象最后统一Insert()。另外过滤掉不需要标注的短边和小零件能减少一半以上的对象数量。我一般会先统计要标注的数量超过 500 条就分批跑每批之间让用户确认。4.4 现象零件标记内容显示为空白或乱码原因Attributes.Content设了一个当前模板里不存在的字段。TEKLA 的标记内容依赖图纸模板模板里没有的字段显示出来就是空白。另一个原因是编码问题中文内容在某些模板下会乱码。解决先用 TEKLA 手动创建一个标记看它默认的Content是什么照着设。中文内容尽量用模板里的字段引用不要直接写死字符串。如果必须写中文确认模板文件编码是 UTF-8。4.5 现象脚本在别人电脑上跑不通报找不到程序集原因TEKLA Open API 的程序集路径依赖安装目录和版本。你本机引用的Tekla.Structures.Drawing.dll路径在别人电脑上可能不存在或者版本不一致。解决不要用绝对路径引用 DLL改用 NuGet 包或者把 DLL 放在项目相对目录下。如果团队里 TEKLA 版本不统一先确认版本号再决定用哪个版本的 API。我一般会在脚本开头打印 TEKLA 版本方便排查。5. 进阶技巧用配置驱动图纸标注让脚本能复用入门跑通之后真正决定这套东西能不能在项目里落地的是「可复用性」。你不可能每张图纸都改一遍代码所以要把标注规则抽成配置。我常用的做法是写一个 JSON 配置文件描述「哪些零件要标、标什么内容、偏移多少」脚本读配置执行。{ rules: [ { partType: Beam, markContent: PART_POS, offsetX: 100, offsetY: 50, dimensionType: LINEAR, minEdgeLength: 200 }, { partType: Column, markContent: PROFILE, offsetX: 150, offsetY: 80, dimensionType: LINEAR, minEdgeLength: 300 } ] }读取配置的代码using System.IO; using System.Text.Json; public class RuleLoader { public ListMarkRule LoadRules(string path) { string json File.ReadAllText(path); var options new JsonSerializerOptions { PropertyNameCaseInsensitive true }; return JsonSerializer.DeserializeListMarkRule(json, options); } } public class MarkRule { public string PartType { get; set; } public string MarkContent { get; set; } public double OffsetX { get; set; } public double OffsetY { get; set; } public string DimensionType { get; set; } public double MinEdgeLength { get; set; } }逻辑说明RuleLoader把 JSON 反序列化成规则列表脚本遍历规则对每类零件应用对应的标注参数。参数说明PartType对应模型里的零件类型MarkContent对应PartMark.Attributes.ContentOffsetX/Y控制标注偏移MinEdgeLength过滤短边。这样改规则不用改代码换个项目只换 JSON 文件就行。验证方法跑完脚本后不要只看图纸「有没有标注」要抽查三类零件最长的一根梁、最短的一根梁、一个柱。看标注位置是否合理、内容是否正确、有没有重叠。我一般会随机抽 5 张图纸手动量 3 个标注的位置和脚本输出的坐标对比误差在 5 毫米以内就算通过。一个具体技巧如果你的项目里图纸数量多不要一次性全跑。先跑一张确认没问题再跑十张最后全量。每次跑完把日志写到一个文本文件里记录「图纸名、插入标注数、耗时、异常」。出问题时日志比图纸本身更有用。我自己踩过最深的坑是早期写脚本时没做坐标转换结果一批图纸的标注全部偏到图框外面甲方审图时才发现返工了两天。从那以后我养成了一个习惯任何涉及坐标的脚本先打印转换前后的值确认无误再往下写。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。