PPT+VBA

새해 맞이 남은 시간 카운터(타이머)(+남은 시간 계산시 주의할 점)

쵸코난 2024. 12. 14. 13:01

 

 

지난 번에 실시간으로 D-Day를 표시하는 것과 비슷한 '남은 시간 카운터'입니다.

새로운 해가 가까이 다가오는 이 시점에서 새해맞이 카운터를 만들었습니다.

요즘 같은 시기 다른 이벤트가 있을 때도 타이머를 만들 때 유용하겠습니다.

 

 

1슬라이드에는 Timer 와 Clock 이라는 텍스트상자를 삽입합니다.

도형 이름으로 도형을 찾아가기 때문에 Alt+F10 창에서 도형 이름을 정확히 입력해야 합니다.

 

VBA코드를 Module1에 넣습니다.

 

더보기
Option Explicit

#If VBA7 Then
    Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, _
        ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
    Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
    Public TimerID As LongPtr                      '다른 타이머와 구별하기 위한 타이머의 고유ID(번호)
#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
    Public TimerID As Long                      '다른 타이머와 구별하기 위한 타이머의 고유ID(번호)
#End If

Const Default As Integer = 1                '시간을 출력할 슬라이드 번호
'"2025/01/01" 은  25년 1월 1일 0시를 가리킴. >> "2025/01/01 00:00:00"로 해도 됨.
Const DefaultTime As String = "2025/01/01"           '타이머 지정 시간

Public TargetTime As Date                   '타이머가 호출된 카운트
Public Pause As Boolean                     '타이머 일시정지용

Private Sub StartNow()
    
    StartTimer

End Sub

Private Sub StopNow()
    
    StopTimer

End Sub

Private Sub myTimer()
'1초마다 실행되는 함수로 절대 에러가 나서는 안됨.
'스스로를 호출하는 경우 에러 발생 가능성 높음.
    On Error Resume Next
    Dim d As Date, sDay As String
    Dim Csp As Long
    
    If Pause Then Exit Sub
    Csp = ActivePresentation.SlideShowWindow.View.CurrentShowPosition
    
    If TargetTime = 0 Then TargetTime = CDate(DefaultTime)
    
    ActivePresentation.Slides(Csp). _
        Shapes("Clock").TextFrame.TextRange.Text = Format(Now, "mm월 dd일 hh:mm:ss")
    
    d = TargetTime - Now
    'Debug.Print d, CDbl(d)
    If d >= 1 Then sDay = CInt(d) & "일 " Else sDay = ""
    ActivePresentation.Slides(Csp). _
        Shapes("Timer").TextFrame.TextRange.Text = sDay & _
            Format(d, "hh:mm:ss") & " 남음"
    If Csp = Default Then
        With ActivePresentation.Slides(Csp). _
            Shapes("Timer").TextFrame.TextRange
                .Font.Size = 66
                .Characters(.Length - 2, 3).Font.Size = 32
        End With
    End If
End Sub


'타이머를 시작 - 슬라이드 쇼 종료전 반드시 StopTimer(KillTimer) 해줘야 함.
Function StartTimer()
    If TargetTime = 0 Then TargetTime = DefaultTime
    If TimerID = 0& Then                                    ' 타이머 ID가 비어 있으면 타이머 시작
        TimerID = SetTimer(0&, 0&, 1000&, AddressOf myTimer)  ' 세번째 인수가 인터벌 간격(1000 = 1초)

    End If
End Function

'타이머를 종료
Function StopTimer()
    Dim i As Integer
    On Error Resume Next
    KillTimer 0&, TimerID       ' 타이머 서비스를 종료
    TimerID = 0&                ' 타이머ID도 초기화
End Function

'타이머를 잠시 중단
Sub PauseTimer()
    Pause = Not Pause
    If Pause Then
        ActivePresentation.SlideShowWindow.View.State = ppSlideShowPaused
    Else
        ActivePresentation.SlideShowWindow.View.State = ppSlideShowRunning
    End If
    
End Sub

'쇼 종료시 자동 실행
Sub OnSlideShowTerminate(SSW As SlideShowWindow)
    StopTimer
End Sub

'슬라이드가 시작하면 자동으로 타이머 시작
Sub OnSlideShowPageChange(ByVal SSW As SlideShowWindow)
    Dim Csp As Long
    Csp = ActivePresentation.SlideShowWindow.View.CurrentShowPosition
    If Csp = Default Or Csp = Default + 1 Then
        StartTimer
    Else
        StopTimer
    End If
End Sub

Private Sub ResetTimer()
    Dim usr As String
    Pause = True
    usr = InputBox("목표시간을 yyyy/mm/dd hh:mm:ss 스타일로 입력하세요." & vbNewLine & _
        "예: 2025/01/29 또는 2025/01/01 00:00:00", "목표시간설정", CStr(TargetTime))
    If Len(usr) = 0 Then Pause = False: Exit Sub
    TargetTime = CDate(usr)
    If TargetTime = 0 Or TargetTime < Now Then _
        MsgBox "yyyy/mm/dd hh:mm:ss 형식이 틀립니다.": Pause = False: Exit Sub
    
    StopTimer
    Pause = False
    StartTimer
