☰
CAD-VBA二次开发入门:从宏和对象模型开始
2026/11/4 2:42:17 网站建设 项目流程

简介:《CAD-VBA开发人员手册》面向需要在AutoCAD平台上进行二次开发与自动化扩展的VBA开发者,也可供熟悉基础绘图、希望系统掌握ActiveX编程的工程技术人员查阅。全书十章由入门逐步推进到高级应用,覆盖嵌入与全局VBA工程、宏与IDE、AutoCAD对象模型、图形环境控制、图元创建编辑、标注与公差、菜单工具栏定制、事件处理、三维坐标与实体编辑、布局打印,以及光栅图像、块和属性等组织技术,兼顾概念说明与对象操作思路。资源包共1个PDF文件,大小约3.16MB,便于集中检索和离线阅读。已有2492人学习下载,适合按章节查漏补缺,也能帮助读者建立从工程组织、对象访问到界面交互与打印输出的完整开发框架。

1. 别被“二次开发”四个字吓退:CAD-VBA 到底是什么

你在 CAD 里画了几年图,图层、标注、图框闭着眼都能点。然后有人递给你一份 CAD-VBA 开发人员手册,目录一翻,十页全是“对象模型”“事件”“集合”“图元”,第一章还没读完就合上了——这是大多数人第一次接触 CAD 二次开发的真实反应,跟聪明不聪明没关系,纯粹是被术语吓的。其实 VBA 干的事朴素得很:把你每天重复点的那几十下,写成几行话,让软件自己点。它不要求你会算法,也不要求你懂编译原理,只要求你熟悉自己每天在 CAD 里做的那些动作。这份手册面向的正是这样的人:会用 CAD 画图、没写过代码、想把重复劳动交出去的新手。

2. 上手前先认清三样东西:工程、宏和开发环境

很多人第一次打开 VBA 开发环境,看到左边一长条树状列表,当场就愣住了:工程是什么?模块是什么?宏又是什么?它们之间到底谁管谁?这一章不写代码,先把这三个名词按顺序讲清楚,你后面才能知道每敲一行字,究竟是落在哪个地方。

2.1 嵌入工程和全局工程:一个跟着图纸走,一个跟着你走

手册第一章一上来就讲这件事,很多人觉得抽象就跳过去了,结果后面所有问题都从这里来。VBA 工程说白了就是“一堆代码文件、窗体和引用的打包”,它有两种存放方式。

嵌入工程,是把这份打包塞进某一张 CAD 图纸文件里。好处是省心:谁打开这张图,你的功能就自动跟着生效,不用他去找文件、装文件,特别适合把做好的小工具发给同事。代价是它被“关”在这张图里了——它没法去打开别的图形,也没法关闭图形,因为它的函数只存在于它所在的那份文档中。手册给了一个很贴切的例子:某张图纸一打开就自动开始记时间日志,记录这张图被用了多久,这种“打开即生效”的需求,就该用嵌入工程。

全局工程,是存成一个独立的工程文件,比如mylib.dvb,它更像一个工具箱,哪个图形都能用,还能自己打开、关闭图形。代价是它不会自动加载,你得手动装进去,而且别人用之前得知道文件放在哪。手册里提到的典型场景是:月底把三十张图纸的材料清单一次性汇总,这种“跨图纸批量处理”的活,只能用全局工程干。

还有一条容易被忽略的规矩:一张图形在同一时间只能有一个嵌入工程。想塞第二个,得先把第一个分离出去。

提示:新手练习阶段,建议先用全局工程,存到固定文件夹,别急着往正式图纸里嵌,免得改乱了自己的图。

2.2 宏:其实就是一个能被点名执行的子程序

宏这个词听着高级,拆开看就是一段写好了但不会自己跑、必须有人叫它才执行的代码。在 VBA 里它的长相是Sub 名字() ... End Sub。一个工程里可以有很多个宏,每个宏干一件事,比如“批量改图层”“批量加图框”。

