VBA运行时错误'1004':添加MsgBox终止确认时OnTime方法异常问题
解决VBA计时器取消异常及运行时错误1004的问题
这个问题的核心在于你使用Application.OnTime取消任务时,没有精确匹配最初调度的执行时间,再加上MsgBox阻塞程序导致的时序偏差,才会出现计时器停不下来、报错1004的情况。
问题原因拆解
- 你的
myTimer过程每次调度下一次执行时,用的是Now + timeValue("00:00:01"),这个时间是动态计算的。但当你弹出MsgBox时,程序会被阻塞,等到用户点击确认时,这个计算出的时间已经和最初调度的时间不一致了。 - 用错误的时间去调用
OnTime取消,自然找不到对应的任务,就会触发1004错误,同时原来的计时器任务还在后台继续运行。
修复方案:存储精确的调度时间
我们需要把每次调度OnTime的精确时间存下来,取消时直接用这个存储的时间去匹配,就能准确终止计时器。
修改后的模块代码
Option Explicit Public StartTime As Single Public NextTimerTime As Date ' 新增:存储下一次计时器执行的精确时间 Public Sub myTimer() Dim elapsedtime As Single elapsedtime = Timer - StartTime UserForm2.Label2.Caption = Format(CDate(elapsedtime / 86400), "hh:nn:ss") ' 存储下一次执行的时间,而不是直接在OnTime里计算 NextTimerTime = Now + TimeValue("00:00:01") Application.OnTime NextTimerTime, "myTimer" End Sub Public Sub myTimer_Cancel() On Error Resume Next ' 防止因时间已过导致的报错 ' 用存储的精确时间取消任务 Application.OnTime NextTimerTime, "myTimer", , False On Error GoTo 0 ' 恢复错误处理 End Sub
修改后的用户窗体代码
Private Sub UserForm_Initialize() StartTime = Timer ' 先初始化开始时间,再启动计时器 Call myTimer End Sub Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode = vbFormControlMenu Then ' 只处理用户点击关闭按钮的情况 If MsgBox("Are you sure to End Time?", vbYesNo) = vbYes Then myTimer_Cancel ' 先取消计时器 ' 可选:重置标签内容 Me.Label2.Caption = "00:00:00" Else Cancel = True ' 取消关闭操作 End If End If End Sub
额外说明
- 添加
On Error Resume Next在取消过程中,可以避免因为调度时间已经过去而触发的1004错误。 - 调整了
UserForm_Initialize里的顺序,确保StartTime先被赋值再启动计时器,避免初始计时误差。 - 增加了
CloseMode判断,只在用户点击窗体关闭按钮时触发确认逻辑,避免其他关闭场景(比如代码主动关闭)的干扰。
这样修改后,就能准确终止计时器,也不会再出现运行时错误1004了。
内容的提问来源于stack exchange,提问作者Ben Ben
相关产品推荐
相关产品推荐

