简介这份文档面向希望用 API 与 VBA 提升 SolidWorks 设计效率的工程师及二次开发入门者围绕宏录制、VBA 编辑调试、SelectByID2 与 GetSelectedObject5 等接口展开帮助读者理解录制宏为何需要删改、如何调整代码结构并完成特征访问等基础操作。压缩包共 1 个 doc 文件约 276KB内容以教程文档形式组织适合按章节阅读和对照练习。已有 6208 人学习说明其在 SolidWorks 二次开发入门资料中具有一定参考价值。读者可从中获得宏录制到代码清理的完整思路、常用 API 调用示例及调试注意事项适合作为自动化设计任务的起步材料。1. 从一段录制的宏说起SolidWorks 二次开发先解决重复改孔深车间里最容易被低估的自动化不是一上来写多复杂的插件而是把每天重复的改孔深、换配置、往装配体里塞零件这几步录下来再改到能稳定跑。SolidWorks 二次开发全教程系列走的就是这条线先录宏再看SelectByID2和GetSelectedObject5怎么选对象接着用GetDefinition、AccessSelections读特征最后用AddComponent4、AddMate2做装配体自动化。它适合刚接触 VBA 的设计工程师也适合把宏升级成部门小工具的开发者。别急着上 C#先把一个.swp跑到不报错后面很多坑会提前暴露。2. 教程骨架与技术选型VBA COM API 的六段式路线这套教程的组织方式很朴素不先讲类库设计也不先搭 WinForm 外壳而是从 SolidWorks 自带的宏录制入口切进去。录制出来的宏就是 VBA 代码能直接看到SldWorks、ModelDoc2、Feature这些对象怎么被调用。SolidWorks 的 API 是 OLE/COM 风格VBA 里一句Set swApp Application.SldWorks就能拿到应用对象再通过ActiveDoc拿到当前模型。对二次开发新手来说这条路径短、反馈快改一行就能在立即窗口里看到结果。2.1 这套教程的模块地图从宏录制到装配体配合按教程文章的顺序拆核心模块可以归成六块。我在拿到这类合集时一般会按下面的路线建自己的练习目录不按文章标题平铺而是按“选择对象、读写数据、装配操作、错误处理”四类归档。模块关键 API落地产出宏录制与编辑宏工具栏、工具-宏-编辑可调试的.swp骨架对象选择SelectByID2、GetSelectedObject5稳定拿到特征、面、零部件特征数据读取GetDefinition、AccessSelections读出孔深、直径、拉伸深度特征数据修改SetDepth、ModifyDefinition改参数并让模型更新装配体插入OpenDoc6、AddComponent4按配置插入零部件装配配合GetFirstFace、Select2、AddMate2选面并添加配合练习目录常见做法是SolidWorks二次开发练习/ 01_宏录制与清理/ 02_选择API/ 03_特征数据读写/ 04_装配体插入/ 05_配合与面选择/ 06_错误处理与重建/这个目录不是让你照搬文件名而是提醒一件事每学一个 API就留一个能独立运行的小宏。后面排错时能快速定位是选择层坏了还是数据层没释放。2.2 为什么先用 VBA 跑通再谈 C#/VB.NET 封装VBA 的优势不是语言本身多强而是它离 SolidWorks 的宏入口最近。录制完点“编辑宏”Microsoft VBA 编辑器直接打开按 F8 单步、看本地窗口、在立即窗口里打印Debug.Print这些都不需要额外工程配置。教程里提到“自动编辑宏”选项勾选后录制结束会自动打开编辑界面最近编辑过的宏也会出现在工具-宏菜单里最多保留九个调试时省去反复找文件。旧宏文件后缀是.swb打开或运行时会自动转成.swp这一点在接手老脚本时很实用。常见做法是先把老.swb另存成.swp再在 VBA 里加Option Explicit把变量声明补全。等对象模型跑顺了再迁到 VB.NET 或 C#此时你关注的是接口签名和生命周期不会被“宏为什么一运行就弹窗”拖住。注意VBA 里引用 SolidWorks 类型库后常量名能不能直接用取决于本机引用和版本。教程里出现swDocPART、swTnExtrusion不通过的情况不是代码逻辑错而是枚举没对上。后面第5章会单独拆这个坑。2.3 环境与工程准备宏工具栏、引用、调试入口开始前把几个入口固定下来工具-宏-录制、工具-宏-编辑、工具-宏-新建。录制时只做目标动作不要顺手旋转视图、缩放、点空白区这些动作会被录进去后面要一行行删。录制完成后先别急着改逻辑把代码里的视图切换、多余选择、未使用变量清掉再运行一次看还能不能复现原动作。宏编辑器里打开“工具-引用”确认 SolidWorks 类型库已勾选。没有引用时SldWorks.SldWorks这种声明会报“用户定义类型未定义”。如果不想依赖早期绑定也可以全部用Object声明但那样就没有智能提示参数顺序容易写错。我的习惯是先在早期绑定下跑通再把关键对象改成Object做一次兼容性测试确认换机器不会因为类型库版本翻车。3. 从宏到特征读写SelectByID2、GetSelectedObject5 和 ModifyDefinition 串起来特征读写是这套教程里最值得逐行敲的部分。录制宏只能帮你拿到“动作录像”真正要稳定必须理解两件事怎么选到对象怎么在选中对象后拿到它的定义数据。SolidWorks 里特征不是一堆公开字段Feature对象本身只告诉你名字和类型参数在FeatureData里而且访问前要AccessSelections改完要ModifyDefinition失败还要ReleaseSelectionAccess。这一套生命周期不顺模型就会出现“看起来改了但没重建”的假成功。3.1 录制宏后必须做的三处清理录制出来的宏常见问题是变量声明一大堆、视图代码夹在中间、选择顺序和实际模型对不上。教程给的建议很直接删掉未使用的变量声明删掉切换视图的代码删掉紧挨着ClearSelection2之前的多余SelectByID2调用。尤其是Part.ActiveView().RotateAboutCenter这类行留着只会让脚本运行时画面乱跳严重时还会影响后续选择。清理后的骨架可以写成下面这样。这个宏只做一件事按名字选中“拉伸1”再把选中对象的名称打印到立即窗口。Option Explicit Dim swApp As SldWorks.SldWorks Dim swModel As ModelDoc2 Dim ok As Boolean Sub SelectExtrudeByName() Set swApp Application.SldWorks Set swModel swApp.ActiveDoc If swModel Is Nothing Then MsgBox 先打开一个零件或装配体 Exit Sub End If Name 用模型树里显示的名称Type 用大写类型BODYFEATURE 表示实体特征 X/Y/Z 传 0 表示不依赖坐标AppendFalse 表示先清空当前选择 Mark 传 0Callout 传 Nothing最后一个选择项传 0 代替 swSelectOptionDefault ok swModel.Extension.SelectByID2(拉伸1, BODYFEATURE, 0, 0, 0, False, 0, Nothing, 0) If Not ok Then Debug.Print 没有选中拉伸1检查名称或当前文档 Exit Sub End If Debug.Print 已选中 swModel.SelectionManager.GetSelectedObject5(1).Name End Sub这段代码的关键在SelectByID2的九个参数。Name是对象名中文环境可能是“拉伸1”英文环境可能是“Extrude1”不要硬编码到跨语言模板里。Type必须是大写字符串特征用BODYFEATURE面用FACE边用EDGE。Append为False时会先清空选择列表再放当前对象为True时是追加如果对象已选中则会从列表移除。Mark用于有序选择后面AddMate2这类需要区分第一选择、第二选择的 API 会用到。Option Explicit打开后教程里提到的swSelectOptionDefault有时不能直接写可以先用0占位。最后一个参数的本质是选择选项不同版本枚举名可能不同先用 0 跑通再回对象浏览器确认。3.2 两个选择 API 的分工按名字选 vs 按当前选择取SelectByID2和GetSelectedObject5经常被混着用。前者是“我告诉你名字你帮我选”后者是“用户已经选好了我按索引取”。教程里用“拉伸1”做例子先SelectByID2选中再用GetSelectedObject5(1)拿到第一个选中对象。实际脚本里如果模型树名称会被用户改按名字选就容易失效如果让用户先选脚本的交互成本又上去了。我一般把两者组合成“优先用当前选择没有选择再按名字找”的策略。下面这段代码先打印当前选择数量再遍历取名字调试选择顺序时很好用。Sub PrintSelectedObjects() Dim swSelMgr As SelectionMgr Dim i As Long Dim count As Long Dim obj As Object Set swApp Application.SldWorks Set swModel swApp.ActiveDoc If swModel Is Nothing Then Exit Sub Set swSelMgr swModel.SelectionManager count swSelMgr.GetSelectedObjectCount Debug.Print 当前选择数量 count For i 1 To count Set obj swSelMgr.GetSelectedObject5(i) If Not obj Is Nothing Then Debug.Print i - obj.Name End If Next i End SubGetSelectedObject5的索引从 1 开始不是 0。GetSelectedObjectCount返回当前选择列表长度循环时不要越界。旧代码里常见GetSelectedObject3新环境优先用 5返回值类型更明确。取到对象后仍要做Nothing判断因为选择列表里可能混入不支持的类型API 会返回空指针。3.3 读取简单直孔GetDefinition AccessSelections读特征参数的标准链路是拿到FeatureGetDefinition得到具体 FeatureDataAccessSelections拿到访问权读属性最后ReleaseSelectionAccess。教程里用简单直孔做例子读Depth和Diameter还读了GetFeatureScopeBodiesCount。这段代码在运行前要先选中一个简单直孔特征。Sub ReadSimpleHole() Dim swSelMgr As SelectionMgr Dim swFeat As Feature Dim swHole As SimpleHoleFeatureData2 Dim swComp As Component2 Dim ok As Boolean Set swApp Application.SldWorks Set swModel swApp.ActiveDoc If swModel Is Nothing Then Exit Sub Set swSelMgr swModel.SelectionManager Set swFeat swSelMgr.GetSelectedObject5(1) If swFeat Is Nothing Then MsgBox 先选中一个简单直孔特征 Exit Sub End If Set swHole swFeat.GetDefinition If swHole Is Nothing Then MsgBox 当前特征不是简单直孔 Exit Sub End If 独立零件里 Component 传 Nothing装配体里要传实际组件 ok swHole.AccessSelections(swModel, swComp) If Not ok Then MsgBox 无法访问特征数据 Exit Sub End If Debug.Print 孔名 swFeat.Name Debug.Print 直径 swHole.Diameter Debug.Print 深度 swHole.Depth Debug.Print 作用实体数 swHole.GetFeatureScopeBodiesCount swHole.ReleaseSelectionAccess End SubAccessSelections的返回值必须判断失败时不要再读属性。swComp在独立零件里是Nothing在装配体上下文里要指向实际组件否则访问的可能是顶层装配体而不是零件。GetFeatureScopeBodiesCount用来确认特征作用到几个实体多实体零件里这个值很关键。读完后ReleaseSelectionAccess要成对出现否则下一次访问同一特征可能拿不到选择访问权。3.4 修改拉伸深度SetDepth ModifyDefinition 重建兜底修改比读取多两步设置新值然后ModifyDefinition把 FeatureData 写回特征。教程里的例子是把基础拉伸深度翻倍同时加了文档类型、空选择、特征类型、基础拉伸四道判断。这段代码可以直接当模板改。Sub DoubleExtrudeDepth() Dim swSelMgr As SelectionMgr Dim swFeat As Feature Dim swExt As ExtrudeFeatureData2 Dim d As Double Dim ok As Boolean Set swApp Application.SldWorks Set swModel swApp.ActiveDoc If swModel Is Nothing Then Exit Sub 1零件2装配体不同版本常量名可能不通过先用整数判断兜底 If swModel.GetType 1 And swModel.GetType 2 Then MsgBox 只允许在零件或装配体里运行 Exit Sub End If Set swSelMgr swModel.SelectionManager Set swFeat swSelMgr.GetSelectedObject5(1) If swFeat Is Nothing Then MsgBox 请先选中基础拉伸特征 Exit Sub End If 教程环境里 swTnExtrusion 常量不通过改成字符串比较更稳 If StrComp(swFeat.GetTypeName, Extrusion, vbTextCompare) 0 Then MsgBox 当前特征不是拉伸 Exit Sub End If Set swExt swFeat.GetDefinition ok swExt.AccessSelections(swModel, Nothing) If Not ok Then MsgBox 无法获取拉伸数据访问权 Exit Sub End If If Not swExt.IsBaseExtrude Then MsgBox 请选中基础拉伸而不是普通拉伸 swExt.ReleaseSelectionAccess Exit Sub End If d swExt.GetDepth(True) swExt.SetDepth True, d * 2 ok swFeat.ModifyDefinition(swExt, swModel, Nothing) If Not ok Then MsgBox 修改特征失败 swExt.ReleaseSelectionAccess Exit Sub End If 修改后让模型重建并保存避免界面显示未更新 swModel.EditRebuild swModel.Save End SubGetType返回 1 和 2 分别对应零件、装配体这是教程里用MsgBox Model.GetType试出来的笨办法但很实用。GetTypeName用字符串Extrusion比较避开了swTnExtrusion常量未定义的问题。IsBaseExtrude用来确认选中的是基础拉伸不是后续的切除或薄壁拉伸。GetDepth(True)里的True表示正向深度SetDepth的第一个参数也要传同一个方向。ModifyDefinition返回False时先ReleaseSelectionAccess再退出不要直接丢掉 FeatureData。教程里提到特征出现“退回”状态时用Save和Rebuild兜底能自动更新但这只是兜底不是根治。生产脚本里要在修改后检查特征状态确认没有回退再继续下一个零件。4. 装配体自动化OpenDoc6、AddComponent4 与 AddMate2 的落地顺序装配体自动化比零件内改特征多一层上下文你操作的不是一个文档而是顶层装配体加若干组件。插入零部件用AddComponent4但教程特别提醒目标文件必须已经在内存里加载过否则函数会失败。这个限制不是可选项是 SolidWorks 的加载模型决定的。所以正确顺序是先OpenDoc6把零件读进内存再AddComponent4按配置插入最后用ClearSelection2、Select2、AddMate2做配合。4.1 AddComponent4 的前置条件文件必须先进内存AddComponent4的签名是compName, configName, x, y, z。compName是带路径的全名configName是配置名x/y/z是组件中心坐标。教程里直接传当前工作目录下的“零件1.SLDPRT”和“配置1”但 remark 里写得很清楚指定文件必须已经加载到内存或者当前装配体里已经包含该文件。没加载就直接调用返回值通常是Nothing。常见错法是只写一句Set swComp swAssy.AddComponent4(partPath, 配置1, 0, 0, 0)如果前面没有打开过partPath这句在不少环境里直接失败。正确做法是先OpenDoc6再把返回的ModelDoc2隐藏窗口保留在内存里。4.2 OpenDoc6 打开零件并隐藏窗口的完整封装OpenDoc6的参数依次是文件名、文档类型、打开选项、配置名、错误输出、警告输出。文档类型里 0 不是 SolidWorks 文件1 是零件2 是装配体3 是工程图。配置名传空时打开最后使用的配置传具体配置名时如果配置不存在也会回退到最后使用的配置。错误和警告用Long变量接调用后要判断。Private Function LoadPartToMemory(ByVal partPath As String, ByVal configName As String) As ModelDoc2 Dim errs As Long Dim warns As Long Dim swPart As ModelDoc2 类型 1零件打开选项按本机枚举填教程环境里静默打开常先用 0 试 Set swPart swApp.OpenDoc6(partPath, 1, swOpenDocOptions_Silent, configName, errs, warns) If errs 0 Then Debug.Print 打开零件出错 errs Set LoadPartToMemory Nothing Exit Function End If If warns 0 Then Debug.Print 打开零件警告 warns End If If Not swPart Is Nothing Then swPart.Visible False End If Set LoadPartToMemory swPart End Function Sub InsertPartIntoAssembly() Dim swAssy As ModelDoc2 Dim swPart As ModelDoc2 Dim swComp As Component2 Dim partPath As String Set swApp Application.SldWorks Set swAssy swApp.ActiveDoc If swAssy Is Nothing Then Exit Sub partPath swApp.GetCurrentWorkingDirectory 零件1.SLDPRT Set swPart LoadPartToMemory(partPath, 配置1) If swPart Is Nothing Then MsgBox 零件没有加载进内存先检查路径和配置名 Exit Sub End If Set swComp swAssy.AddComponent4(partPath, 配置1, 0, 0, 0) If swComp Is Nothing Then MsgBox 插入零部件失败 Exit Sub End If Debug.Print 已插入 swComp.Name2 End SubLoadPartToMemory把打开和隐藏封装在一起调用方只关心返回的ModelDoc2是否为空。swPart.Visible False只是隐藏文档窗口不会关闭文件也不会把零件从内存里卸载所以后面AddComponent4仍能拿到。路径拼接用GetCurrentWorkingDirectory只适合练习正式脚本建议用绝对路径或配置表避免工作目录切换后找不到文件。4.3 面选择与 AddMate2用 GetBody/GetFirstFace/GetNextFace 遍历配合的难点不在AddMate2本身而在选面。教程里说得很实在面的命名没有规律很多是程序自动命名的用SelectByID2按名字选面很不可靠用坐标选面更糟模型一改坐标全废。可行的做法是拿到组件的Body2用GetFirstFace和GetNextFace遍历所有面再按面积、法向、相邻边或索引挑目标面。Private Function PickFaceByIndex(ByVal swComp As Component2, ByVal idx As Long) As Face2 Dim swBody As Body2 Dim swFace As Face2 Dim i As Long Set swBody swComp.GetBody() If swBody Is Nothing Then Exit Function Set swFace swBody.GetFirstFace i 1 Do While Not swFace Is Nothing If i idx Then Set PickFaceByIndex swFace Exit Function End If Set swFace swFace.GetNextFace i i 1 Loop End Function Sub AddCoincidentMate(ByVal compA As Component2, ByVal compB As Component2) Dim swAssy As AssemblyDoc Dim swModel As ModelDoc2 Dim fA As Face2 Dim fB As Face2 Dim mateErr As Long Dim swMate As Mate2 Set swModel swApp.ActiveDoc Set swAssy swModel 配合前先清空选择避免旧选择混进 Mark 顺序 swModel.ClearSelection2 True Set fA PickFaceByIndex(compA, 1) Set fB PickFaceByIndex(compB, 1) If fA Is Nothing Or fB Is Nothing Then MsgBox 没有遍历到目标面 Exit Sub End If Mark 用来区分第一选择和第二选择AddMate2 会按顺序读 fA.Select2 True, 1 fB.Select2 True, 2 AddMate2 参数个数和枚举名随版本有差异先用本机类型库签名核对 Set swMate swAssy.AddMate2(swMateCOINCIDENT, swMateAlignCLOSEST, False, _ 0, 0, 0, 0, False, False, 0, 0, mateErr) If mateErr 0 Then Debug.Print 添加配合失败错误码 mateErr End If swModel.ClearSelection2 True End SubPickFaceByIndex是最小可用版本只按遍历顺序取第 N 个面。实际模型里面的顺序可能随重建变化所以更稳的筛选条件是面积区间、法向与坐标轴夹角、面中心到某点的距离或者先选边再取相邻面。Select2的第一个参数Append传True表示追加选择第二个参数Mark传 1 和 2让AddMate2知道谁是第一选择、谁是第二选择。AddMate2的参数多常见包括配合类型、对齐方式、翻转、距离、角度、错误码。不同版本枚举名可能对不上代码里用swMateCOINCIDENT、swMateAlignCLOSEST之前先在对象浏览器里确认本机类型库有没有这些常量。没有就查枚举值或者在模块顶部用Const定义本地常量别让编译错误卡住整个宏。5. 避坑与排查宏能跑和稳定跑之间差的那几行宏能跑一次不代表能交给别人用。录制宏带进来的视图代码、常量引用差异、装配体上下文、选择顺序都会让脚本在另一台机器上翻车。下面几条是这套教程里最容易踩的坑按“现象、原因、解决”拆开记排错时直接对照。5.1 宏编辑与类型判断的坑现象录制完直接运行就弹“对象变量或 With 块变量未设置”或者选中对象为空。原因录制宏把视图旋转、缩放、空白区点击也录进去了选择状态在运行中被这些动作打乱另外录制时选中的对象名称可能带临时后缀换一个模型就对不上。解决先删掉ActiveView().RotateAboutCenter这类视图代码再删掉紧挨着ClearSelection2之前的多余SelectByID2。运行前手动选中目标特征用GetSelectedObject5(1)取不要一上来就依赖名字。名字选择只放在“用户没选时”的兜底分支里。现象swDocPART、swDocASSEMBLY、swTnExtrusion这些常量报“变量未定义”。原因VBA 工程没有引用对应版本的 SolidWorks 类型库或者不同版本枚举名有差异教程环境里就出现过swDocPART不通过、swTnExtrusion不通过的情况。解决文档类型先用整数兜底1 是零件2 是装配体用MsgBox swModel.GetType确认后再写判断。特征类型用GetTypeName返回的字符串比较比如Extrusion比硬编码常量更抗版本差异。确实要用枚举时打开对象浏览器搜swSelectType_e、swDocumentTypes_e按本机签名补。现象Option Explicit打开后swSelectOptionDefault编译不通过。原因这个枚举在当前引用里不可见或者拼写与版本不一致。解决教程里的做法是先用 0 代替最后一个选择选项把主流程跑通等确认选择行为正确再回对象浏览器找实际枚举值。不要因为一个选择选项卡住整段逻辑先把选择结果打印出来看。5.2 特征访问与装配体插入的坑现象ModifyDefinition返回True但模型界面没变化或者特征树出现退回状态。原因FeatureData 写回后没有重建或者AccessSelections没有释放下一次访问拿到旧状态也可能是特征本身处于回退状态修改被挂起。解决修改成功后调用EditRebuild和Save让模型刷新。失败分支里先ReleaseSelectionAccess再退出。教程里用Save加Rebuild兜底能自动更新但正式脚本要检查ModifyDefinition返回值并在重建后确认特征没有退回。现象AddComponent4返回Nothing或者插入后装配体里看不到零件。原因目标零件没有先加载进内存compName不是全路径configName写错文件被其他进程占用。解决先OpenDoc6打开零件检查errs和warns再把Visible设为False保留在内存。路径用绝对路径或GetCurrentWorkingDirectory拼全名配置名从零件配置列表里取不要手写猜测。插入失败时打印AddComponent4返回值是否为空再回看打开阶段的错误码。现象用SelectByID2选面总是失败或者选到别的面。原因面的名称由程序自动生成没有稳定规律坐标选择在模型尺寸变化后失效。解决拿到组件的Body2用GetFirstFace、GetNextFace遍历按面积、法向、相邻边筛选。选面时用Select2设置Append和Mark配合前先ClearSelection2配合后再清一次。索引选择只适合练习正式脚本要把筛选条件写成可配置规则。6. 二次开发改造把一次性宏拆成选择层、数据层和回滚层宏写顺之后下一步不是马上堆功能而是把一次性脚本拆成四层选择层负责拿到特征或面数据层负责GetDefinition和AccessSelections执行层负责SetDepth、ModifyDefinition、AddComponent4回滚层负责失败时释放选择和恢复状态。这样拆完同一个选择函数可以给读孔深、改拉伸、加配合三处复用排错时也能直接判断是哪一层返回了空值。层职责改造点选择层按当前选择或名称拿到对象统一空选择分支返回Boolean数据层取 FeatureData 并申请访问权成对调用AccessSelections和ReleaseSelectionAccess执行层改参数、插零件、加配合每个 API 检查返回值不吞错误回滚层失败后清选择、重建、保存先释放访问权再决定是否重建验证方法我一般按三条路径跑第一条空选择什么都不选直接运行看是否给出提示而不是报错第二条错误类型选一个不是拉伸的特征去跑改拉伸看本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?