点名的方式有好几种。最直接的是打开宏对话框,从列表里挑一个,点运行。命令行也可以直接输入宏名执行。等你学完手册第六章,还能把它挂到菜单和工具栏按钮上,别人点一下按钮就跑了,根本不知道后面有代码。

对话框里还有一个“逐语句”按钮,很多新手从没用过,这其实是排查问题最有效的入口:它会让代码跑到第一行就停住,然后你可以一行一行往下走,看每一步的结果对不对。手册第七章讲的调试和报错中断,根基就在这里。

2.3 VBA 开发环境:四个窗口认全了就不慌

打开开发环境,界面上东西不少,但日常真正用得上的就四块。

工程窗口在左边,是一棵树。最上面是工程名,下面挂着代码模块、类模块、窗体,还有“引用”这一项。你写的每个 Sub 都存在某个模块里,找不到模块就是找不到代码。

属性窗口通常就在工程窗口下面,用来改选中对象的各种设置。最常用的一个动作,就是改工程名——新建的工程默认都叫ACADProject,你不改,以后装了两个工程就分不清谁是谁。

代码窗口是主战场,顶部有两个下拉框,左边选对象,右边选过程,可以快速在代码之间跳;左下角有个小图标能在“全模块视图”和“单过程视图”之间切换,代码短的时候其实无所谓。

窗体窗口配着一个工具箱,用来做自定义对话框。从工具箱里把控件拖到窗体上摆好位置,双击控件就能跳到它对应的代码。第一次做界面会觉得挺有意思,但建议先把命令行版本跑通,再去做窗体。

2.4 算一笔时间的账:为什么值得学

假设一张图里有 20 个图框需要统一改成新模板的标题栏,每个手改 30 秒,一张图就是 10 分钟;一个项目 30 张图,就是 5 个小时。写这段脚本,第一次可能要磨两个小时,第二次遇到同样的活,就是改几个参数、点一下运行的事。更关键的是,手点会出错,脚本不会——它每次都一模一样地执行。

这也是为什么手册要花整整一章讲对象模型、又花一章讲菜单和工具栏:它想让你做出来的东西,最终是给不写代码的同事用的,而不是只给自己看的玩具。

3. 第一个例子:十行代码在 CAD 里画一条线

概念听完,该动手了。第一个例子不要贪大,就从“画一条线”开始——它足够简单,能跑通,又能让你看到代码和画面之间的因果关系。跑通这一次,后面所有操作都是在这个骨架上加东西。

3.1 动手前的三件小事

第一件,确认你的 CAD 装了 VBA 组件。部分版本默认不安装,表现就是你在命令行敲开发环境的命令,它回你一句“未知命令”。遇到这种情况,重新跑一遍安装程序,把 VBA 相关的选项勾上。

第二件,找到 VBA 管理器。在命令行输入VBAMAN,会弹出一个管理界面,可以装载、卸载、新建、嵌入、分离工程。点“新建”,你就得到了一个空工程,默认名字是ACADProject。

第三件,打开开发环境。命令行输入VBAIDE,或者从管理器的界面里进去。进去之后先看一眼工程窗口,确认你新建的工程在列表里。这时候它还是“未保存”状态,建议立刻另存为一个.dvb文件,放到你专门建的一个练习文件夹里——这一步是给自己留后悔药,后面你会感谢自己。

新建完工程,还得插入一个模块:在开发环境的“插入”菜单里选“模块”,工程窗口里就会多出一项。代码要写在模块里,不能凭空写在工程上。

3.2 第一个例子:画一条从原点到 (100, 50) 的线

在新建的模块里粘贴下面这段代码,把光标放到过程内部,按 F5 运行。

