尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

SolidWorks二次开发实战:用Python将宏录制改造成批量自动化脚本

发布时间:2026/9/29 1:54:49

资讯中心
01
ARTICLE

SolidWorks二次开发实战:用Python将宏录制改造成批量自动化脚本

SolidWorks二次开发实战:用Python将宏录制改造成批量自动化脚本
做SolidWorks二次开发最典型的场景就是模型画好了但后面的活全是重复劳动改属性、导格式、出BOM。录个宏能省一次两次的事可当任务量变成几十个文件、上百个模型时宏那种“记录操作”的思路就走不通了。于是越来越多的人把目光转向Python——语法简单、生态丰富而且通过COM接口可以直接驱动SolidWorks的API。这篇文章就是我的一次完整实战记录从最基础的宏录制开始把它一步步改造成真正的自动化脚本中间会讲清楚选型理由、API转换的关键概念、批量任务落地的代码结构以及那些只有真正跑过才会踩的坑。适合已经会用SolidWorks、想用Python做批量处理的工程师也适合完全没接触过API的初学者当作第一份入门材料。1. 为什么绕开VBA最终选择了Python做二次开发1.1 宏录制的本质一份操作录像宏录制是SolidWorks二次开发最友好的入口这一点没有争议。你在模型上做的每一步操作SolidWorks都会翻译成对应的VBA指令保存成.swp宏文件。比如你插入一个自定义属性宏里就会多出一段CustomInfoManager相关的调用。我第一次录完宏打开代码编辑器第一反应是这哪是什么神秘代码根本就是SolidWorks给我写的学习笔记。但宏也有天花板。它记录的是一个有固定顺序的操作序列没有循环没有条件判断没有异常处理。录制3个模型的操作需要跑3遍录制100个模型也不会有任何改变。真正面对批量需求时宏只能作为“参照脚本”而不是“自动化方案”。所以我的建议是不要试图用宏本身解决批量问题而要把宏当成一份API用料清单。看它调用了哪些方法、传了哪些参数、操作顺序是什么然后用真正的编程语言把它重写出来。这一步思路转过来之后后面的路就顺了。1.2 为什么用Python而不是继续写VBA用过一段时间VBA的人多少会有这种感觉小功能跑得爽一旦复杂度上来就变难受。首先VBA没有真正顺手的包管理代码分散在一个个宏文件里版本对比和多人在线协作都很麻烦。其次VBA的调试能力偏弱尤其是当你需要处理网络请求、数据库读写、长时间批量任务时错误处理和日志记录都不太够用。Python在这个场景下的优势很直接通过pywin32访问COM接口调用的还是同一套SolidWorks API只是“遥控器”换了有pandas做BOM/属性表格处理有requests对接Web接口有schedule做定时任务代码可以放Git管理可以做单元测试可以打包成exe给别人用不用装Python环境把核心逻辑封装成库之后换项目、换人接手都容易得多用一句话总结VBA是SolidWorks自带的遥控器Python是你自己组装的遥控器按钮更多、可编程性更强但前提是你得知道它按的是同一个电视盒。1.3 选型时先想清楚的问题不是所有场景都适合切Python。如果你只是偶尔录个宏处理单个文件VBA完全够用没必要引入额外依赖。但当你出现下面这些信号时就值得认真考虑Python需要遍历多个文件夹、多类文档做批量操作需要与PLM、ERP、MES或者数据库做数据交换希望脚本能被计划任务或Jenkins在无人值守的环境下运行希望脚本逻辑可以被测试、被维护、被他人接手选型没有标准答案关键看你的自动化需求到底是“录一次用一次”还是“录一次用一百次”。后者才是Python真正发挥价值的舞台。2. 从宏录制到能跑通的Python脚本最小路径2.1 用宏录制一段真实操作空谈概念没用先录一段最实的宏。假设需求是在当前打开的零件文档里添加一个名为“设计者”的自定义属性值为“RD Team”。操作步骤很简单打开任意一个SolidWorks零件文件顶部菜单工具 → 宏 → 录制执行操作文件 → 属性 → 自定义新增一行属性名称填“设计者”类型选“文字”数值填“RD Team”确定菜单工具 → 宏 → 停止保存宏文件比如命名 add_prop.swp录制完成后在宏工具栏点“编辑”按钮就能看到这段操作对应的VBA源码。这就是后面所有工作的出发点。很多人第一次看到宏编辑器里的代码会觉得陌生其实不用怕它的结构比想象中规整得多。2.2 录制出来的宏代码长什么样我在实际录制中得到的代码大致长这样Dim swApp As SldWorks.SldWorks Dim swModel As SldWorks.ModelDoc2 Dim swCustPropMgr As SldWorks.CustomPropertyManager Set swApp Application.SldWorks Set swModel swApp.ActiveDoc Set swCustPropMgr swModel.Extension.CustomPropertyManager() swCustPropMgr.Add2 设计者, swCustomInfoText, RD Team这段代码信息量很大它暴露了三个核心APIApplication.SldWorks拿到SolidWorks应用对象这是所有API调用的根ActiveDoc拿到当前活动文档对象相当于模型在内存中的入口Extension.CustomPropertyManager()获得文档的自定义属性管理器第二个参数为空表示操作的是整个文档而不是某个配置Add2 设计者, swCustomInfoText, RD Team添加自定义属性第一个参数是属性名第二个参数是属性类型枚举第三个是属性值注意宏代码里swCustomInfoText是枚举常量不是字符串。字符串本来就是值但这三个里哪个是枚举、哪个是字符串不查文档很容易搞混。在我印象里当时一开始就把类型参数写成了文字结果API跑不通折腾了好久才反应过来。2.3 在Python里把这段宏复制出来要在Python里驱动SolidWorks先装好COM支持库pip install pywin32然后写一个最小脚本import win32com.client as win32 # 连接已经打开的SolidWorks没开就用DispatchEx新起一个 try: sw_app win32.Dispatch(SldWorks.Application) except Exception: sw_app win32.DispatchEx(SldWorks.Application) sw_app.Visible True sw_model sw_app.ActiveDoc if sw_model is None: raise RuntimeError(当前没有打开的模型文件) sw_ext sw_model.Extension cust_prop_mgr sw_ext.CustomPropertyManager() # swCustomInfoText 枚举值在SolidWorks里是30 cust_prop_mgr.Add2(设计者, 30, RD Team) print(属性添加完成)这里有个关键点VBA代码里的swCustomInfoText是枚举常量Python里不能直接用需要查它的数值。在SolidWorks API文档里swCustomInfoText对应的值是30。这类枚举值我一般直接在项目里定义成常量避免到处写魔法数字。这个脚本跑通后你可以继续扩展改材质、改颜色、设置质量属性都可以用同样的套路。2.4 VBA转Python的固定套路跑通第一个脚本后总结一下VBA到Python翻译的规律后面所有宏都可以照这个思路处理Set xxx yyy在Python里就是普通赋值xxx yyy枚举常量要先查值再定义成Python常量或直接传数值COM方法返回值直接接收不用预先声明变量类型布尔参数用True/False不要写0/-1用完的COM对象可以del必要时用pythoncom做释放这一套流程熟练之后一个宏从录制到跑成Python脚本基本可以在十分钟内完成。但如果你只停留在“翻译宏”的阶段还谈不上二次开发只是换了个语言重复同样的事。要真正做自动化必须理解宏背后的API逻辑这就是下一章要讲的内容。3. 宏代码背后的API逻辑不搞懂这些转换必出错3.1 对象关系从SldWorks到ModelDoc到FeatureSolidWorks API是一棵对象树根节点是SldWorks也就是正在运行的SolidWorks程序。从它往下ActiveDoc拿到当前模型文档OpenDoc6按路径打开文档。文档下面是各类管理器FeatureManager管特征SelectionManager管选中项CustomPropertyManager管自定义属性ConfigurationManager管配置。这么设计的原因很好理解SolidWorks本身把模型拆成“文档—特征—几何—属性”几个层次API也尽量一一对应。你在模型树里看到的一个特征、一个草图基本都能在FeatureManager的Feature遍历里找到。理解了对象树你就知道很多宏为什么“录得出来却改不了”——因为你录到的操作可能用了界面上的选中状态而脚本环境里没有“光标”这个概念。这是从录制宏到写自动化脚本最关键的一个思维转变。3.2 参数转换里最容易翻车的三类情况第一类是枚举常量。VBA能直接用名字因为VB编辑器自带类型库Python没有。我处理这个问题的方法是在项目里建一个模块专门定义枚举比如swCustomInfoText 30 swCustomInfoDate 31 swDocPART 0 swDocASSEMBLY 2 swDocDRAWING 1写的时候查一次API文档之后其他人接手也不用再去翻。第二类是输出参数。COM接口里不少方法用ByRef传输出的值比如读取模型质量属性时VBA里要先声明一个vMass再调用GetMassProperties把它填上。Python直接接收返回值就行但要注意返回的数组下标。SolidWorks的COM接口很多是从1开始计数和Python习惯的0开始完全相反循环取数时极其容易踩坑。我建议每拿到一个数组先打印看一遍再写业务逻辑。第三类是布尔和整数精度的坑。前面提过SolidWorks的VARIANT_BOOL在原生COM层面True是-1某些API实现里对参数值敏感传True和传1可能表现不同。遇到诡异问题先试试传-1。这种问题初看很莫名其妙但确实是COM世界里特有的历史包袱理解它就不用慌。3.3 单位和选中状态两个隐形大坑单位问题经典案例。SolidWorks默认模板是MMGS毫米、克、秒但很多外资公司用IP英寸、磅、秒模板。如果你的脚本从API里直接读尺寸数值不做单位转换那同一套逻辑在不同模板下结果完全不同。我的处理方式是在脚本开头检查文档单位units sw_model.GetUnits() # 0mm, 1cm, 2m, 3in, 4ft, 5um然后定义一个换算因子统一转成毫米再参与计算。别问为什么这么谨慎问就是处理过一个“50mm零件读出来是1.97”的诡异bug折腾了半天才发现是英寸模板。另一个坑是选中状态依赖。宏录制经常记录用户“选中了某个面/特征”再执行操作比如删除面、加厚、测量。到自动化的场景里没有用户在界面上点击SelectionManager.GetSelectedObject基本拿不到东西。必须改成程序化遍历在FeatureManager里用GetFirstFeature/GetNextFeature循环找目标特征或者用名称搜索。这一步是从“录制”升华到“编程”的真正门槛。4. 自动化脚本的工程化批量导出与属性同步落地4.1 典型需求假设你手头有个文件夹里面几十个三维零件和装配体领导要你把它们全部导出成STEP文件再把每个模型的自定义属性物料号、版本、设计者汇总成一张Excel表格。这种需求在传统流程里意味着至少半天的重复手工劳动用Python脚本基本可以做到“一键跑完”。处理思路很简单把第二章“单个模型操作”的流程套进一个遍历文件夹的循环。核心动作三件打开文档、导出格式、关闭文档。4.2 代码结构怎么设计才不容易崩我写的首版脚本结构大概是这样的import os import glob import win32com.client as win32 import pythoncom def connect_solidworks(): pythoncom.CoInitialize() try: app win32.Dispatch(SldWorks.Application) except Exception: app win32.DispatchEx(SldWorks.Application) app.Visible True return app def export_step(app, src_path, dst_path): model app.OpenDoc6(src_path, 0, 1, , 0, 0) if not model: raise RuntimeError(f打开失败: {src_path}) # 第三个参数24是STEP格式 app.ActiveDoc.SaveAs3(dst_path, 0, 24) app.CloseDoc(model.GetTitle()) def main(): app connect_solidworks() src_dir rD:\models dst_dir rD:\export_step os.makedirs(dst_dir, exist_okTrue) stat [] for src_path in glob.glob(os.path.join(src_dir, *.SLDPRT)): dst_path os.path.join(dst_dir, os.path.basename(src_path).replace(.SLDPRT, .STEP)) try: export_step(app, src_path, dst_path) stat.append((os.path.basename(src_path), OK)) except Exception as e: stat.append((os.path.basename(src_path), str(e))) for row in stat: print(row) if __name__ __main__: main()这段代码能跑但有几个设计上的习惯很重要第一连接SolidWorks实例只做一次不要放在循环里。每次Dispatch都挺耗时而且容易创建多个SolidWorks进程。第二每个文件单独被try/except包围。批量任务里出现一个坏文件很正常但如果异常没有捕获整个脚本会在中途挂掉前面的工作白做。第三处理完立刻CloseDoc。SolidWorks跑久了内存会涨尤其是大装配体不关文档很快就卡死。第四OpenDoc6的第二个参数是文档类型枚举0代表零件2代表装配体1代表工程图。如果文件名后缀判断不靠谱应该先根据扩展名映射类型。4.3 属性汇总到Excel写属性汇总其实更简单。读取自定义属性用的是CustomPropertyManager.Get之类的接口把所有属性名和值取出来塞进pandas的DataFrame最后to_excel。前提是先装好pandas和openpyxlpip install pandas openpyxl示例代码片段import pandas as pd from pathlib import Path def get_props(app, src_path): model app.OpenDoc6(src_path, 0, 1, , 0, 0) if not model: return {} cm model.Extension.CustomPropertyManager() props {} for key in [物料号, 版本, 设计者, 备注]: props[key] cm.Get(key) app.CloseDoc(model.GetTitle()) return props rows [] for p in Path(rD:\models).glob(*.SLDPRT): rows.append({file: p.name, **get_props(app, str(p))}) df pd.DataFrame(rows) df.to_excel(bom.xlsx, indexFalse)实际开发中注意不同模型的属性名不一定一致直接用字典展开到DataFrame时缺失的列会自动填NaN这正是我们想要的效果。如果还想兼容不同版本API里Get返回值的差异建议加一行调试打印确认返回结构再正式跑全量。4.4 进一步扩展命令行参数与定时任务脚本写得再顺手也不可能一直用IDE跑。把它改造成带命令行入口的工具是自动化真正落地的一步import argparse parser argparse.ArgumentParser(descriptionSolidWorks批量导出工具) parser.add_argument(--source, requiredTrue, help源文件夹) parser.add_argument(--output, requiredTrue, help输出文件夹) parser.add_argument(--type, choices[STEP, PDF, X_T], defaultSTEP) args parser.parse_args()加了这层壳之后Windows的任务计划程序、Jenkins流水线、甚至其他程序都能直接调用它。我在实际项目中还接过一个简单的HTTP接口让业务部门的同事在网页上点一个按钮就能触发批量任务Python处理这部分非常方便。5. 实战中踩过的坑与性能调优建议5.1 后台模式与COM线程相爱相杀SolidWorks本身是STA单线程套间模型COM对象的生命周期绑定创建它的线程。用pywin32写多线程脚本时如果子线程直接操作SolidWorks的COM接口轻则调用失败重则整个进程假死。网上有很多“为什么Python多线程调用SolidWorks会卡死”的讨论根因基本都是这个。我的解决原则很简单不用多线程用多进程。每个进程单独启动一个SolidWorks实例各自处理一批文件。这样虽然内存开销变大但稳定性好得多。我实测过三进程并行处理三批模型速度几乎可以线性提升代价是内存占用会涨到2-3GB机器要有心理准备。另外长时间运行的SolidWorks实例会有“疲劳”现象具体表现是反应越来越慢、偶尔无响应。遇到这种情况与其反复救它不如在脚本里加一个“工间操”机制——每处理完N个文件就主动重启一次SolidWorks实例看似粗暴实测能避免很多玄学问题。5.2 使命必达的路上最常见的三个意外第一个是文件锁定。脚本异常退出时SolidWorks还开着的模型下次再打开会提示文件已被占用。应对办法是在脚本开头增加“清理现场”的逻辑枚举当前已经打开的所有文档并关闭再开始新的任务。def close_all_docs(app): while app.DocumentCount 0: doc app.ActiveDoc if doc: app.CloseDoc(doc.GetTitle())第二个是许可证问题。如果你公司用的是网络浮动许可长时间占用会被系统判定为闲置并回收等脚本需要再次激活时就拿不到许可SolidWorks可能直接崩溃或弹错误框。稳妥的做法是控制单次任务时长或者给关键任务申请专用的固定许可。第三个是文件路径和名称的特殊字符。中文路径多数情况下能处理但偶发的编码异常很让人头疼。我建议在批量文件命名规范里就约定全英文同时在代码里用pathlib而不是字符串拼接管理路径能少掉很多莫名其妙的坑。5.3 性能优化按优先级排序很多初学者一上来就想着多进程并行其实大部分项目卡的不是并行而是单文件处理过程中的低效操作。优化优先级我总结成三步先把不必要的打开/关闭搞掉。如果同时要导出STEP和PDF在同一文档打开状态下连续调用两次SaveAs3远比打开两次文件要快。再考虑轻化模式。只读属性、读几何信息的场景用轻化打开文档OpenDoc6的flag参数里指定轻化加载能明显减少内存和重建计算速度提升很可观。最后才是多进程。而且多进程并行前先确认你的SolidWorks许可数量允许开多个实例否则反而会因为许可冲突变得更慢。优化手段适用场景提升幅度注意点复用已打开文档多次导出、连续读取明显控制内存及时关闭轻化模式加载只读属性/几何中到高部分操作不支持轻化多进程并行多文件夹大任务接近线性内存和许可数6. 把常用操作封装成类一个让后续开发变轻松的实操技巧写了几百行脚本之后我越来越意识到一件事SolidWorks的API用起来并不难但每次都写Dispatch、OpenDoc6、CloseDoc这一串样板代码既啰嗦又容易出错。我抽了个时间把这些常用操作收敛到了一个类里后续所有脚本都基于这个类扩展开发速度提升非常明显。import os import pythoncom import win32com.client as win32 class SolidWorksHelper: def __init__(self, visibleFalse): pythoncom.CoInitialize() try: self.app win32.Dispatch(SldWorks.Application) except Exception: self.app win32.DispatchEx(SldWorks.Application) self.app.Visible visible def open_model(self, file_path, doc_type0): model self.app.OpenDoc6(file_path, doc_type, 1, , 0, 0) if not model: raise RuntimeError(f无法打开: {file_path}) return model def get_custom_property_manager(self, model): return model.Extension.CustomPropertyManager() def set_custom_property(self, model, name, value, prop_type30): cm self.get_custom_property_manager(model) cm.Add2(name, prop_type, str(value)) def export_step(self, model, dst_path): self.app.ActiveDoc.SaveAs3(dst_path, 0, 24) def export_pdf(self, model, dst_path): self.app.ActiveDoc.SaveAs3(dst_path, 0, 18) def close_model(self, model): title model.GetTitle() self.app.CloseDoc(title) def close_all(self): while self.app.DocumentCount 0: doc self.app.ActiveDoc if doc: self.app.CloseDoc(doc.GetTitle())封装之后之前的批量导出代码可以简写成sw SolidWorksHelper(visibleFalse) for path in all_files: model sw.open_model(path) sw.set_custom_property(model, 批次, 2024-08) sw.export_step(model, path.replace(.SLDPRT, .STEP)) sw.close_model(model)读代码的人一眼就能看出来在干什么完全不用被COM的繁琐细节干扰。这个方法看起来很“土”但对于团队协作和维护来说价值比想象中的大得多。我在实际项目中这个类后来陆陆续续加了导出工程图、生成缩略图、读取自定义属性、查找特征等功能已经成了团队的“公共工具箱”。如果你准备系统性地做SolidWorks二次开发强烈建议前期先花半天时间把这类基础封装打好后面每写一个脚本都会感谢当初的自己。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。