특정 시간 동안 일시 중지하는 방법(Excel/VBA)
저는 다음과 같은 매크로가 있는 Excel 워크시트를 가지고 있습니다.1초마다 반복하고 싶지만 그럴 수 있는 기능을 찾을 수 있다면 위험합니다.가능하지 않나요?
Sub Macro1()
'
' Macro1 Macro
'
Do
Calculate
'Here I want to wait for one second
Loop
End Sub
대기 방법을 사용합니다.
Application.Wait Now + #0:00:01#
또는 (Excel 2010 이상의 경우):
Application.Wait Now + #12:00:01 AM#
모듈에 추가합니다.
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
또는 64비트 시스템의 경우 다음을 사용합니다.
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
매크로에서 다음과 같이 호출합니다.
Sub Macro1()
'
' Macro1 Macro
'
Do
Calculate
Sleep 1000 ' delay 1 second
Loop
End Sub
다음을 사용하는 대신:
Application.Wait(Now + #0:00:01#)
나는 선호합니다.
Application.Wait(Now + TimeValue("00:00:01"))
왜냐하면 나중에 읽는 것이 훨씬 더 쉽기 때문입니다.
이것은 완벽하게 작동합니다. "do until" 루프 앞이나 뒤에 코드를 삽입하십시오.당신의 경우, 5줄(time1= & time2= & "do until" 루프)을 당신의 do 루프 안의 끝에 놓습니다.
sub whatever()
Dim time1, time2
time1 = Now
time2 = Now + TimeValue("0:00:01")
Do Until time1 >= time2
DoEvents
time1 = Now()
Loop
End sub
커널 32.dll의 슬립 선언은 64비트 엑셀에서 작동하지 않습니다.이것은 조금 더 일반적일 것입니다.
#If VBA7 Then
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
clemo 코드의 정리된 버전만 - 응용프로그램이 없는 Access에서 작동합니다.대기 기능.
Public Sub Pause(sngSecs As Single)
Dim sngEnd As Single
sngEnd = Timer + sngSecs
While Timer < sngEnd
DoEvents
Wend
End Sub
Public Sub TestPause()
Pause 1
MsgBox "done"
End Sub
제시된 솔루션의 대부분은 애플리케이션을 사용합니다.대기 - 현재 초 카운트가 시작된 후 이미 경과한 시간(밀리초)을 고려하지 않으므로 최대 1초의 고유한 부정확성이 있습니다.
타이머 접근 방식이 가장 좋은 해결책이지만 자정에 재설정해야 하므로 타이머를 사용한 매우 정확한 절전 방법은 다음과 같습니다.
'You can use integer (1 for 1 second) or single (1.5 for 1 and a half second)
Public Sub Sleep(vSeconds As Variant)
Dim t0 As Single, t1 As Single
t0 = Timer
Do
t1 = Timer
If t1 < t0 Then t1 = t1 + 86400 'Timer overflows at midnight
DoEvents 'optional, to avoid excel freeze while sleeping
Loop Until t1 - t0 >= vSeconds
End Sub
이를 사용하여 절전 기능을 테스트합니다. (debug 즉시 창 열기: CTRL+G)
Sub testSleep()
t0 = Timer
Debug.Print "Time before sleep:"; t0 'Timer format is in seconds since midnight
Sleep (1.5)
Debug.Print "Time after sleep:"; Timer
Debug.Print "Slept for:"; Timer - t0; "seconds"
End Sub
VBA 실행 일시 중지에 대한 전체 가이드
배경 정보 및 설명
모든 Microsoft Office 응용 프로그램은 기본 사용자 인터페이스와 동일한 스레드에서 VBA 코드를 실행합니다.즉, VBA 코드가 호출되지 않는 한DoEvents코드를 실행하면 전체 응용 프로그램이 중지됩니다(작업 관리자에서 "응답 없음"으로 표시됨).여기에는 다음에 대한 통화도 포함됩니다.SleepAPI 함수입니다.한번만Sleep시간이 경과하거나 강제로 응용 프로그램을 종료하고 다시 시작하지 않고는 이 상태에서 복구할 수 없습니다.
앱이 다음과 같이 표시되지 않는다는 점을 제외하고 Excel 전용도 이 문제로 인해 어려움을 겪고 있습니다.not responding이 경우에는 작업 관리자에 있습니다.여전히 사용자에게 응답하지 않습니다.
이 문제를 피하는 방법은 전화입니다.DoEvents다른 사람들이 이미 지적했듯이, 순환적으로.하지만, 이것은 다른 문제와 함께 옵니다.애플리케이션은 가능한 한 빨리 VBA 코드를 실행하려고 하기 때문에 DoEvents는 달성 가능한 최대 속도로 호출되며 기본적으로 CPU를 해당 단일 스레드에서 완전히 포화시켜 불필요한 CPU 및 전력 사용량이 높고 UI에서 더 중요한 다른 작업을 지연시킬 수 있습니다.
중지하도록 이 두 입니다.DoEvents대응력을 유지하기 위해 그리고Sleep최대 CPU 사용량을 방지합니다.이에 대한 구현은 다음과 같습니다.
유니버설 솔루션
는 다음코는다구다니현합음을을 합니다.WaitSeconds Sub위에서 언급한 모든 문제를 방지하면서 지정된 시간 동안 실행을 일시 중지합니다.다음과 같이 사용할 수 있습니다.
Sub UsageExample()
WaitSeconds 3.5
End Sub
이렇게 하면 애플리케이션이 중지되거나 과도한 CPU 사용량이 발생하지 않고 매크로가 3.5초 동안 일시 중지됩니다.이 기능이 작동하려면 다음 코드를 표준 코드 모듈의 맨 위에 복사하기만 하면 됩니다.
#If Mac Then
#If VBA7 Then
Private Declare PtrSafe Sub USleep Lib "/usr/lib/libc.dylib" Alias "usleep" (ByVal dwMicroseconds As Long)
#Else
Private Declare Sub USleep Lib "/usr/lib/libc.dylib" Alias "usleep" (ByVal dwMicroseconds As Long)
#End If
#Else
#If VBA7 Then
Private Declare PtrSafe Sub MSleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
#Else
Private Declare Sub MSleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
#End If
#End If
'Sub providing a Sleep API consistent with Windows on Mac (argument in ms)
'Authors: Guido Witt-Dörring, https://stackoverflow.com/a/74262120/12287457
' Cristian Buse, https://stackoverflow.com/a/71176040/12287457
Public Sub Sleep(ByVal dwMilliseconds As Long)
#If Mac Then 'To avoid overflow issues for inputs > &HFFFFFFFF / 1000:
Do While dwMilliseconds And &H80000000
USleep &HFFFFFED8
If dwMilliseconds < (&H418937 Or &H80000000) Then
dwMilliseconds = &H7FBE76C9 + (dwMilliseconds - &H80000000)
Else: dwMilliseconds = dwMilliseconds - &H418937: End If
Loop
Do While dwMilliseconds > &H418937
USleep &HFFFFFED8: dwMilliseconds = dwMilliseconds - &H418937
Loop
If dwMilliseconds > &H20C49B Then
USleep (dwMilliseconds * 500& Or &H80000000) * 2&
Else: USleep dwMilliseconds * 1000&: End If
#Else
MSleep dwMilliseconds
#End If
End Sub
'Sub pausing code execution without freezing the app or causing high CPU usage
'Author: Guido Witt-Dörring, https://stackoverflow.com/a/74387976/12287457
Public Sub WaitSeconds(ByVal seconds As Single)
Dim currTime As Single: currTime = Timer()
Dim endTime As Single: endTime = currTime + seconds
Dim cacheTime As Single: cacheTime = currTime
Do While currTime < endTime
Sleep 15: DoEvents: currTime = Timer() 'Timer function resets at 00:00!
If currTime < cacheTime Then endTime = endTime - 86400! '<- sec per day
cacheTime = currTime
Loop
End Sub
플랫폼에 내용은 다음과 같습니다.Sleep위의 코드에 포함된 항목은 여기와 여기에서 찾을 수 있습니다.
매우 또는 사용자 작용이 않는 ), 은 " " " " " (" " " " " " " " 를 호출하는 입니다." " " " " " " " " " 입니다.Sleep직접적으로.이것이 위의 솔루션에서 다음과 같이 선언되는 이유입니다.Public:Sleep인수를 밀리초로 사용합니다.
'Does freeze application
Sub UsageExample()
Sleep 3.5 * 1000
End Sub
중요 참고 사항:
『 』의 시간
Timer()이 솔루션에 사용된 기능은 Windows에서 더 낫지만 Mac에서는 해상도가 1초라는 설명서의 주장은 잘못된 것입니다.Mac에서도 0.1초보다 해상도가 좋습니다.그래도 ~보다 훨씬 더 나은 해상도를 기대해서는 안 됩니다.0.1이 솔루션에서 몇 초!WaitSeconds 1에서 기다리겠습니다.1.015 ± 0.02초 단위로 설정합니다.이 기능을 사용하여 코드를 장시간 일시 중지하거나 OP와 같은 경우에도 작업에 적합한 도구를 사용하지 않을 가능성이 높습니다.Excel을 사용하는 경우 를 확인해 보십시오(다음 섹션 참조).
VBA 실행을 일시 중지하는 대신 운영을 위한 더 나은 솔루션
opp가 던진 질문은 그의 문제에 대한 최선의 해결책으로 이어지지 않습니다.XY-문제입니다.
매초마다 워크북을 다시 계산하기 위해 백그라운드에서 VBA 코드를 중단 없이 실행할 필요는 없습니다.이는 에서도 수행할 수 있는 일반적인 태스크의 예입니다.
복사 붙여넣기 솔루션을 포함한 상세 가이드를 통해 데이터 재계산Range 시간 ≥ 1s여기서 사용할 수 있습니다.
를 사용하는 의 큰 Application.OnTime이는 지속적으로 실행되는 매크로를 방지하기 때문에 매크로가 실행되는 동안 사용할 수 없는 다른 매크로 또는 기타 기능을 사용할 수 있습니다.
이 스레드의 다른 모든 솔루션에 대한 메타 분석
제가 이 답변을 작성한 이유는 이 스레드에 제시된 다른 모든 솔루션(이 게시물 작성 당시)에는 다음 두 가지 심각한 단점 중 하나 이상이 있기 때문입니다.
- 호출 응용 프로그램을 완전히 중지하여 더 이상 사용자 입력에 응답하지 않게 하거나,
- 호출을 통해 과도한 CPU 사용량(호출 애플리케이션의 스레드에서 100%)이 발생합니다.
DoEvents고리 모양으로
또한 제안된 솔루션의 대부분은 다음과 같은 다른 문제를 안고 있습니다.
일부는 Windows에서만 작동합니다.
일부는 Excel에서만 작동합니다.
일부는 1초 이상의 고유한 부정확성을 가지고 있습니다.
어떤 것들은 다른 문제나 심지어 버그를 가지고 있습니다.
다음 표에서는 이 스레드의 모든 솔루션과 해당 기능에 대한 간략한 개요를 제공합니다.
범례
| 기둥. | ✅ (좋음) | ❌ (나쁨) |
|---|---|---|
| 앱 응답 | 애플리케이션의 응답성 및 사용 가능성 유지 | 호출 중인 앱을 완전히 중지합니다. |
| CPU 사용량 | CPU 사용량이 거의 없음 | 단일 실행 스레드에서 100% CPU 사용량 |
| 교차 앱 | Excel 외부에서 작업 | Excel에서만 작동합니다. |
| Win/Mac | Windows와 Mac 모두에서 작동합니다. | Windows에서만 작동합니다. |
| 정밀한 | 시간 정밀도 < 0.1초 | 시간 정밀도 > 0.1초 (보통 약 1초) |
| 기타 문제 | 기타 문제 없음 | 아래 표에 설명된 다른 문제가 있습니다. |
개요
| 솔루션 기준 | 앱 응답 | CPU 사용량 | 교차 앱 | Win/Mac | 정밀한 | 기타 문제 |
|---|---|---|---|---|---|---|
| Ben S(인정) | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ |
| 버가빌 | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 아차이부 카림 | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ |
| 메이코 모우라 | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ |
| 클레모 | ✅ | ❌ | ❌ | ✅ | ❌ | ✅ |
| 사이버펑크 | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
| 버스커크 | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ |
| 리버스 | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
| 아나스타시야로마노바 秀 | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ |
| 앱스크립트.나야. | ❌ | ✅ | ❌ | ✅ | ❌ | ✅ |
| 브라이언 번스 | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
| 손에 넣다 | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ |
| ITI | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ |
| 데이브 | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ |
| GWD(본 게시물) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
기타 이슈
| 솔루션 사용자 | 기타 이슈 |
|---|---|
| 사이버펑크 | 호출 시 이 솔루션은 무기한 절전 모드로 전환됩니다.Timer() + vSeconds > 172800(vSevonds는 입력 값입니다.실제로, 이것은 큰 문제가 되지 않을 것입니다. 왜냐하면Timer()항상 86400 이하이므로 입력 값은 하루인 86400보다 커야 합니다.이러한 기능은 일반적으로 그렇게 오랫동안 호출되어서는 안 됩니다. |
| 리버스 | 이 솔루션은 특정 시간 동안 일시 중지할 수 없습니다!전화를 얼마나 자주 걸 것인지 지정하기만 하면 됩니다.DoEvents 기간은시스템의.이 기간은 시스템 속도에 따라 다릅니다.PC에서 를 내 PC 서최있이는함호출수에a라고 Long는 ( (일시 중지할 수 ) 약약 동안 (2147483647) (으)로 표시됩니다.는 약 1434초 또는 약 24분 동안 일시 중지됩니다.분명히, 이것은 끔찍한 "해결책"입니다. |
| 브라이언 번스 | 호출 시 이 솔루션은 무기한 절전 모드로 전환됩니다.Timer() + sngSecs > 86400(sngSecs는 입력 값입니다. ㅠㅠTimer()는 최대 86400까지 값을 반환할 수 있으며, 자정 직전에 이 함수를 호출하면 매우 작은 입력 값에서도 이 버그가 발생할 수 있습니다.이것은 심각한 버그이며 고려되어야 합니다! |
| 손에 넣다 | 이 솔루션은 전혀 대기하지 않습니다.,Application.Wait Second(Now) + dblInput다음보다 작은 입력 값을 전혀 기다리지 않습니다.CDbl(Now) - 60# / 86400#이것을 쓸 때 44815이고, 그것보다 더 큰 입력 값에 대해서는, 그것은 기다릴 것입니다.dblInput - CDbl(Now) - Second(Now) / 86400#days. 시간될 수 . 입력 값은 적절한 시간 동안 대기하도록 구성할 수 있지만, 이는 매우 어렵습니다.끔찍한 "해결책". |
| ITI | 코멘트는 이 기능이 최대 99초의 지연을 유발할 수 있다고 설명합니다.입력 값이 다음 위치에 있기 때문에 잘못된 것입니다.T Mod 100 > 60(Tparameter)는.is input parameter)에 됩니다.다음과 같이 함수를 호출하여 이를 확인할 수 있습니다.Delay 61 |
| 데이브 | 으로 이솔션은작만추지설가다정니됩로으적동올하바게를 설정합니다.Application.EnableEvents = True아무 이유 없이호출 코드가 이 속성을 다음으로 설정한 경우False그리고 합리적으로 이것과 관련이 없는 기능이 그것을 설정할 것이라고 기대하지 않습니다.True이로 인해 호출 코드에 심각한 버그가 발생할 수 있습니다.해당 라인이 삭제되면 해결책이 정상입니다. |
대기 및 절전 기능은 Excel을 잠그고 지연이 끝날 때까지 다른 작업을 할 수 없습니다.반면에 루프 지연은 대기 시간을 정확하게 제공하지 않습니다.
그래서, 저는 이 두 개념을 조금 결합하는 방법을 만들었습니다.원하는 시간이 될 때까지 순환합니다.
Private Sub Waste10Sec()
target = (Now + TimeValue("0:00:10"))
Do
DoEvents 'keeps excel running other stuff
Loop Until Now >= target
End Sub
웨이스트10에 전화하시면 됩니다.지연이 필요한 경우 초
수면에 대한 대안은 다음과 같습니다.
Sub TDelay(delay As Long)
Dim n As Long
For n = 1 To delay
DoEvents
Next n
End Sub
다음 코드에서 저는 사용자가 "문제가 있을" 경우 스핀 버튼에서 "글로우" 효과를 깜박여 사용자에게 지시합니다. 루프에서 "sleep 1000"을 사용하면 눈에 보이는 깜박임은 없지만 루프는 잘 작동합니다.
Sub SpinFocus()
Dim i As Long
For i = 1 To 3 '3 blinks
Worksheets(2).Shapes("SpinGlow").ZOrder (msoBringToFront)
TDelay (10000) 'this makes the glow stay lit longer than not, looks nice.
Worksheets(2).Shapes("SpinGlow").ZOrder (msoSendBackward)
TDelay (100)
Next i
End Sub
Application.Wait Second(Now) + 1
Function Delay(ByVal T As Integer)
'Function can be used to introduce a delay of up to 99 seconds
'Call Function ex: Delay 2 {introduces a 2 second delay before execution of code resumes}
strT = Mid((100 + T), 2, 2)
strSecsDelay = "00:00:" & strT
Application.Wait (Now + TimeValue(strSecsDelay))
End Function
저는 주로 타이머 기능을 사용하여 애플리케이션을 일시 중지합니다.이 코드를 당신의 코드에 삽입하세요.
T0 = Timer
Do
Delay = Timer - T0
Loop Until Delay >= 1 'Change this value to pause time for a certain amount of seconds
저는 문제에 답하기 위해 이것을 만들었습니다.
Sub goTIMER(NumOfSeconds As Long) 'in (seconds) as: call gotimer (1) 'seconds
Application.Wait now + NumOfSeconds / 86400#
'Application.Wait (Now + TimeValue("0:00:05")) 'other
Application.EnableEvents = True 'EVENTS
End Sub
응용프로그램을 사용할 수 있습니다.wait now + time value("00:00:01") 또는 Application.지금 대기 + 시계열(0,0,1)
사용해 보십시오.
Threading.thread.sleep(1000)
언급URL : https://stackoverflow.com/questions/1544526/how-to-pause-for-specific-amount-of-time-excel-vba
'programing' 카테고리의 다른 글
| Objective-C에서 객체 유형을 테스트하려면 어떻게 해야 합니까? (0) | 2023.04.28 |
|---|---|
| Eclipse에 일부 보이지 않는/흰색 공백 문자 표시 (0) | 2023.04.28 |
| 이름을 기준으로 속성 값을 가져오는 방법 (0) | 2023.04.23 |
| SQL Server에 10진수 값을 저장하는 방법 (0) | 2023.04.23 |
| Azure 자원 그룹이 특정 지역에 관련지어지는 이유는 무엇입니까? (0) | 2023.04.23 |