VBA宏总崩溃?Python脚本老闪退?这招让你的代码从此“抗摔”!
off999 2025-09-01 11:26 35 浏览 0 评论
导语:
上周有个读者急吼吼地私信我:“老师,我写了个VBA宏整理半年数据,结果跑到第800行的时候弹出个Error 1004,前功尽弃!有没有办法让宏‘抗摔’?”还有位Python新手更崩溃:“明明写了检查空值的代码,结果因为一个单元格是文本格式,整个脚本直接闪退,半小时白干……”
别慌!这不是你技术菜,而是没掌握编程圈的“保命神技”——错误处理。今天第五讲,我用20年编程经验总结的“防崩指南”,手把手教你让VBA和Python代码从“玻璃心”变“金刚不坏”,从此告别“改不完的bug,流不完的眼泪”!
第五讲:错误处理——让代码“稳如老狗”的终极法则
程序员圈有句扎心真相:“完美的代码不存在,但能优雅处理错误的代码才专业。” 无论是VBA还是Python,错误处理不是“加分项”,而是“生存线”。它能让你在用户骂“这破程序又崩了”时,淡定地说:“我早料到了。”
第一部分:VBA——用“安全网”兜住所有意外
VBA的错误处理逻辑像极了“老司机的应急反应”:预判可能翻车的点,提前铺好安全网,出事了就顺着网爬回安全区。 它的核心工具是On Error语句,这是VBA程序员的“保命符”。
1. 必杀技:On Error GoTo——精准跳转错误处理区
这是VBA最经典的错误捕获模式,相当于给代码装了个“GPS导航”:主逻辑跑着跑着出错了?立刻跳转到指定标签的“急救站”处理。
Sub 批量计算佣金()
' 1. 启动“安全模式”:一旦出错,跳转到ErrorHandler标签
On Error GoTo ErrorHandler
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("数据源") ' 可能出错点1:工作表不存在
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row ' 可能出错点2:A列全空
Dim i As Long, sales As Double, commission As Double
For i = 2 To lastRow
sales = ws.Cells(i, "A").Value
If sales < 0 Then
Err.Raise vbObjectError + 999, , "销售额不能为负!" ' 主动抛错(自定义错误)
End If
commission = sales * 0.1 ' 可能出错点3:sales是文本格式(类型错误)
ws.Cells(i, "B").Value = commission
Next i
MsgBox "计算完成!", vbInformation
Exit Sub ' 正常结束,跳过错误处理区
' 2. 错误处理区(急救站)
ErrorHandler:
' 显示具体错误信息(错误号+描述+来源)
MsgBox "错误号:" & Err.Number & vbCrLf & _
"错误原因:" & Err.Description & vbCrLf & _
"错误来源:" & Err.Source, vbCritical, "程序异常"
' 可选操作:记录错误日志(写入文本文件)
Open ThisWorkbook.Path & "\错误日志.txt" For Append As #1
Print #1, "[" & Now() & "] 错误号:" & Err.Number & ";描述:" & Err.Description
Close #1
' 清除错误状态,避免影响后续代码
Err.Clear
End Sub
这段代码能处理哪些崩溃?
- 如果“数据源”工作表被删除,触发错误号9:下标越界,跳转到处理区并记录日志;
- 如果A列全是空值,lastRow会是1,循环从2到1不执行,但不会报错;
- 如果A列有文本(如“无效数据”),sales = ws.Cells(i, "A").Value会触发错误号13:类型不匹配,同样被捕获;
- 主动用Err.Raise抛出的自定义错误(如销售额为负),也会被精准捕获。
2. 进阶技巧:On Error Resume Next——小心使用的“免死金牌”
这条语句的意思是:“出错了?别管,继续执行下一句。” 它适合处理“无关痛痒”的小错误(比如删除一个不存在的文件),但新手慎用——用不好会让程序“带病运行”,埋下更大隐患。
Sub 清理临时文件()
On Error Resume Next ' 开启“免死金牌”
Kill "C:\Temp\old_report.xlsx" ' 文件不存在?忽略错误
Kill "D:\Backup\temp.xls" ' 路径错误?也忽略
On Error GoTo 0 ' 关闭“免死金牌”,恢复严格错误提示
MsgBox "临时文件清理完成(可能有遗漏)", vbInformation
End Sub
VBA错误处理哲学: 像老司机开车——提前检查路况(预判错误点),出事故立刻靠边停车(跳转处理区),修好后继续上路(清除错误状态)。
第二部分:Python——用“精密陷阱”捕获所有异常
Python的错误处理更像“工程师设计精密仪器”:提前预判所有可能的故障点,为每种故障定制“专属陷阱”,程序跑着跑着出错了?陷阱自动触发,稳稳接住! 它的核心是
try...except...else...finally结构,这是Python程序员的“防崩秘籍”。
1. 四大利器:
try...except...else...finally
- try:放可能出错的“危险代码”;
- except:针对不同错误类型(如除零、文件不存在)定制陷阱;
- else:如果try里的代码没出错,执行这里的“成功逻辑”;
- finally:无论是否出错,最后一定要执行的“收尾动作”(如关闭文件、释放资源)。
import xlwings as xw
import logging # 导入日志模块,专业记录错误
# 配置日志:将错误写入文件(比弹窗更专业)
logging.basicConfig(filename='error.log', level=logging.ERROR,
format='%(asctime)s - %(levelname)s - %(message)s')
def 计算佣金(sales):
try:
# 危险操作1:读取Excel单元格(可能为空、非数值)
if sales < 0:
raise ValueError("销售额不能为负数!") # 主动抛自定义异常
return sales * 0.1
except ZeroDivisionError:
logging.error("除零错误:销售额为0,无法计算佣金")
return 0
except TypeError as e:
logging.error(f"类型错误:输入应为数值,实际是{type(sales)},错误详情:{e}")
return None
except ValueError as e:
logging.error(f"自定义错误:{e}")
return None
except Exception as e: # 兜底陷阱,捕获所有未预期的错误
logging.error(f"未知错误:{e}", exc_info=True) # 记录完整堆栈信息
return None
else:
logging.info("佣金计算成功") # 仅当无错误时执行
finally:
print("佣金计算流程结束(无论成功与否)") # 必执行的收尾动作
# 主程序:循环处理数据
def 批量处理():
try:
wb = xw.books.open("销售数据.xlsx") # 危险操作2:打开不存在的文件
sheet = wb.sheets["数据"]
last_row = sheet.range("A" + str(sheet.cells.last_cell.row)).end("up").row
for row in range(2, last_row + 1):
sales = sheet.range(f"A{row}").value
commission = 计算佣金(sales)
sheet.range(f"B{row}").value = commission
except FileNotFoundError:
logging.critical("文件未找到:请检查'sales数据.xlsx'路径是否正确")
except PermissionError:
logging.critical("权限不足:请关闭Excel文件后重试")
except Exception as e:
logging.critical(f"批量处理失败:{e}", exc_info=True)
finally:
try:
wb.close() # 无论是否出错,尝试关闭工作簿
except:
pass # 如果wb未成功打开,忽略此错误
批量处理()
这段代码有多“抗造”?
- 文件不存在?触发FileNotFoundError,记录日志并提示;
- 权限不足?触发PermissionError,避免程序崩溃;
- 销售额是文本?触发TypeError,记录类型错误详情;
- 销售额为负?触发自定义ValueError,明确提示原因;
- 所有操作结束后,无论成功与否,finally都会尝试关闭工作簿,防止资源泄露。
2. 高手进阶:自定义异常类——让错误“更懂你”
Python允许你自定义异常类型,让错误信息更贴合业务场景。比如电商系统中,定义库存不足异常、支付超时异常,代码会更清晰。
class 库存不足异常(Exception):
"""当商品库存小于订单数量时抛出的异常"""
def __init__(self, 商品名称, 当前库存, 订单数量):
self.商品名称 = 商品名称
self.当前库存 = 当前库存
self.订单数量 = 订单数量
super().__init__(f"{商品名称}库存不足!当前库存{当前库存},订单需要{订单数量}")
# 使用自定义异常
def 下单(商品名称, 当前库存, 订单数量):
if 订单数量 > 当前库存:
raise 库存不足异常(商品名称, 当前库存, 订单数量)
print("下单成功!")
# 测试
try:
下单("手机", 10, 15)
except 库存不足异常 as e:
print(f"下单失败:{e}") # 输出:下单失败:手机库存不足!当前库存10,订单需要15
Python错误处理哲学: 像工程师设计电路——每个可能的故障点都有对应的保险丝(except),主电路(try)负责正常工作,保险丝熔断(捕获错误)时启动备用方案(处理逻辑),最后无论是否熔断都要切断总电源(finally)。
核心实战:用错误处理“复活”崩溃脚本
场景: 你需要写一个脚本,从Excel读取员工绩效分,计算奖金(绩效分×1000),并将结果写入新工作表。但实际数据中可能存在:
- 绩效分是文本(如“优秀”);
- 绩效分超过100(系统限制最高100);
- 目标工作表已存在(需先删除旧表)。
VBA“防崩版”解法:
Sub 生成奖金表()
On Error GoTo ErrorHandler
Dim wsSource As Worksheet, wsTarget As Worksheet
Set wsSource = ThisWorkbook.Sheets("绩效数据")
Dim lastRow As Long: lastRow = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row
' 检查目标表是否存在,存在则删除(可能出错点:工作表被保护)
On Error Resume Next
Application.DisplayAlerts = False ' 关闭删除确认弹窗
ThisWorkbook.Sheets("奖金表").Delete
Application.DisplayAlerts = True
On Error GoTo ErrorHandler
' 创建新目标表
Set wsTarget = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
wsTarget.Name = "奖金表"
wsTarget.Range("A1:B1").Value = Array("姓名", "奖金")
' 计算奖金
For i = 2 To lastRow
Dim 姓名 As String, 绩效分 As Double, 奖金 As Double
姓名 = wsSource.Cells(i, "A").Value
绩效分 = wsSource.Cells(i, "B").Value
' 检查绩效分是否为数值
If Not IsNumeric(绩效分) Then
Err.Raise vbObjectError + 100, , "绩效分必须为数值!"
End If
' 检查绩效分是否超上限
If 绩效分 > 100 Then
Err.Raise vbObjectError + 101, , "绩效分不能超过100!"
End If
奖金 = 绩效分 * 1000
wsTarget.Cells(i, "A").Value = 姓名
wsTarget.Cells(i, "B").Value = 奖金
Next i
MsgBox "奖金表生成成功!", vbInformation
Exit Sub
ErrorHandler:
MsgBox "错误:" & Err.Description & vbCrLf & "请联系管理员。", vbCritical
' 记录日志(同上,此处省略)
Err.Clear
End Sub
Python“防崩版”解法:
import xlwings as xw
import logging
logging.basicConfig(filename='奖金表错误.log', level=logging.ERROR)
def 生成奖金表():
try:
wb = xw.books.open("绩效数据.xlsx")
ws_source = wb.sheets["绩效数据"]
last_row = ws_source.range("A" + str(ws_source.cells.last_cell.row)).end("up").row
# 删除已存在的奖金表(可能出错点:表被保护/不存在)
try:
wb.sheets["奖金表"].delete()
except:
pass # 表不存在时忽略
# 创建新奖金表
ws_target = wb.sheets.add("奖金表")
ws_target.range("A1:B1").value = ["姓名", "奖金"]
# 计算奖金
for row in range(2, last_row + 1):
姓名 = ws_source.range(f"A{row}").value
绩效分 = ws_source.range(f"B{row}").value
# 检查绩效分是否为数值
if not isinstance(绩效分, (int, float)):
raise TypeError(f"第{row}行绩效分非数值:{绩效分}")
# 检查绩效分是否超上限
if 绩效分 > 100:
raise ValueError(f"第{row}行绩效分超上限:{绩效分}")
ws_target.range(f"A{row}").value = 姓名
ws_target.range(f"B{row}").value = 绩效分 * 1000
wb.save("奖金表.xlsx")
wb.close()
print("奖金表生成成功!")
except FileNotFoundError:
logging.error("绩效数据.xlsx未找到,请检查路径")
except PermissionError:
logging.error("文件被占用,请关闭后重试")
except (TypeError, ValueError) as e:
logging.error(f"数据错误:{e}")
except Exception as e:
logging.error(f"未知错误:{e}", exc_info=True)
finally:
try:
wb.close() # 确保关闭工作簿
except:
pass
生成奖金表()
终极对比:VBA与Python的错误处理谁更强?
特性 | VBA | Python |
错误捕获方式 | On Error GoTo跳转 | try...except精准捕获 |
错误类型支持 | 仅内置错误号(如Error 1004) | 支持自定义异常类,类型更灵活 |
日志记录 | 需手动写文件(麻烦) | 内置logging模块(专业) |
代码可读性 | 错误处理与业务逻辑混杂(易乱) | 异常块独立(结构清晰) |
适用场景 | 小范围、单一功能的Excel宏 | 复杂系统、需要多人协作的脚本 |
比喻 | 老司机的“应急工具箱” | 工程师的“精密故障排查系统” |
千万别学Excel结语:错误处理,是程序员的“职业尊严”
从今天起,请记住:
- 写VBA时,每个Sub和Function的第一行都加上On Error GoTo,别让崩溃成为习惯;
- 写Python时,每个try块都明确列出可能出现的异常类型,别让“万能except”毁了代码的可维护性;
- 无论用什么语言,日志记录都是你的“后悔药”——出错了没关系,但至少要知道怎么错的。
最后送你一句话: 用户不会因为你处理了错误而夸你,但一定会因为你没处理错误而骂你。而专业的程序员,连“被骂的机会”都不给自己。
互动话题: 你在写代码时遇到过最离谱的崩溃是什么?是因为单元格格式错了?还是文件被同事误删了?在评论区分享你的“血泪史”!
Excel #Python #VBA #错误处理 #编程技巧 #办公自动化 #代码健壮性
【测试题】3道题测测你的错误处理水平
- VBA中,用于跳转到错误处理代码块的关键字是? A. On Error Resume Next B. On Error GoTo C. Exit Sub D. Err.Clear
- Python中,若要捕获“文件未找到”错误,应使用哪个异常类? A. TypeError B. ValueError C. FileNotFoundError D. ZeroDivisionError
- 以下哪项是错误处理的核心目的? A. 让代码永远不报错 B. 让程序崩溃时更美观 C. 在出错时优雅应对,减少损失 D. 提高代码运行速度
【答案】
- B(On Error GoTo用于跳转到错误处理标签)
- C(FileNotFoundError专门捕获文件未找到错误)
- C(错误处理的目的是在出错时减少损失,而非完全避免错误)
欢迎关注:千万别学excel,这里有数千篇excel相关视频和文章,带你玩转excel!祝你早日升任CEO,迎娶白富美,走上人生巅峰~( ̄▽ ̄~)~
相关推荐
- 安全教育登录入口平台(安全教育登录入口平台官网)
-
122交通安全教育怎么登录:122交通网的注册方法是首先登录网址http://www.122.cn/,接着打开网页后,点击右上角的“个人登录”;其次进入邮箱注册,然后进入到注册页面,输入相关信息即可完...
- 大鱼吃小鱼经典版(大鱼吃小鱼经典版(经典版)官方版)
-
大鱼吃小鱼小鱼吃虾是于谦跟郭麒麟的《我的棒儿呢?》郭德纲说于思洋郭麒麟作诗的相声,最后郭麒麟做了一首,师傅躺在师母身上大鱼吃小鱼小鱼吃虾虾吃水水落石出师傅压师娘师娘压床床压地地动山摇。...
-
- 哪个软件可以免费pdf转ppt(免费的pdf转ppt软件哪个好)
-
要想将ppt免费转换为pdf的话,我们建议大家可以下一个那个wps,如果你是会员的话,可以注册为会员,这样的话,在wps里面的话,就可以免费将ppt呢转换为pdfpdf之后呢,我们就可以直接使用,不需要去直接不需要去另外保存,为什么格式转...
-
2026-02-04 09:03 off999
- 电信宽带测速官网入口(电信宽带测速官网入口app)
-
这个网站看看http://www.swok.cn/pcindex.jsp1.登录中国电信网上营业厅,宽带光纤,贴心服务,宽带测速2.下载第三方软件,如360等。进行在线测速进行宽带测速时,尽...
- 植物大战僵尸95版手机下载(植物大战僵尸95 版下载)
-
1可以在应用商店或者游戏平台上下载植物大战僵尸95版手机游戏。2下载教程:打开应用商店或者游戏平台,搜索“植物大战僵尸95版”,找到游戏后点击下载按钮,等待下载完成即可安装并开始游戏。3注意:确...
- 免费下载ppt成品的网站(ppt成品免费下载的网站有哪些)
-
1、Chuangkit(chuangkit.com)直达地址:chuangkit.com2、Woodo幻灯片(woodo.cn)直达链接:woodo.cn3、OfficePlus(officeplu...
- 2025世界杯赛程表(2025世界杯在哪个国家)
-
2022年卡塔尔世界杯赛程公布,全部比赛在卡塔尔境内8座球场举行,2022年,决赛阶段球队全部确定。揭幕战于当地时间11月20日19时进行,由东道主卡塔尔对阵厄瓜多尔,决赛于当地时间12月18日...
- 下载搜狐视频电视剧(搜狐电视剧下载安装)
-
搜狐视频APP下载好的视频想要导出到手机相册里方法如下1、打开手机搜狐视频软件,进入搜狐视频后我们点击右上角的“查找”,找到自已喜欢的视频。2、在“浏览器页面搜索”窗口中,输入要下载的视频的名称,然后...
- 永久免费听歌网站(丫丫音乐网)
-
可以到《我爱音乐网》《好听音乐网》《一听音乐网》《YYMP3音乐网》还可以到《九天音乐网》永久免费听歌软件有酷狗音乐和天猫精灵,以前要跳舞经常要下载舞曲,我从QQ上找不到舞曲下载就从酷狗音乐上找,大多...
- 音乐格式转换mp3软件(音乐格式转换器免费版)
-
有两种方法:方法一在手机上操作:1、进入手机中的文件管理。2、在其中选择“音乐”,将显示出手机中的全部音乐。3、点击“全选”,选中所有音乐文件。4、点击屏幕右下方的省略号图标,在弹出菜单中选择“...
- 电子书txt下载(免费的最全的小说阅读器)
-
1.Z-library里面收录了近千万本电子书籍,需求量大。2.苦瓜书盘没有广告,不需要账号注册,使用起来非常简单,直接搜索预览下载即可。3.鸠摩搜书整体风格简洁清晰,书籍资源丰富。4.亚马逊图书书籍...
- 最好免费观看高清电影(播放免费的最好看的电影)
-
在目前的网上选择中,IMDb(互联网电影数据库)被认为是最全的电影网站之一。这个网站提供了各种类型的电影和电视节目的海量信息,包括剧情介绍、演员表、评价、评论等。其还提供了有关电影制作背后的详细信息,...
- 孤单枪手2简体中文版(孤单枪手2简体中文版官方下载)
-
要将《孤胆枪手2》游戏的征兵秘籍切换为中文,您可以按照以下步骤进行操作:首先,打开游戏设置选项,通常可以在游戏主菜单或游戏内部找到。然后,寻找语言选项或界面选项,点击进入。在语言选项中,选择中文作为游...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
win7系统还原步骤图解(win7还原电脑系统的步骤)
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
python入门到脱坑 输入与输出—str()函数
-
16949认证费用是多少(16949审核员太难考了)
-
linux软件(linux软件图标)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
windows7旗舰版多少钱(win7旗舰版要多少钱)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