Sub DrawFirstLine() ' 声明两个数组,用来装起点和终点的坐标 Dim startPt(0 To 2) As Double Dim endPt(0 To 2) As Double ' 起点:(0, 0, 0) startPt(0) = 0: startPt(1) = 0: startPt(2) = 0 ' 终点:(100, 50, 0) endPt(0) = 100: endPt(1) = 50: endPt(2) = 0 ' 声明一个线对象变量 Dim lineObj As AcadLine ' 在模型空间里添加这条线,并把返回的对象交给 lineObj Set lineObj = ThisDrawing.ModelSpace.AddLine(startPt, endPt) ' 刷新一下,让它在屏幕上显示出来 lineObj.Update ' 弹出对话框告诉你这条线有多长 MsgBox "线画好了,长度是 " & Format(lineObj.Length, "0.00") End Sub

切回 CAD 界面,你应该看到一条斜线躺在模型空间里,同时弹出一个提示框,告诉你长度是 111.80。如果没看到线,别急着怀疑代码,先在命令行输入ZOOM再输入E(范围缩放),大概率是线跑到了当前视图之外。

3.3 逐句拆开看:这十行到底在干什么

Dim startPt(0 To 2) As Double这一行,是全书出现频率最高的写法,值得多说两句。CAD 里的点是用三个数字表示的,分别是 X、Y、Z。VBA 里装三个数字最方便的就是数组,下标从 0 到 2,正好对应三个方向。为什么不是 1 到 3?因为 VBA 默认从 0 开始数,而 CAD 的接口约定也是 0 是 X、1 是 Y、2 是 Z,两边刚好对上。以后你看到pt(1),脑子里要立刻翻译成“这个点的 Y 坐标”。

Set lineObj = ThisDrawing.ModelSpace.AddLine(startPt, endPt)这一行信息量最大,拆成三段看。ThisDrawing是“当前这张图”的代号;ModelSpace是这张图里的模型空间,你可以理解成装所有图元的那个大容器;AddLine是这个容器提供的一个动作,往里加一条线,并把新加的那条线交还给你。三个点连起来读就是:在当前图形的模型空间里加一条线,把这条线记下来。

前面的Set不能省。VBA 里给普通变量赋值直接写等号,但给“对象”赋值必须加Set,因为对象变量存的不是值,而是指向那个东西的线索。省了Set,运行时会给你一个很典型的报错。

lineObj.Update的意思是“刷新显示”。有些操作其实已经生效了,只是屏幕没重画,看起来像没反应,加这一句最稳妥。

最后的lineObj.Length是读属性。注意这里没有括号,因为它不是动作,是这条线自带的一个数值。属性是只读还是可改,要看具体是哪个——长度你改不了,但颜色、图层都能改,下一节就动它。

3.4 改三个参数,让它变成你自己的线

跑通之后,最该做的事是“乱改”。把endPt(0)从 100 改成 300,把endPt(1)从 50 改成 -80,再运行一次,看线的方向变没变。这一步看着幼稚,但它是你建立“代码和图形一一对应”感觉的最快方式,比看十页讲解都管用。

改完坐标,再来动颜色和图层。下面这段代码会把线画在一个叫MyLines的图层上,颜色设成红色。

Sub DrawOnMyLayer() Dim s(0 To 2) As Double, e(0 To 2) As Double s(0) = 0: s(1) = 0: s(2) = 0 e(0) = 200: e(1) = 120: e(2) = 0 ' 先找图层,找不到就临时忽略错误 Dim lay As AcadLayer On Error Resume Next Set lay = ThisDrawing.Layers("MyLines") On Error GoTo 0 ' 如果图层不存在(变量还是空的),就新建一个 If lay Is Nothing Then Set lay = ThisDrawing.Layers.Add("MyLines") End If Dim ln As AcadLine Set ln = ThisDrawing.ModelSpace.AddLine(s, e) ln.Layer = "MyLines" ' 指定图层 ln.Color = acRed ' 指定颜色常量 ln.Update End Sub

On Error Resume Next的意思是“出错也别停,接着往下走”。这里为什么要用它?因为去取一个不存在的图层会直接报错中断,而“图层可能不存在”是正常情况,不该当成故障。取不到就把错误吞掉,靠If lay Is Nothing判断一下,没有就自己建一个。这种“先找、找不到再建”的写法,在批量处理图纸时几乎天天用得上。

