
엑셀로 시계를 만든다?
놀랍지만 실제로 작동하는 아날로그 시계가 가능합니다!
오늘은 VBA(매크로)를 활용해, 엑셀 워크시트 위에 실시간으로 움직이는 시계를 구현하는 방법을 소개할게요.
💡 어떤 시계인가요?
이 매크로는 엑셀 시트에 다음과 같은 시계를 만들어줍니다:
- 🕒 12시 방향 숫자와 눈금이 있는 원형 시계
- ⏰ 시침/분침/초침이 실시간으로 갱신
- 🟢 매 1초마다 자동 업데이트 (Application.OnTime 사용)
- ⚙ 필요 시 시계 정지 버튼도 제공 (StopClock)
📌 핵심 구성요소
구성요소설명
| DrawClockFace | 시계 외곽, 숫자, 눈금, 중심 점 생성 |
| UpdateClock | 현재 시간을 읽어 바늘 각도 계산 후 그리기 |
| StartClock | 시계 시작 (초기화 및 타이머 등록) |
| StopClock | 시계 중지 (타이머 해제) |
📽 VBA 코드
Option Explicit
' ===== 설정값 =====
Private nextTime As Date
Private Const SHT As String = "Clock"
Private Const CX As Single = 200 ' 중심 X
Private Const CY As Single = 200 ' 중심 Y
Private Const R As Single = 150 ' 반지름
Private Const PI As Double = 3.14159265358979
' ===== 공개 진입점 =====
Public Sub StartClock()
Dim ws As Worksheet: Set ws = EnsureSheet(SHT)
DrawClockFace ws
UpdateClock
End Sub
Public Sub StopClock()
On Error Resume Next
Application.OnTime earliesttime:=nextTime, procedure:="UpdateClock", schedule:=False
On Error GoTo 0
End Sub
' ===== 유틸 =====
Private Function EnsureSheet(ByVal name As String) As Worksheet
On Error Resume Next
Set EnsureSheet = ThisWorkbook.Worksheets(name)
On Error GoTo 0
If EnsureSheet Is Nothing Then
Set EnsureSheet = ThisWorkbook.Worksheets.Add
EnsureSheet.name = name
End If
End Function
Private Sub DeleteByPrefix(ws As Worksheet, ByVal prefix As String)
Dim i As Long
For i = ws.Shapes.Count To 1 Step -1
If Left$(ws.Shapes(i).name, Len(prefix)) = prefix Then
ws.Shapes(i).Delete
End If
Next i
End Sub
Private Sub DeleteIfExists(ws As Worksheet, ByVal nm As String)
On Error Resume Next
ws.Shapes(nm).Delete
On Error GoTo 0
End Sub
' ===== 시계판 그리기 =====
Private Sub DrawClockFace(ws As Worksheet)
Dim i As Long, ang As Double
Dim x1 As Single, y1 As Single, x2 As Single, y2 As Single
Application.ScreenUpdating = False
' 이전 시계판 지우기(바늘 포함 모든 시계 객체)
DeleteByPrefix ws, "CLK_"
' 외곽 원판
With ws.Shapes.AddShape(msoShapeOval, CX - R, CY - R, 2 * R, 2 * R)
.name = "CLK_Dial"
.Fill.ForeColor.RGB = RGB(255, 255, 255)
.Line.Weight = 2
End With
' 12개 눈금 + 숫자
For i = 1 To 12
ang = (i / 12) * 2 * PI - PI / 2
' 굵은 눈금
x1 = CX + (R - 12) * Cos(ang): y1 = CY + (R - 12) * Sin(ang)
x2 = CX + (R - 2) * Cos(ang): y2 = CY + (R - 2) * Sin(ang)
With ws.Shapes.AddLine(x1, y1, x2, y2)
.name = "CLK_Tick_" & i
.Line.Weight = 2
End With
' 숫자
With ws.Shapes.AddTextbox(msoTextOrientationHorizontal, _
CX + (R - 28) * Cos(ang) - 10, _
CY + (R - 28) * Sin(ang) - 10, 30, 20)
.name = "CLK_Num_" & i
.TextFrame.Characters.Text = CStr(i)
.TextFrame.HorizontalAlignment = xlHAlignCenter
.TextFrame.VerticalAlignment = xlVAlignCenter
.Line.Visible = msoFalse
End With
Next
' 중심 캡
With ws.Shapes.AddShape(msoShapeOval, CX - 4, CY - 4, 8, 8)
.name = "CLK_Center"
.Fill.ForeColor.RGB = RGB(0, 0, 0)
.Line.Visible = msoFalse
End With
Application.ScreenUpdating = True
End Sub
' ===== 바늘 갱신 =====
Public Sub UpdateClock()
Dim ws As Worksheet: Set ws = EnsureSheet(SHT)
Dim h As Long, m As Long, s As Long
Dim ang As Double
Dim hLen As Single, mLen As Single, sLen As Single
h = Hour(Now): m = Minute(Now): s = Second(Now)
hLen = R * 0.5
mLen = R * 0.7
sLen = R * 0.85
Application.ScreenUpdating = False
' 이전 바늘 안전 삭제 (개별 삭제 → 1004 방지)
DeleteIfExists ws, "CLK_Hour"
DeleteIfExists ws, "CLK_Minute"
DeleteIfExists ws, "CLK_Second"
' 시침(분/초 반영)
ang = ((h Mod 12) + m / 60# + s / 3600#) * (2 * PI / 12#) - PI / 2
With ws.Shapes.AddLine(CX, CY, CX + hLen * Cos(ang), CY + hLen * Sin(ang))
.name = "CLK_Hour"
.Line.Weight = 4
End With
' 분침(초 반영)
ang = (m + s / 60#) * (2 * PI / 60#) - PI / 2
With ws.Shapes.AddLine(CX, CY, CX + mLen * Cos(ang), CY + mLen * Sin(ang))
.name = "CLK_Minute"
.Line.Weight = 3
End With
' 초침
ang = s * (2 * PI / 60#) - PI / 2
With ws.Shapes.AddLine(CX, CY, CX + sLen * Cos(ang), CY + sLen * Sin(ang))
.name = "CLK_Second"
.Line.Weight = 1
.Line.ForeColor.RGB = RGB(200, 0, 0)
End With
Application.ScreenUpdating = True
' 1초 후 예약
nextTime = Now + TimeSerial(0, 0, 1)
Application.OnTime earliesttime:=nextTime, procedure:="UpdateClock"
End Sub
✍ 사용 방법
1️⃣ VBA 코드 붙여넣기
- Alt + F11 → VBA 편집기 열기
- 새 모듈(Module) 생성 → 코드 전체 복사 & 붙여넣기
2️⃣ 시계 시작
StartClock
- 즉시 새로운 시트(Clock)에 시계가 생성됩니다.
- 초침이 1초마다 움직입니다.
3️⃣ 시계 정지
StopClock
- 타이머를 해제하여 시계 작동을 멈춥니다.
⚙ 주요 코드 포인트 설명
📐 시계 그리기: DrawClockFace
- 외곽 원판: 중심 좌표(CX, CY), 반지름(R)
- 눈금 & 숫자: Cos, Sin을 활용한 원형 배치
- 중심 점: 작고 검은 원으로 표현
ang = (i / 12) * 2 * PI - PI / 2 x = CX + R * Cos(ang) y = CY + R * Sin(ang)
🔄 시간 바늘 그리기: UpdateClock
- Now 함수로 시/분/초 추출
- 각도 계산 후 AddLine으로 바늘 그리기
- 기존 바늘은 삭제 후 새로 생성
🧪 실시간 동작 로직
nextTime = Now + TimeSerial(0, 0, 1) Application.OnTime earliesttime:=nextTime, procedure:="UpdateClock"
- 매 1초 후 UpdateClock 다시 실행
- Windows 시간과 싱크되어 정확하게 작동
⚠ 주의사항
항목설명
| 실행 중 중단 | Alt + Break 또는 StopClock을 호출해야 완전히 중단됩니다. |
| 다중 실행 | 여러 번 실행 시 바늘 중복 가능 → 중복 방지 코드 포함됨 |
| 파일 저장 | 매크로 포함 파일로 저장하세요 (.xlsm) |
💬 마무리
"엑셀로 시계 만든다니... 진짜 될까?"
→ 됩니다!