ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 78864|回复: 16

[分享] VBA(VB)中实现延时(等待)的3种方法

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2016-1-19 16:15 | 显示全部楼层 |阅读模式
本帖最后由 weiyingde 于 2016-1-19 16:44 编辑

在程序流程中经常要延时一段时间后再继续往下执行,在VB中常用的有以下几种方法(因为Timer控件打乱了程序的流程所以一般不用它):
1.使用Windows API函数Sleep
新建一个工程,添加一个TextBox控件和一个CommandButton控件,再将以下代码复制到代码窗口:
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)
Private Sub Command1_Click()Sub Command1_Click()
Text1 = "sleep begin"
Sleep 3000
Text1 = "sleep end"
End Sub
按F5执行,按下Command1按钮,程序停止执行,3秒钟内不对用户的操作做出反应,并且Text1里的内容并没有发生改变。这是怎么回事呢?原来,Sleep函数功能是将调用它的进程挂起dwMilliseconds毫秒时间,在这段时间内,此进程不对用户操作做出反应,程序中虽然将Text1的Text属性改成Sleep begin,但还没等完成对屏幕的更新进程就被挂起了,对用户来说程序象是死机一样。所以这种方法虽然简单,但并不适用。

2.使用Timer()函数
这是用的最多的一种方法,也是在VB联机手册中所推荐的。添加一个CommandButton控件,再将以下代码添加到代码窗口中:
Private Sub Command2_Click()Sub Command2_Click()
Dim Savetime As Single
Text1 = "Timer begin"
Savetime = Timer '记下开始的时间
While Timer < Savetime + 5 '循环等待
DoEvents '转让控制权,以便让操作系统处理其它的事件
Wend
Text1 = "Timer ok"
End Sub
这种方法虽然也很简单,但却有有一个致命缺陷,那就是Timer函数返回的是从午夜开始到现在经过的秒数。所以Timer返回的最大值也只是60*60*24-1秒,如果从一天的23:59:58秒开始计时等待5秒,那么程序会永远地循环下去。要进行改良,就要加上判断是否又开始了新的一天,那岂不是太麻烦。下面给大家推荐另一个Windows API函数。
3.使用Windows API函数timeGetTime()
timeGetTime函数没有参数,返回值是从开机到现在所经历的毫秒数,这个毫秒数是非周期性递增的,所以不会出现Timer()函数出现的问题,而且这种方法的精确性高于上一种方法。添加一个CommandButton控件,再将以下代码添加到代码窗口中:
Private Declare Function timeGetTime()Function timeGetTime Lib "winmm.dll" () As Long
Private Sub Command3_Click()Sub Command3_Click()
Dim Savetime As Double
Text1 = "timeGetTime begin"
Savetime = timeGetTime '记下开始时的时间
While timeGetTime < Savetime + 5000 '循环等待
DoEvents '转让控制权,以便让操作系统处理其它的事件
Wend
Text1 = "timeGetTime end"
End Sub

评分

9

查看全部评分

TA的精华主题

TA的得分主题

发表于 2017-10-7 19:46 | 显示全部楼层
路过收藏一下

TA的精华主题

TA的得分主题

发表于 2017-10-9 11:12 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2017-10-10 18:33 | 显示全部楼层
phsu 发表于 2017-10-9 11:12
Application.Wait Now + TimeValue("00:00:03")也可以。

这个到没有试过,谢谢分享

TA的精华主题

TA的得分主题

发表于 2017-12-13 15:41 | 显示全部楼层
phsu 发表于 2017-10-9 11:12
Application.Wait Now + TimeValue("00:00:03")也可以。

这个wait会导致CPU占用率很高,你延时1分钟,看看CPU占用率。
我一般用第一种方法较多。
第二种方法,API声明在32位office和64位office下有个关键字ptrsafe的不同,代码不通用,兼容性不好。32位能运行64位就报错,64位能运行32位office就报错,很烦。

