• 최초 작성일: 2022-11-21
  • 최종 수정일: 2022-11-21
  • 조회수: 2,149 회
  • 작성자: 권현욱 (엑셀러)
  • 강의 제목: 이벤트를 알면 무엇을 할 수 있을까?

엑셀러 권현욱

들어가기 전에 ㅡ 스페이스 펜 프로젝트

미국과 소련의 냉전이 한창이던 시절. 미국항공우주국 NASA은 우주에서 사용할 수 있는 펜을 개발하는 '스페이스 펜 프로젝트'를 진행했습니다. 수많은 전문가들을 동원하고 120만 달러를 들인 끝에 '우주 볼펜' 개발에 성공했습니다.

로드 중...

(이미지 출처: 위키피디아)

그런데 소련은 돈 한푼 들이지 않고 이 문제를 해결했습니다. 어떻게 된 것일까요?

문제의 본질에 천착하면 의외로 해결책이 쉽게 나올 수도 있습니다. '스페이스 펜 프로젝트'에서 문제 해결의 목적은 무엇일까요? 무중력 상태에서 필기할 도구를 찾는 것입니다. 소련은 연필을 사용함으로써 문제를 쉽게 해결한 반면 미국은 문제의 본질을 제대로 이해하지 못해서 어려운 길을 둘러갔습니다.

엑셀과 VBA를 배우는 목적도 마찬가지입니다(그렇지. 엑셀 얘기가 안 나올 리가 없지 ㅎㅎ). 여러 가지 현란한 기술을 습득하려 욕심내기 보다는 하나를 하더라도 깊이 있게 이해하는 것이 중요합니다. 문제의 근본 원인에 대한 고민은 말할 것도 없겠지요.



이번 강의 콘텐츠는 <엑셀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. 이벤트 프로시저 작성 순서

이벤트 프로시저는 '특정한 이벤트(동작)가 발생할 때 실행'되는 프로시저이며, 이벤트는 '특정한 개체와 연계되는 경우가 많다'라는 점을 다시 한 번 리마인드 하면서 진도를 나가도록 합니다. 꼭 이런 순서로 해야 한다고 어디 법전 같은데 나와 있는 건 아니지만 아래 순서로 접근하면 편리합니다.

  1. 어떤 이벤트를 사용할 것인지 결정한다.
  2. VB Editor Visual Basic Editor를 연다.
  3. VB Editor의 '프로젝트 탐색기'에서 해당 개체를 더블 클릭하고 이벤트를 선택한다. 예를 들어 워크북 관련 이벤트이면 '현재 통합 문서'를, 워크시트 관련 이벤트를 작성할 것이라면 해당 워크시트 개체를 더블 클릭한다.
  4. 개체용 코드 창다른 말로 클래스 모듈(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 개체에 대한 기본 개념이 이벤트 프로시저라는 새로운 것을 만나서 파워가 또 한 단계 업그레이드 되는 겁니다.

사건 사고가 빈번해서 인지 이번 가을은 여느 때보다 길게 느껴집니다. '그럼에도 불구하고' 깊어가는 가을을 만끽해야겠습니다.