尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
QCAD脚本实战:批量归图层、生成孔位、自动编号与长度统计
写QCAD脚本这件事最让我喜欢的地方在于它真的能杀掉那些重复操作的时间。一套图纸画完之后整理图层、排孔位、加编号、统计长度这些活儿说难不难但点鼠标点到手酸。这一篇是“QCAD 代码片段”系列的第二篇按老规矩我不讲太复杂的框架只挑四个能直接拿来用的片段按文本内容批量归图层、网格孔位自动生成、给选中实体加批量编号、统计选中线段的长度总和。每个片段都配有代码和注释适合刚接触QCAD脚本的朋友也适合已经会一些基础操作、想提高出图效率的人做参考。下面所有代码都是基于QCAD自带的ECMAScript接口写的不同版本的类名和参数可能会有一点点差异用到时以你本地的接口为准。1. 内容整体设计与思路拆解1.1 为什么自己写脚本而不是装现成插件平时用QCAD出图处理外来图纸时最常遇到的情况就是图形乱、图层乱、文字乱。市场上有不少现成的辅助工具但实际用下来的体验往往是装了一堆能用上的没几个。比如你只是想“把文字批量归到某个图层”为这个单一需求去装一个大而全的插件还要忍受它带来的额外工具栏、快捷键甚至菜单整体来说非常不划算。更关键的一点是现成插件通常被设计成“通用方案”不会完全贴合你的规则需求。你自己写脚本就不一样了想按内容归类就按内容归类想加前缀就加前缀规则完全由你定。而且脚本写好一次后面遇到类似图纸就是纯复用这种长期积累的价值比装一个黑盒插件要大得多。写脚本这件事本身也没有想象中那么难。QCAD的脚本语法是ECMAScript和JavaScript基本没有区别不需要额外的编译环境也不用装任何工具链。哪怕你只写过几行网页脚本也能很快看懂QCAD的脚本在做什么。刚开始不熟悉API没关系先把别人的代码拿过来改改着改着就摸清楚那一套逻辑了。我自己就是从“想复制几个圆都写不明白”的水平起步的现在处理批量操作基本不慌。1.2 这期片段的选题原则这期选的四个片段背后其实有一条共同标准它们在出图流程里都够高频而且每个片段都对应QCAD脚本的一个典型能力方向。按文本内容归图层核心是遍历实体和修改属性网格孔位自动生成核心是批量创建实体给选中实体批量编号核心是读取选中集和创建标注统计线段长度核心是遍历数据并做数值计算。这四个方向几乎覆盖了日常脚本里最常用的操作类型。把这几个片段吃透之后遇到“批量做什么”的需求基本都能套同一套思路来解决。另外我特意没有选择那些“看起来很炫但实际用不上”的脚本场景。比如自动生成复杂的参数化图案这种需求本身就冷门代码还长不适合放进一个讲实操的系列里。系列内容的价值就在于解决真实问题不是展示技巧。这一篇延续上一篇的基调代码尽量短注释尽量多场景尽量贴近真实工作让大家抄完就能跑起来。1.3 脚本的运行方式先交代清楚进入代码之前有必要把运行环境讲清楚否则代码拿过去不知道往哪儿放。QCAD从比较早的版本开始就内置了ECMAScript支持不需要额外安装运行库。日常最快速的验证方式是打开QCAD自带脚本控制台把代码直接粘进去回车执行适合临时跑一次。如果想长期使用建议把脚本保存成独立的脚本文件放到用户配置目录下做成命令来调用。这个目录的具体位置以及怎么注册成命令我在第三大节会展开讲这里只需要记住控制台适合试验脚本文件适合复用。两种方式都不涉及复杂的配置拿到代码后很快就能试起来。2. 核心细节解析与实操要点2.1 片段一按文本内容批量归图层适用场景外来的DWG文件经常出现一种问题所有文字都堆在0图层没有分层导致显示颜色、打印线宽完全不受控制。手动一个个选中再做属性修改偶尔处理几个还行几十上百个文字时就很折磨人。这段脚本的作用就是自动遍历当前图纸中的所有文本实体找到包含指定关键词的文字把它移动到目标图层。目标图层不存在时会自动创建存在就直接复用。function batchMoveTextByContent() { var doc app.getDocument(); if (isNull(doc)) { qWarning(未获得活动文档); return; } var storage doc.getStorage(); var entityIds storage.getEntityIds(); var op new RAddObjectsOperation(); for (var i 0; i entityIds.length; i) { var entity storage.queryObject(entityIds[i]); if (entity.getType() ! RS.EntityText) { continue; } var txt entity.getText(); if (txt.indexOf(标题) ! -1) { var layerId doc.getLayerId(TEXT_TITLE); if (layerId -1) { layerId doc.addLayer(TEXT_TITLE, RColor(255, 0, 0)); } entity.setLayerId(layerId); storage.updateObject(entity); } } } batchMoveTextByContent();关键解析doc.getStorage()拿到的是当前图形数据库也就是所有实体和图层信息存放的地方。storage.getEntityIds()返回全部实体ID数组这是QCAD脚本里遍历图形的基础操作。拿到ID之后通过storage.queryObject(entityIds[i])取回实体对象再用getType()判断类型。这里匹配的是RS.EntityText也就是文本实体如果你想同时处理尺寸标注里的文字需要额外判断其它类型。图层判断这里有个细节。doc.getLayerId(TEXT_TITLE)是拿图层ID如果返回的是无效ID说明图层不存在就用doc.addLayer()新建。我特意把新建操作放在循环里判断而不是一开始就假设图层存在这样脚本能兼容“图层已经有了”和“图层还没有”两种情况。新图层直接指定为红色255,0,0实际使用时可以根据公司图层标准改颜色。注意事项跑这种批量修改类脚本之前一定要先另存一份图纸。我现在养成习惯是把原图复制一份叫“xxx_bak.dxf”脚本风险再低也抵不过一次误操作。关键词匹配用的是indexOf(标题)只要文本内容里包含“标题”两个字就会被选中如果想精确前缀匹配可以换成txt.startsWith(标题)这样只有开头是“标题”的文字才会被移动。还有一个容易忽略的点脚本运行完成后记得检查目标图层的颜色和线型设置否则文字虽然归层了但显示效果不一定符合预期。2.2 片段二网格孔位批量生成适用场景通风板、挡板、导轨安装孔这些孔要么排成整齐阵列要么按固定间距错位分布。手动复制的话孔稍微多一点就容易点得眼花间距还不一定准。脚本按数学规则生成间距误差几乎为零而且孔的数量、直径、行列数都可以通过参数随时调整改起来比手动重画快太多了。function createHoleGrid() { var doc app.getDocument(); if (isNull(doc)) { return; } var startX 0.0, startY 0.0; var holeDiameter 8.0; var gapX 25.0, gapY 25.0; var cols 5, rows 3; var op new RAddObjectsOperation(); for (var r 0; r rows; r) { for (var c 0; c cols; c) { var cx startX c * gapX; var cy startY r * gapY; var circle new RCircle(new RVector(cx, cy), holeDiameter / 2.0); op.addObject(circle); } } doc.getDocumentInterface().applyOperation(op); doc.getDocumentInterface().regenerate(); } createHoleGrid();关键解析双层循环的结构很直观外层管行数rows内层管列数cols每次循环算出当前孔位的圆心坐标(cx, cy)。这里有一个很常见的坑RCircle构造函数的第二个参数是半径不是直径。我在写代码时先把holeDiameter定义成直径然后在传入时除以2这样参数含义清楚也不太容易搞混。如果你直接拿直径传进去生成的圆就会比预期大整整一倍。RAddObjectsOperation是QCAD脚本里一个非常实用的对象它可以把多个创建操作打包进同一个事务。这样做有两个直接好处一是性能好比逐个提交对象要快不少二是撤销方便执行完以后按一次撤销整批孔就全部消失不会出现一格一格删的尴尬局面。代码末尾的applyOperation(op)是把事务提交到文档上regenerate()则是强制刷新视图让新对象立刻显示出来。变体思路这套网格生成逻辑很好扩展。错位排孔只需要加一个判断奇数行时把cx整体偏移gapX / 2.0就能生成常见的不锈钢网板孔位。如果只想在某些位置出孔可以在循环里加if条件跳过特定行列。想控制孔位所在图层也可以创建一个layerId在new RCircle()之后调用circle.setLayerId(layerId)。目前代码是在默认图层生成实际项目和图层标准配合时这一步往往不能省。2.3 片段三给选中的实体批量编号适用场景装配图里给每个零件标序号检测报告里给每个测点加编号这些场景都有一个共同特点实体已经摆在图里了你需要的只是快速给它们赋上“N-1”“N-2”“N-3”这样的标签。手动输入文本、手动摆放位置数量多且格式难以统一。这段脚本的思路是读取当前选中的所有实体在每个实体的端点位置自动放置一个有递进序号的文本。function numberSelectedEntities() { var doc app.getDocument(); if (isNull(doc)) { return; } var ids doc.querySelectedEntities(); if (ids.length 0) { qInfo(未选中任何实体); return; } var op new RAddObjectsOperation(); var prefix N-; var startNo 1; var textHeight 3.0; for (var i 0; i ids.length; i) { var entity doc.queryObject(ids[i]); if (isNull(entity)) { continue; } var pos entity.getEndPoint(); if (isNull(pos)) { continue; } var label prefix (startNo i); var txt new RText(pos, label, textHeight, 0.0); op.addObject(txt); } doc.getDocumentInterface().applyOperation(op); } numberSelectedEntities();关键解析doc.querySelectedEntities()返回的是一个ID数组内容就是当前图纸中被选中的实体。这里先做了一次空判断没有选中任何东西就直接提示退出避免脚本静默运行后让你一脸疑惑。getEndPoint()方法对线段、圆弧这类实体非常有效会返回终点坐标对文字或其它复杂实体返回位置的含义可能会有差异。因此代码里加了isNull(pos)检查拿不到有效位置就跳过不让一个异常实体影响整批编号。RText构造函数的前四个参数分别是放置点、文本内容、字高和旋转角度。这里字高统一用的3.0实际项目中需要根据图纸比例调整。文本内容用prefix (startNo i)拼接跑完以后会得到“N-1”“N-2”一直到“N-10”这样的序列。如果你希望从某个特定数字开始编直接改startNo就行。注意事项文本都放在getEndPoint()的位置实体的端点和文本插入点如果靠得太近编号文字就会和图形本身重叠。这种情况下可以在代码里加一点偏移比如生成pos后手动构造一个新的RVector(pos.x 2.0, pos.y 2.0)再传给文本对象。还有一个批次撤销的好消息整个脚本的所有文本都在一个事务里撤销一次就全没了不会留下半截编号。但反过来也需要注意如果你想把这次编号和之前的某个操作区分开撤销就得拆成两次执行。2.4 片段四快速统计选中线段长度总和适用场景材料统计、线材预算、外框测量这类需求经常要算“图中所有线段一共有多少长度”。手动打开属性面板一个个看长度再加总效率太低而且中途接个电话就容易忘记算到哪一条。脚本直接输出两个结果选中了几条线段、总长度是多少。尤其适合全部选中或者框选一块区域后统计几秒钟出结果。function sumSelectedLineLength() { var doc app.getDocument(); if (isNull(doc)) { return; } var ids doc.querySelectedEntities(); var total 0.0; var count 0; for (var i 0; i ids.length; i) { var entity doc.queryObject(ids[i]); if (entity.getType() RS.EntityLine) { total entity.getLength(); count; } } qInfo(选中线段数量: count , 总长度: total.toFixed(3)); } sumSelectedLineLength();关键解析getLength()是QCAD给线型实体提供的方法调用后直接拿长度值。这里用getType() RS.EntityLine筛掉其它类型的实体只统计真正的直线段。total.toFixed(3)是JavaScript的数值格式化方法会把结果保留到三位小数避免输出一长串浮点数。打印用的qInfo()会输出到脚本控制台信息量适中适合做结果展示。常见扩展这个脚本改一改就能支持更多统计需求。比如想统计圆弧的总长度在if条件里加上|| entity.getType() RS.EntityArc圆弧长度也会被累加。想统计多段线则需要额外解析多段线的顶点逐段求距离再加总。输出方式也可以升级不只打印到控制台而是生成一个文本实体放到图里或者写进CSV文件留档。这种扩展思路其实就是把QCAD脚本当“带图形界面的数据处理器”来用价值比单纯画圆画线高不少。2.5 四个片段怎么选一个速查表整理成一张表方便你按需求快速定位该用哪段脚本。片段核心API典型场景建议先改的参数按内容归图层getEntityIds / setLayerId外来图纸文字整理关键词、目标图层名网格孔位生成RCircle / RAddObjectsOperation钣金、通风板、安装孔行列数、间距、孔径批量编号querySelectedEntities / RText零件序号、测点编号前缀、起始号、字高统计线长getLength / qInfo材料统计、线材预算统计类型、输出格式3. 实操过程与核心环节实现3.1 脚本文件应该放在哪里长期使用的脚本不建议放在QCAD安装目录里因为以后升级软件时可能被覆盖。个人建议放到用户配置目录下的scripts文件夹中。Windows下通常在用户目录下能找到QCAD相关配置Linux和Mac下一般是~/.config/QCAD下对应的路径。你可以在QCAD菜单里查看脚本路径相关设置确认自己机器上的准确位置。放进去之后脚本就能被QCAD识别和调用但如果你想让它出现在某个特定命令下还需要做一点注册工作。这部分取决于你使用的QCAD版本最简单可靠的参照是安装目录自带的一堆插件示例。3.2 从控制台运行到脚本文件执行最快的验证方式是打开脚本控制台。在QCAD里找到控制台入口把代码整体粘贴进去直接回车。脚本末尾的batchMoveTextByContent()、createHoleGrid()这类语句会立刻执行控制台窗口会输出相应结果。这一段适合用来验证代码有没有写错也适合临时处理一次图纸。脚本文件的方式更适合高频复用。把代码保存成.js或.qs文件放到scripts目录后在QCAD的“运行脚本”入口选择该文件执行。两种方式跑出来的效果完全一致区别只在于代码的存在位置。结合我自己经验建议先用控制台跑通再保存成文件这样能把“代码没写对”和“路径放不对”这两个问题分开排查。3.3 进阶注册成菜单命令如果想让自己的脚本像内置功能一样出现在菜单或工具栏里就需要按照QCAD的插件写法注册。思路大体是这样定义一个继承自EAction的动作类重写相关生命周期方法在初始化时通过registerAction注册命令再用addPostListener挂载到启动流程中。下面是一个可以参照的骨架具体到某些方法名和参数要以你当前版本的官方示例为准。include(scripts/Example.js); function MyBatchAction() { EAction.call(this); } MyBatchAction.prototype new EAction(); MyBatchAction.prototype.beginEvent function(event) { EAction.prototype.beginEvent.call(this, event); batchMoveTextByContent(); this.terminate(); }; MyBatchAction.init function() { var action new MyBatchAction(); EAction.registerAction(batchMoveTextByContent, action); }; MyBatchAction.getMenuActions function() { return []; }; addPostListener(MyBatchAction, MyBatchAction.init);这段骨架最大的作用是给读者一个印象注册脚本没有想象中复杂无非是把你的业务函数包到动作类里。实际上QCAD安装目录自带的插件代码就是最好的参考手册把官方的示例复制一份出来替换自己的业务逻辑比自己从零研究可靠得多。我以前有几次就是对着官方示例改的效率极高建议你也这么做。3.4 调试脚本的几个习惯调试QCAD脚本最实用的习惯有几个。一个是多放qInfo打印在循环内部、判断分支前后输出当前变量的值能快速定位“哪一步没有按预期走”。另一个是做小范围验证脚本刚写好时只选中两个实体先跑一次别一上来就全图处理出了问题也好恢复。还有一个被我念叨很多次的老话批量改动前备份。哪怕脚本看起来再安全出一次错就够你难受很久备份是世界上成本最低的后悔药。4. 常见问题与排查技巧实录4.1 执行没反应但也没有报错脚本运行完没有报错图形却一点变化都没有这种情况多数是“事务没有提交”。确认一下代码里是否调用了applyOperation(op)如果只是创建了对象或修改了实体属性但没有提交到文档图形就不会有任何变化。另外一个常见原因是函数定义了但没调用。脚本控制台粘贴代码后只执行函数定义不会运行内部逻辑必须在结尾写上batchMoveTextByContent()这样的调用语句才能触发执行。检查顺序通常是先看没调用再看没提交第三查没刷新。4.2 中文匹配不上或控制台乱码QCAD脚本文件如果保存的编码不是UTF-8中文关键词很容易出现匹配不上的情况控制台输出也可能乱码。解决办法很简单保存脚本文件时选择UTF-8编码。如果你拿到的脚本是从旧项目里拷出来的尤其要检查一下编码格式。还有一种比较保守的规避方式在脚本调试阶段先把关键词换成英文比如用TITLE代替标题验证整体流程没问题之后再改回中文。4.3 API方法名或类型名对不上QCAD不同版本之间个别API方法名和常量类型名确实会有差异。遇到报错说“某某方法不存在”或者“某某常量未定义”先别急着怀疑自己写错去QCAD自带插件里搜一下类似的类名和调用方式。我多次靠这个办法解决了问题官方示例代码就是活字典直接搜某个类的关键词看它怎么用照搬过来往往就能跑通。需要注意QCAD对大小写敏感getEntityIds和getEntityIDs可能就是不兼容的两个名字复制代码时尽量保持和官方示例一致。4.4 海量实体操作卡顿图纸里有几千甚至上万个实体时脚本运行时间会明显拉长。最有效的优化是减少事务提交次数。把创建和修改操作尽量塞进同一个RAddObjectsOperation最后统一提交一次不要循环一次就提交一次。还有一个经验是减少不必要的regenerate()调用这种刷新操作很耗时在最终提交后调用一次就够了。处理特别大的图纸时还可以先备份原图再用脚本在副本上做实验避免卡住影响正图工作。4.5 批量改动之后想反悔因为整个脚本的改动都打包在一个事务里撤销一次就能全部还原这是批量脚本比较舒服的地方。但如果你在脚本执行后又做了其它操作撤销顺序会叠加在一起不一定能精确回到某个中间状态。所以最稳妥的方案仍然是执行前备份图纸。我自己就遇到过一种情况脚本逻辑本身没有问题但参数设错了批量把一批文字移动到了错误图层如果没有备份恢复起来会非常麻烦。备份一下几秒钟的事能省下大量返工时间。最后说点实际感受。这四个片段里我平时用得最多的是统计线长那个脚本因为做材料表几乎每周都要算长度以前靠手动点属性面板现在几秒钟出结果。踩过几次坑之后我的体会是QCAD脚本这条路最怕的不是不会写而是不敢写。先从这种几行的批量小工具练手遇到搞不定的就翻官方示例慢慢就能积累出自己的脚本库。东西不在于花哨能解决手边的实际问题就是好代码。这一篇先聊到这儿后续要是有新的实用片段我再继续补充。
RELATED

