이번 강의 콘텐츠는 <엑셀VBA 파워 코딩의 정석>(디지털북스)에서 편집/인용하였으며 저작권법의 보호를 받습니다.
컴퓨터 프로그래밍에서 이벤트Event란 '엑셀 작업 과정에서 벌어지는 어떤 상황'을 의미합니다. 파일을 열고 닫거나 버튼을 클릭하면 이벤트가 발생합니다. ENTER 키를 누르거나 셀의 값이 변경될 때에도 마찬가지입니다. 이벤트가 언제 발생하고 이벤트와 연계된 프로시저는 어떻게 활용하면 좋은 지 살펴보겠습니다.
이벤트 개념 이해
이벤트는 다양한 상황에서 발생합니다. 예를 들어 다음에 해당하는 경우 이벤트가 생깁니다.
- 워크북을 열거나 닫을 때
- 워크시트를 선택하거나 삽입 또는 삭제할 때
- 셀에 값을 입력하거나 수정할 때
- 특정한 키를 누를 때(예를 들어 PgUp, End 키)
- 특정 시간에 되었을 때(예를 들어 앞으로 5분 후 또는 오후 3시)
- 에러가 발생했을 때
이벤트 종류
지금까지 배운 프로시저는 대부분 사용자가 어떤 의도나 목적을 가지고 실행을 시켜야 작동하는 '일반 프로시저'였습니다. 이에 반해 '어떤 이벤트가 발생할 때 자동으로 실행되는 프로시저'가 있는데 이것을 '이벤트' 핸들러 프로시저Event-handler Procedure 또는 줄여서 이벤트 프로시저라고 부릅니다. 엑셀에서는 다양한 종류의 이벤트를 사용할 수 있습니다.
이벤트 프로시저는 특정한 개체와 연계되어 작동하는 경우가 많습니다. OnTime이나 OnKey 처럼 예외가 있기도 합니다만, 여기에서는 실무에서 많이 사용되는 워크북과 워크시트 이벤트를 중심으로 다룹니다.
1. 워크북 관련 이벤트
특정한 워크북과 관련된 이벤트입니다. 워크북을 열 때 발생하는 Open 이벤트, 워크북을 저장할 때 발생하는 BeforeSave 이벤트 등이 대표적입니다.
이벤트명 | 발생 시점 |
---|---|
Activate | 워크북이 활성화 되었을 때 |
BeforeClose | 워크북을 닫을 때 |
BeforePrint | 워크북을 출력할 때 |
BeforeSave | 워크북을 저장할 때 |
Deactivate | 워크북이 비활성화 될 때 |
NewSheet | 새로운 시트를 추가할 때 |
Open | 워크북을 열 때 |
SheetActivate | 워크북 내의 시트가 활성화 될 때 |
SheetBeforeDoubleClick | 셀을 더블 클릭할 때 |
SheetBeforeRightClick | 셀을 마우스 오른쪽 버튼으로 클릭할 때 |
SheetChange | 셀에 변동이 있을 때 |
SheetDeactivate | 시트가 비활성화 될 때 |
SheetSelectionChange | 선택이 변경될 때 |
WindowActivate | 창이 활성화 될 때 |
WindowDeactivate | 창이 비활성화 될 때 |
2. 워크시트 관련 이벤트
특정한 워크시트와 관련된 이벤트입니다. 셀 내용이 변경할 때 발생하는 Change 이벤트나 셀 선택을 변경할 때 생기는 SelectionChange 이벤트가 실무에서 많이 사용됩니다.
이벤트명 | 발생 시점 |
---|---|
Activate | 워크시트가 활성화 되었을 때 |
BeforeDelete | 워크시트를 지울 때 |
BeforeDoubleClick | 워크시트 내의 셀이 더블 클릭 되었을 때 |
BeforeRightClick | 워크시트 내의 셀을 마우스 오른쪽 버튼으로 클릭할 때 |
Change | 워크시트 내의 셀에 변동이 있을 경우 |
Deactivate | 워크시트가 비활성화 될 때 |
FollowHyperlink | 하이퍼링크를 클릭할 때 |
PivotTableUpdate | 피벗 테이블이 업데이트 될 때 |
SelectionChange | 선택 영역이 변경될 때 |
이쯤에서 이런 의문이 듭니다.
그렇다면 이렇게 많은 이벤트 프로시저를 다 외워야 하나요?
설마 그러기야 하려고요. 외울 필요 전혀 없습니다(그런 시도조차 하지 마세요^^). 이벤트 이름을 통해 어떤 경우에 사용될 지 짐작할 수 있을 정도면 충분합니다.
이벤트 프로시저 작성 방법
이벤트 프로시저라고 해서 일반 프로시저와 문법적인 차이가 있는 것은 아닙니다. 다만 프로시저를 작성하는 위치가 일반 모듈Module이 아니라 특정한 개체Object에 딸려 있다는 것과 실행할 때 고유의 인수를 받아서 함께 실행하는 경우가 자주 있다는 점에 유의하시기 바랍니다.
1. 이벤트 프로시저 작성 순서
이벤트 프로시저는 '특정한 이벤트(동작)가 발생할 때 실행'되는 프로시저이며, 이벤트는 '특정한 개체와 연계되는 경우가 많다'라는 점을 다시 한 번 리마인드 하면서 진도를 나가도록 합니다. 꼭 이런 순서로 해야 한다고 어디 법전 같은데 나와 있는 건 아니지만 아래 순서로 접근하면 편리합니다.
- 어떤 이벤트를 사용할 것인지 결정한다.
- VB Editor Visual Basic Editor를 연다.
- VB Editor의 '프로젝트 탐색기'에서 해당 개체를 더블 클릭하고 이벤트를 선택한다. 예를 들어 워크북 관련 이벤트이면 '현재 통합 문서'를, 워크시트 관련 이벤트를 작성할 것이라면 해당 워크시트 개체를 더블 클릭한다.
- 개체용 코드 창다른 말로 클래스 모듈(Class Module)에 코딩을 한다.
2. SelectionChange 이벤트 초간단 예제
'Sheet1'의 특정 셀을 선택하거나 영역을 선택할 때마다 선택된 영역의 주소를 메시지 박스에 표시해 주는 이벤트 프로시저를 작성해 보겠습니다.
(1) 워크시트 상태에서 ALT + F11 키를 눌러서 VB Editor가 나타나도록 합니다.
(2) VB Editor의 프로젝트 탐색기에서 'Sheet1' 개체를 더블 클릭합니다.
(3) '개체' 드롭 박스에서 'Worksheet'를, '프로시저' 드롭 박스에서 'SelectionChange'를 각각 선택합니다. 이렇게 하면 Private Sub Worksheet_SelectionChange 이벤트 프로시저가 자동으로 만들어집니다.
(4) 코드를 작성합니다. SelectionChange 프로시저는 하나의 인수(Target)를 넘겨 받아서 실행합니다. Target은 선택된 셀이나 셀 범위를 뜻합니다.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
MsgBox "선택하신 영역은 " & Target.Address & "입니다"
End Sub
CODE
활용 예 ㅡ 선택 영역 하이라이팅하고 합계 구하기
그림과 같은 표가 있습니다. 표 내부의 셀을 선택하면 그 셀이 속한 행과 열 방향을 특정한 색으로 강조 표시합니다. 동시에 선택된 영역과 관련된 다양한 합계(행/열/교차 영역)를 표 왼쪽 위에 함께 표시하는 예제를 만들어 보겠습니다.
완성 예 (1) ㅡ 단일 셀 선택
테이블 내에 있는 여러 개의 셀을 선택해도 제대로 작동합니다.
완성 예 (2) ㅡ 여러 셀 선택
[완성 예] 기능을 구현하기 위해 사용된 코드입니다. 'Range 개체 생성'과 관련된 이전 강의를 제대로 공부하셨다면 이해할 수 있는 수준입니다. 주석 설명과 함께 차분히 전체적인 흐름을 따라오시기 바랍니다.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rTbl As Range ''' 작업 대상 테이블에 접근하기 위한 변수
Dim rInter As Range ''' 교차 영역에 접근하기 위한 변수
Dim rUnion As Range ''' 지정 영역의 행/열 방향에 접근
Dim rRow As Range ''' 지정 영역의 행 방향에 접근
Dim rCol As Range ''' 지정 영역의 열 방향에 접근
On Error Resume Next ''' 오류가 발생하더라도 무조건 다음 구문 실행
Set rTbl = Me.Range("B4").Resize(15, 8) ''' 작업 대상 영역에 접근
If TypeName(Selection) <> "Range" Then Exit Sub ''' 선택된 대상이 Range 개체가 아니면 실행 중단
Set rInter = Intersect(Selection, rTbl) ''' 선택된 영역과 rTbl 영역이 중첩될 경우 rInter 변수에 저장
If rInter Is Nothing Then Exit Sub ''' rTbl 바깥 영역이 선택되었다면 실행 중단
''' 유효한 영역이 선택되었다면 행/열 방향 영역을 rRow, rCol, rUnion 변수에 각각 저장
Set rRow = Intersect(rInter.EntireRow, rTbl)
Set rCol = Intersect(rInter.EntireColumn, rTbl)
Set rUnion = Union(rRow, rCol)
With rTbl
.Interior.ColorIndex = xlNone ''' 셀 배경색 초기화
.Font.ColorIndex = 1 ''' 글자색을 검정색으로 지정
.Cells(1).Offset(-1) = "행 합계: " & Application.Sum(rRow) & _
", 열 합계: " & Application.Sum(rCol) & _
", 교차 영역 합계: " & Application.Sum(rInter)
''' Sum 함수를 이용하여 여러 영역의 합계를 구하고 셀에 표시
''' rTbl.Cells(1)은 B4 셀. 여기에서 Offset(-1), 즉 행 방향으로 1만큼 위로 이동한 B3 셀
End With
rUnion.Interior.ColorIndex = 6 ''' 선택된 영역의 행/열 방향 전체 영역에 노란색 배경색 지정
With rInter ''' 행과 열이 중첩되는 영역에 대해
.Font.ColorIndex = 2 ''' 글자색은 흰색
.Interior.ColorIndex = 3 ''' 셀 배경색은 빨간색
End With
End Sub
CODE
'VBA 필수 개체 이해하기' 강의에서 다루었던 Intersect와 Union 메서드에 대한 이해를 필요로 하는 내용이었습니다. 무슨 일이든 기본기를 잘 익혀두면 사방팔방으로 활용할 수 있습니다. Range 개체에 대한 기본 개념이 이벤트 프로시저라는 새로운 것을 만나서 파워가 또 한 단계 업그레이드 되는 겁니다.
사건 사고가 빈번해서 인지 이번 가을은 여느 때보다 길게 느껴집니다. '그럼에도 불구하고' 깊어가는 가을을 만끽해야겠습니다.