ln.Color = acRed里的acRed是一个现成的颜色常量,不用记数字。手册里图层、颜色、线型这一节列了一整套常量,初学阶段记住几个常用的就行。要提醒的是,如果你把线型设成某种虚线却发现没生效,多半是那张图里根本没加载这种线型,得先把线型加载进来,这是新手很常见的翻车点。

4. 从“会画线”到“会干活”:对象模型是绕不开的坎

能画线之后,你自然会想:那我怎么批量改已有一百条线的颜色?怎么找到某一张图里所有的文字?这些问题都得靠对象模型回答。手册第二章整整一章都在讲它,看着枯燥,但它是所有操作的说明书。

4.1 对象模型是一棵家谱树

把 CAD 想象成一个公司。最上面是软件本身(Application),下面是“文档”这个部门,文档部门里管着所有打开的图纸;每一张图纸(Document,代码里通常写成ThisDrawing)下面又分好几个小组:模型空间、图纸空间、图层表、块表、标注样式表等等;每个小组里才是具体的人和物——一条线、一个圆、一段文字。

想改某条线的颜色,你得沿着这棵树一路点下去:先找到图纸,再找到模型空间,再找到那条线,最后改它的颜色。手册里说的“访问对象层次”,讲的就是这条路径。路径写错一步,就会得到“对象不存在”或者“方法无效”这类报错——绝大多数新手错误,本质都是路径没走对。

为什么非得这么绕?因为路径本身就是定位。你想想,如果图纸里有一百条线,你不告诉程序“哪张图的哪个空间里的第几条”,它凭什么知道你要改哪一条。

4.2 集合、属性、方法:三个词管住所有操作

这棵树上有三种东西,认全了,手册后面的章节你基本能自己看懂。

集合,就是“一类东西的袋子”。模型空间是个集合,图层表是个集合,里面装着同类对象。集合有三个常用动作:数一数有多少个(Count),按序号或名字取出一个(Item),往里加一个新的(Add)。ThisDrawing.Layers就是图层集合,ThisDrawing.Layers("MyLines")就是从中按名字取出那一个。

属性,是对象身上的“形容词”。一条线有颜色、图层、线型、长度、起点、终点;一张图有文件名、保存路径。读属性就是问它“你现在是什么样”,写属性就是命令它“变成这样”。前面那段代码里的ln.Layer = "MyLines"就是在写属性。

方法,是对象能做的“动词”。给模型空间“加一条线”,给图形“重新生成”,给对象“删除”。方法后面通常跟一对括号,里面放参数,比如AddLine(起点, 终点)。

三者组合起来,几乎所有 CAD 自动化代码都长这个样子:从某个集合里取出一个对象,读它的属性做判断,改它的属性,或者调用它的方法。手册第四章讲的“创建对象”“编辑对象”,拆开看全是这个套路。

4.3 动手:把模型空间里的图元一个个数出来

光看概念容易飘,写一段遍历的代码,感受一下就实了。

Sub WalkModelSpace() Dim ent As AcadEntity Dim i As Long Dim msg As String i = 0 ' 逐个遍历模型空间里的每一个图元 For Each ent In ThisDrawing.ModelSpace i = i + 1 ' ObjectName 能告诉你它到底是线、圆还是文字 msg = msg & i & " → " & ent.ObjectName & vbCrLf Next ent MsgBox "一共 " & i & " 个图元" & vbCrLf & msg End Sub

For Each ... In ...是遍历集合的标准写法,意思是“把袋子里的东西一个一个拿出来”。ent的类型声明成AcadEntity,这是所有图元的“父类型”,线、圆、文字都能装进去——具体是什么,运行时用ObjectName问它。vbCrLf是换行符,让弹出的提示框好看一点。