相关推荐

USB转串口驱动怎么装?FT232在Windows/Linux/macOS下的安装与排障全攻略

USB转串口驱动怎么装?FT232在Windows/Linux/macOS下的安装与排障全攻略

简介:Z-TEK(力特)FT-232 USB转串口驱动多系统通用安装包,主要面向嵌入式开发者、电子工程师及设备调试维护人员,解决FT232芯片设备在Windows与macOS下无法自动识别串口的问题,适用于单片机下载调试、Modem与…

📅 2026/10/17 8:24:23
给 AI 助手装一个失活自毁开关

给 AI 助手装一个失活自毁开关

文章目录为什么需要这个三阶段流程核心设计:fail-safe 优先防误伤的五道锁分批执行:被审批逼出来的设计沙盒实测总结给想做类似东西的人的建议为什么需要这个 个人 AI 助手是个矛盾体:它越有用,知道的就越多——账号凭证、聊天记…

📅 2026/10/17 8:24:23
FT-232 USB转串口驱动全攻略:多系统安装与排查指南

FT-232 USB转串口驱动全攻略:多系统安装与排查指南

简介:Z-TEK(力特)FT-232 USB转串口驱动是一份跨平台通用驱动资源,面向需要USB转RS-232通信的开发调试人员、工业控制及嵌入式设备使用者,可解决现代电脑缺少串口、外接串口设备无法识别的问题。压缩包内共108个文件&am…

