首页/文章/ 详情

用 AI 写 SolidWorks 宏:从宏录制到 AI 改造的完整工作流

53分钟前浏览0
  

核心结论:不会 VBA 也能写 SolidWorks 宏。关键不是从零学编程,而是用录制器拿到一段能跑但很脏的真实代码,再让 AI Agent 工具直接读写宏文件、自动清理和改造。你出操作和目标,Agent 出代码。


为什么这条路可行

SolidWorks 宏录制器(工具 > 宏 > 录制)会把你的每一步操作翻译成 VBA 代码,保存为 .swp 文件。这段代码有两个特点:

  • 它是真实可运行的——它调用的每一个 API、传的每一个参数,都是 SolidWorks 自己用过的,不存在“AI 凭空编错方法名”的问题。

  • 但它很脏——里面塞满了视图缩放、旋转、平移的冗余调用,硬编码的坐标和尺寸,以及大量未使用的变量。

这恰好是 AI 最擅长处理的场景:给它一段确定能跑的代码,让它做清理、改造和增强。反过来,如果直接让 AI 从零“写一个宏”,比如“批量将装配体中零件添加冻结栏的宏”,它很容易编造不存在的 API 方法或用错参数单位,你又看不懂,根本没法调试。


准备工作

工具一:SolidWorks 本身。用途:录制宏、运行宏、VBA 编辑器。说明:不需要额外安装任何东西,宏功能内置。入口:工具 > 宏 > 录制 / 编辑 / 运行。

工具二:AI 编程 Agent 工具。用途:直接打开并修改宏文件,自动迭代。说明:codex、workbuddy、豆包工作、DSH 等。这些工具能直接在本地打开文件夹和文件,自己读代码、改文件,不需要你手动复 制粘贴。SolidWorks API 和 VBA 都在它们的训练数据里。

关于文件格式:SolidWorks 的 .swp 是 OLE 复合文档(二进制),Agent 工具不能直接打开。你需要在 VBA 编辑器里右键模块 → 导出文件,存为 .bas 纯文本文件。导出后,Agent 工具就能像打开普通文本文件一样直接读和改它了。改完后在 VBA 编辑器里用“导入文件”导回即可。导出和导入这两步需要你在 SW 里手动操作,Agent 控制不了 SW 界面。


第一步:录制宏

录制前先在脑子里把操作走一遍,避免录进多余动作。录制时只做核心建模操作,刻意不做这些事:

  • 不要缩放、旋转、平移视图——这些会被录成一堆无用的 API 调用。

  • 不要中途按 Esc 或点错后撤销——错误操作也会被录进去。

  • 不要切换显示样式(线架图/上色等)。

操作路径:工具 > 宏 > 录制,开始做你想自动化的操作,做完点停止,保存为 .swp 文件。如果录完发现录进了多余动作,直接重录一遍比事后清理更快——建议新手录两三次以消除视图操作。

 

第二步:拿到录制的代码

录制完成后,选 工具 > 宏 > 编辑,选中刚保存的 .swp,会打开 VBA 编辑器。你会看到类似这样的代码:

这一段执行了:打开文档的冻结栏;将冻结栏放置在“Extrude2”这个特征之后。

现在别急着自己改。右键左侧工程窗口中的模块 → 导出文件,把它存为 .bas,放进一个专门的文件夹(比如 D:\sw-macros\)。这就是 Agent 工具要操作的文件。

vba 

一段典型的录制宏代码(创建一个圆) Dim swApp As Object

Dim Part As Object

Dim boolstatus As Boolean

Dim longstatus As Long, longwarnings As Long

Sub main()

Set swApp = Application.SldWorks

Set Part = swApp.ActiveDoc

swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swUserEnableFreezeBar, True

boolstatus = Part.Extension.SelectByID2("Extrude2", "BODYFEATURE", 0, 0, 0, False, 0, Nothing, 0)

boolstatus = Part.FeatureManager.EditFreeze(swMoveFreezeBarTo_e.swMoveFreezeBarToAfterFeature, "Extrude2", False)

End Sub

 

第三步:用 AI Agent 工具改造宏文件

聊天粘贴 vs Agent 直接改文件:

聊天窗口的工作流是你复 制代码 → 粘贴给 AI → 复 制返回结果 → 粘回 VBA 编辑器。来回倒腾容易出错,而且 AI 看不到你的文件全貌。Agent 类工具(Cursor、Claude Code、GitHub Copilot Chat 等)改变了这一点:它们直接在你电脑上打开一个文件夹,自己读文件、改文件,然后告诉你改了什么。你不需要手动复 制粘贴,只需要告诉它目标。


给 Agent 的指令模板:

在 Agent 工具里打开放 .bas 文件的文件夹,然后在对话框输入你的指令,把你的需求描述清楚。注意:你不需要粘贴代码——Agent 自己会读文件。

指令示例:“G:\doubao\07_SWP\冻结栏1.bas 是我用 SOLIDWORKS 宏录制器录制的 VBA 代码。我执行的操作是,将零件的冻结栏拉至特征最底部。我的需求是:1.将其修改为在装配体中遍历所有零件,并执行冻结栏拉至特征最底部;2.跳过只读文件;3.添加错误提示和执行结果提示。”

常见的改造方向:

清理冗余(删除视图操作、多余的 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,它会读文件、定位问题、直接改。

  • 结果不对但不报错:比如弹窗执行成功,但是实际没有执行,或者执行结果不对等。

Agent 的优势在这里体现得最明显:它记住了整个对话上下文和文件内容,你不需要每次重新粘贴代码。迭代时注意:每次只说一个问题,改完就测。不要一次让 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,它就能帮你改造成通用工具。


来源:三维机械设计工程师
ACT通用SolidWorksUM控制Origin装配
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2026-10-14
最近编辑:53分钟前
SOLIDWORKS艾金米
SOLIDWORKS增值服务商
获赞 230粉丝 160文章 1063课程 2
点赞
收藏
作者推荐

免费 5.0
未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