深入探讨Excel Application对象OnTime方法的死穴

时间:2022-09-27 02:49:05

深入探讨Excel Application对象OnTime方法的死穴

[摘 要]因为Excel集数据库和程序设计于一体,令广大VBA编程爱好者前赴后继地奔走在Excel考试系统路上,定时器作为考试系统的基本要求,而Excel却没有Timer,使爱好者乱了方寸,幸好Application对象OnTime方法带来了一线生机,但它又无法感知系统时间被修改的弊端,成了Excel考试系统的死穴,又让爱好者垂头丧气。

[关键词]探讨 Excel Application对象 OnTime方法

中图分类号:TP311.52 文献标识码:A 文章编号:1009-914X(2016)02-0351-01

Excel考试系统的重点和难点都是定时器的实现,但定时器作为任何考试系统的基本要求,又无法回避,怎样彻底实现Excel考试系统的定时器功能呢?

一、实现定时器的基本方法

虽然Excel VBA没有提供定时器,但可以通过Application对象的OnTime方法实现简单的定时器功能,OnTime方法能够安排一个过程在将来的特定时间运行,既可以是具体指定的某个时间,也可以是指定的一段时间之后。

语法如下:Application.OnTime EarliestTime,Procedure,LatestTime,Schedule

在OnTime方法中递归调用Procedure过程,就可实现定时器。

二、致命的死穴

尽管OnTime方法可以具体指定的某个时间和指定的一段时间之后两种方式执行Procedure,但本质上都是具体指定的某个时间,因此一旦修改系统时间,不管是提前或延后时间,让其错过指定时刻,或让指定时刻延后数小时或更长,导致OnTime方法失效,从而失去定时器的功能,成为Excel考试系统的死穴。

三、解决方案

许多编程爱好者都在苦苦探索一旦修改系统时间,立刻让Excel感知系统时间被修改了,从而调整定时器方案,其中想利用类似lostfocus和getfocus事件的Workbook_Activate()、Workbook_SheetActivate()、Workbook_WindowActivate()等事件的探索者,均以失败而告终,因为WindowActivate等事件都是在有两个以上workbook打开时(也就是多个excel文件),互相之间切换起作用,而不是workbook和其他程序窗口间切换。同理,WindowDeactivate也得是在多个workbook时起作用。

经过多次探索,终于发现Worksheet_Change()或Workbook_SheetChange()可担当此大任,两个事件都在编辑单元格后触发事件,类似TextChange事件,因为一般而言,Excel随时随地都处于编辑状态,所以时时刻刻都会触发Worksheet_Change()或Workbook_SheetChange()事件,只要在事件中获取系统时间,并比较前后时间的变化,即可判断系统时间是否被修改。尤其是系统时间被修改为以前的时间,更容易感知,因为时间毕竟不能倒流。

四、具体实现方法

首先定义两个全局变量Public pass As Date,Public nowtime As Date,在Workbook_Open()事件中获取系统时间,启动定时器过程displaytime()。

Private Sub Workbook_Open()

nowtime = Now()

pass = nowtime - TimeValue("01:00:00") '防恶意修改系统时间

displaytime

End Sub

而在定时器中递归调用过程displaytime()。

Public Sub displaytime()

nexttime = Now + TimeValue("00:00:01")

If Range("D2").Value > TimeValue("00:00:00") Then

Application.OnTime nexttime, "ThisWorkbook.displaytime", , True

End If

End Sub

在Worksheet_Change()或Workbook_SheetChange()事件中利用DateDiff函数比较pass和nowtime两个变量,当nowtime比pass还早,说明修改了系统时间,提示并作关闭Excel处理。

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

nowtime = Now()

If DateDiff("s", pass, nowtime) < 0 Then '修改系统时间,按提交处理

Response = MsgBox(" 恶意修改系统时间 ", 0, "提示")

ActiveWorkbook.Save

Application.Quit

Else

pass = nowtime '正常,时间在一分一秒过去

End If

End Sub

五、定时器在考试系统中的注意事项

在考试系统中,发现修改系统时间进行异常处理时,一般都要在Workbook_SheetChange()中记录考试状态和退出考试的原因,并存放在Excel文档中,此时又会触发Workbook_SheetChange()形成递归调用,而又没有递归的退出机制,导致堆栈空间溢出,Excel出现1004号错误,使整个考试系统崩溃,那么又怎样避免Workbook_SheetChange()形成递归调用呢?可在事件处理中使用Application.EnableEvents=False禁止触发事件,而处理完成后Application.EnableEvents=True重新启动触发事件。

至此,Excel考试系统的重点和难点――定时器的实现方法探讨完毕,整个考试系统彻底健壮起来了,真正完成了Excel考试系统的开发工作。

参考文献

[1] 张志群,EXCEL单元格自定义数字格式探讨,微型电脑应用,2008,24

[2] 甘伟明,用Excel构建计算机等级考试自动改卷评分系统,电脑学习 2010,2

上一篇:试论绿色船舶设计、制造的实施策略 下一篇:红柳煤矿I020201综采工作面顶板运动规律分析