🙋♀️本期工具展示
🔍 遇到的问题
做CAD设计的时候,经常需要在图纸里塞一堆计算表格,一个项目下来,少说也有十几个表格要处理。📊比如修改了一个梁的尺寸,可能要连带修改各个工程量表……每个表格都得重新算一遍、改一遍。手动点击、逐个修改,不仅耗时,还特别容易出错。💡 解决思路 1.0
既然在CAD里改表格这么痛苦,那就换个思路——在Excel里算!Excel有强大的计算功能,改一个参数,所有公式自动更新,多爽!算完后复制粘贴到CAD就行了。听起来很美好?实际用起来发现:复制粘贴也是个体力活!😭而且最恐怖的是:一旦设计有小改动,又得把所有表格重新粘贴一遍!牵一发而动全身,简直要疯掉。💡 解决思路 2.0(终极版)
既然手工粘贴这么累,那就让Python来干这个活!🤖核心目标:实现Excel设计表批量自动导入CAD,做到无感、自动、快速定位!📋 在Excel里配置好哪些表格要导入、导入到哪里01 界面设计
文件选择区- 选择包含设计表的Excel文件工作表配置区- 显示要导入的表格列表,可以勾选操作日志区- 实时显示处理进度和状态操作按钮区- 一键批量处理,预览数据等界面自动定位到屏幕右上角,不会挡住CAD视图,非常贴心。😊1. Excel配置表设计
为了适应不同项目的需求,我设计了一个**"CAD导入"配置表**,放在Excel文件里:A列:工作表名称(要导入哪个表)B列:起始列(从哪列开始复制)C列:终止列(复制到哪列)D列:定位块的B属性值(自动定位用)E列:目标宽度(粘贴后缩放到多宽)F列:X轴偏移(在块位置基础上偏移多少)G列:Y轴偏移
如果填了D~G列,就会自动定位;如果不填,就粘贴到原点,后续可以手动调整位置。这样配置一次,后面无论改多少次设计参数,都可以一键更新所有表格!🎉2. 自动定位的秘密
自动定位是怎么实现的呢?关键在于建立Excel表格和CAD块之间的对应关系。以我的CAD图纸里的图框作为定位块(块名统一叫tk-att),每个图框都有一个属性B,用来标识这是哪个表格的位置。def_build_block_b_to_insertion_cache(self,doc,block_name,required_b_values=None):"""一次扫描同名块构建 B->插入点 缓存"""cache={}ms=doc.ModelSpace遍历模型空间,找到所有定位块foriinrange(ms.Count):ent=ms.Item(i)ifgetattr(ent,"Name","")==block_name:读取块的B属性attrs=ent.GetAttributes()forattrinattrs:ifattr.TagString=="B":b_val=attr.TextString.strip()记录这个B值对应的插入点坐标p=ent.InsertionPointcache[b_val]=(p[0],p[1],p[2])breakreturncache
这样一来,程序就知道"光纤表"应该粘贴到坐标(1000, 2000), "电缆表"应该粘贴到(5000, 2000)……全自动!3. 缩放与定位
从Excel复制过来的表格,大小往往不合适。我实现了自动缩放到指定宽度的功能:def_move_and_scale_entities(self,doc,entities,placement,target_width):"""将实体缩放到目标宽度并移动到指定位置"""1. 计算当前表格的边界框min_x=min_y=1e99max_x=max_y=-1e99forentinentities:lo,hi=ent.GetBoundingBox()min_x=min(min_x,lo[0])max_x=max(max_x,hi[0])...2. 计算缩放比例current_width=max_x-min_xscale_factor=target_width/current_width3. 先移动到目标位置forentinentities:ent.Move(from_pt,to_pt)4. 再缩放到目标大小forentinentities:ent.ScaleEntity(base_pt,scale_factor)
这样粘贴过来的表格,自动就是合适的大小,不用再手工调整!4. 攻克ZWCAD的"点击地狱"
ZWCAD(中望CAD)在粘贴Excel表格时,每次都会弹出一个"OLE文字大小"对话框,需要手动点"确定"。如果要粘贴10个表格,就得点10次……完全做不到自动化!我的解决方案:启动一个后台线程,自动识别弹窗并点击确定!def_watch_and_close_ole_dialog():"""持续监听并自动关闭OLE对话框"""for_inrange(50):最多等待10秒try:获取前台窗口hwnd_fg=win32gui.GetForegroundWindow()title_fg=win32gui.GetWindowText(hwnd_fg)检测是否是OLE对话框if"OLE"intitle_fgor"文字大小"intitle_fg:发送回车键,相当于点击"确定"win32gui.PostMessage(hwnd_fg,win32con.WM_KEYDOWN,win32con.VK_RETURN,0)self.log("已自动确认OLE对话框")breakexcept:passtime.sleep(0.2)每0.2秒检测一次在粘贴前启动监听线程threading.Thread(target=_watch_and_close_ole_dialog,daemon=True).start()
虽然这是一种"假性顺利"(对话框还是会弹出来,只是被自动点掉了),但至少不需要人工干预了!整个批量粘贴过程可以自动完成。✨5. 性能优化:缓存机制
最初版本有个大问题:每粘贴一个表格,都要全图搜索一遍定位块!我的图纸里有1400多个tk-att块,每次搜索都要遍历一遍,一个表格就要9秒……10个表格就是90秒,太慢了!😱优化思路:第一次搜索时建立缓存,后续表格直接查表!批量处理开始时初始化缓存self._block_placement_cache=Nonedef_paste_to_cad_auto(self,sheet_name,config):第一个表格:搜索并建立缓存(耗时9秒)ifself._block_placement_cacheisNone:self._block_placement_cache=self._build_block_b_to_insertion_cache(doc,"tk-att")后续表格:直接查缓存(耗时<0.01秒)block_pt=self._block_placement_cache.get(config['block_attr_b'])
优化效果:第一个表格9秒,后续每个表格<0.01秒!10个表格从90秒降到了10秒左右,快了9倍!🚀6. 批量处理流程
defbatch_copy_process(self):"""批量复制处理"""1. 打开Excel文件excel=win32com.client.Dispatch("Excel.Application")workbook=excel.Workbooks.Open(excel_file)2. 初始化块缓存(只做一次)self._block_placement_cache=None3. 遍历每个选中的工作表forsheet_nameinself.selected_sheets:3.1 在Excel中选中并复制数据sheet=workbook.Worksheets(sheet_name)range_str=f"{start_col}{first_row}:{end_col}{last_row}"sheet.Range(range_str).Copy()3.2 粘贴到CAD并自动定位ifconfig.get('block_attr_b'):有配置自动定位self._paste_to_cad_auto(sheet_name,config)else:无配置则粘贴到原点self._cad_paste_at_origin(doc)self.log(f"✓{sheet_name}完成")
本来想用CAD的选择集过滤器,只选中特定块名的块,避免遍历全图。但不知道为什么,ZWCAD的过滤器总是不生效……尝试了各种写法:尝试1:基础过滤(不生效)filter_type=[0,2]实体类型、块名filter_data=["INSERT",block_name]selection.Select(1,filter_type,filter_data)尝试2:VT_I4变体(不生效)ft_i4=VARIANT(pythoncom.VT_ARRAY|pythoncom.VT_I4,[0,2])fd_v=VARIANT(pythoncom.VT_ARRAY|pythoncom.VT_VARIANT,["INSERT",block_name])尝试3:AND操作符(还是不生效)filter_type_and=[-4,0,2,-4]filter_data_and=[","INSERT",block_name,"AND>"]
最后只能回退到遍历+过滤的方式。如果有大佬知道ZWCAD选择集过滤的正确姿势,欢迎留言指教!🙏虽然实现了自动点击,但检测对话框有0.2秒的轮询间隔,偶尔会有一点点卡顿感。04 总结
通过这个工具,终于可以:在Excel里改设计参数,点一下按钮,所有CAD图纸里的表格自动更新!🎊开始过年!🚀
🙋♀️ 作者:leilei
💫 碎碎念学习记录
📅 更新时间:2026年2月14日