如果你正打算用SolidWorks宏(Macro)把那些重复到令人发指的建模、装配、出图操作自动化,恭喜你,你踏上的是一条“省时省力”与“血压飙升”并存的修罗场。我是火星人教育的SolidWorks讲师,带过上千名学员从宏录制走向脚本自由。这篇文章不教你怎么点按钮,只告诉你:在VBA自动化这条路上,哪几个坑摔得人最多、最惨,以及怎么优雅地绕过去。
先泼一盆冷水:SolidWorks宏不是万能药。它基于VBA(Visual Basic for Applications),本质是调用SolidWorks的API(应用程序接口)来操控软件。这意味着你写的每一行代码,都是在和一套庞大、古老、文档不全的COM组件打交道。下面这7个坑,每一个都沾着我和学员们的血泪。

坑1:录制宏当宝,回放全是错——相对引用与绝对路径的致命陷阱
现象
你精心录制了一段“打开模板→拉伸→倒角→保存”的宏,在自己的电脑上跑得飞起。发给同事,或者换台机器,立刻报错:“文件未找到”或“对象变量未设置”。
根因
录制的宏把文件路径写死了,而且是绝对路径。例如 Set swDoc = swApp.OpenDoc6("C:\Users\张三\Desktop\模板.SLDPRT", ...)。换台电脑,这个路径根本不存在。更隐蔽的是,录制时SolidWorks会记录你鼠标点击的每一个坐标和选择操作,这些选择依赖于当前的视图状态和模型状态。回放时,只要视图稍有不同,选择集就会错乱。
解决方案
永远不要直接使用录制的代码。把它当作“API调用字典”来查,而不是可执行程序。手动改写路径为相对路径或通过对话框获取。用 swApp.GetOpenFileName2 让用户选择文件,或者用 ThisFile 获取当前宏所在目录,再拼接相对路径。
' 正确做法:获取宏所在目录,拼接相对路径
Dim macroPath As String
macroPath = swApp.GetCurrentMacroPathName
Dim baseDir As String
baseDir = Left(macroPath, InStrRev(macroPath, "\") - 1)
Dim templatePath As String
templatePath = baseDir & "\templates\part.prtdot"
预防措施
- 录制宏只用于学习API对象和方法名,绝不直接运行。
- 所有文件路径必须动态获取,禁止硬编码。
- 在宏开头添加
On Error GoTo错误处理,捕获路径错误并提示用户。
技巧:在SolidWorks API帮助中搜索“GetOpenFileName2”,这是获取用户选择文件的标准方法,比硬编码路径可靠一万倍。
坑2:选择集是玄学——为什么我的宏总是选错面?
现象
宏里写 swDoc.Extension.SelectByID2("Face1", "FACE", 0, 0, 0, False, 0, Nothing, 0),有时成功,有时报“对象未找到”。或者明明想选一个面,结果选到了边线。
根因
SolidWorks的命名是持久引用ID(Persistent Reference ID)机制,但录制宏生成的名称往往是临时名称(如“Face1”、“Edge2”),这些名称在模型修改后会重新分配。而且 SelectByID2 的坐标参数(x, y, z)是模型空间坐标,用于辅助定位,如果坐标点不在目标面上,选择就会失败。
解决方案
放弃按名称选择。改用遍历几何体+条件筛选。例如,要选择所有圆柱面,遍历 Body2.Faces,检查 Face.Surface.IsCylinder。或者使用标记(Mark)和选择过滤器。更高级的做法是用 IFace2.GetTessTriangles 获取面信息,但性能较差。推荐使用 IModelDocExtension.SelectByRay 通过射线投射选择,稳定得多。
' 遍历所有面,选择圆柱面
Dim swBody As SldWorks.Body2
Set swBody = swPart.Body2
Dim swFace As SldWorks.Face2
Set swFace = swBody.GetFirstFace
Do While Not swFace Is Nothing
Dim surf As SldWorks.Surface
Set surf = swFace.GetSurface
If surf.IsCylinder Then
swFace.Select4 True, Nothing
End If
Set swFace = swFace.GetNextFace
Loop
预防措施
- 永远不要依赖录制宏生成的选择名称。
- 使用几何属性(面类型、面积、法向)来筛选目标。
- 选择前先清除选择集:
swDoc.ClearSelection2 True。

坑3:单位与坐标系——你的10mm不是我的10mm
现象
宏里创建一个点,坐标写 (0.01, 0, 0),你以为单位是米(SolidWorks API默认单位),结果模型单位是毫米,点跑到了0.01毫米处,肉眼看不见。或者装配体配合时,零件位置完全错乱。
根因
SolidWorks API内部使用米作为长度单位,弧度作为角度单位。但用户界面显示的单位由文档设置决定。录制宏时,如果你在毫米环境下操作,录制的坐标值可能被转换为米,也可能没有,这取决于API版本和具体方法。很多API方法(如 CreatePoint2)明确要求米,而有些(如草图坐标)又使用文档单位。混乱至极。
解决方案
统一在宏内部使用米和弧度。所有用户输入(如从InputBox获取的毫米值)立即乘以0.001转换为米。输出给用户时再转换回毫米。对于角度,使用 Pi/180 转换。务必查阅API帮助中每个方法的“Units”说明。
预防措施
- 在宏开头定义常量:
Const MM_TO_M As Double = 0.001,Const DEG_TO_RAD As Double = 3.14159265358979 / 180。 - 所有API调用参数显式转换,不要相信录制宏的数值。
- 使用
swDoc.GetUserPreferenceIntegerValue(swUnitsLinear)检查文档单位,但不要依赖它做计算。
注意:
SelectByID2的坐标参数也是米!很多人在这里栽跟头。
坑4:性能黑洞——循环调用API让SolidWorks卡死
现象
宏需要处理100个零件,每个零件执行“打开→修改→保存→关闭”。代码写了个For循环,结果运行了半小时,SolidWorks无响应,甚至崩溃。
根因
每次 OpenDoc6 和 CloseDoc 都会触发SolidWorks的完整重建和界面刷新。VBA的COM调用开销巨大,尤其是在循环中频繁访问API属性(如 Feature.Name)时,每次访问都是一次跨进程调用。此外,SolidWorks默认开启“重建模型”和“图形刷新”,这些在批处理时纯属浪费。
解决方案
- 关闭界面刷新:
swApp.Visible = False(但会隐藏SolidWorks,谨慎使用),或swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisableGraphicsUpdates, True。 - 批量操作:尽量在单个文档内完成所有修改,减少打开/关闭次数。
- 使用早期绑定:在VBA中引用SolidWorks类型库,声明具体对象类型(如
Dim swPart As SldWorks.PartDoc),比后期绑定(As Object)快数倍。 - 避免在循环中访问属性:将
Feature.Name等属性一次性读入数组,再处理。
' 开启性能模式
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisableGraphicsUpdates, True
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisableFeatureTreeUpdates, True
' ... 执行批量操作 ...
' 恢复
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisableGraphicsUpdates, False
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swDisableFeatureTreeUpdates, False
预防措施
- 任何超过10次迭代的循环,都必须先关闭图形更新。
- 使用
swApp.DocumentVisible False, swDocPART在后台打开文档,不显示窗口。 - 用
Stopwatch类(需引用Scripting.Runtime)计时,找出性能瓶颈。
坑5:事件陷阱——宏没反应,因为事件没绑定
现象
你想写一个宏,在用户保存文档时自动运行。你写了 swApp.ActiveDocChangeNotify 事件处理程序,但死活不触发。
根因
SolidWorks API的事件模型需要显式绑定。在VBA中,你必须使用 WithEvents 关键字声明一个类模块,并在其中定义事件处理程序。而且,事件只在宏运行期间有效,宏结束后事件绑定自动失效。很多人把事件代码写在标准模块里,那是无效的。
解决方案
在VBA编辑器中插入一个类模块(Class Module),命名为 SwEventClass。在类模块中:
Public WithEvents swApp As SldWorks.SldWorks
Private Sub swApp_ActiveDocChangeNotify()
MsgBox "文档已切换!"
End Sub
然后在标准模块中初始化:
Dim swEventClass As SwEventClass
Sub InitEvents()
Set swEventClass = New SwEventClass
Set swEventClass.swApp = swApp
End Sub
预防措施
- 事件处理必须用类模块+WithEvents,没有例外。
- 宏停止时事件失效,如需持久监听,需制作成SolidWorks插件(Add-in),而非宏。
- 调试事件时,在事件处理程序第一行加
Debug.Print,确认是否触发。
忠告:宏适合“一次性批处理”,插件适合“持续监听”。别用宏做插件的事。
坑6:错误处理缺失——一个未捕获的错误让整个宏崩溃
现象
宏运行到一半,弹出一个VBA错误对话框:“运行时错误‘91’:对象变量或With块变量未设置”。点击调试,发现某行代码试图访问一个Nothing对象。整个自动化流程中断,前面做的修改全部丢失。
根因
VBA默认没有全局错误处理。任何未处理的错误都会中断执行。而SolidWorks API调用失败时,往往返回Nothing或False,而不是抛出异常。如果你不检查返回值,就会在后续代码中崩溃。
解决方案
在每个Sub/Function开头添加 On Error GoTo ErrorHandler。在错误处理标签中记录错误信息,并优雅退出。对于关键API调用,检查返回值:
Dim swDoc As SldWorks.ModelDoc2
Set swDoc = swApp.ActiveDoc
If swDoc Is Nothing Then
MsgBox "没有打开的文档!"
Exit Sub
End If
预防措施
- 每个过程都要有错误处理,不要偷懒。
- 使用
Err.Number和Err.Description记录详细错误。 - 在错误处理中释放对象:
Set swDoc = Nothing。 - 考虑使用
On Error Resume Next仅用于明确知道可能失败且可忽略的调用,但之后必须检查Err.Number并重置Err.Clear。
坑7:版本兼容性——你的宏在2020能跑,2024就崩
现象
公司升级SolidWorks到2024,你三年前写的宏开始报错:“方法未找到”或“参数计数不匹配”。
根因
SolidWorks API每年都在演进,旧方法可能被弃用,新方法增加参数。更麻烦的是,早期绑定的宏在引用类型库时,如果版本不匹配,会直接编译错误。而后期绑定的宏虽然能运行,但可能调用到已移除的方法。
解决方案
对于需要跨版本运行的宏,使用后期绑定(As Object),并动态检查方法是否存在。但后期绑定性能差。折中方案:使用条件编译,根据SolidWorks版本调用不同API。
#If SWVER >= 2024 Then
' 使用新方法
swDoc.Extension.SelectByRay ...
#Else
' 使用旧方法
swDoc.Extension.SelectByID2 ...
#End If
但VBA不支持直接获取SolidWorks版本常量,需要手动定义或通过 swApp.RevisionNumber 判断。
预防措施
- 在宏中显式检查SolidWorks版本:
If Val(swApp.RevisionNumber) < 2020 Then ... - 尽量使用稳定的核心API,避免使用新特性。
- 为不同版本维护不同分支,或使用插件架构隔离兼容性问题。
- 测试,测试,再测试。在目标版本上完整回归。
| 坑位 | 核心问题 | 一句话解药 |
|---|---|---|
| 1 | 绝对路径硬编码 | 动态获取路径,永不硬编码 |
| 2 | 选择集依赖临时名称 | 遍历几何体,按属性筛选 |
| 3 | 单位混乱(米vs毫米) | 内部统一用米,输入输出转换 |
| 4 | 循环API导致卡死 | 关闭图形更新,批量处理 |
| 5 | 事件不触发 | 类模块+WithEvents,宏非插件 |
| 6 | 未处理错误导致崩溃 | 每个过程加On Error |
| 7 | 版本升级宏失效 | 后期绑定+版本判断 |

看到这里,你可能已经发现:SolidWorks宏自动化的核心难点不在于VBA语法,而在于对SolidWorks API对象模型的深刻理解,以及对软件底层机制的敬畏。每一个稳定的宏背后,都是无数次崩溃、卡死、报错换来的经验。如果你不想自己踩遍所有坑,想要系统性地掌握从宏录制到API精通的完整技能树,并且在实际工业项目中落地自动化,那么找对学习路径至关重要。
关于火星人教育:火星人教育创办24年来,始终专注于数字艺术与AIGC实战职业技能培训。我们开设的课程涵盖AI漫剧创作、AIGC视觉设计、UE5游戏特效、室内全屋定制、MAYA三维动画、C4D动态设计、工业设计、NUKE影视后期、摄影摄像实训等方向。在北京、深圳双校区开设线下面授班,面向美术生、在校大学生及意向转行的职场人群,以项目化实训教学,夯实专业技能,助力就业与职业提升。如果你对SolidWorks二次开发、工业设计自动化有浓厚兴趣,欢迎联系我们:010-65918670。我们的工业设计课程中,专门设有SolidWorks API与宏自动化模块,用真实项目带你跨过这些坑,直抵高效设计的彼岸。








评论(0)