为什么这条路可行
SolidWorks 宏录制器(工具 > 宏 > 录制)会把你的每一步操作翻译成 VBA 代码,保存为 .swp 文件。这段代码有两个特点:
它是真实可运行的——它调用的每一个 API、传的每一个参数,都是 SolidWorks 自己用过的,不存在“AI 凭空编错方法名”的问题。
但它很脏——里面塞满了视图缩放、旋转、平移的冗余调用,硬编码的坐标和尺寸,以及大量未使用的变量。
这恰好是 AI 最擅长处理的场景:给它一段确定能跑的代码,让它做清理、改造和增强。反过来,如果直接让 AI 从零“写一个宏”,比如“批量将装配体中零件添加冻结栏的宏”,它很容易编造不存在的 API 方法或用错参数单位,你又看不懂,根本没法调试。
准备工作
工具一:SolidWorks 本身。用途:录制宏、运行宏、VBA 编辑器。说明:不需要额外安装任何东西,宏功能内置。入口:工具 > 宏 > 录制 / 编辑 / 运行。
工具二:AI 编程 Agent 工具。用途:直接打开并修改宏文件,自动迭代。说明:codex、workbuddy、豆包工作、DSH 等。这些工具能直接在本地打开文件夹和文件,自己读代码、改文件,不需要你手动复 制粘贴。SolidWorks API 和 VBA 都在它们的训练数据里。
第一步:录制宏
录制前先在脑子里把操作走一遍,避免录进多余动作。录制时只做核心建模操作,刻意不做这些事:
不要缩放、旋转、平移视图——这些会被录成一堆无用的 API 调用。
不要中途按 Esc 或点错后撤销——错误操作也会被录进去。
不要切换显示样式(线架图/上色等)。
操作路径:工具 > 宏 > 录制,开始做你想自动化的操作,做完点停止,保存为 .swp 文件。如果录完发现录进了多余动作,直接重录一遍比事后清理更快——建议新手录两三次以消除视图操作。
第二步:拿到录制的代码
录制完成后,选 工具 > 宏 > 编辑,选中刚保存的 .swp,会打开 VBA 编辑器。你会看到类似这样的代码:
这一段执行了:打开文档的冻结栏;将冻结栏放置在“Extrude2”这个特征之后。
现在别急着自己改。右键左侧工程窗口中的模块 → 导出文件,把它存为 .bas,放进一个专门的文件夹(比如 D:\sw-macros\)。这就是 Agent 工具要操作的文件。
第三步:用 AI Agent 工具改造宏文件
聊天粘贴 vs Agent 直接改文件:
聊天窗口的工作流是你复 制代码 → 粘贴给 AI → 复 制返回结果 → 粘回 VBA 编辑器。来回倒腾容易出错,而且 AI 看不到你的文件全貌。Agent 类工具(Cursor、Claude Code、GitHub Copilot Chat 等)改变了这一点:它们直接在你电脑上打开一个文件夹,自己读文件、改文件,然后告诉你改了什么。你不需要手动复 制粘贴,只需要告诉它目标。
给 Agent 的指令模板:
在 Agent 工具里打开放 .bas 文件的文件夹,然后在对话框输入你的指令,把你的需求描述清楚。注意:你不需要粘贴代码——Agent 自己会读文件。
常见的改造方向:
清理冗余(删除视图操作、多余的 ClearSelection2、未使用变量,每次改造第一步,代码量直接砍一半);
参数化(把硬编码的坐标、尺寸、特征名提取为变量,或用 InputBox 让用户每次输入);
错误处理(检查是否打开了文档、选中对象是否存在,否则弹提示并退出);
批量循环(把单次操作改成遍历所有特征/组件/配置);
加界面(让 Agent 生成一个 UserForm,把参数做成输入框和下拉菜单)。
改造前后对比:
vba
AI 改造后的代码(清理 + 参数化 + 错误处理)
******************************************************************************
' 装配体批量移动冻结栏到特征树最底部(两遍式,处理完自动关闭零件)
' 第一遍:遍历组件,收集去重后的零件路径(跳过只读/抑制/轻量级)
' 第二遍:逐个打开零件 -> 激活 -> EditFreeze2 移到末尾 -> 保存 -> 关闭
' 最后切回装配体,弹汇总结果
' ******************************************************************************
Option Explicit
Dim swApp As Object
Sub main()
Dim swAssy As Object
Dim swPart As Object
Dim swComp As Object
Dim vComps As Variant
Dim i As Long
Dim j As Long
Dim lRet As Long
Dim successCount As Long
Dim skipReadOnlyCount As Long
Dim skipLightCount As Long
Dim failCount As Long
Dim msgResult As String
Dim failDetails As String
Dim originalTitle As String
Dim errors As Long
Dim warnings As Long
Dim saveErr As Long
Dim paths() As String
Dim pathCount As Long
Dim sPath As String
Dim found As Boolean
On Error GoTo ErrHandler
Set swApp = Application.SldWorks
' --- 1. 检查活动文档 ---
Set swAssy = swApp.ActiveDoc
If swAssy Is Nothing Then
MsgBox "没有打开的文档,请先打开一个装配体文件。", vbExclamation, "批量移动冻结栏"
Exit Sub
End If
If swAssy.GetType <> swDocumentTypes_e.swDocASSEMBLY Then
MsgBox "当前文档不是装配体,请在装配体环境下运行本宏。", vbExclamation, "批量移动冻结栏"
Exit Sub
End If
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swUserEnableFreezeBar, True
originalTitle = swAssy.GetTitle
vComps = swAssy.GetComponents(True)
If Not IsArray(vComps) Then
MsgBox "装配体中没有任何组件。", vbInformation, "批量移动冻结栏"
Exit Sub
End If
successCount = 0
skipReadOnlyCount = 0
skipLightCount = 0
failCount = 0
failDetails = ""
pathCount = 0
ReDim paths(0)
' --- 2. 第一遍:收集去重后的零件路径 ---
For i = 0 To UBound(vComps)
Set swComp = vComps(i)
If swComp.IsSuppressed() Then GoTo NextComp1
Set swPart = swComp.GetModelDoc2
If swPart Is Nothing Then
skipLightCount = skipLightCount + 1
failDetails = failDetails & " - " & swComp.Name2 & ":未加载或为轻量级组件,已跳过" & vbCrLf
GoTo NextComp1
End If
If swPart.GetType <> swDocumentTypes_e.swDocPART Then GoTo NextComp1
If swPart.IsOpenedReadOnly() Then
skipReadOnlyCount = skipReadOnlyCount + 1
GoTo NextComp1
End If
sPath = swPart.GetPathName
If sPath = "" Then GoTo NextComp1
found = False
For j = 1 To pathCount
If UCase(paths(j)) = UCase(sPath) Then
found = True
Exit For
End If
Next j
If Not found Then
pathCount = pathCount + 1
ReDim Preserve paths(pathCount)
paths(pathCount) = sPath
End If
NextComp1:
Next i
' --- 3. 第二遍:逐个处理零件 ---
For j = 1 To pathCount
errors = 0
warnings = 0
Set swPart = swApp.OpenDoc6(paths(j), swDocumentTypes_e.swDocPART, 1, "", errors, warnings)
If swPart Is Nothing Then
failCount = failCount + 1
failDetails = failDetails & " - " & paths(j) & ":打开失败(错误码 " & errors & ")" & vbCrLf
GoTo NextPath
End If
' 再次检查只读(多用户环境下可能在打开时变为只读)
If swPart.IsOpenedReadOnly() Then
skipReadOnlyCount = skipReadOnlyCount + 1
swApp.CloseDoc swPart.GetTitle
Set swPart = Nothing
GoTo NextPath
End If
' 激活零件文档
On Error Resume Next
errors = 0
Set swPart = swApp.ActivateDoc3(swPart.GetTitle, False, 0, errors)
If Err.Number <> 0 Or swPart Is Nothing Then
failCount = failCount + 1
failDetails = failDetails & " - " & paths(j) & ":激活失败 - " & Err.Description & vbCrLf
Err.Clear
On Error GoTo ErrHandler
On Error Resume Next
swApp.CloseDoc swPart.GetTitle
On Error GoTo ErrHandler
Set swPart = Nothing
GoTo NextPath
End If
On Error GoTo ErrHandler
' 核心:移动冻结栏到最底部(不依赖返回值,只看运行时错误)
On Error Resume Next
lRet = swPart.FeatureManager.EditFreeze2(swMoveFreezeBarToEnd, "", False, False)
If Err.Number <> 0 Then
failCount = failCount + 1
failDetails = failDetails & " - " & paths(j) & ":EditFreeze2 错误 " & Err.Number & " - " & Err.Description & vbCrLf
Err.Clear
Else
saveErr = 0
swPart.Save3 1, saveErr
successCount = successCount + 1
End If
On Error GoTo ErrHandler
' 关闭零件文档,避免文档堆积
On Error Resume Next
swApp.CloseDoc swPart.GetTitle
Set swPart = Nothing
On Error GoTo ErrHandler
NextPath:
Next j
' --- 4. 切回装配体 ---
On Error Resume Next
errors = 0
swApp.ActivateDoc3 originalTitle, False, 0, errors
On Error GoTo ErrHandler
' --- 5. 汇总 ---
msgResult = "批量移动冻结栏执行完成" & vbCrLf & String(28, "-") & vbCrLf
msgResult = msgResult & "成功(已保存并关闭):" & successCount & " 个零件" & vbCrLf
msgResult = msgResult & "跳过(只读):" & skipReadOnlyCount & " 个零件" & vbCrLf
If skipLightCount > 0 Then
msgResult = msgResult & "跳过(未加载/轻量级):" & skipLightCount & " 个" & vbCrLf
End If
msgResult = msgResult & "失败:" & failCount & " 个"
If failDetails <> "" Then
msgResult = msgResult & vbCrLf & String(28, "-") & vbCrLf & "明细:" & vbCrLf & failDetails
End If
MsgBox msgResult, vbInformation, "执行结果"
Exit Sub
ErrHandler:
MsgBox "宏发生错误:" & vbCrLf & "错误号:" & Err.Number & vbCrLf & "描述:" & Err.Description, vbCritical, "批量移动冻结栏"
End Sub
对比一眼可见。以上 VBA 代码仅经过小规模测试,实际超大模型的执行效果未知。
第四步:测试与迭代
Agent 改完文件后,回到 SolidWorks VBA 编辑器,用 文件 > 导入文件 把改好的 .bas 导回去,按 F5 运行。通常第一轮不会一次全对,常见情况和处理方式:
编译报错(红色高亮):回到 Agent 对话框,直接说运行报错了,错误信息是……把报错原文贴给它。Agent 会自己打开文件找到那一行并修改。
运行时报错:SW 会弹一个对话框提示错误行号。把错误信息发给 Agent,它会读文件、定位问题、直接改。
结果不对但不报错:比如弹窗执行成功,但是实际没有执行,或者执行结果不对等。
常见坑与边界
坑一:AI 编造不存在的 API。
避免方式:始终以录制代码为基础让 Agent 改造,不要让它从零写。如果 Agent 返回了录制代码里没有的方法名,在 SolidWorks API 帮助文档里搜一下确认存在。
坑二:单位错误。
避免方式:SolidWorks API 内部一律用米,你画的 50mm 在代码里就是 0.05。Agent 有时会直接写 50,导致圆大得离谱。让 AI 加注释标明单位。
坑三:选择集依赖。
避免方式:录制代码里的 Extrude2 依赖当前模型里确实存在叫“Extrude2”这个拉伸特征。换个零件就报错。让 Agent 改成按类型遍历或让用户先选好再运行。
坑四:一次性给太多需求。
避免方式:不要一上来就让 Agent“做成一个完整的参数化打孔工具,带界面,支持批量”。先做最小可用版本(单个孔、写死参数),跑通后再逐步加功能。
坑五:改坏了找不回。
避免方式:Agent 工具通常自带版本历史,但保险起见,每次让 Agent 大改之前,先把当前 .bas 文件复 制一份(如 macro_v1.bas)。改坏了直接回退。
工作流一览
这条路的本质是:录制器负责保证代码能跑,Agent 负责让代码好用。你不需要学会 VBA 的每一个语法细节,只需要能判断这个操作我录一遍能不能录出来——能录出来的,把 .bas 文件丢给 Agent,它就能帮你改造成通用工具。