这段代码的价值不在结果,而在思路:你以后要做的“批量为所有圆加标注”“批量把所有文字换成新字体”,骨架都是它,只是把中间的判断和修改换掉。

4.4 变体与坐标数组:新手最容易写错的两个地方

变体(Variant)是 VBA 里的万能盒子,什么都能装。它烦人的地方在于,CAD 有些接口返回的就是变体,你不接住就没法用。最典型的是让用户点一个点:

Sub LineByClick() Dim p1 As Variant, p2 As Variant ' 逗号不能省:第一个参数留空表示不指定基准点 On Error GoTo Canceled p1 = ThisDrawing.Utility.GetPoint(, "点一下起点:") p2 = ThisDrawing.Utility.GetPoint(p1, "再点一下终点:") ThisDrawing.ModelSpace.AddLine p1, p2 ThisDrawing.Regen acAllViewports Exit Sub Canceled: MsgBox "取消了,没有画线。" End Sub

GetPoint返回的是一个包含三个数字的变体数组,可以直接丢给AddLine,不用手动拆。第一个调用的第一个参数留空但逗号必须保留,这是个纯语法坑,漏了逗号会直接语法报错,很多人卡在这里半天。第二个调用把p1当基准点传进去,用户就能看到一条橡皮筋线跟着鼠标动,体验好很多。

按 Esc 取消取点会触发错误,所以用On Error GoTo Canceled接住,跳到标签那里给个提示再退出。没有这个保护,用户手一抖按了取消,程序就弹一个红叉报错框,很不体面。

另一个常见坑是数组下标。自己声明数组时一定要写(0 To 2),别写成(1 To 3)。虽然语法上都合法,但从 1 开始的那种,传给 CAD 会把 Z 坐标搞丢,画出来的线位置不对,而且它不报错——这种不报错但结果错的问题,最难查。

5. 新手避坑清单:五个最容易翻车的瞬间和它们的解法

下面这五条,几乎每个刚开始写 CAD 脚本的人都撞过。提前看一眼,能省下好几个晚上。

5.1 代码看着没毛病,一运行就报“对象变量未设置”

现象:按 F5,弹出运行时错误,提示某个对象变量或 With 块变量未设置,光标停在Set那一行或者下一行。

原因:多数情况是当前没有打开的图形。ThisDrawing指的是当前活动的那张图,一张图都没开,它自然是空的。另一种情况是你在全局工程里操作一个已经关掉的文档对象,引用还在,实物没了。

解决:先确认 CAD 里确实开着一张图,再运行。如果脚本要连续处理多张图,别一直用ThisDrawing,改成遍历文档集合,逐个打开、逐个处理、逐个关闭,处理完再统一保存。养成在过程开头先判断一下的习惯,比事后查半天强。

5.2 点了运行,什么都没发生,也不报错

现象:代码明明有反应,应该弹提示框、应该画线,结果屏幕纹丝不动。

原因:最常见的是装工程时弹了宏病毒警告,你顺手点了“禁用代码”。工程装载成功,但里面所有代码都被冻住,点了运行等于什么都没干。第二种可能是“出错时允许中断”这个选项被关掉了,出错时它只闪一个警告框然后结束,你根本没注意到。

解决:回到 VBA 管理器,把工程卸掉重新装载,这次认真看弹窗,选启用代码。再去宏对话框的选项里,确认“出错时允许中断”是勾上的——勾上之后,代码出错会停在出错那一行并高亮,你能直接看到是哪个变量出的问题,这是排查问题最省力的开关。

5.3 想往同一张图里塞第二个工程,被拦住了

现象:点嵌入,提示无法嵌入,或者报错说已存在嵌入工程。

原因:一张图形同一时间只能容纳一个嵌入工程,这是硬规矩,不是 bug。你之前试手的时候已经嵌进去一个了。

解决:先在管理器里选中那个旧工程,点分离,系统会问你要不要先导出保存,选“是”存成.dvb文件,然后再嵌新的。这里有个血泪教训:分离时如果选了“否”,工程数据就从图里直接删掉了,没有回收站。所以分离前一定先导出。

