• 최초 작성일: 2000-08-08
  • 최종 수정일: 2026-09-30
  • 조회수: 9 회
  • 작성자: 권현욱 (엑셀러)
  • 강의 제목: Class Module 사용하기

들어가기 전에

오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.

대체로 실행(CommandButton) 버튼에는 이벤트 핸들러 프로시저가 연결이 되어 있습니다. 아래의 "Today's Sample" 버튼도 마찬가지입니다. 버튼에 특정 코드가 assign, 즉 매달려 있기 때문에 버튼을 클릭하면, 그에 따른 작동을 하게 되는 것입니다.

지금까지 강좌를 진행해 오면서 많은 유저폼 양식, 각종 컨트롤 등에 대해 설명을 드렸는데 대체적으로 한 개의 유저폼에 사용된 오브젝트의 수는 많아야 20개를 넘지 않았습니다. 그런데 오늘의 예제처럼 커맨드 버튼이 한 유저폼에 수십 개가 된다면? 그리고 각 버튼을 클릭할 때마다 특정한 작업을 수행하도록 프로그램 을 짜야한다면 어떻게 해야 할까요?

말로 하니까 먼 소린지 이해가 안가시지요? ^^ 절대 말로 해치우는 "Excel에 날개달기"가 아니니까… 아래 버튼을 눌러서 예제를 보고 오시기 바랍니다.

권현욱(엑셀러)
저자: 권현욱(엑셀러), 아이엑셀러 대표

필자는 Excel 컨설턴트, 작가, 그리고 크리에이터입니다. 현재 Microsoft Excel MVP이며, 『챗GPT+엑셀 업무자동화 정석』을 비롯한 10여 권의 도서를 집필했습니다. Excel 자동화 및 생산성 향상 분야에서 25년 넘는 경력을 보유하고 있습니다.

권현욱(엑셀러) 님의 최신 포스트:
  • 최신 글을 불러오는 중...


26년 경력 Microsoft MVP 권현욱(엑셀러) 대표 직강 1강 무료

🎁 파워툴스 마스터클래스 · 엑셀 바이브 코딩

AI에게 말로 지시해서 '나만의 엑셀 도구'를 만들고 리본에 장착합니다.

  • 코딩 지식 없이 시작 · 코드는 AI가 작성
  • 엑셀 리본에 내 탭과 버튼을 만들고 XLAM으로 공유
  • 1강 무료 수강 가능
수강 신청하기 강의 소개 보기

Class Module 사용하기

핵심 요약: 클래스 모듈로 버튼 이벤트 공유

클래스 모듈에서 WithEvents로 컨트롤을 선언하고 배열로 연결하면 수십 개 버튼의 이벤트를 한 곳에서 처리할 수 있습니다.

  • 1단계: 클래스 모듈 MyButtonClass에 Public WithEvents MyGroup을 선언하고 Click 이벤트를 작성합니다.
  • 2단계: 유저폼에 Dim MyButtons() As New MyButtonClass 배열을 선언합니다.
  • 3단계: Initialize에서 각 버튼을 ReDim Preserve로 늘린 배열에 Set으로 연결합니다.

Step 1: 결과 미리 보기

무슨 프로그램을 만들어 볼려는지 아시겠지요? 버튼을 클릭하니까 수십 개의 버튼이 달린 유저폼이 하나 나타납니다. 그리고 각각의 버튼을 다시 클릭하게 되면 "몇 번째 버튼이 클릭되었는지, 그 버튼의 유저폼 상에서의 좌표" 등에 대한 정보를 화면상에 표시하는 그런 프로그램입니다.

코드를 보시기 전에… 어떻게 프로그래밍을 했을지 생각해 보시기 바랍니다. 버튼을 몇십 개 만든다음에 각 버튼에 대한 코드를 모두 하나씩 코딩을 했을까요? 물론 시간이 팡팡 남아도 는 용감한(?) 사람이라면 그렇게 할 수도 있을 것입니다. 하지만 엄청난 인내를 요하는 작업이 되겠지요?

Today's Sample은 클래스 모듈을 사용한 것입니다.

Step 2: 클래스 모듈이란?

Class Module이란 용어를 들어 보셨는지? 아마 많은 분들이 처음 접해보시리라 생각합니다. 클래스 모듈을 잘 이해하시면 여러분의 내공은 또 한 단계 상승할 것입니다. 잘 익혀 두시기 바랍니다.