📅 2026/10/17 8:24:23
MORE NEWS

更多资讯

📰

C++ libcurl工业级实战:断点续传、进度回调与SSL证书校验

简介:本资源是一套面向C中高级开发者与跨平台网络编程学习者的实战项目包,聚焦libcurl在HTTP文件上传与下载场景下的工程化应用,并配套Node.js服务端用于端到端功能验证。资源共872个文件,涵盖227个JavaScript服务端逻辑文件、128…

📰

artcraft:融合数字艺术与手工工艺的创作实践指南

1. 项目定位与创作思路拆解1.1 “artcraft”到底要做什么“artcraft”这个名字,我第一次看到时就觉得挺有意思:前半段是 art(艺术),后半段是 craft(工艺、手艺)。很多人把它理解成“艺术手作”&…

📰

Flutter Sliver 固定头布局:SliverPersistentHeader 与 SliverToBoxAdapter 实战

在 Flutter 的滚动体系里,Sliver 家族算是把“灵活”两个字玩到极致的一层。很多人第一次接触 CustomScrollView 的时候,看到一堆 Sliver 前缀的组件会本能地犯怵,觉得这玩意儿比 ListView 复杂太多。但真正在项目里做过复杂头部交互的人都知…

📰

OSPF区域外路由计算:FA值与Type-4/5 LSA深度解析

1. 从一个让人抓头的现象说起如果你平时维护过企业内网或者数据中心的网络,大概率遇到过这种场景:明明路由表里看到了一条外部路由,下一跳也正确,但数据包就是不通。抓包一看,流量被丢到了错误的出口,或者干…

📰

图表即代码:diagram-design让架构图像代码一样可维护、评审、复用

写这套图表脚本,我前后重构了三次,中间推翻过两版,才找到一套真正能扛住真实业务压力的结构。如果你也在用手拖拽画架构图、时序图,画完发现版本对不上、变更查不到、图形风格全靠个人手感,那这篇东西应该对你有用。这…

📰

用代码定义架构图:diagram-design 的设计与落地实践

有没有遇到过这种场景:方案评审会上,四五个人嘴里各自长出一张完全不同的架构图。产品说数据先到网关再进服务,前端说页面渲染依赖三个接口,后端一直强调他心里的那条调用链。没人说得清到底谁对,因为根本没有一张所有…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