总是听到或看到有人问,编程好学吗?如何入门?多久能学会?它能做些什么?怎么写代码呀?执行过程中出问题了谁能帮帮我...如果你也有类似的问题那就赶快关注我的公众号,一起学起来吧!
Timer内置函数是 VBA 中最基本、最重要的计时相关函数,凡是涉及和时间相关的编程,都有它飘逸的身影
若想快速了解 Timer 的工作原理,不妨通过一个很有意思的案例来辅助理解、加深印象——比起枯燥的长篇讲解,这样学起来更轻松也更易记住
视频中展示的是利用 Timer +Userform窗体实现的计时器功能:计时器以 00:00:00 的格式显示,界面上有开始、暂停、重置三个选项,考虑到操作习惯,将“开始”和“暂停”共用一个按键技术难点:计时器给人最直观的感受是当秒数达到 60 时向分钟进位,分钟达到 60 时再向小时进位没想到吧?这个看似很普通的时分秒进位逻辑问题,竟然成了这次编码的头号大敌2.1Userform设计及代码
主要完成的功能:初始化及善后清理工作,并对用户点击按钮进行响应,以“开始”和“暂停”按钮加以说明
开始按钮:按下“开始”键时,会进入到Private Sub StartTimer(),记录当前时间并保存到变量 startTime 中,具体通过 startTime = Timer 这行代码实现。例如,12:33分按下“开始”按钮,那么startTime变量里面存储的内容如下图所示
看到这一串数值是不是脑袋瓜子嗡嗡的?和传统意义上的时间完全不对等呢?其实,Timer返回的是从午夜(00:00:00)开始到当前时刻(12:33)的秒数 ,顺着这个思路我们进行计算:
45201刚好等于12×3600+33*60+21,即12点33分21秒
暂停按钮:则需要记录从计时开始到按下暂停按钮之间经过的秒数,保存在elapsedTime中。这样,后续点击“继续”按钮时,计时器就能在之前累计的时间基础上接着计时,而不会从0开始
' 在UserForm模块顶部声明变量Private nextTick As DoublePrivate timerEnabled As BooleanPrivate Sub UserForm_Initialize() ' 初始化变量和界面 elapsedTime = 0 isRunning = False timerEnabled = False lblTimer.Caption = "00:00:00" cmdStartPause.Caption = "开始"End SubPrivate Sub cmdStartPause_Click() If Not timerEnabled Then ' 第一次开始计时 StartTimer cmdStartPause.Caption = "暂停" ElseIf isRunning Then ' 正在运行,点击则暂停 PauseTimer cmdStartPause.Caption = "继续" Else ' 已暂停,点击则继续 ResumeTimer cmdStartPause.Caption = "暂停" End IfEnd SubPrivate Sub cmdReset_Click() ' 重置计时器 ResetTimerEnd SubPrivate Sub StartTimer() ' 开始计时 startTime = Timer isRunning = True timerEnabled = True ' 安排第一次更新 ScheduleNextTickEnd SubPrivate Sub PauseTimer() ' 暂停计时 If isRunning Then ' 计算经过的时间并累加到总时间 elapsedTime = elapsedTime + (Timer - startTime) isRunning = False ' 取消预定的下一次更新 On Error Resume Next ' 防止没有预定任务时报错 Application.OnTime nextTick, "UpdateTimerDisplay", , False On Error GoTo 0 End IfEnd SubPrivate Sub ResumeTimer() ' 继续计时 If Not isRunning Then startTime = Timer isRunning = True ScheduleNextTick End IfEnd SubPrivate Sub ResetTimer() ' 重置计时器 isRunning = False timerEnabled = False ' 取消预定的下一次更新 On Error Resume Next Application.OnTime nextTick, "UpdateTimerDisplay", , False On Error GoTo 0 elapsedTime = 0 lblTimer.Caption = "00:00:00" cmdStartPause.Caption = "开始"End SubPrivate Sub ScheduleNextTick() ' 安排1秒后更新 nextTick = Now + TimeValue("00:00:01") Application.OnTime nextTick, "UpdateTimerDisplay"End SubPrivate Sub UserForm_Terminate() ' UserForm关闭时清理预定的任务 On Error Resume Next Application.OnTime nextTick, "UpdateTimerDisplay", , False On Error GoTo 0End SubPrivate Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode = vbFormControlMenu And isRunning = False Then '停止计时可关闭 Cancel = False Else ' 计时器未停止,禁止点击右上角“X”关闭窗体 MsgBox "请停止计时器后,再关闭", vbInformation Cancel = True End IfEnd Sub
UpdateTimerDisplay实现的核心功能:通过全局变量获取startTime和 elapsedTime,实时更新计时器的显示,让界面上的时间随着程序运行持续刷新,形成“跑表”效果
FormatTime子过程则是将秒数转换成我们习惯的格式00:00:00输出,原来是通过整除和取模运算自动处理60秒进位和60分钟进位,不需要另行写逻辑判断进位问题了,省时省力
' 在标准模块中声明公共变量(与UserForm共享状态)Public ufTimer As Object ' 改为Object类型避免循环引用Public nextTick As DoublePublic startTime As DoublePublic elapsedTime As DoublePublic isRunning As BooleanSub ShowTimerForm() Set ufTimer = New UserForm1 ' UserForm名称为UserForm1 ufTimer.ShowEnd SubSub UpdateTimerDisplay() If ufTimer Is Nothing Then Exit Sub If isRunning Then Dim currentTime As Double currentTime = elapsedTime + (Timer - startTime) ufTimer.lblTimer.Caption = FormatTime(currentTime) ' 安排1秒后再次更新 nextTick = Now + TimeValue("00:00:01") Application.OnTime nextTick, "UpdateTimerDisplay" End IfEnd SubFunction FormatTime(totalSeconds As Double) As String Dim hours As Integer, minutes As Integer, seconds As Integer hours = Int(totalSeconds / 3600) minutes = Int((totalSeconds Mod 3600) / 60) seconds = Int(totalSeconds Mod 60) FormatTime = Format(hours, "00") & ":" & _ Format(minutes, "00") & ":" & _ Format(seconds, "00")End Function
好了,今天的编程知识到此结束了。计划从今天起,每天在文末和大家分享一个与计算机相关的冷知识,希望大家喜欢
今天分享的是一位非常厉害的人物:艾伦·图灵(Alan Turing),被誉为计算机科学之父,因此图灵奖也是计算机领域的最高荣誉,被誉为“计算机界的诺贝尔奖”
本公众号一直在不间断地分享免费的编程案例和实用技巧。无论您是用来提升自动化办公效率还是想提升自我,请关注我的公众号,解锁更多的编程知识