클래스 모듈은 모듈은 모듈인데 좀 특수한 형태의 것입니다. 지금까지는 두 가지 종류의 모듈을 사용해서 프로그램을 작성해 왔었습니다. 일반 VBA 모듈(general VBA module)과 코드 모듈(code module for VBA) 이 그것이었지요? 클래스 모듈이 VBA에 도입된 것은 Excel 97 버전부터인 것으로 기억이 됩니다.

클래스 모듈이란 "프로그래머로 하여금 새로운 오브젝트 클래스를 만들도록 해 주는 것" 이라고 할 수 있겠습니다(물론 그렇다고 해서 지금까지 존재하지 않던 그런 새로운 것이라는 뜻은 아닙니다).

쉽게 설명을 드리자면... 국화빵을 만들 때 빵틀과 국화빵의 관계를 잘 생각해 보시면 되겠군요. 국화빵 장수가 빵을 만들 때 사용하는 빵틀이 클래스 오브젝트의 역할을 수행한다고 생각하시기 바랍니다. 빵틀을 한번만 만들어 두면 열 번이고 스무 번이고 계속해서 같은 모양의 것을 생산해 낼 수가 있겠지요.

자, 그러면 국화빵틀을… 아니 클래스 모듈을 한번 만들어 보도록 하겠습니다.

Step 3: 유저폼과 클래스 모듈 만들기

(1) UserForm을 하나 삽입을 한 다음 아래와 같이 컨트롤들을 삽입합니다.예고한 바와 같이 각 컨트롤에 대한 상세한 설명은 생략합니다.

명령 버튼 25개와 종료 버튼이 있는 유저폼
아이엑셀러

(1) 클래스 모듈 작성

(2) VB Editor 상태에서 현재의 프로젝트에다가 클래스 모듈을 하나 삽입합니다. 프로젝트라고 하니까 '프 로젝트는 또 뭐야?' 하시는 분이 있으실지 모르겠는데 그냥 파일(워크북)이라고 생각하세요. 클래스 모듈이 삽입되었으면 이름을 Class1에서 "MyButtonClass"로 고쳐 줍니다. 이름은 어떻게 바꾸느냐 고요? 속성창에서(만약 속성창이 없으면 <F4>키를 눌러 보세요) 이름 속성을 바꾸어 주시면 됩니다.

클래스 모듈시트에 아래의 코드를 입력합니다.

Option Explicit
Public WithEvents MyGroup As MSForms.CommandButton
'Public이라는 새로운 것이 하나 나왔군요. 지금까지는 변수를 선언할 때 주로 Dim문을 사용했습니다.
'Dim문을 통해 변수를 정의하면 해당 프로시저 내에서만 사용을 할 수 있습니다(물론 모듈 도입부에
'사용하면 달라지긴 하지만…)
'Public으로 변수를 선언하면 (현재) 모듈 전체에서 그 변수를 (매번 선언하지 않아도) 사용할 수가 있게
'됩니다.

'만약 커맨드 버튼이 아니라 옵션 버튼에 대해 설정을 하고 싶다고 할 경우, Public WithEvents 선언을
'다음과 같이 바꾸어 주면 됩니다.
'Public WithEvents MyGroup As MSForms.OptionButton

Private Sub MyGroup_Click()
'아래 부분은 MyGroup의 클릭 이벤트에 대한 코드인데 별로 어려운 부분은 없을 것입니다.

    Dim Msg As String

    Const ID = "//Exceller"
    Msg = MyGroup.Caption & " 번 버튼을 선택하셨습니다." & vbCr & vbCr
    Msg = Msg & "버튼의 좌표는" & vbCr & vbCr
    Msg = Msg & "위에서부터 " & MyGroup.Top & "," & vbCr
    Msg = Msg & "왼쪽에서부터 " & MyGroup.Left & vbCr & vbCr
    Msg = Msg & "입니다."

    If Err <> 0 Then
        MsgBox "에러가 발생하였습니다.", , ID
        Exit Sub
    Else
        MsgBox Msg, vbInformation, ID
    End If
End Sub

(2) 유저폼 호출 프로시저

(3) 일반 VBA 모듈(general VBA module)을 하나 삽입한 다음, 유저폼을 호출하기 위한 코드를 작성합니다.

Sub ShowUserForm()
    UserForm1.Show
End Sub

(3) 유저폼 초기화 이벤트