TA的精华主题

TA的得分主题

发表于 2019-7-2 12:04 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2019-9-30 08:57 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
硅谷少年 发表于 2017-12-13 15:41
这个wait会导致CPU占用率很高,你延时1分钟,看看CPU占用率。
我一般用第一种方法较多。
第二种方法,A ...

没有你说的占CPU资源现象啊

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-7 12:51 | 显示全部楼层
weiyingde 发表于 2017-10-10 18:33
这个到没有试过,谢谢分享

b时间相关函数
━━━━━━━━━━━━━━━━━━━━━━━━━
timeGetTime只能精确到18毫秒
timer 控件只能精确到55毫秒
算法要和主频有关,无法对每个机子精确.
━━━━━━━━━━━━━━━━━━━━━━━━━

1、Timer()函数,vb自有函数,非API,无须声明,且精确到毫秒,推荐!!!

Timer 函数
返回一个 Single,代表从午夜开始到现在经过的秒数。

说明
Microsoft Windows中,Timer函数返回一秒的小数部分(毫秒)如 46.785。

示例
运用 Timer 函数来计算本代码运行所化的时间。

Sub 示例_1_040()
    Dim t, i & , a
    t = Timer
    For i = 1 To 1000000
        a = a + i
    Next i
    MsgBox Timer - t & "秒"  ‘返回0.046875秒
End Sub

这是用的最多的一种方法,也是在VB联机手册中所推荐的。添加一个Commanon控件,再将以下代码添加到代码窗口中:
Private Sub Command2_Click()
    Dim Savetime As Single
    Text1 = "Timer begin"
    Savetime = Timer ‘记下开始的时间
    While Timer < Savetime + 5 ‘循环等待
        DoEvents ‘转让控制权,以便让处理其它的事件。
    Wend
    Text1 = "Timer ok"
End Sub

━━━━━━━━━━━━━━━━━━━━━━━━━
2、timeGetTime

Declare Function timeGetTime Lib "winmm.dll" Alias "timeGetTime" () As Long
Dim lngtmp As Long
Do While '这里写结束条件
    lngtmp = timeGetTime
    While timeGetTime - lngtmp < x ' 这里的x是你需要精确的数,如1就是1/1000=0.001秒
        DoEvents
    Wend
    '你要执行的代码
Loop

━━━━━━━━━━━━━━━━━━━━━━━━━
3、GetTickCount

Dim T0 As Long
Dim T1 As Long
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Sub Form_Click()
    T0 = GetTickCount
End Sub
Private Sub Form_DblClick()
    T1 = GetTickCount
    MsgBox (T1 - T0)
End Sub
毫秒级的哦!(其他答案都不可以的)

━━━━━━━━━━━━━━━━━━━━━━━━━
4. Sleep
新建一个工程,添加一个TextBox控件和一个Commanon控件,再将以下代码复制到代码窗口:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub Command1_Click()
    Text1 = "sleep begin"
    Sleep 3000
    Text1 = "sleep end"
End Sub

━━━━━━━━━━━━━━━━━━━━━━━━━
示例
━━━━━━━━━━━━━━━━━━━━━━━━━
vb中返回当前系统毫秒数的函数是Timer。
'第一次操作
t1 = Timer
'第二次操作
For i = 1 To 1000000
    x = x + i
Next
t2 = Timer
Debug.Print Int((t2 - t1) * 1000) '时间差,精确到毫秒
━━━━━━━━━━━━━━━━━━━━━━━━━
VB 延时函数
Private Sub WaitTime(t As Single)
    Dim starttime As Single
    starttime = Second(Now)
    Do Until (60 + Second(Now) - starttime) Mod 60 > t

    Loop
End Sub

━━━━━━━━━━━━━━━━━━━━━━━━━

TA的精华主题

TA的得分主题

发表于 2019-10-7 14:13 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2020-12-1 19:32 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-19 08:45 , Processed in 0.050214 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表