问题
I'm currently having a PowerPoint presentation that's being used on a computer as some sort of kiosk or information screen. It reads it's text from a text file on the disk. The text in this text file is displayed in a textbox in PowerPoint and this is being refresh every 5 seconds. This way we can edit the text in the PowerPoint without editing the PowerPoint presentation itself so it will continue to run. Work great so far, only PowerPoint VBA does not contain the Application.Wait function. See here the full 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
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
As you can see I've got a loop within a loop to create a 5 second sleep / wait function, as PowerPoint doesn't have a Application.Wait function.
While running this macro my CPU load on my 7th gen i5 goes up to 36%. The kiosk computer has slightly worse hardware so the CPU load will be quite high and the fan of this PC will make a lot of noise.
I think the sleep / wait function doesn't really "sleep", it just continues to loop until 5 seconds have past.
Question 1 : Is my assumption that the function doesn't really sleep true? Question 2 : If the answer to question 1 is true, is there a better, less CPU intensive way, to create a sleep function?
回答1:
To wait for a specific amount of time, call WaitMessage followed by DoEvents in a loop. It's not CPU intensive and the UI will remain responsive:
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
回答2:
Sleep
does not require CPU cycle.
Sleep
is a windows function and not a VBA Function, but you can still use this function in VBA code by calling the windows Sleep
API. Actually sleep
is a function present inside Windows DLL files. So, before using them you have to declare the name of API above the code in your module.
The syntax of Sleep
statement is as follows:
Sleep (delay)
Example :
#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
So basicly your code would be as below :
#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
Conclusion : You didn't use the real sleep
function. What you were doing was using CPU Cycle..
Note that several information in this answer were found on this website : --> source
回答3:
Try the following
#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
It uses the Sleep
API function, which is windows-based and therefore not limited to Excel.
Sleep uses a value in milliseconds, so in this case you need 5000
EDIT
#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
As per this thread
来源:https://stackoverflow.com/questions/57268161/sleep-wait-timer-in-powerpoint-vba-thats-not-cpu-intensive