(4) UserForm1을 불러낸 다음, 유저폼의 컨트롤이 없는 빈 공간을 더블클릭하여 코드 모듈이 나타나도록 합니다. 그 다음에 이벤트 선택상자에서 초기화 이벤트(Initialize)를 발생시키고 아래의 코드를 작성합니다.

Option Explicit
Option Base 1
Dim MyButtons() As New MyButtonClass
'먼저, MyButtons()라는 오브젝트 배열(Object Array)을 하나 선언을 합니다.

Private Sub UserForm_Initialize()
    Dim ctl As Control
    Dim intCount As Integer
    '필요한 변수를 미리 선언 해두고…

    For Each ctl In UserForm1.Controls
    '유저폼 내의 모든 컨트롤들을 대상으로 작업을 하되 "CommandButton"인 경우에만 If~EndIf 구문 내의
    '작업을 수행합니다.

        If TypeName(ctl) = "CommandButton" Then
            If ctl.Name <> "btnClose" Then
                intCount = intCount + 1
                ctl.Caption = intCount
                ReDim Preserve MyButtons(intCount)
                'ReDim문은 아실테고… Preserve라는 것은 사전적인 의미로는 "보존하다, 유지하다" 뭐 이런
                '뜻일 것입니다. 즉 "동적 배열변수의 저장공간을 재할당"하는 명령입니다. 다시 말해서 배열의
                '마지막 차원의 길이를 변경하고자 할 때, 동적배열에 이미 담겨져 있는 기존 자료를 보존하기
                '위한 명령입니다.

                '어떤 업무를 할 때 "이 일이 과연 할 필요가 있는 일인가?"하는 의구심이 들 때, 여러분은 어떻게
                '하십니까?" 그런 생각이 들면 그 일을 한번 하지 말아 보십시오. 그러다가 일정 시간이 지난 다음
                '에 누군가가 그 일(또는 결과물)을 다시 찾게 되면 필요한 일이고 그렇지 않으면 불필요한 일이
                '겠지요 ^^.

                '프로그래밍도 마찬가지입니다. Preserve라는 명령어가 무슨 역할을 수행하는지 궁금하시면
                '이것을 생략하고 프로그램을 실행시켜 보시면 되겠지요? 그래서 제대로 돌아가면 불필요한 것
                '이고 문제가 생기면 꼭 필요한 요소라 할 수 있을 것입니다.

                Set MyButtons(intCount).MyGroup = ctl
            End If
        End If
    Next ctl
End Sub

Private Sub btnClose_Click()
    Unload Me
End Sub

마무리

이렇게 하시면 됩니다. 이제 클래스 모듈이 무엇이고, 어떨 때 사용할 수 있는 것인지 아시겠습니까? 처음 볼 때 잘 이해가 안되면 일단 덮어두었다가 한 달쯤 지난 뒤에 다시 보시기 바랍니다. 서두에 말씀드린 바와 같이, 오늘 강좌를 이해하시면 공력이 한단계 올라갈 것입니다.

다음 시간에 또…

정리 — 클래스 모듈 핵심

구분 사용한 코드 역할
이벤트 선언 Public WithEvents MyGroup As MSForms.CommandButton 컨트롤 이벤트 수신
이벤트 처리 Private Sub MyGroup_Click() 공통 클릭 코드
배열 선언 Dim MyButtons() As New MyButtonClass 클래스 배열
배열 확장 ReDim Preserve MyButtons(intCount) 기존 값 보존
컨트롤 연결 Set MyButtons(intCount).MyGroup = ctl 버튼과 클래스 연결

자주 묻는 질문 (FAQ)

Q1. 클래스 모듈은 언제 사용하나요?

유저폼에 같은 종류의 컨트롤이 수십 개 있어서 각각 코드를 작성하기 어려울 때처럼, 새로운 오브젝트 클래스를 만들어 재사용하고 싶을 때 사용합니다.

Q2. Public으로 선언하면 무엇이 달라지나요?

변수를 매번 선언하지 않고도 모듈 전체에서 사용할 수 있습니다.

Q3. 옵션버튼에도 같은 방법을 쓸 수 있나요?

Public WithEvents 선언을 MSForms.OptionButton으로 바꾸면 됩니다.

마치며

처음에는 이해가 어려우면 일단 덮어 두었다가 한 달쯤 뒤에 다시 보시기 바랍니다.