End Sub

 

재생 화면 미리보기:

 

1슬라이드에서 타이머가 자동으로 시작되게 하려면 크게 두 가지 방법이 있습니다.

 

1. OnSlideShowPageChange 를 이용해서 1슬라이드이면 타이머를 시작하게 하는 것과

2. 클래스를 하나 만들고 이 클래스에서 OnSlideShowBegin 슬라이드쇼 이벤트를 감시하게 하는 방법이 있습니다.

 

2번은 클래스를 만들어야 해서 번거로워서 단순한 1번 방법을 이용했습니다.

하지만 1번 방법은 간혹 시작하지 않는 경우가 있는데 이 때 1슬라이드에 텍스트상자와 같은 Active-X 컨트롤을 삽입하면 그런 경우를 예방할 수 있습니다. 

그리고 기본적으로 ppt가 읽기전용 상태로 열리면 슬라이드의 텍스트를 바꿀 수 없으로 위 코드는 작동하지 않습니다.

 

 

대상 시간은 Const DefaultTime As String = "2025/1/29" 에서 설정합니다.

"2025/01/01" 은  25년 1월 1일 0시를 가리킵니다.

"2025/01/01 00:00:00"로 시간까지 지정해도 됩니다.

 

🎇시간을 계산할 때 주의할 점이 있습니다.

 

DateDiff("d", 시간1, 시간2) 로 계산하면 남은 시간이 하루 이하인 경우도 하루로 결과값을 리턴합니다.

Day(남은 시간)을 계산해도 반올림해서 하루 로 결과값을 리턴합니다.

그래서 남은 시간이 1이상일 경우만 하루 이상 남은 것으로 계산해야 합니다.

 

시간 혹은 날짜와 관련해서 VBA나 컴퓨터에서는 하루동안의 시간양을 숫자 1로 봅니다.

1900년 1월 1일에서 계속 1씩 즉 하루씩 증가시켜서 해당 날짜를 표현합니다.

예를 들어 2024/12/14 은 45640째 날이네요.

30은 한 달로 보고 365는 1년동안의 시간양입니다.

숫자 1 아래의 소숫점은 하루 안의 시분초를 나타냅니다.

60초*60분*24시간 = 86400초이므로 1초는 1/86400 입니다.

 

또 하나 주의할 것은 DateDiff 는 '단위'에 주의해야 합니다.

DateDiff("d", Date, Date+365) 는 오늘 날짜와 365'일' 후의 날짜의 차이인 365를  출력합니다.

DateDiff("m", Date, Date+365)  은 12를 출력합니다.

그런데 DateDiff("y", Date, Date+365) 는 1을 출력할 것 같지만 하지만 365를 출력합니다.

"y"는 년도의 양을 가리키는 것이 아니라 1년 안의 날수(Day of Year)를 나타내므로 365가 맞습니다.

DateDiff("yyyy", Date, Date+365) 라고 하면 1을 구할 수 있습니다.

주수는 w가 아니라 ww를 사용해야 하고 분은 m 이 아니라 n을 사용해야 합니다.

DateAdd 를 사용할 때도 마찬가지로 적용이 됩니다.

 

사소하지만 주의할 것 또 하나는 DateSerial(0,0,1)은 1일(하루동안)의 시간양을 나타내지 않습니다.

1900년 1월 1일부터 시작하므로 0년이라는 개념은 그 이전년도 과거를 의미합니다.

0월이라는 것도 1월에서 뒤로 한 달이므로 그 전년도 12월을 가리키게 됩니다.

DateSerial(0,0,1) 은 1900년 1월 1일에서 과거의 시간을 나타내므로  1을 리턴하지 않고 36495 라는 예상치 못한 결과를 리턴합니다.

 

참고: DateDiff/DateAdd의 날짜및시간단위

https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/datediff-function

 

 

>> 카운터 시간을 클릭하면 잠시 타이머를 멈춥니다.

 

>> 왼쪽 상단 톱니바퀴를 누르면 잠시 타이머를 멈추고 새로운 대상 시간을 설정합니다.

2025/01/29 이나 2025/01/29 00:00:00 으로 설정할 수 있습니다. 시스템 날짜 규칙 패턴을 따릅니다.

 

 

>> 시연 영상:

 

 

 

>> 읽기전용으로 열리는 경우 작동하지 않으므로 경기천년바탕Bold 체를 미리 설치하고 파워포인트 재시작하세요.

https://www.gg.go.kr/uploads/CONTENTS/site/gg/%EA%B2%BD%EA%B8%B0%EC%B2%9C%EB%85%84%EC%B2%B4_220929.zip

 

 

>> 샘플 파일:

송구영신1.pptm
7.13MB

 

 

>> 지식인 링크