【问题标题】:DoEvents not giving control to Windows in ExcelDoEvents 没有在 Excel 中控制 Windows
【发布时间】:2020-01-03 10:04:17
【问题描述】:

我正在尝试在 Excel 中创建自动保存功能,因为当前的 Microsoft 不支持本地文件。

这是我想出的VB。但仍然只有宏在运行,没有给 Windows 任何控制权。 DoEvents 似乎不起作用。

Sub Auto_save()   
    Do While 1 < 2    
        ActiveWorkbook.Save
        Application.Wait (Now + TimeValue("0:00:05"))
        DoEvents
    Loop

End Sub

(我使用的是 Excel 365 Pro Plus。)

【问题讨论】:

  • 你有一个永无止境的循环吗?
  • @QHarr,看起来是这样,但如果您想构建自己的自动保存功能,则合乎逻辑......
  • @Luuklag 我相信你,但为什么?
  • @Qharr 打败了我...也许工作表更改事件可以解决问题,根据 lastsavetime 检查当前时间,如果差异较大,则保存。
  • VBA 将在Application.Wait (Now + TimeValue("0:00:05")) 5 秒后保持控制,在您知道Do..Loop 的其余代码将结束之前!如果您想构建 Auto_Save,那么您可以使用为 excel 等中的数字时钟发布的代码示例。例如stackoverflow.com/questions/11867225/…

标签: excel vba


【解决方案1】:

您要求 VBA 等待 5 秒,这将在此期间冻结 Excel,并且只有在 Wait 完成后,DoEvents 才会触发。

一种常见的解决方案是实现自己的wait-函数,使用包含DoEvents 的循环,例如https://stackoverflow.com/a/21405463/7599798 建议(从那里复制)

Private Sub delay(seconds As Long)
    Dim endTime As Date
    endTime = DateAdd("s", seconds, Now())
    Do While Now() < endTime
        DoEvents
    Loop
End Sub

但是,我认为这并不是一个很好的解决方案,因为它会使您的 CPU 保持忙碌。另一种方法是使用OnTime 函数:

Sub SaveMe()
    ActiveWorkbook.Save
    Application.OnTime Now + TimeValue("00:00:05"), "SaveMe"
End Sub

旁注:您不应该使用ActiveWorkbook,因为焦点很容易切换到不同的工作簿,在这种情况下您不会保存您期望的工作簿。

【讨论】:

  • 问:如果我正确阅读了代码,SaveMe Sub 是递归的。我有一些(非常少,谢天谢地)实例,其中使用递归函数将调用堆栈构建得太高,并且它崩溃了。保存工作簿是否有助于清除调用堆栈?或者,如果包含此代码的工作簿打开时间过长,是否会出现潜在问题?
  • @FunThomas ThisWorkbook.Save 而不是 ActiveWorkbook
  • @BND:不一定 - 取决于代码是否在 OP 要自动保存的工作簿中。
  • @Mistella:是和不是。 Sub 称自己为“未来”,但不会等到那时,所以堆栈不会增加。
  • @BND:您可以将其添加到您的personal 工作簿中并运行几分钟,循环遍历所有打开的工作簿。但是,请记住,如果您自动保存所有打开的文件,则无法在不保存的情况下关闭 - 就个人而言,我经常搞砸文件并且很高兴退出并重新启动。也许使用SaveCopyAs 可能是一个解决方案。
【解决方案2】:

您不需要DoEvents。从How do I show a running clock in Excel?复制和编辑的示例代码

Dim TimerActive As Boolean
Sub StartTimer()
    Start_Timer
End Sub
Private Sub Start_Timer()
    TimerActive = True
    Application.OnTime Now() + TimeValue("00:00:05"), "Timer"
End Sub
Private Sub Stop_Timer()
    TimerActive = False
End Sub
Private Sub Timer()
    If TimerActive Then
        ThisWorkbook.Save
        ThisWorkbook.Sheets(1).Range("A1").Value = "Last saved by : " & Application.UserName & " on " & Format(Now(), "dd-mm-yy hh:mm:ss")
        Application.OnTime Now() + TimeValue("00:00:05"), "Timer"
    End If
End Sub

【讨论】:

  • 请注意,此解决方案需要使用工作表 1 上的单元格 A1。
【解决方案3】:

从 Excel 365/2016 开始,VBA 代码中需要两个连续的 DoEvents 命令才能更新动态绘图。奇怪但真实。每次都有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-21
    • 2022-07-07
    • 1970-01-01
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    相关资源
    最近更新 更多