【问题标题】:Sleep / wait timer in PowerPoint VBA that's not CPU intensivePowerPoint VBA 中非 CPU 密集型的睡眠/等待计时器
【发布时间】:2019-12-07 15:20:29
【问题描述】:

我目前有一个 PowerPoint 演示文稿,它在计算机上用作某种信息亭或信息屏幕。 它从磁盘上的文本文件中读取它的文本。此文本文件中的文本显示在 PowerPoint 的文本框中,并且每 5 秒刷新一次。这样,我们可以在 PowerPoint 中编辑文本,而无需编辑 PowerPoint 演示文稿本身,因此它将继续运行。 到目前为止工作得很好,只有 PowerPoint VBA 不包含 Application.Wait 函数。在这里查看完整的子:

Sub Update_textBox_Inhoud()

Dim FileName As String
TextFileName = "C:\paht\to\textfile.txt"
If Dir$(FileName) <> "" Then

Application.Presentations(1).SlideShowSettings.Run
Application.WindowState = ppWindowMinimized


While True


    Dim strFilename As String: strFilename = TextFileName
    Dim strFileContent As String
    Dim iFile As Integer: iFile = FreeFile
    Open strFilename For Input As #iFile
    strFileContent = Input(LOF(iFile), iFile)
    Application.Presentations(1).Slides(1).Shapes.Range(Array("textBox_Inhoud")).TextFrame.TextRange = strFileContent
    Close #iFile


    waitTime = 5
    Start = Timer
    While Timer < Start + waitTime
        DoEvents
    Wend

Wend

Else

End If
End Sub

如您所见,我在循环中有一个循环来创建 5 秒睡眠/等待功能,因为 PowerPoint 没有 Application.Wait 功能。

在运行此宏时,我的第 7 代 i5 上的 CPU 负载高达 36%。 kiosk 计算机的硬件稍差,因此 CPU 负载会很高,而且这台 PC 的风扇会发出很大的噪音。

我认为睡眠/等待功能并没有真正“睡眠”,它只是继续循环直到 5 秒过去。

问题 1:我的假设是函数并没有真正休眠吗? 问题 2:如果问题 1 的答案是正确的,是否有更好、更少 CPU 密集型的方法来创建睡眠功能?