5.4 改了半天代码,关掉软件全没了

现象:写了两个小时,关了 CAD 再打开,代码消失得干干净净。

原因:嵌入工程的保存是跟着图形文件走的,图纸没保存,工程就没保存;全局工程则要单独另存为.dvb文件,开发环境里没有那种“随手自动保存”的机制。

解决:养成两个习惯。第一,新建工程的第一件事就是另存为.dvb,先给个名字和位置,别等写完。第二,每改完一小段、确认能跑通,就按一次保存。这不是谨慎,是必须——我见过太多人在最后一步崩溃的时候,连重写的力气都没有了。

5.5 逐语句调试走到一半,程序卡住不动了

现象:用逐语句运行,走到某一行之后,CAD 界面像死了一样,点什么都没反应。

原因:多半是那一行在等用户输入,比如GetPoint或者某个选择图元的调用,而你没意识到它已经切回 CAD 界面在等你了。另一种是弹了个对话框在你没注意的角落,或者被其他窗口挡住了。

解决:先按 Alt+Tab 把所有窗口扫一遍,看看有没有藏起来的提示框。确认是在等取点时,就正常去 CAD 界面点一下。如果确定是死循环,别硬关软件,先在开发环境里点停止按钮中断执行,再回头检查循环的退出条件——For Each遍历集合时,如果在循环体里删除了元素,很容易出这种问题。

6. 接下来学什么:一份按周走的入门路线

跑通画线、能遍历图元之后,最容易犯的错是抱着手册从第一页啃到最后一页。这份手册十章、五百多页,按目录顺序读,大概率读到第三章就断了。更合适的走法,是按“先能干活、再补基础”的顺序挑着读。

阶段重点章节目标大概投入
第 1 周第 1 章、第 3 章会用管理器和开发环境,能打开、保存、关闭图形,会读系统变量每天 1 小时
第 2 周第 4 章能批量创建和修改图元,会改图层、颜色、线型、文字每天 1 小时
第 3 周第 2 章、第 5 章把对象模型彻底理顺,能画标注、能改标注样式每天 1 到 2 小时
第 4 周第 6 章、第 9 章把脚本挂到菜单和按钮上,跑通出图和打印周末集中两三天
之后第 7、8、10 章事件、三维、块与光栅图像,按项目需要挑着看看情况

具体操作上,我建议你从第二周开始就维护一个自己的“小工具工程”:一个.dvb文件,里面按用途分模块,LayerTools放图层相关的,TextTools放文字处理相关的,每个宏只干一件事,名字起得能一眼看懂。坚持三个月,这个文件就是你自己攒出来的工具箱,比任何现成的插件都顺手。

还有一个小技巧值得单独说:每次写新脚本,别从空白模块开始,从你已经跑通的那个复制过来,改里面的参数。新手写代码最大的时间浪费不是想不出逻辑,而是卡在一个拼写错误或者漏掉的Set上。从能跑的代码改,等于默认跳过了一堆低级坑。

至于事件那一章,我的建议是先放着。事件是“当用户做了某个动作时自动触发”,听着很酷,但它对调试的要求高得多,新手很容易写出一堆互相触发的代码,最后连自己都不知道是谁在调用谁。等你手上已经有五六个能稳定运行的小工具了,再回来看这一章,会顺很多。

最后说个我自己的教训。刚学那会儿,我写完一个批量改图层的脚本,兴冲冲地拿一张正式的施工图试,结果图层名匹配写错了一个字符,整张图的图层全被塞进了新建的临时图层里,等我发现的时候已经保存过了。从那以后我每次写涉及“批量修改”的脚本,都强制走一遍固定流程:先复制一份测试图,再在小样本上跑,确认输出和预期一致,才敢碰正式文件。多花的那五分钟,比返工一整天便宜太多。希望这份路线能帮你少走几步弯路,早点把重复劳动交出去。

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

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

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

立即咨询