【问题讨论】:

    标签: vba powerpoint wait sleep


    【解决方案1】:

    Sleep 不需要 CPU 周期。

    Sleep 是 windows 函数而不是 VBA 函数,但您仍然可以通过调用 windows Sleep API 在 VBA 代码中使用此函数。实际上sleep 是存在于 Windows DLL 文件中的一个函数。因此,在使用它们之前,您必须在模块中的代码上方声明 API 的名称。

    Sleep语句的语法如下:

    Sleep (delay)
    

    示例:

    #If VBA7 Then  
        Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr) 'For 64 Bit Systems  
    #Else  
        Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds as Long) 'For 32 Bit Systems  
    #End If  
    Sub SleepTest()  
    MsgBox "Execution is started"  
    Sleep 10000 'delay in milliseconds  
    MsgBox "Execution Resumed"  
    End Sub  
    

    所以基本上你的代码如下:

    #If VBA7 Then
    
        Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal Milliseconds As LongPtr)
    
    #Else
    
        Public Declare Sub Sleep Lib "kernel32" (ByVal Milliseconds As Long)
    
    #End If
    
        Sub Update_textBox_Inhoud()
    
        Dim FileName As String
        TextFileName = "C:\paht\to\textfile.txt"
        If Dir$(FileName) <> "" Then
            Application.Presentations(1).SlideShowSettings.Run
            Application.WindowState = ppWindowMinimized
    
            While True
                Dim strFilename As String: strFilename = TextFileName
                Dim strFileContent As String
                Dim iFile As Integer: iFile = FreeFile
                Open strFilename For Input As #iFile
                strFileContent = Input(LOF(iFile), iFile)
                Application.Presentations(1).Slides(1).Shapes.Range(Array("textBox_Inhoud")).TextFrame.TextRange = strFileContent
                Close #iFile
    
               Sleep 5000
            Wend
        Else
    
        End If
        End Sub
    

    结论:你没有使用真正的sleep函数。你正在做的是使用 CPU Cycle..

    请注意,在此网站上找到了此答案中的一些信息:--> source

    【讨论】:

    • 感谢您的建议。我也在其他地方发现了这个睡眠功能,但是当我将它添加到我的代码中并运行它时,PowerPoint 变得无响应。好像它没有执行睡眠,只是变成了一个无限循环。
    • 你的系统是什么? @Roy 32 位还是 64 位?
    • @Roy 也许您可以尝试使用Wait 函数,但它会使用 CPU .. 要我编辑吗?
    • 然后停止使用这些资源并改用文档。说应该使用LongPtr因为它是一个Windows API是没有意义的。 LongPtr 应该用于指针大小的值。 Sleepaccepts a DWORD。无论操作系统位数如何,DWORD 都是 32-bit unsigned integer。指针大小的值的示例是 HWND,即HANDLE,即PVOID,它是指向void指针
    • 也许您也应该尝试一下。就像我之前说的,Sleep 在 32 位和 64 位 Windows 上都接受一个 32 位整数值,在 VBA 中是一个Long
    【解决方案2】:

    试试下面的

    #If VBA7 Then
    
        Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal Milliseconds As LongPtr)
    
    #Else
    
        Public Declare Sub Sleep Lib "kernel32" (ByVal Milliseconds As Long)
    
    #End If
    
    Sub Update_textBox_Inhoud()
    
    Dim FileName As String
    TextFileName = "C:\paht\to\textfile.txt"
    If Dir$(FileName) <> "" Then
        Application.Presentations(1).SlideShowSettings.Run
        Application.WindowState = ppWindowMinimized
    
        While True
            Dim strFilename As String: strFilename = TextFileName
            Dim strFileContent As String
            Dim iFile As Integer: iFile = FreeFile
            Open strFilename For Input As #iFile
            strFileContent = Input(LOF(iFile), iFile)
            Application.Presentations(1).Slides(1).Shapes.Range(Array("textBox_Inhoud")).TextFrame.TextRange = strFileContent
            Close #iFile
    
           Sleep 5000
        Wend
    Else
        'Is there no code here?
    End If
    End Sub
    

    它使用Sleep API 函数,该函数基于 Windows,因此不限于 Excel。

    睡眠使用以毫秒为单位的值,因此在这种情况下您需要5000

    编辑

    #If VBA7 Then
        Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal _
        lpTimerFunc As Long) As Long
    
        Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long 
    #Else
        Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal _
        lpTimerFunc As Long) As Long
    
        Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    #End If
    
    
    Dim lngTimerID As Long
    Dim blnTimer As Boolean
    
    Sub StartOnTime()
        If blnTimer Then
            lngTimerID = KillTimer(0, lngTimerID)
            If lngTimerID = 0 Then
                MsgBox "Error : Timer Not Stopped"
                Exit Sub
            End If
            blnTimer = False
    
        Else
            lngTimerID = SetTimer(0, 0, 5000, AddressOf Update_textBox_Inhoud)
            If lngTimerID = 0 Then
                MsgBox "Error : Timer Not Generated "
                Exit Sub
            End If
            blnTimer = True
        End If
    End Sub
    
    Sub KillOnTime()
        lngTimerID = KillTimer(0, lngTimerID)
        blnTimer = False
    End Sub
    
    Sub Update_textBox_Inhoud()
    
    Dim FileName As String
    TextFileName = "C:\paht\to\textfile.txt"
    If Dir$(FileName) <> "" Then
        Application.Presentations(1).SlideShowSettings.Run
        Application.WindowState = ppWindowMinimized
    
        Dim strFilename As String: strFilename = TextFileName
        Dim strFileContent As String
        Dim iFile As Integer: iFile = FreeFile
        Open strFilename For Input As #iFile
        strFileContent = Input(LOF(iFile), iFile)
        Application.Presentations(1).Slides(1).Shapes.Range(Array("textBox_Inhoud")).TextFrame.TextRange = strFileContent
        Close #iFile
    Else
        'Is there no code here?
    End If
    End Sub
    

    根据this thread

    【讨论】:

    • 这将使 PowerPoint 变得无响应 analystcave.com/vba-sleep-vs-wait
    • 是的,但我认为这不是问题,因为 Sleep 函数会在演示文稿更新后出现,而且演示文稿通常包含静态图像。
    • dwMilliseconds 始终是 As Long,而不是 LongPtr
    • 最重要的是,它是SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtrKillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
    【解决方案3】:

    要等待特定的时间,请在循环中调用WaitMessage,然后调用DoEvents。它不是 CPU 密集型的,并且 UI 将保持响应:

    Private Declare PtrSafe Function WaitMessage Lib "user32" () As Long
    
    
    Public Sub Wait(Seconds As Double)
        Dim endtime As Double
        endtime = DateTime.Timer + Seconds
        Do
            WaitMessage
            DoEvents
        Loop While DateTime.Timer < endtime
    End Sub
    

    【讨论】:

    • 这确实为我解决了。 CPU 在 0% 和 1% 之间运行,PowerPoint 没有无响应。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-03
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多