vba : introducing vba - cau.ac.krcau.ac.kr/~orist/2005_2/vb/vba.pdf · vba 입문강좌:...

62
VBA 입문강좌 : Introducing VBA BASIC & VB 관한 기초 지식 그러면 VBA 무엇인가? Introducing the Visual Basic Editor 코드 창에서 작업하기 Visual Basic 이라고 하니까, '그거... 예전에 사용하던 BASIC 비슷한 언어가 아닌가?' 하고 생각하는 분이 혹시 있을지도 모르겠습니다. 맞습니다! 하지만 사실 뿌리는 BASIC 두고 있습니다만 예전의 BASIC 언어와는 사뭇 다릅니다. BASIC & VB 관한 기초 지식 BASIC Beginner's All purpose Symbolic Instruction Code 이라는 프로그래밍 언어는 1964 미국의 Dartmouth 대학에서 개발한 프로그래밍 언어입니다. BASIC 이라는 단어에서도 있듯이 배우기가 상대적으로 용이한 언어라고 있습니다. 언어는 일반 사용자들도 쉽게 프로그래밍 있도록 하기 위해 인간의 언어(당연히 영어겠지요 ^^)유사하게 만들어진 언어라는 점에서 당시로서는 획기적인 일이었습니다. 하여튼 이렇게 개발된 BASIC 오랜 세월을 거치면서 꾸준히 발전을 하게 됩니다. 그러나 초기의 개발 컨셉처럼 '배우기는 (다른 랭귀지보다) 상대적으로 쉬운 '이지만 깊이 들어가면 갈수록 불편한 점이 두가지가 아니었으므로 프로그래밍을 처음 입문하는 단계에서 거쳐가는 언어라는 인식이 강했습니다. 이런 연유로 소위 컴퓨터 전문가들로부터는 천대를 받아온 것이 사실입니다. 그러다가 1991 Microsoft 사가 윈도우용 VB Visual Basic for Windows 세상에 내놓으면서부터 세간의 주목을 받게 됩니다. 제품이 나오면서부터 윈도우용 독립 실행 애플리케이션 stand-alone application 손쉽게 만들 있게 되었습니다. 결국 Visual Basic BASIC 뿌리를 두고 있으되 초기의 그것과는 사뭇 다른 형태를 갖추게 것이지요. Visual BASIC 같은 언어를 4 세대 언어 4GL 라고 하며, 별도의 독립된 프로그램 개발 전문 도구입니다. 과거 BASIC 언어에서 개체지향형 Object-oriented 언어로 탄생한 새로운 개념의 언어입니다. '개체지향형'이라고 하고 보니까 아주 그럴 보입니다만 알고 보면 것도 아닙니다. BASIC 같은 3 세대 언어에서는 하나에서 열까지 모두 새로 만들어 사용해야만 했습니다. 예를 들어서 네모 박스를 하나 그리려고 해도 점을 하나하나 찍어서 사각형을 만들어 밖에 없는, 속된 말로 땅에 헤딩을 밖에 없었습니다. 또한 이렇게 어렵사리 한번 작성한 것도 이곳 저곳에서 불러다 사용하기가 매우 힘이 들어 매번 맨땅에 대고 헤딩(?)해야 하는 경우도 적지 않았습니다.

Upload: dangminh

Post on 11-Mar-2018

238 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

VBA 입문강좌 Introducing VBA

bull BASIC amp VB 에 관한 기초 지식

bull 그러면 VBA 란 무엇인가

bull Introducing the Visual Basic Editor

bull 코드 창에서 작업하기

Visual Basic 이라고 하니까 그거 예전에 사용하던 BASIC 과 비슷한 언어가 아닌가 하고

생각하는 분이 혹시 있을지도 모르겠습니다 맞습니다 하지만 사실 그 뿌리는 BASIC 에 두고

있습니다만 예전의 BASIC 언어와는 사뭇 다릅니다

BASIC amp VB 에 관한 기초 지식

BASICBeginners All purpose Symbolic Instruction Code 이라는 프로그래밍 언어는 1964 년 미국의 Dartmouth

대학에서 개발한 프로그래밍 언어입니다 BASIC 이라는 단어에서도 알 수 있듯이 배우기가

상대적으로 용이한 언어라고 할 수 있습니다 즉 이 언어는 일반 사용자들도 쉽게 프로그래밍 할 수

있도록 하기 위해 인간의 언어(당연히 영어겠지요 ^^)와 유사하게 만들어진 언어라는 점에서

당시로서는 획기적인 일이었습니다

하여튼 이렇게 개발된 BASIC 은 오랜 세월을 거치면서 꾸준히 발전을 하게 됩니다

그러나 초기의 개발 컨셉처럼 배우기는 (다른 랭귀지보다) 상대적으로 쉬운 편이지만 깊이 들어가면

갈수록 불편한 점이 한 두가지가 아니었으므로 프로그래밍을 처음 입문하는 단계에서 거쳐가는

언어라는 인식이 강했습니다 이런 연유로 소위 컴퓨터 전문가들로부터는 천대를 받아온 것이

사실입니다 그러다가 1991 년 Microsoft 사가 윈도우용 VBVisual Basic for Windows 를 세상에

내놓으면서부터 세간의 주목을 받게 됩니다 이 제품이 나오면서부터 윈도우용 독립 실행

애플리케이션 stand-alone application 을 손쉽게 만들 수 있게 되었습니다 결국 Visual Basic 은 BASIC 에

뿌리를 두고 있으되 초기의 그것과는 사뭇 다른 형태를 갖추게 된 것이지요

Visual BASIC 과 같은 언어를 4 세대 언어 4GL 라고 하며 별도의 독립된 프로그램 개발 전문

도구입니다 과거 BASIC 언어에서 개체지향형 Object-oriented 언어로 탄생한 새로운 개념의 언어입니다

개체지향형이라고 하고 보니까 아주 그럴 듯 해 보입니다만 알고 보면 별 것도 아닙니다 BASIC 과

같은 3 세대 언어에서는 하나에서 열까지 모두 새로 만들어 사용해야만 했습니다 예를 들어서 네모

박스를 하나 그리려고 해도 점을 하나하나 찍어서 사각형을 만들어 낼 수 밖에 없는 속된 말로 맨

땅에 헤딩을 할 수 밖에 없었습니다 또한 이렇게 어렵사리 한번 작성한 것도 이곳 저곳에서 불러다

사용하기가 매우 힘이 들어 매번 맨땅에 대고 헤딩()을 해야 하는 경우도 적지 않았습니다

그러던 것이 Visual BASIC 이 등장하면서부터는 웬만한 것들은 이미 다 만들어져 있어서

프로그래머는 원하는 것을 마우스로 콕콕 찍어주기만 하면 되게 되었습니다 그래서 Visual 이라는

수식어가 앞에 붙었습니다(아마 그럴 것입니다) 그리고 이렇게 만들어진 네모 박스 같은 것을

오브젝트 Object 라고 합니다 이것을 그냥 오브젝트라고 부르면 좋을 것을 개체니 객체니 하고 굳이

번역을 해 놓아야 직성이 풀리는 모양이더군요 원래 의미대로 하자면 개체보다는 객체가 어울릴 듯

합니다

그러면 VBA 란 무엇인가

엑셀을 수년 동안 사용해 오던 분 중에서도 엑셀에 VBA 엔진이 장착되어 있다는 사실조차 모르고

지내는 분이 많더군요

그러면 VB 는 그렇게 해서 탄생하였다는 것을 알겠는데 VBA 는 또 머여요

이런 의문이 드시지요(들어야 정상입니다 ^^)

VBA 란 Visual Basic for Application 의 줄임말 입니다 즉 VB 는 VB 인데 특정한 애플리케이션을

위한 VB 라는 의미가 되는 것입니다 그러면 Application 은 또 뭔데요 하는 분이 저기 계시는군요

그냥 쉽게 엑셀이나 워드 파워포인트 등을 의미한다고 생각하세요 따라서 엑셀에서 VB 를 다룬다면

Visual Basic for Excel Application 이 되고 워드에서 접근한다면 Visual Basic for Word

Application 가 되겠지요 실제로 VB 등에서 프로그래밍을 할 때에는 그냥 Application 이라고 쓰는

대신 ExcelApplication 또는 WordApplication 등과 같은 형태로 사용합니다

현재 엑셀은 10 번째 버전까지 나와 있습니다 엑셀 XP 또는 엑셀 2002 이라고 불리는 것이 바로

그것입니다 엑셀에 VBA 가 포함된 것은 엑셀 5 버전부터이며 오피스 2000 버전부터는 모든 응용

프로그램에 VBA 엔진이 장착되었습니다(Auto CAD 같은 다른 벤더들의 Application 에도 VBA 가

포함되어 있습니다) 따라서 만약 여러분이 엑셀에 붙어있는 (다른 VBA 에 비해 상대적으로 복잡한)

VBA 를 마스터하신다면 다른 애플리케이션의 VBA 도 덩달아 마스터하게 됨은 물론이려니와 다른

애플리케이션을 위한 솔루션을 개발할 수도 있게 되는 것입니다 매력적이지 않습니까

Introducing Visual Basic Editor

자 그렇다면 그런 훌륭한 프로그래밍 도구가 Excel 의 어느 구석에 자리잡고 있는지 살펴보지

않을래야 않을 재간이 없지요 도구 - 매크로 - Visual Basic Editor 메뉴를 선택합니다(또는 Alt

+ F11 키를 눌러도 됩니다) 그러면 그림과 같은 Visual Basic Editor(이하 VB Editor)가

나타납니다 사용자마다 이 화면의 모양새가 조금씩 틀리겠지만 일단 이 4 개의 창이 가장 기본이

되는 것이라 할 수 있습니다 따라서 VB Editor 의 각 창에 대해 살펴보도록 하겠습니다

1 프로젝트 탐색기 Project Explorer window

탐색기라는 단어에서도 알 수 있듯이 현재 열려있는

파일(Workbook) 그 파일이 담고 있는 개체 등에 대한

정보를 제공해 주는 창입니다

만약 이 창이 화면에 나타나 있지 않다면 VB Editor

상태에서 보기 - 프로젝트 탐색기 상태에서 보기 - 프로젝트

탐색기 메뉴를 선택하거나 Ctrl + R 키를 누릅니다

프로젝트라고 하니까 뭔가 전문가적인 냄새()가 나고

거창해 보이는데 워크북(엑셀 파일)이나 추가기능 Add-in 파일

등이 각각 하나의 프로젝트 입니다

왼쪽 그림에서 + 표시가 되어 있는 부분을 클릭하면 -

표시로 바뀌면서 하위의 개체들이 펼쳐집니다 반대로 -

표시가 되어있을 때 이 부분을 클릭하면 하위의

오브젝트들이 숨겨집니다

2 속성 창 Property window

해당 개체오브젝트의 속성프로퍼티 값에 대한 정보를 보여줍니다

이 창에서 속성값들을 직접 변경해 줄 수 있습니다

만약 속성 창이 보이지 않는다면 보기 - 속성 창 메뉴를

선택하거나 F4 키를 누르면 나타날 것입니다

3 코드 입력 창 Code window

매크로 기록기를 사용해서 기록을 하거나 사용자가 직접 코드를 입력할 수 있는 창입니다 해당

파일에 모듈 시트가 하나도 없다면 이 창은 회색 바탕의 공백 화면으로 보일 수도 있습니다 만약 이

창이 화면에 나타나 있지 않다면 VB Editor 상태에서 보기 - 코드 메뉴를 선택하거나 F7 키를

눌러주면 나타날 것입니다

4 직접 실행 창 Immediate window

VBA 는 뛰어난 디버깅 Debugging 오류 바로 잡기 도구를 가지고 있는데 그 중 하나가 이 직접 실행

창입니다 말 그대로 입력한 코드가 잘 작동하는지의 여부를 직접 실행해 볼 수 있는 창입니다

사용해 보면 아주 편리한 도구라는 것을 알 수 있습니다 직접 실행 창이 보이지 않으면 보기 - 직접

실행 창 메뉴를 선택하거나 Ctrl + G 키를 누릅니다

코드 창 Code window 에서 작업하기

이상에서 VBA 의 얼굴이라고 할 수 있는 VB Editor window 에 대해 살펴보았습니다 이제

여러분들이 VBA 와 친해질수록 점점 더 많은 시간을 보내게 될 코드 창 Code window 에서 코드를

작성하고 실행하는 방법에 대해 탐험해 보겠습니다

(1) 파일 - 새로 만들기 메뉴를 선택하여 새로운 통합 문서를 하나 만듭니다

(2) 도구 - 매크로 - Visual Basic Editor 메뉴를 선택하여 VB Editor 창으로 들어갑니다

(3) 삽입 - 모듈 메뉴를 선택하면 모듈이 한 장 삽입됩니다 만약 코드 창 윗부분에 Option

Explicit 라는 문장이 나타나면 삭제를 하거나 앞에 (작은 따옴표)를 붙여 주석으로 처리합니다

(4) 코드 창에 아래와 같이 코드를 입력합니다

Sub 안녕하세요()

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

If Answer = vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

End Sub

(5) 입력이 끝났으면 실행을 시켜 보아야겠지요 실행을 시키는 데에는 몇 가지 방법이 있습니다

실행하고자 하는 코드 내에 커서를 위치시킨 다음

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 2: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

그러던 것이 Visual BASIC 이 등장하면서부터는 웬만한 것들은 이미 다 만들어져 있어서

프로그래머는 원하는 것을 마우스로 콕콕 찍어주기만 하면 되게 되었습니다 그래서 Visual 이라는

수식어가 앞에 붙었습니다(아마 그럴 것입니다) 그리고 이렇게 만들어진 네모 박스 같은 것을

오브젝트 Object 라고 합니다 이것을 그냥 오브젝트라고 부르면 좋을 것을 개체니 객체니 하고 굳이

번역을 해 놓아야 직성이 풀리는 모양이더군요 원래 의미대로 하자면 개체보다는 객체가 어울릴 듯

합니다

그러면 VBA 란 무엇인가

엑셀을 수년 동안 사용해 오던 분 중에서도 엑셀에 VBA 엔진이 장착되어 있다는 사실조차 모르고

지내는 분이 많더군요

그러면 VB 는 그렇게 해서 탄생하였다는 것을 알겠는데 VBA 는 또 머여요

이런 의문이 드시지요(들어야 정상입니다 ^^)

VBA 란 Visual Basic for Application 의 줄임말 입니다 즉 VB 는 VB 인데 특정한 애플리케이션을

위한 VB 라는 의미가 되는 것입니다 그러면 Application 은 또 뭔데요 하는 분이 저기 계시는군요

그냥 쉽게 엑셀이나 워드 파워포인트 등을 의미한다고 생각하세요 따라서 엑셀에서 VB 를 다룬다면

Visual Basic for Excel Application 이 되고 워드에서 접근한다면 Visual Basic for Word

Application 가 되겠지요 실제로 VB 등에서 프로그래밍을 할 때에는 그냥 Application 이라고 쓰는

대신 ExcelApplication 또는 WordApplication 등과 같은 형태로 사용합니다

현재 엑셀은 10 번째 버전까지 나와 있습니다 엑셀 XP 또는 엑셀 2002 이라고 불리는 것이 바로

그것입니다 엑셀에 VBA 가 포함된 것은 엑셀 5 버전부터이며 오피스 2000 버전부터는 모든 응용

프로그램에 VBA 엔진이 장착되었습니다(Auto CAD 같은 다른 벤더들의 Application 에도 VBA 가

포함되어 있습니다) 따라서 만약 여러분이 엑셀에 붙어있는 (다른 VBA 에 비해 상대적으로 복잡한)

VBA 를 마스터하신다면 다른 애플리케이션의 VBA 도 덩달아 마스터하게 됨은 물론이려니와 다른

애플리케이션을 위한 솔루션을 개발할 수도 있게 되는 것입니다 매력적이지 않습니까

Introducing Visual Basic Editor

자 그렇다면 그런 훌륭한 프로그래밍 도구가 Excel 의 어느 구석에 자리잡고 있는지 살펴보지

않을래야 않을 재간이 없지요 도구 - 매크로 - Visual Basic Editor 메뉴를 선택합니다(또는 Alt

+ F11 키를 눌러도 됩니다) 그러면 그림과 같은 Visual Basic Editor(이하 VB Editor)가

나타납니다 사용자마다 이 화면의 모양새가 조금씩 틀리겠지만 일단 이 4 개의 창이 가장 기본이

되는 것이라 할 수 있습니다 따라서 VB Editor 의 각 창에 대해 살펴보도록 하겠습니다

1 프로젝트 탐색기 Project Explorer window

탐색기라는 단어에서도 알 수 있듯이 현재 열려있는

파일(Workbook) 그 파일이 담고 있는 개체 등에 대한

정보를 제공해 주는 창입니다

만약 이 창이 화면에 나타나 있지 않다면 VB Editor

상태에서 보기 - 프로젝트 탐색기 상태에서 보기 - 프로젝트

탐색기 메뉴를 선택하거나 Ctrl + R 키를 누릅니다

프로젝트라고 하니까 뭔가 전문가적인 냄새()가 나고

거창해 보이는데 워크북(엑셀 파일)이나 추가기능 Add-in 파일

등이 각각 하나의 프로젝트 입니다

왼쪽 그림에서 + 표시가 되어 있는 부분을 클릭하면 -

표시로 바뀌면서 하위의 개체들이 펼쳐집니다 반대로 -

표시가 되어있을 때 이 부분을 클릭하면 하위의

오브젝트들이 숨겨집니다

2 속성 창 Property window

해당 개체오브젝트의 속성프로퍼티 값에 대한 정보를 보여줍니다

이 창에서 속성값들을 직접 변경해 줄 수 있습니다

만약 속성 창이 보이지 않는다면 보기 - 속성 창 메뉴를

선택하거나 F4 키를 누르면 나타날 것입니다

3 코드 입력 창 Code window

매크로 기록기를 사용해서 기록을 하거나 사용자가 직접 코드를 입력할 수 있는 창입니다 해당

파일에 모듈 시트가 하나도 없다면 이 창은 회색 바탕의 공백 화면으로 보일 수도 있습니다 만약 이

창이 화면에 나타나 있지 않다면 VB Editor 상태에서 보기 - 코드 메뉴를 선택하거나 F7 키를

눌러주면 나타날 것입니다

4 직접 실행 창 Immediate window

VBA 는 뛰어난 디버깅 Debugging 오류 바로 잡기 도구를 가지고 있는데 그 중 하나가 이 직접 실행

창입니다 말 그대로 입력한 코드가 잘 작동하는지의 여부를 직접 실행해 볼 수 있는 창입니다

사용해 보면 아주 편리한 도구라는 것을 알 수 있습니다 직접 실행 창이 보이지 않으면 보기 - 직접

실행 창 메뉴를 선택하거나 Ctrl + G 키를 누릅니다

코드 창 Code window 에서 작업하기

이상에서 VBA 의 얼굴이라고 할 수 있는 VB Editor window 에 대해 살펴보았습니다 이제

여러분들이 VBA 와 친해질수록 점점 더 많은 시간을 보내게 될 코드 창 Code window 에서 코드를

작성하고 실행하는 방법에 대해 탐험해 보겠습니다

(1) 파일 - 새로 만들기 메뉴를 선택하여 새로운 통합 문서를 하나 만듭니다

(2) 도구 - 매크로 - Visual Basic Editor 메뉴를 선택하여 VB Editor 창으로 들어갑니다

(3) 삽입 - 모듈 메뉴를 선택하면 모듈이 한 장 삽입됩니다 만약 코드 창 윗부분에 Option

Explicit 라는 문장이 나타나면 삭제를 하거나 앞에 (작은 따옴표)를 붙여 주석으로 처리합니다

(4) 코드 창에 아래와 같이 코드를 입력합니다

Sub 안녕하세요()

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

If Answer = vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

End Sub

(5) 입력이 끝났으면 실행을 시켜 보아야겠지요 실행을 시키는 데에는 몇 가지 방법이 있습니다

실행하고자 하는 코드 내에 커서를 위치시킨 다음

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 3: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

1 프로젝트 탐색기 Project Explorer window

탐색기라는 단어에서도 알 수 있듯이 현재 열려있는

파일(Workbook) 그 파일이 담고 있는 개체 등에 대한

정보를 제공해 주는 창입니다

만약 이 창이 화면에 나타나 있지 않다면 VB Editor

상태에서 보기 - 프로젝트 탐색기 상태에서 보기 - 프로젝트

탐색기 메뉴를 선택하거나 Ctrl + R 키를 누릅니다

프로젝트라고 하니까 뭔가 전문가적인 냄새()가 나고

거창해 보이는데 워크북(엑셀 파일)이나 추가기능 Add-in 파일

등이 각각 하나의 프로젝트 입니다

왼쪽 그림에서 + 표시가 되어 있는 부분을 클릭하면 -

표시로 바뀌면서 하위의 개체들이 펼쳐집니다 반대로 -

표시가 되어있을 때 이 부분을 클릭하면 하위의

오브젝트들이 숨겨집니다

2 속성 창 Property window

해당 개체오브젝트의 속성프로퍼티 값에 대한 정보를 보여줍니다

이 창에서 속성값들을 직접 변경해 줄 수 있습니다

만약 속성 창이 보이지 않는다면 보기 - 속성 창 메뉴를

선택하거나 F4 키를 누르면 나타날 것입니다

3 코드 입력 창 Code window

매크로 기록기를 사용해서 기록을 하거나 사용자가 직접 코드를 입력할 수 있는 창입니다 해당

파일에 모듈 시트가 하나도 없다면 이 창은 회색 바탕의 공백 화면으로 보일 수도 있습니다 만약 이

창이 화면에 나타나 있지 않다면 VB Editor 상태에서 보기 - 코드 메뉴를 선택하거나 F7 키를

눌러주면 나타날 것입니다

4 직접 실행 창 Immediate window

VBA 는 뛰어난 디버깅 Debugging 오류 바로 잡기 도구를 가지고 있는데 그 중 하나가 이 직접 실행

창입니다 말 그대로 입력한 코드가 잘 작동하는지의 여부를 직접 실행해 볼 수 있는 창입니다

사용해 보면 아주 편리한 도구라는 것을 알 수 있습니다 직접 실행 창이 보이지 않으면 보기 - 직접

실행 창 메뉴를 선택하거나 Ctrl + G 키를 누릅니다

코드 창 Code window 에서 작업하기

이상에서 VBA 의 얼굴이라고 할 수 있는 VB Editor window 에 대해 살펴보았습니다 이제

여러분들이 VBA 와 친해질수록 점점 더 많은 시간을 보내게 될 코드 창 Code window 에서 코드를

작성하고 실행하는 방법에 대해 탐험해 보겠습니다

(1) 파일 - 새로 만들기 메뉴를 선택하여 새로운 통합 문서를 하나 만듭니다

(2) 도구 - 매크로 - Visual Basic Editor 메뉴를 선택하여 VB Editor 창으로 들어갑니다

(3) 삽입 - 모듈 메뉴를 선택하면 모듈이 한 장 삽입됩니다 만약 코드 창 윗부분에 Option

Explicit 라는 문장이 나타나면 삭제를 하거나 앞에 (작은 따옴표)를 붙여 주석으로 처리합니다

(4) 코드 창에 아래와 같이 코드를 입력합니다

Sub 안녕하세요()

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

If Answer = vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

End Sub

(5) 입력이 끝났으면 실행을 시켜 보아야겠지요 실행을 시키는 데에는 몇 가지 방법이 있습니다

실행하고자 하는 코드 내에 커서를 위치시킨 다음

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 4: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

표시가 되어있을 때 이 부분을 클릭하면 하위의

오브젝트들이 숨겨집니다

2 속성 창 Property window

해당 개체오브젝트의 속성프로퍼티 값에 대한 정보를 보여줍니다

이 창에서 속성값들을 직접 변경해 줄 수 있습니다

만약 속성 창이 보이지 않는다면 보기 - 속성 창 메뉴를

선택하거나 F4 키를 누르면 나타날 것입니다

3 코드 입력 창 Code window

매크로 기록기를 사용해서 기록을 하거나 사용자가 직접 코드를 입력할 수 있는 창입니다 해당

파일에 모듈 시트가 하나도 없다면 이 창은 회색 바탕의 공백 화면으로 보일 수도 있습니다 만약 이

창이 화면에 나타나 있지 않다면 VB Editor 상태에서 보기 - 코드 메뉴를 선택하거나 F7 키를

눌러주면 나타날 것입니다

4 직접 실행 창 Immediate window

VBA 는 뛰어난 디버깅 Debugging 오류 바로 잡기 도구를 가지고 있는데 그 중 하나가 이 직접 실행

창입니다 말 그대로 입력한 코드가 잘 작동하는지의 여부를 직접 실행해 볼 수 있는 창입니다

사용해 보면 아주 편리한 도구라는 것을 알 수 있습니다 직접 실행 창이 보이지 않으면 보기 - 직접

실행 창 메뉴를 선택하거나 Ctrl + G 키를 누릅니다

코드 창 Code window 에서 작업하기

이상에서 VBA 의 얼굴이라고 할 수 있는 VB Editor window 에 대해 살펴보았습니다 이제

여러분들이 VBA 와 친해질수록 점점 더 많은 시간을 보내게 될 코드 창 Code window 에서 코드를

작성하고 실행하는 방법에 대해 탐험해 보겠습니다

(1) 파일 - 새로 만들기 메뉴를 선택하여 새로운 통합 문서를 하나 만듭니다

(2) 도구 - 매크로 - Visual Basic Editor 메뉴를 선택하여 VB Editor 창으로 들어갑니다

(3) 삽입 - 모듈 메뉴를 선택하면 모듈이 한 장 삽입됩니다 만약 코드 창 윗부분에 Option

Explicit 라는 문장이 나타나면 삭제를 하거나 앞에 (작은 따옴표)를 붙여 주석으로 처리합니다

(4) 코드 창에 아래와 같이 코드를 입력합니다

Sub 안녕하세요()

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

If Answer = vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

End Sub

(5) 입력이 끝났으면 실행을 시켜 보아야겠지요 실행을 시키는 데에는 몇 가지 방법이 있습니다

실행하고자 하는 코드 내에 커서를 위치시킨 다음

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 5: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

4 직접 실행 창 Immediate window

VBA 는 뛰어난 디버깅 Debugging 오류 바로 잡기 도구를 가지고 있는데 그 중 하나가 이 직접 실행

창입니다 말 그대로 입력한 코드가 잘 작동하는지의 여부를 직접 실행해 볼 수 있는 창입니다

사용해 보면 아주 편리한 도구라는 것을 알 수 있습니다 직접 실행 창이 보이지 않으면 보기 - 직접

실행 창 메뉴를 선택하거나 Ctrl + G 키를 누릅니다

코드 창 Code window 에서 작업하기

이상에서 VBA 의 얼굴이라고 할 수 있는 VB Editor window 에 대해 살펴보았습니다 이제

여러분들이 VBA 와 친해질수록 점점 더 많은 시간을 보내게 될 코드 창 Code window 에서 코드를

작성하고 실행하는 방법에 대해 탐험해 보겠습니다

(1) 파일 - 새로 만들기 메뉴를 선택하여 새로운 통합 문서를 하나 만듭니다

(2) 도구 - 매크로 - Visual Basic Editor 메뉴를 선택하여 VB Editor 창으로 들어갑니다

(3) 삽입 - 모듈 메뉴를 선택하면 모듈이 한 장 삽입됩니다 만약 코드 창 윗부분에 Option

Explicit 라는 문장이 나타나면 삭제를 하거나 앞에 (작은 따옴표)를 붙여 주석으로 처리합니다

(4) 코드 창에 아래와 같이 코드를 입력합니다

Sub 안녕하세요()

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

If Answer = vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

End Sub

(5) 입력이 끝났으면 실행을 시켜 보아야겠지요 실행을 시키는 데에는 몇 가지 방법이 있습니다

실행하고자 하는 코드 내에 커서를 위치시킨 다음

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 6: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

(3) 삽입 - 모듈 메뉴를 선택하면 모듈이 한 장 삽입됩니다 만약 코드 창 윗부분에 Option

Explicit 라는 문장이 나타나면 삭제를 하거나 앞에 (작은 따옴표)를 붙여 주석으로 처리합니다

(4) 코드 창에 아래와 같이 코드를 입력합니다

Sub 안녕하세요()

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

If Answer = vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

End Sub

(5) 입력이 끝났으면 실행을 시켜 보아야겠지요 실행을 시키는 데에는 몇 가지 방법이 있습니다

실행하고자 하는 코드 내에 커서를 위치시킨 다음

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 7: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

① F5 키를 누르는 방법

② 실행 - Sub사용자 정의 폼 실행 메뉴를 사용하는 방법

③ 도구 모음에 있는 실행 아이콘을 클릭하는 방법

어떤 방법을 선택하느냐는 여러분의 가치관( 이랄 것 까지야 없겠군요 ^^)에 따라 편한 방법을

골라 쓰시면 됩니다 이 세 가지 방법 중 하나를 선택하면 다음과 같은 메시지 박스가 나타날

것입니다

예 또는 아니오 버튼 중 하나를 눌러보면 코드로 작성한 메시지가 나타납니다

컴퓨터(엑셀) 한테서 인사를 받아본 기분이 어떠신가요 그저 딱딱한 기계 덩어리로만 생각해 오던

컴퓨터가 보다 인간적인 모습으로 다가오지 않나요 ^^ 코드를 살펴보도록 하지요

Sub 안녕하세요()

어쩌고 저쩌고

End Sub

이처럼 Sub 로 시작해서 End Sub 로 끝나는 코드를 프로시저 또는 서브 프로시저라고 부릅니다

즉 Sub ~ End Sub 사이에 코드를 작성함으로써 컴퓨터에게 작업 지시를 내리는 것입니다

어쩌고 저쩌고

Msg = ApplicationUserName amp 님 안녕하세요

Answer = MsgBox(Msg vbYesNo)

어쩌고 저쩌고

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 8: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

ApplicationUserName 이라는 것은 현재 애플리케이션(즉 엑셀)의 사용자명을 알아내는

명령어입니다 엑셀을 설치할 때 사용자 기본 정보를 입력하게 되는데 이 때 등록된 사용자명을

알아냅니다 그런 다음 amp 연산자를 이용하여 두 개의 문자열로 합쳐서 Msg 라는 문자열 변수에 값을

저장해 둡니다

MsgBox 함수는 메시지 박스를 화면에 띄워주는 함수입니다 직접 실행 창에다가 아래와 같이

입력하고 엔터키를 쳐 보세요 안녕하세요 라는 메시지 박스가 나타납니다

Msgbox 안녕하세요

그런데 MsgBox 함수에 보니까 vbYesNo 라는 이상한 것이 있지요 이것을 내장 상수 Built-in

constants 라고 하는데 MsgBox 에 어떤 버튼이 표시되도록 할 것인지를 지정합니다 아래와 같이

다양한 값을 지정해 줄 수 있습니다

상 수 값 설 명

vbOKOnly 0 확인 단추 전용(default)

vbOKCancel 1 확인 취소 단추

vbAbortRetryIgnore 2 중지 다시 시도 무시 단추

vbYesNoCancel 3 예 아니오 취소 단추

vbYesNo 4 예 아니오 단추

vbRetryCancel 5 다시 시도 취소 단추

vbCritical 16 치명적 오류 메시지

vbQuestion 32 경고 질문

vbExclamation 48 경고 메시지

vbInformation 64 정보 메시지

vbDefaultButton1 0 첫째 단추가 기본값입니다(default)

vbDefaultButton2 256 둘째 단추가 기본값입니다

vbDefaultButton3 512 셋째 단추가 기본값입니다

vbDefaultButton4 768 넷째 단추가 기본값입니다

vbApplicationModal 0 응용 프로그램 모달 메시지 상자(default)

vbSystemModal 4096 시스템 모달 메시지 상자

vbMsgBoxHelpButton 16384 메시지 상자에 도움말 단추를 추가합니다

vbMsgBoxSetForeground 65536 메시지 상자를 전경 창으로 지정합니다

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 9: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

vbMsgBoxRight 524288 텍스트가 오른쪽 맞춤 되었습니다

vbMsgBoxRtlReading 1048576 히브리어와 아랍어 시스템의 경우 텍스트의

읽기 방향이 오른쪽에서 왼쪽으로

나타나도록 지정합니다

여기서 상수 대신 값을 써 주어도 됩니다 즉 아래 두 문장의 결과는 같습니다

MsgBox 안녕하세요vbYesNo

MsgBox 안녕하세요4

화면에 두 개의 버튼이 있는 MsgBox 가 나타나는데 사용자는 이 중에서 하나의 버튼을 누르게

됩니다 예와 아니오 중 어느 것을 선택했는지 알아야 나중에 다른 작업을 할 수 있겠지요 어떤

버튼을 눌 는지를 파악해서 Answer 라는 변수에 담아두는 과정이 아래의 한 줄로 해결이 됩니다

Answer=MsgBox(MsgvbYesNo)

워크시트에서 If 구문을 사용할 때

If(조건식 참인 경우 거짓인 경우)

이러한 형태로 사용을 하였지요 VBA 상에서도 비슷한 형태로 사용합니다 Answer 라는 변수에

저장된 값이(즉 사용자가 선택한 버튼이) vbYes 이면 안녕하시다니 다행이네요 메시지를 저장된

값이 vbNo 라면 저런 무슨 일이 있었나요 라는 메시지 박스가 화면에 나타납니다

If Answer=vbYes Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

이 때 MsgBox 함수의 반환값은 상수 형태를 사용해도 되고 값 형태를 사용해도 됩니다 즉 위의

코드는 아래와 같이 바꿀 수 있다는 얘기가 되지요 어떤 것이 편리한 지는 자명할 것입니다

If Answer=6 Then

MsgBox 안녕하시다니 다행이네요

Else

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 10: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

MsgBox 저런 무슨 일이 있었나요

End If

상 수 값 설 명

vbOK 1 확인

vbCancel 2 취소

vbAbort 3 중단

vbRetry 4 다시 시도

vbIgnore 5 무시

vbYes 6 예

vbNo 7 아니오

한꺼번에 너무 많이 하면 머리에 쥐가 날 지도 모르니까 이번 강좌는 여기서 접도록 하지요

예 이미 너무 많이 해서 머리가 아프시다구요 쩝

도대체 이 나라는 대통령 뽑을라구 있는 나라인지 허구헌 날 왜 이러나 모르겠습니다 하지만

조직은 딱 제 수준에 맞는 우두머리를 가진다는 Nigel Nicholson 의 말이 맞는다면 우리 정치

수준이 이것 밖에 안된다는 의미가 되므로 씁쓸해 집니다 누가 당선되든 간에 국민 무서운 줄

뼈저리게 느끼도록 본 때를 보여줘야 할 텐데

VBA 입문강좌 애플리케이션 오브젝트 프로퍼티 그리고 메서드

bull 애플리케이션(Application)

bull 오브젝트(Object)

bull 프로퍼티(Property)

bull 메서드(Method)

이제 VBA 의 얼굴과는 많이 친해지셨나요 엉 VBA 가 얼굴이 어딨어 하는 분이 저기 두어분

계시는군요 ^^ VB Editor 즉 도구-매크로-Visual Basic Editor 메뉴(또는 Alt + F11)를 선택하면

나타나는 화면이 바로 VBA 의 얼굴입니다 이제 첫 인사를 나누었으니 몇 가지 중요한 개념을

정립하고 넘어가도록 합니다

먼저 애플리케이션 오브젝트의 계보 hierarchy 를 잠깐 눈여겨 보도록 하세요 엑셀에서도 그러하였지만

VBA 를 배우는데 있어 가장 훌륭한 스승은 도움말 입니다 VB Editor 상태에서 도움말을 찾아보면

아래와 같은 계보 즉 엑셀의 족보가 나타납니다

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 11: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

딸린 식솔들이 엄청나게 많아 보이십니까 따지고 보면 그리 많지도 않습니다 우리가 누구입니까

학교다닐 때 그 어렵다는 VOCA 22000 33000 도 모자라 55000 도 거뜬히 책을 한권씩은 산

의지의 한국인들 아닙니까 ^^

애플리케이션(Application)

우리가 지금 배우고 있는 것이 Visual Basic for Application 즉 특정한 응용 프로그램 Application 을

위한 VB 입니다 위에서 Application 은 Excel 이 되는 것입니다 그런데 VBA 엔진은 엑셀에만 있는

것이 아니고 모든 MS-Office 제품군에 장착이 되어 있습니다 만약 워드에서 VBA 를 사용한다면

Application 은 워드가 되고 억세스에서 VBA 를 사용한다면 Application 은 당연히 억세스가 된다는

얘기입니다 VBA 를 잘 모르는 사람들은

웬 파일들이 이렇게나 많고 용랑이 커 비싸기만 하고

하겠지요 VBA 라는 아주 똘똘한 부하가 언제든 주인의 명령을 내려주기만 기다리고 있다는 사실은

모르고 말입니다 이런 걸 모르고 하드디스크 자리나 차지하게 방치해 두는 것도 낭비 중의 낭비일

것입니다

이제 애플리케이션이 무엇인지 감이 좀 오십니까 당연히() 안 오신다구요 그러시리라 짐작

했습니다 ^^ 쉽게 엑셀 그 자체가 애플리케이션이다라고 생각하시면 되겠습니다 물론 워드라면

워드 그 자체가 애플리케이션이다가 되겠지요

오브젝트(Object 개체)

컴퓨터를 가만히 살펴보세요 우선 모니터가 있고 본체가 있고 키보드가 있고 옆에 마우스도

보이는군요 본체를 사알~짝 뜯어보면 메인보드가 있고 CPU 가 있고 RAM 이 있고 비디오 카드 등이

있습니다 이처럼 컴퓨터는 여러 가지 부품들의 조합으로 이루어져 있습니다 이 때 컴퓨터라는

총합체가 Application 이고 각각의 부품들(모니터 키보드 CPU 등)이 오브젝트라고 생각하시면

되겠습니다

아이들이 가지고 노는 장난감 중에 레고 Lego 라는 것이 있지요 여러 가지 형태의 조그만 부속품을

이리 맞추고 저리 끼우고 하여 집도 만들고 성도 만들고 배나 비행기도 만듭니다 이 때 각각의

장난감 조각이 오브젝트이고 조각이 만들어 낸 집이나 비행기가 Application 인 것입니다 그러고

보니 우리 주변에 보이는 모든 것이 무언가의 조합에 의해 이루어진 것이란 생각이 듭니다 모든

것이 부품화 되어 있고 부속품을 조립하여 다른 완성품을 만들듯이 프로그래밍에 있어서도 이러한

개념이 도입되었는데 이것을 컴포넌트 Component 프로그래밍이라고 부릅니다

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 12: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

엑셀도 마찬가지 입니다 엑셀도 수많은 부속품(위의 계보에서 Workbooks Worksheets Charts

Windows 등이 모두 여기에 해당됩니다)들이 모여서 만들어진 것입니다 엑셀에는 이런 오브젝트가

47 개가 있습니다(엑셀 2000 기준 아직 XP 는 몇 개인지 세어보지 않았습니다 누구 세어 보신 분

계시면 좀 알려주세요)

그런데 모든 것을 부품화 해 놓으면 도대체 어떤 장점이 있는 것일까요 예를 들어 자동차를

조립하는 회사에서 타이어를 하청 업체로부터 공급받지 않고 직접 제조한다면 유리창도 하도급

업체에서 받아오는 것이 아니라 자신들이 직접 생산한다면 얼마나 많은 중복되는 생산라인이 필요할

것이며 얼마나 많은 기술력과 전문가들을 보유하고 있어야 하겠습니까 아마도 불가능 할 것입니다

돈만 가지고 있으면 하청업체들로부터 부속품들을 구매해서 조립하고 핵심 역량만 지속적으로 개발해

나가는 것이 훨씬 효율적이겠지요

Microsoft 에서 엑셀을 개발하는 프로그래머들도 엑셀 신 버전을 만들 때에도 모든 것을 만들어

내거나 맨 처음부터 다시 시작하는 것은 아닙니다 업그레이드 한다는 것은 엑셀의 수많은 부품 중

일부를 보다 나은 부품으로 바꿔 끼우거나 기존에 없던 부품을 새로 꽂는 것을 의미합니다 이런

방법을 취함으로써 지속적인 개선이 가능한 것입니다

오브젝트에는 두 가지 종류가 있습니다 하나는 그냥 오브젝트이고 다른 하나는 컬렉션 Collection

오브젝트 입니다 아파트를 가만히 보면 A 아파트 B 아파트 C 아파트 등은 모두 아파트라는 보다

큰 카테고리에 속해 있습니다 즉 각각의 아파트는 서로 다른 것이지만 아파트들

이라는 집합체(Collection) 속에 포함되는 것입니다 자동차 타이어를 다시 예로 들어보면

자동차에는 4 개의 타이어가 있습니다 각각의 타이어는 모두 오브젝트가 되겠고 4 개의 타이어를

합쳐서 타이어들 이라는 컬렉션(집합체)으로 취급한다는 이야기 입니다 즉 타이어는 오브젝트인

동시에 컬렉션의 한 구성요소라고 할 수 있습니다

컬렉션이라는 것은 A group of objects of the same class 즉 같은 클래스의 집합체 라고 할 수

있습니다 짜증이 막 날라구 그러지요(클래스는 또 뭐야 학급이란 뜻인가) 많이 헷갈리시리라

생각됩니다 위 엑셀 계보도에서 오브젝트 뒤에 s 가 붙은 것(예를 들면 Workbooks Worksheets

Names Windows)은 모두 컬렉션 오브젝트라고 보시면 됩니다 여러 개가 모여서 하나의 큰

덩어리를 이루고 있는 집합체라고만 알아 두세요 앞으로 자주 나오게 될 테니까

프로퍼티(Property 속성)

프로퍼티를 다른 말 이라기 보다 우리 말로 속성이라고 합니다 책을 오브젝트라고 가정한다면

프로퍼티는 그 책의 두께나 크기 저자 무게 가격 표지 색깔 등 오브젝트가 가진 성질머리라고 할

수 있습니다

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 13: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

책두께 = 566 페이지

책표지색깔 = 빨간색

책가격 = 20000 원

책저자 = Exceller

이렇게 표현할 수 있을 것입니다 이제 실제로 코딩은 어떻게 하는지 살펴보도록 하겠습니다 아래의

코드를 모듈시트에 복사해 넣고 실행시켜 보세요 모듈시트를 삽입하고 코드를 삽입하는 방법은 지난

시간에 소개 드렸지요 잠잠 (다시 한번) 드렸지요 혹여라도 긴가민가 하는 분은 아래

게시물을 다시 한번 살펴보세요 모든 것은 부단한 반복입니다

bull 코드 창에서 작업하기

Sub AboutProperty()

Dim strTemp As String

strTemp = 안녕하세요 amp ApplicationUserName amp 님 amp vbCr

strTemp = strTemp amp 현재 사용중인 엑셀 버전은 amp ApplicationVersion amp 입니다

MsgBox strTemp wwwiExcellercom

End Sub

ApplicationUserName 은 엑셀을 설치할 때 입력한 사용자의 이름을 ApplicationVersion 은

엑셀의 버전 정보를 알려주는 프로퍼티입니다 여러분이 사용하고 계신 엑셀의 버전이나 사용자

이름 등에 대한 정보를 누가 갖고 있느냐 하면 바로 Application 오브젝트가 가지고 있습니다

우리네 실생활에서도 사정은 크게 다르지 않습니다 창고에 TV 가 몇 대 남았는지 냉장고 재고

상태가 어떤지를 알려면 창고의 재고 담당자에게 물어야지 공장의 생산설비 담당이나 연구소

직원에게 물어서는 곤란하겠지요 그런 의미에서 VBA 로 프로그래밍을 한다는 것은 누가(즉 어느

오브젝트가) 어떤 정보를 가지고 있는 지를 파악해서 일을 시키는 것이라 할 수 있을 것입니다

그러기 위해서 오브젝트들과 우선 친해져야 하고 그런 다음 각 오브젝트의 성질머리(프로퍼티)와

행위(메서드)를 파악해 나가는 것입니다

메서드(Method 방법)

메서드를 한 마디로 표현하자면 동사(Verb)라고 할 수 있습니다

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 14: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

갑돌이가 잠을 잔다

영식이가 달려 간다

만득이가 눈을 깜빡거린다

바둑이가 짖는다

비가 내린다

여기서 갑돌이 영식이 만득이 등은 오브젝트입니다 반면 잠을 잔다 달려 간다 눈을 깜빡거린다

처럼 오브젝트에 대한 동작 명령은 메서드방법라고 합니다 메서드는 오브젝트를 움직이도록 만드는

수단이며 우리말로 방법이라고 번역합니다

모든 오브젝트는 적어도 한 개 이상의 프로퍼티나 메서드를 가지고 있습니다 그리고 오브젝트에

명령을 내릴 때 프로퍼티를 이용할 수도 있고 메서드를 사용할 수도 있습니다

갑돌이잠 = True

이렇게 갑돌이의 상태를 프로퍼티로 표현할 수도 있고(오브젝트명속성명 = 속성값)

갑돌이잠을잔다

와 같이 메서드로 나타낼 수도 있습니다(오브젝트명메서드) 두 가지 방법 중 어떤 것을 택할

것인가는 프로그래머가 그때그때 상황에 맞게 선택하여 사용합니다

아래의 코드를 모듈시트에 붙여 넣고 실행시켜 보세요

Sub ValueProperty()

Dim i As Integer

For i = 1 To 20

Cells(i 1)Value = 안녕하세요

Next i

End Sub

Sub ClearContentsMethod()

Dim i As Integer

For i = 1 To 20

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 15: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Cells(i 1)ClearContents

Next i

End Sub

어떤 일이 일어났습니까 ValueProperty 를 실행시키니까 A1A20 영역의 셀에 안녕하세요라는

문자열이 한꺼번에 좌~악 입력되지요 이것은 Range 오브젝트의 Value 프로퍼티를 이용한

것입니다 Range 오브젝트에 대해서는 다음 강좌 시간에 아주 자세히 다룰 예정입니다

이번에는 ClearContentsMethod 프로시저를 실행시켜 보세요 A1A20 영역에 입력되어 있던 값들이

순식간에 어디론가 사라졌습니다 이것은 역시 Range 오브젝트의 ClearContents 메서드를 사용한

것입니다

이맘때쯤 되면 무지 헷갈리실 것입니다 Exceller 가 위에서 프로퍼티와 메서드는 분명히 다르다고

하니까 그런가 보다 하고 넘어왔는데 어떻게 다른 것인지 그리고 어떨 때 프로퍼티를 쓰고 또 다른

경우에는 메서드를 사용하는지

프로퍼티와 메서드는 공히 오브젝트를 움직이게 하는 수단입니다 차이점이 있다면 달리게 한다거나

잠을 자게 한다거나 눈을 깜빡이게 한다거나 하는 등 동사적 변화를 주는 것은 메서드 머리 색깔이나

눈동자 색깔을 묘사하는 것과 같이 형용사적 변화를 주는 것은 프로퍼티라고 생각하시면 되겠습니다

다음 시간에는 아주 중요한 (그렇다고 오늘 강좌나 지난 강좌가 중요하지 않다는 것은 절대 아님)

Range 오브젝트를 포함한 몇 가지 오브젝트에 대해 살펴보도록 하겠습니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 소개해 드린 바와 같이 엑셀의 오브젝트 중 가장 두목 오브젝트가 애플리케이션

오브젝트입니다 달리 말하자면 엑셀 그 자체가 바로 Application 이라고 할 수 있습니다 이

애플리케이션 오브젝트가 거느리고 있는 부하가 여럿 있는데 그 중에 워크북 오브젝트 Workbook

Object 라는 믿음직한 녀석이 있습니다

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 16: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

워크북 오브젝트(Workbook Object)

워크북 오브젝트란 엑셀 통합 문서 즉 엑셀 파일을 의미합니다 여러분 PC 에 보관된 모든 엑셀

파일은 모두 Workbook 오브젝트입니다 아래 그림을 잘 들여다 보세요

Application(즉 엑셀 그 자체) 밑에 Workbooks 라는 것이 있으며 그 아래에 Workbook 오브젝트가

있지요 오브젝트명 뒤에 s 가 붙어있는 것을 컬렉션 오브젝트 Collection Object 집합체라고 합니다 쉬운

예로 자동차 타이어를 생각해 보면 자동차에는 4 개의 타이어가 있습니다 이 때 각각의 타이어는

모두 하나의 오브젝트가 되겠고 4 개의 타이어를 합쳐서 타이어들 이라는 컬렉션으로 취급한다는

얘기입니다 즉 타이어는 오브젝트인 동시에 컬렉션이기도 하다는 것이지요

컬렉션이라는 것은 a group of objects of the same class 즉 같은 성격을 가진 클래스의

집합체입니다(짜증이 날라구 그러지요 클래스는 또 뭐야 학급이란 것인가) 클래스란 것은 나중에

가면 다시 상세히 설명드릴 기회가 있을 것으로 생각됩니다만 여러분이 Excelexe 파일을 클릭하는

순간 Book1xls 라는 워크북 오브젝트가 생성됩니다 이것은 바로 Excelexe 가 가지고 있는

Workbook Class 에 의해 새로운 워크북 오브젝트가 생성되는 것입니다 Class 는 쉽게 붕어빵

장수가 붕어빵을 구워낼 때 쓰는 빵 틀과 비슷한 것입니다 붕어빵 장수가 붕어빵을 어떻게 만들어

냅니까 쇠로 된 빵 틀에다가 가루 반죽과 팥 고물을 넣고 뚜껑을 덮은 다음 구워내기만 하면 같은

모양의 붕어빵을 얼마든지 만들어 낼 수가 있지요 이 때 클래스는 빵 틀이고 오브젝트는 붕어빵

이라고 할 수 있을 것입니다

이를 좀 유식()한 말로 표현하면 오브젝트는 클래스에 의해 만들어진 생성물이고 클래스는

오브젝트를 만들어 내는 템플릿 Template 이라고 할 수 있습니다

지난 시간에 보여드린 EXCEL 네 집안 족보(계보도)를 머리 속에 떠올려 보세요 Workbooks

Worksheets Windows Charts 등과 같이 오브젝트명 뒤에 s 가 붙는 것들이 있었지요 이것은

같은 성격을 가진 오브젝트가 여럿 존재할 경우 이것을 하나의 그룹으로 보아 하나의

집합체 Collection 로 간주한다는 것입니다

어느 회사의 총무부에 담당자가 여럿 있는데 그 중에서 한 사람을 지칭할 때 총무부(제일 고참)

총무부(김담당) 총무부(이담당) 이런 식으로 표현을 할 수가 있겠지요 컬렉션 중에서 특정

오브젝트를 지칭할 때에도 Worksheets(Sheet1) 또는 Worksheets(1) 과 같은 식으로 표현할 수

있습니다

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 17: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

百聞이 不如一見이요 百見이 不如一打(혹자는 백타가 불여一作이라고도 하더군요)이므로 아래의

코드를 모듈시트에 삽입한 다음 실행-매크로 실행 메뉴를 선택해 보세요

Sub MakeWorkbook()

WorkbooksAdd

End Sub

어떤 일이 생겼나요 새로운 통합 문서가 하나 만들어 질 것입니다 이번에는 새로 만들어진 통합

문서를 Tempxls 라는 이름으로 저장까지 되도록 해 볼까요

Sub MakeWorkbook()

WorkbooksAdd

ActiveWorkbookSaveAs Filename=ApplicationDefaultFilePath amp ₩Tempxls

End Sub

여기서 DefaultFilePath 라는 것은 파일을 파일을 열 때 사용되는 기본 경로를 의미합니다 도구-옵션

메뉴의 일반 탭을 선택해 보면 기본 파일 위치라는 항목에서 지정해 준 경로를 의미합니다

이제 조금 더 응용을 해 보도록 합시다 즉 그냥 통합 문서만 하나 덜 만드는 것이 아니라 몇 개를

만들 것인지 사용자가 입력을 할 수 있도록 하고 또 만들어진 통합 문서들을 바둑판식으로

배열되도록 해 봅니다

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 18: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Sub MakeWorkbook()

Dim wrkWorkbook As Workbook

Dim intWorkbook As Integer

Dim intCount As Integer

Dim Msg As String

On Error GoTo ET

intWorkbook = InputBox(몇 개의 워크북을 만들까요 wwwiExcellercom)

If intWorkbook lt 1 Then intWorkbook = 1

If intWorkbook gt 10 Then intWorkbook = 10

For intCount = 1 To intWorkbook

WorkbooksAdd

Next intCount

WindowsArrange xlTiled

Msg = Msg amp intWorkbook amp 개의 워크북이 순식간에 만들어졌지요

MsgBox Msg wwwiExcellercom

ET

If ErrNumber ltgt 0 Then

MsgBox ErrDescription 오류 번호 amp ErrNumber

ErrClear

End If

End Sub

위의 코드를 보신 초보님들 중에 뭐가 이런 복잡한 것이 다 있나 하고 지레 겁먹지 않으셔도

됩니다 코드는 나중에 자연스레 이해하시게 될 것이므로 (정말입니다) 여기서는 코드를

모듈시트에 붙여 넣고 실행해 보는 것 그리고 실제로 작동되는 것을 직접 눈으로 확인해 보는 과정

자체가 중요한 것이니까요

위의 코드를 실행하고 InputBox 에 5 라는 값을 넣었다면 아래와 같은 결과가 나타날 것입니다

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 19: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

어라 분명히 5 를 입력했으면 다섯개의 워크북이 만들어져야지 왜 여섯개야 하는 분이 계실까요

이 시점에서 초등학교 때 배운 소풍가는 아기 돼지 이야기가 불현듯 생각나는군요 돼지들이

소풍을 가서 인원 점검을 했는데 자기는 빼고 카운팅을 해서 밤새 돌아오지 못했대나 어쨌대나

^^

이번 시간 강좌에서 중요한 것은 우리가 엑셀을 실행한 다음 파일을 추가하고 이름을 변경하고 하는

등의 작업을 하기 위해서는 Workbook Object 에 접근을 하지 않고서는 불가능하다는 것입니다

우리가 돈을 빌릴 때에도 돈을 가진 사람이 누군지를 알아야 가서 사정을 하든 협박()을 하든 해도

하겠지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 20: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

워크북 오브젝트의 하위에 있는 오브젝트 중 하나로서 워크시트를 만들어 주는 오브젝트가 워크시트

오브젝트 Worksheet Object 입니다 워크북 오브젝트와 마찬가지로 워크시트 오브젝트도 Worksheets

라는 컬렉션과 Worksheet 오브젝트가 있습니다 컬렉션 오브젝트에 대해서는 지난 시간 강좌를

참고하세요

컬렉션에 대해 살펴보기

워크시트 오브젝트(Worksheet Object)

워크시트 오브젝트란 쉽게 말하면 워크시트 그 자체를 의미합니다 우리가 돈을 빌리려면 우선 돈을

가진 사람이 누구인지를 먼저 알고 있어야 가서 사정을 하든 협박()을 하든 해도 하겠지요

워크시트의 이름을 바꾼다거나 셀에 어떤 값을 입력하고자 할 때에도 마찬가지 입니다

Sub FindActiveSheetName()

MsgBox 지금 보시는 시트는 amp ActiveSheetName amp 입니다

End Sub

이 코드를 실행시키면 현재 시트 ActiveSheet 의 이름을 알려줍니다

MsgBox 라는 것은 지정한 명령을 수행하고 난 결과를 화면상에 나타내라는 함수이고 그 다음에

ActivesheetName 이라는 것은 지금 선택되어 있는 시트(ActiveSheet)의 이름(Name)을

알아내라는 명령입니다 Active 라는 단어는 ActiveCell ActiveWindow ActivePane

ActiveWorkbook ActiveChart 등과 같이 자주 사용되는 것이므로 잘 기억해 두시기 바랍니다 다른

사람에게 일을 시킬 때 철수야 물 좀 떠와라고 할 수도 있지만 거기 움직이는 녀석 물 좀

떠와라고 할 수도 있겠지요 이 때 후자에 해당되는 표현이라고 이해하시면 되겠습니다

워크시트 삽입하기

Sub AddWorkSheet()

WorksheetsAdd

End Sub

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 21: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

워크시트를 삽입하려면 Add 메서드를 사용하여 위와 같이 하면 됩니다 삽입-워크시트

메뉴를 선택하거나 위의 프로시저를 실행하면 현재 시트의 왼쪽에 새로운 워크시트가 한 장

삽입됩니다

워크시트 삽입하기 2 삽입 위치와 매수 함께 지정하기

Sub AddWorkSheet2()

WorksheetsAdd after=Worksheets(1) Count=2

End Sub

Add 메서드 뒤에 after Count 인수를 추가하면 시트를 삽입할 위치와 삽입 매수를 지정할 수

있습니다

시트 선택하기

Sub GoToSheet2()

Worksheets(Sheet2)Activate

End Sub

이 때 Activate 대신 Select 메서드를 사용해도 결과는 동일합니다 물론 Sheet2 라는 시트가

당연히 있어야 오류가 발생하지 않겠지요

시트 선택하고 이름 바꾸기

Sub RenSheetName()

Worksheets(Sheet2)Activate

ActiveSheetName = MySheet

End Sub

딱 한 줄이 추가 되었네요

ActiveSheetName = MySheet

현재시트이름 = MySheet 즉 현재 활성화된 시트 이름을 MySheet 로 바꾸어라

보통 수학에서 A=B 라고 하게 되면 A 와 B 는 같다라는 것으로 인식되나 프로그래밍에

있어서는 우측의 값을 좌측으로 대입하라는 의미입니다 다만 If 조건문에서는 If A=B 라고

하면 A 와 B 가 같은지 다른지를 비교합니다

시트 이동 복사하기

Sub SheetMove()

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 22: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Worksheets(Sheet1)Move after=Worksheets(Sheet3)

End Sub

만약 after 인수를 생략하여 Worksheets(Sheet1)Move 라고만 하면 어떤 일이 생길까요

직접 한번 해 보세요 ^^ 시트를 이동하는 것이 아니라 복사를 하려면 짐작하시겠습니다만

Move 대신 Copy 메서드를 사용하시면 되겠습니다

시트 삭제하기

Sub DeleteSheet()

ApplicationDisplayAlerts = False

ActiveSheetDelete

ApplicationDisplayAlerts = True

End Sub

시트를 삭제할 때에는 Delete 속성을 사용합니다 그런데 시트를 삭제할 때에는 그림과 같은

삭제 확인 메시지가 나타나므로 다시 한번 삭제 버튼을 눌러주어야 하는 문제점이 있습니다

이것을 해결하기 위해 DisplayAlerts 속성을 사용하여 위의 프로시저와 같이 해줍니다

워크시트는 얼마나 클까(디지털북스 엑셀 XP - 예제 활용 50 Page 에서 편집 인용)

산술적으로 계산해 보면 하나의 워크시트는 16777216 개의 셀로 구성되어 있습니다 만약

여러분이 VBA 표준 모드에서 행 높이와 열 너비를 변경하지 않았다면 18 개의 행과 9 개의

열 따라서 162 개의 셀을 한 화면에서 볼 수 있을 것입니다 이것은 전체 워크시트의 0001

퍼센트밖에 안되는 것입니다 다시 말해서 현재 화면에 나타난 영역의 104000 배나 되는

정보가 하나의 워크시트 안에 들어갈 수 있다는 의미입니다

만약 여러분이 워크시트이 모든 셀에 1 초에 한 글자씩 잠도 안자고 밥도 안먹고 쉬지도

않고 입력한다고 가정하면 194 일 정도가 소요될 것입니다 그리고 이렇게 입력한 것을

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 23: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

프린터로 출력하면 A4 사이즈 용지로 36000 장 이상의 출력물이 나오는데 이것을

쌓아놓으면 대략 2m 정도가 될 것입니다 셀의 디폴트 크기 기준으로 출력해 보면 하나의

셀은 가로 204mm 세로 48mm 정도 됩니다 따라서 하나의 워크시트는 가로 522m 세로

3145m 정도의 크기가 됩니다 이것을 100 배율로 A4 용지에 출력해서 한데 모아보면

아무 축구장 크기 만할 것입니다(중략)

강좌를 들으시는 아니 보시는 분 중에는 뭐 이런 쉬운 것을 일일이 설명하나 그리고 이런 토막

토막난 것을 배워 뭐에 써 먹나 하는 분이 일곱분 계시는군요 ^^ 쉬운 것을 알아야 어려운 것을

해결할 수 있습니다 어설프게 10 개를 아는 것보다 하나를 알더라도 확실하게 알고 있어야 응용력이

생깁니다

이번에는 현재 워크북에 어떤 시트들이 있는지 알아내라고 컴퓨터에게 일을 시켜 볼까요

Sub WhatsInThisbook()

Dim strName() As String

Dim strTemp As String

Dim i As Integer

Dim intCount As Integer

intCount = SheetsCount

ReDim strName(1 To intCount) As String

For i = 1 To intCount

strName(i) = Sheets(i)Name

strTemp = strTemp amp strName(i) amp vbLf

Next i

MsgBox strTemp

End Sub

수행하는 기능이 복잡하니 코드 또한 어지럽지요(사실 알고보면 아무 것도 아니지만 말입니다) 위

프로시저를 수행하면 워크북 내의 모든 시트의 이름이 메시지 박스에 표시됩니다

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 24: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

위의 코드에서는 배열 Array 이라는 것을 사용하였습니다 배열이란 쉽게 설명하자면 같은 성격을 가진

변수의 집합이라고 할 수 있습니다 배열에 대해서는 나중에 변수에 대해 살펴볼 때 자세히 다룰

예정이므로 아 이런 것도 있구나 정도만 이해하고 넘어가도 전혀 지장이 없겠습니다

이번 시간에는 여기까지

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

Range 오브젝트는 VBA 로 프로그래밍을 할 때 가장 빈번하게 사용되는 가장 중요한 오브젝트

입니다 엑셀에 입력되는 대부분의 데이터들이 바로 Range 오브젝트에 보관됩니다 레인지

오브젝트의 개념만 잘 이해하면 나머지 오브젝트에 대한 것은 거저먹기나 마찬가지 입니다 Range

오브젝트는 워크시트 오브젝트의 하위 오브젝트로 시트 내에 한 개 또는 복수 개의 셀들로

이루어집니다

Range 오브젝트에 접근하는 방법은 여러 가지가 있습니다 다음은 대표적인 몇 가지 방법입니다

Range 속성을 사용하는 방법

Cells 속성을 사용하는 방법

Offset 속성을 사용하는 방법

Union 메서드를 사용하는 방법

앞 강좌에서 워크시트 오브젝트의 크기에 대해 잠깐 설명드린 적이 있습니다 다음 프로시저를

실행시켜 보면 하나의 워크시트에는 몇 개의 셀이 있는 지 알 수 있습니다

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 25: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Sub HowManyCells()

Dim lngRow As Long

Dim intColumn As Integer

Dim lngCell As Long

Dim strMsg As String

lngRow = ActiveSheetRowsCount

시트 내의 행 수를 카운팅하여 lngRow 변수에 담습니다

intColumn = ActiveSheetColumnsCount

시트 내의 열 수를 카운팅하여 intColumn 변수에 담습니다

lngCell = lngRow intColumn

행 수와 열 수를 곱해서 셀 수를 구한 다음 결과값을 lngCell 변수에 저장합니다

strMsg = strMsg amp 시트 내 행의 수 amp lngRow amp vbCr

strMsg = strMsg amp 시트 내 열의 수 amp intColumn amp vbCr amp vbCr

strMsg = strMsg amp 전체 셀의 수 amp lngCell

MsgBox strMsg

End Sub

VBA 에서 가장 중요한 오브젝트 중 하나인 레인지 오브젝트에 자유자재로 접근하기 위한 첫번째

과제는 우선 셀을 선택하는 것입니다 그러기 위해서는 Range 속성과 Cells 속성의 특성을 잘

이해하고 있어야 합니다 두 속성에는 각각 어떤 장단점이 있는 지 어떤 경우에 사용하면 좋은지 잘

정리해 두시기 바랍니다

Range 속성

다음 코드를 실행하면 Sheet1 시트의 A1 셀에 100 이라는 값이 입력됩니다

Worksheets(Sheet1)Range(A1)Value = 100

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 26: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

이것은 Worksheets(Sheet1)이라는 워크시트 오브젝트의 Range(A1)이라는 레인지

오브젝트의 Value 속성값을 100이라고 지정해 준 것입니다 Range 오브젝트의 디폴트 default

속성값은 Value 입니다 자동차를 살 때에도 기본으로 딸려나오는 것이 있고 옵션으로 선택하는 것이

있지요 디폴트 속성은 속성명을 따로 붙이지 않아도 붙인 것으로 해석하는 것입니다 자동차에서

별도로 주문하지 않아도 함께 제공되는 것과 마찬가지로 말입니다

이번에는 여러 셀에 동일한 값을 넣어볼까요 입력하고자 하는 위치에 다른 값이 들어있으면

메시지를 표시하고 실행합니다

Sub WriteData_2()

Worksheets(Sheet1)Range(A1)Select

If Selection ltgt Then

선택된 셀이 공란이 아니면 If 구문 내부의 명령을 실행합니다

MsgBox 입력된 값이 있으나 지우겠습니다

SelectionClearContents

선택된 영역의 데이터를 지웁니다

메서드 설 명

Clear 내용과 서식을 모두 지웁니다

ClearContents 내용만 지웁니다

ClearFormats 서식만 지웁니다

End If

Worksheets(Sheet1)Range(A1A10)Value = 엑셀 VBA

MsgBox A1A10 영역에 값을 입력하였습니다

End Sub

이번에는 불연속적인 여러 개의 셀에 값을 넣는 방법에 대해 살펴봅니다

Sub WriteData_3()

Worksheets(Sheet1)Range(A1)Select

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 27: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Range(A1)CurrentRegionSelect

MsgBox SelectionAddress amp 영역을 선택하였습니다 값을 지우겠습니다

SelectionClearContents

With Range(A1A3A5A7A9B2B4B6B8B10)

Select

Value = 엑셀 VBA

End With

MsgBox A1A3A5A7A9B2B4B6B8B10 셀에 값을 입력하였습니다

End Sub

CurrentRegion 은 현재 영역 즉 인접해 있는 상하좌우의 영역을 반환해 주는 속성입니다 먼

소리냐 하면 다음 그림에서 현재 A1 셀이 선택된 상태에서

Range(A1)CurrentRegionSelect 라고 하면 A1 셀과 인접해 있는 주변 셀이 모두 선택됩니다

Cells 속성

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 28: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Cells 속성을 사용해도 셀을 선택할 수 있습니다 다음 코드를 실행하면 현재 시트의 B5 셀에 숫자

100을 입력합니다

Cells(52) = 100

Cells 속성의 경우 Cells(행 열)의 형식으로 표기합니다 이것은 Range 속성의 표현 방법과는 반대

순서이므로 주의하시기 바랍니다

Cells 속성으로 셀 범위를 참고하고자 할 경우에는 Range 속성과 조합을 해서 사용합니다

Range(Cells(3 2) Cells(10 5))Select

Cells 속성(Range 속성의 경우에도 마찬가지입니다) 앞에 아무 것도 붙이지 않으면 현재 워크시트를

대상으로 합니다 워크시트 이름을 앞에 명기하면 당연히 지정한 워크시트에 접근한 다음 작업을

합니다 다음은 MySheet 시트의 A2 셀에 지정한 값을 입력합니다

Worksheets(MySheet)Cells(2 1)Value = VBA Programming

여기서 한 가지 주의할 점이 있습니다 만약 Cells(3 2)라고 하면 어느 셀을 지정한다고

생각하십니까 아마도 지금까지 공부를 제대로 해 온 분이라면

그것도 질문이라고 행 방향으로 3 열 방향으로 2 만큼 이동한 곳의 셀이니까 당연히 B3

셀이지

이렇게 대답하실 것입니다 정답은 그럴 수도 있고 아닐 수도 있다 입니다 먼 소린지 알 듯 말 듯

하시지요 어떤 범위 내에서 명령을 사용하느냐에 따라 달라진다는 의미입니다 즉 Cells 속성 앞에

아무 것도 없이 그냥 Cells(3 2)라고 한다면 3 행과 2 열이 만나는 B3 셀을 의미합니다 하지만 앞에

단서가 붙어 있으면 사정은 달라집니다 다음과 같은 문장이 있다고 할 경우 어느 셀에 100 이라는

값을 넣어주게 될까요

Range(B2E9)Cells(3 2) = 100

Range(B2E9)Cells(3 2)라는 것은 B2E9 영역 내에서 행 방향으로 3 번째 열 방향으로

2 번째에 있는 셀을 의미합니다 따라서 C4 셀에 숫자 100 을 입력하게 됩니다

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 29: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Range 속성과 Cells 속성은 각각 어떤 경우 사용하면 좋은가

지금까지 Range 속성과 Cells 속성에 대해 살펴보았습니다 그런데 Cells 속성의 경우

정의된 이름을 사용할 수 없고 셀 범위를 설정할 때에도 단독으로는 사용할 수 없고 Range

속성과 조합을 해야 합니다

잘못된 사용 예 (X) 바른 사용 예 (O)

Cells(지역별_매출)Select Range(지역별_매출)Select

Cells(Cells(2 1) Cells(5 7))Select Range(Cells(2 1) Cells(5 7))Select

그렇다면 불편하게만 보이는 Cells 프로퍼티는 뭐하러 만들어 놓았을까요

Cells 프로퍼티의 가장 큰 장점은 인수에 숫자값을 사용할 수 있다는 것입니다 다음과 같은

구구단 테이블을 만든다고 생각해 보세요

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 30: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

만약 Range 속성만으로 이러한 것을 만들어야 한다면 머리가 심하게 아파 옵니다(물론

불가능한 것은 아닙니다) 이런 경우 For ~ Next 반복문과 Cells 속성을 조합하면 아주

간단히 해결할 수 있습니다 어떻게 하면 될 지 3 분간 로직을 생각해 보신 다음 코드를

보시기 바랍니다

Sub 구구단_테이블()

Dim i As Integer

Dim j As Integer

For i = 2 To 9

For j = 1 To 9

Cells(j + 1 i - 1) = i amp X amp j amp = amp i j

Next j

Next i

Columns(AH)AutoFit

End Sub

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 31: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

생각보다 간단하지 않습니까

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

지난 시간에 Range 오브젝트를 생성하는 방법 두 가지를 소개해 드렸습니다

오브젝트를 생성하다니 그런걸 언제 가르쳐 줬어

눈을 동그랗게 뜨고 이렇게 항의 할려고 준비하는 분이 계실 것입니다

오브젝트에 접근한다는 것을 흔히 오브젝트를 생성한다 라고 표현하기도 합니다 엄 히 말하자면

오브젝트를 생성한 다음에 접근한다고 해야 하겠지만 말입니다 하여튼 이번 시간에는 또 다른

방법으로 레인지 오브젝트를 생성하는 방법에 대해 살펴 보겠습니다

이번 강좌는 Exceller 의 VBA 책에서 약간 편집 인용한 것입니다 ^^V

Rows 속성 Columns 속성

Range 오브젝트를 만들어 주는 또 다른 방법으로 Rows 나 Columns 속성을 사용할 수도 있습니다

다음 코드를 실행시켜 보세요

Sub Rows_Property_1()

Range(B3E7)Select

SelectionRows = Test

End Sub

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 32: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub Rows_Property_2()

Rows(37)Value = Test

원래 이 문장은 ActiveSheetRows(37)Value = Test 라고 해 주어야 할 것을

축약해서 표현한 형태입니다

End Sub

여기서 우리는 한 가지 중요한 사실을 알 수 있습니다 같은 Rows 속성을 사용하더라도 앞에 어떤

오브젝트가 선택되었느냐에 따라 적용 범위는 전혀 달라진다는 것입니다 즉 앞의 Rows_Property_1

프로시저에서는 특정한 영역(B3E7)을 먼저 선택하고 Rows 속성을 사용하였으므로 B3E7 셀에만

Test라는 문자열 값이 입력되었습니다 반면 Rows_Property_2 프로시저에서는 지정한 행 전체에

영향을 미쳤습니다

요약하자면 앞의 프로시저는 Range 오브젝트에 대해 Rows 속성을 이용한 예제이고 뒤의

프로시저는 워크시트 오브젝트에 대해 Rows 속성을 사용한 예제입니다

Columns 속성의 경우에도 Rows 속성의 경우와 동일합니다 다음의 두 코드가 각각 어떻게

작동하는지 모듈 시트에 복사하신 다음 직접 확인해 보시기 바랍니다

Sub Columns_Property_1()

Range(B3E7)Select

SelectionColumns = Test

End Sub

Sub Columns_Property_2()

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 33: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Columns(BE)Value = Test

End Sub

EntireRow 속성 EntireColumn 속성

이번에는 Range 오브젝트가 이미 선택되어 있는 상태에서 범위를 행 전체로 또는 열 전체로

확대하는 방법에 대해 살펴보겠습니다

Sub Rows_Property_3()

Range(B2E3)Select

MsgBox 이제 선택된 범위를 행 전체로 확대합니다 wwwiExcellercom

SelectionEntireRowSelect

MsgBox 선택 범위가 행 전체로 확대되었지요 wwwiExcellercom

Range(B2E3)Select

MsgBox 이번에는 선택 범위를 열 전체로 확대합니다 wwwiExcellercom

SelectionEntireColumnSelect

MsgBox 선택 범위가 열 전체로 확대되었지요 wwwiExcellercom

End Sub

보신 바와 같이 작업 대상 영역을 특정한 범위에서 행 전체로 넓힐 때에는 Rows 속성 대신

EntireRow 속성을 열 전체로 범위를 확장할 때에는 Columns 속성 대신 EntireColumn 속성을

사용하면 됩니다 쉽지요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 34: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

엑셀에는 여러 오브젝트가 있고 무엇 하나 안 중요한 것이 없습니다만 프로그래밍을 할 때 가장

활용도가 높은 오브젝트는 과연 무엇일까~요 맞습니다 Range 오브젝트 입니다 이번 시간에는

Range 오브젝트를 생성하는 방법 중 CurrentRegion 과 UsedRange 속성에 대해 살펴보겠습니다

CurrentRegion 속성

CurrentRegion 이란 셀 포인터가 놓여 있는 위치를 중심으로 하여 빈 행과 빈 열로 둘러싸인

영역을 의미합니다 좀 다르게 표현하자면 현재 선택된 셀을 중심으로 상하좌우 방향으로 인접해

있는 영역을 말합니다 먼 소린가 하는 분들을 위해 다음 그림을 보세요

셀 포인터가 A1 셀에 위치하고 있습니다 이 경우 CurrentRegion 즉 현재 영역은 어디가 될까요

위쪽과 왼쪽으로는 더 이상 갈 곳이 없고 오른쪽과 아래쪽 방향으로 빈 행과 빈 열이 나올 때까지

주욱 따라가 보면 G 열 그리고 8 행을 만나게 됩니다 따라서 A1 셀의 CurrentRegion 은 빈

행열을 만나기 바로 전까지의 영역인 A1F7 영역이 되는 것입니다

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 35: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

특정 셀에 대한 현재 영역을 선택하려면 다음과 같이 표현하면 됩니다

Sub CurrentRegion_Property()

Range(A1)CurrentRegionSelect

End Sub

이 때 Range(A1) 부분은 굳이 A1 셀이 아니더라도 상관 없습니다 테이블 내부의 아무 셀이나

지정하면 됩니다 그냥 현재 영역만 덜 선택하는 예제는 별로 재미가 없으니까 현재 영역의 외곽에

실선을 그려보면 재미가 있을까요

말 그대로 B3E7 영역의 모든 행들(그러니까 결국은 지정한 영역 내의 모든 셀들)에 Test 라는

문자열을 채우게 됩니다 만약 특정한 행 전체에 어떤 값을 입력하려면 다음과 같이 표현합니다

Sub CurrentRegion_Property_2()

Range(A1)CurrentRegionBorderAround Weight=xlMedium

End Sub

지정한 범위에 테두리선을 그릴 때에는 BorderAround 메서드를 사용하고 선의 굵기는 Weight

인수를 통해 지정합니다 앗 이 시점에서 이런 탄식이 어디선가 들려오는 듯 합니다

이런 것을 어떻게 다 외워서 사용한단 말인가

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 36: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

절대로 머리 싸매고 외울 필요가 없습니다 그것은 일부 천재들이나 할 법한 짓()이랍니다 우리는

매크로 기록기를 사용하여 괘선을 그리는 과정을 기록한 다음 작성된 코드를 보고 아 이런

경우에는 이런 메서드나 속성을 기록하는 군 그러니까 이 부분을 이렇게 저 부분을 저렇게

고치기만 하면 되겠네 하고 느끼기만 하면 됩니다

현재 영역에 괘선을 그리는 것도 하고 보니 별로 재미가 없습니다 그렇다면 응용력을 조금

발휘해서 표의 타이틀 부분을 제외한 영역에만 색상을 지정하는 것을 만들어 볼까요 그렇게

하려면 CurrentRegion 속성 외에도 Offset Resize 속성 등을 조합해서 사용해야 합니다 다음

코드를 잘 보세요

Sub CurrentRegion_Property_3()

Range(A1)CurrentRegionSelect

MsgBox 현재 영역을 선택하였습니다wwwiExcellercom

SelectionOffset(01)Select

MsgBox 현재 영역 중에서 타이틀 부분을 제외하였습니다wwwiExcellercom

SelectionResize(SelectionRowsCount - 1 SelectionColumnsCount)Select

MsgBox 이제 색칠을 합니다 wwwiExcellercom

SelectionInteriorColorIndex = 44

End Sub

위 코드를 실행하면 그림과 같은 결과가 나타납니다 한결 재미있지요 ^^

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 37: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

UsedRange 속성

CurrentRegion 속성을 사용하면 특정한 셀에 인접해 있는 영역을 구할 수는 있습니다만 떨어져

있는 영역에 대해서는 접근할 수 없습니다 다음과 같이 떨어져 있는 영역을 포함하여 워크시트

중에서 사용된 모든 영역을 선택하려면 UsedRange 속성을 이용하면 됩니다 여기서 한 가지

유의할 점 앞에서 설명드린 CurrentRegion 속성은 Range 오브젝트의 똘마니 속성인데 비해

UsedRange 속성은 Worksheet 오브젝트에 딸린 속성인 점에 주의하시기 바랍니다 즉

Range(A1E100)Select 와 같은 형태로는 사용할 수 없다는 얘기입니다

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 38: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Sub UsedRange_Property()

ActiveSheetUsedRangeSelect

MsgBox 현재 시트의 UsedRange 는 amp SelectionAddress amp 입니다

End Sub

위에서 소개해 드린 코드들은 작업의 진행 상황을 시각적으로 보여드리기 위해 불필요한 구문들이

다소 들어 있습니다 실제 프로그래밍에서 이렇게 했다가는 재떨이 날아올 수 있으니까 기본적인

원리를 파악하신 다음 코드를 최적화 해 보시기 바랍니다

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트 그 세번째 시간으로 Union 메서드와 Intersect 메서드에 대해 살펴보겠습니다

이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 발췌하여 싣습니다

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 39: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Union 메서드

수학에서 집합을 배울 때 집합에는 합집합 교집합 부분집합 차집합 여집합 공집합 유한집합

무한집합 등 여러 종류가 있다고 들으셨을 것입니다(참으로 많기도 하지요 ^^) 이 중에서 Union

메서드는 서로 떨어져 있는 여러 영역(Range 오브젝트)의 합집합을 구하고자 할 때 사용합니다

다음과 같은 데이터가 있다고 할 경우 합집합에 해당하는 영역은 무엇일까요

그림에서 선택한 영역 즉 A1E16 그리고 G11J16 영역이 되겠지요

이것을 어떻게 구하느냐 하면 바로 Union 메서드를 이용하면 된다는 것입니다

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 40: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Sub Union_Method()

Dim shtSheet As Worksheet

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngUnion As Range

Set shtSheet = Sheets(Sheet6)

Set rngFirst = shtSheetRange(A1)CurrentRegion

Set rngSecond = shtSheetRange(G11)CurrentRegion

Set rngUnion = ApplicationUnion(rngFirst rngSecond)

rngUnionSelect

MsgBox 두 영역의 합집합 amp SelectionAddress(rowabsolute=False _

columnabsolute=False)

End Sub

아 상당히 복잡해 보입니다 하지만 엑셀이나 VBA 강좌 시간에 여러 차례 말씀드린 것처럼 복잡한

것과 복잡해 보이는 것과는 차이가 있습니다 위의 코드는 지금껏 우리가 VBA 기초강좌 시간에

보아왔던 것에 비해 길이가 조금 길어 복잡해 보이는 것일 뿐 실제로 복잡한 것은 아닙니다 실제로

복잡한 것의 진수()를 보여 드릴까요

그가 생각하는 것을 나도 생각한다고 그가 생각하리라는 것을 나는 생각한다John F Nash Jr

지정한 영역(A1 셀과 G11 셀)의 CurrentRegion 값을 rngFirst 와 rngSecond 변수에 담아 둔 다음

이것을 Union 메서드를 이용하여 합치는 것입니다

황모군 그렇다면 질문이 하나 있는데요 이딴거는 배워서 어디다 써 먹나요

좋은 질문입니다 이것을 조금 응용해 보도록 하지요 A1A100 영역 중에서 짝수 행 데이터만을

선택한 다음 녹색으로 칠하는 예제를 만들어 보도록 하지요

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 41: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

대상 영역이 A1A100 영역 정도밖에 되지 않으니 다행이지 A1A1000 혹은 A1A10000 영역쯤

된다고 생각해 보세요 Ctrl 키를 누른 채 마우스를 눌러대려면 손가락에 쥐가 납니다 하지만

우리는 다음과 같은 간단한 코드 몇 줄로 해결할 수 있습니다(이래도 VBA 안 배운다고 버팅기는

분이 계실래나)

Sub Union_Method_2()

Dim i As Integer

Dim rngUnion As Range

Set rngUnion = Cells(2 1)

For i = 2 To 100 Step 2

Set rngUnion = Union(rngUnion Cells(i 1))

Next i

rngUnionSelect

SelectionInteriorColorIndex = 10

MsgBox 짝수 행 셀에만 녹색을 칠하였습니다 wwwiExcellercom

End Sub

황모군 에이~~ 그것도 그다지 실용적이지 못한 것 같은데요

Exceller (정색을 하고 가까이 다가서며) 과연 그럴까요

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 42: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

황모군 (뜻밖의 강한 반응에 순간 움찔하다 다시 따지듯) 그게 아니라 실무에서 그렇게 딥다

색칠만 하는 경우가 어디 있어요

황모군처럼 앞의 예제도 전혀 실용성이 없다고 생각하는 분들을 위해 한 가지 예를 더 보여드리도록

하지요 다음과 같은 성적표가 있다고 할 때 등급이 합격인 사람만 녹색으로 표시하는 예제입니다

Sub Union_Method_3()

Dim rngCell As Range

Dim rngAverage As Range

Dim rngSource As Range

Dim rngUnion As Range

Set rngAverage = Range(평균)

Set rngSource = Range(Source)

With rngSource

InteriorColorIndex = xlNone

FontColorIndex = 1

End With

MsgBox 기존 서식을 지웠습니다 이제 합격자들에 대해 표시를 합니다

For Each rngCell In rngAverage

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 43: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

With rngCell

If Offset(0 1) = 합격 Then

If rngUnion Is Nothing Then

Set rngUnion = Range(Offset(0 -4) Offset(0 1))

Else

Set rngUnion = Union(rngUnion Range(Offset(0 -4) Offset(0 1)))

End If

End If

End With

Next rngCell

rngUnionSelect

With Selection

InteriorColorIndex = 10

FontColorIndex = 2

End With

End Sub

Intersect 메서드

Intersect 메서드와는 반대로 Intersect 메서드를 사용하면 두 개 이상의 영역 중에서 서로 겹쳐지지

않는 영역의 주소를 알아낼 수 있습니다 수학으로 치면 교집합에 해당하는 영역을 구해주는

것입니다

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 44: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Sub Intersect_Method()

Dim rngFirst As Range

Dim rngSecond As Range

Dim rngIntersect As Range

Dim i As Integer

Set rngFirst = ActiveSheetRange(A1D8)

Set rngSecond = ActiveSheetRange(C5G12)

rngFirstSelect

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 45: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

MsgBox 첫번째 영역입니다 wwwiExcellercom

rngSecondSelect

MsgBox 두번째 영역입니다 이제 교차영역을 표시합니다 wwwiExcellercom

Set rngIntersect = ApplicationIntersect(rngFirst rngSecond)

rngIntersectSelect

For i = 1 To 1000

rngIntersectInteriorColorIndex = Rnd 56

Next i

End Sub

어느 곳에 어떻게 활용할 것인가 하는 것은 결국은 응용력의 문제이며 응용력은 평소에 (자신의

문제를) 얼마나 문제의식을 갖고 깊이 있게 고민해 보았느냐에 따라 결정됩니다 그래서 VBA

프로그래밍의 경우 신입사원이나 업무에 익숙하지 않은 분들보다 해당 업무에 노련한 분들이 대체로

빨리 습득하시더군요 어떻게 응용할 것인지에 대해 많이 고민해 보세요

VBA 입문강좌 중요한 오브젝트 몇 가지

가 워크북 오브젝트(Workbook Object)

나 워크시트 오브젝트(Worksheet Object)

다 레인지 오브젝트(Range Object)

레인지 오브젝트에 대한 마지막 시간입니다 앞서 설명드린 것 이외에도 레인지 오브젝트에 접근하는

방법은 더 있습니다만 이번 시간에 소개해 드리는 것까지해서 10 여 가지 남짓 되는 속성이나

메서드만 잘 이해하시면 거의 이해를 하셨다고 생각해도 좋을 것입니다 자~~ 눈에 힘을 주고

시작해 볼까요

역시나 이번 강좌도 Exceller 의 책 ltVBA 로 엑셀에 날개달기gt에서 인용한 것입니다

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 46: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

SpecialCells 메서드

셀(레인지 오브젝트)에는 여러 종류의 정보가 들어갈 수 있습니다 상수변하지 않는 수가 들어있는 셀

내용이 아예 들어있지 않은 셀 수식이 입력되어 있는 셀 등과 같이 말이지요 이 중에서 특정한

타입의 영역을 선택해야 할 경우에 SpecialCells 메서드를 사용합니다 이것은 워크시트 상태에서

편집-이동 메뉴를 선택한 다음 옵션 버튼을 클릭하면 나타나는 이동 옵션 대화상자를 통해

조작한 것과 같은 기능을 수행합니다

Tip - 이동 옵션 대화상자를 호출하는 단축키

워크시트 상태에서 ltF5gt 키나 ltCtrl + Ggt 키를 눌러도 이동 옵션 대화상자가 나타납니다

다시 말해서 SpecialCells 메서드로 특정한 조건을 충족하는 셀을 지정하는 것은 이동 옵션

대화상자에서 특정한 조건을 지정하는 동작에 해당합니다 SpecialCells 메서드의 기본적인 사용법은

다음과 같습니다

작업 대상 영역SpecialCells (Type Value)

ltType 인수gt

상 수 셀 타입

xlCelltypeAllFormatConditions 표시 형식이 설정되어 있는 셀

xlCelltypeValidations 유효성 조건이 설정된 셀

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 47: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

xlCelltypeBlanks 빈 문자열이 들어있는 셀

xlCelltypeComments 메모가 들어있는 셀

xlCelltypeConstants 상수가 포함되어 있는 셀

xlCelltypeFormulas 수식이 들어있는 셀

xlCelltypeLastCell 사용된 범위 내의 마지막 셀

xlCelltypeSameFormatConditions 같은 서식을 가진 셀

xlCelltypeSameValidation 같은 유효성 조건을 가진 셀

xlCelltypeVisible 화면에 보이는(나타나 있는) 모든 셀

ltValue 인수gt

상 수 셀 타입

xlErrors 에러값

xlLogical 논리값

xlNumbers 숫자값

xlTextValues 문자열값

예를 들어 현재 워크시트 내에서 데이터가 입력되어 있는 마지막 셀을 선택하려면 다음과 같이

표현합니다

Sub SpecialCells_Method()

ActiveSheetCellsSpecialCells(xlCellTypeLastCell)Select

MsgBox 마지막 데이터 셀 주소는 amp SelectionAddress amp 이고 amp vbCr amp _

입력된 값은 amp SelectionValue amp 입니다

End Sub

이 코드를 실행하면 그 결과는 아래와 같이 될 것입니다

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 48: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

기본적인 사용법을 알았으니 이번에는 보다 실용적인 예제를 만들어 볼까요 시트 내에서 수식이

입력된 셀의 배경색을 노란색으로 칠해 보도록 하지요 다음 그림처럼 말입니다

어떻게 하면 위와 같이 할 수 있을까요 늘 그러하듯 정상적인 예습복습을 철저히 하고 정규 교과

과정을 제대로 이수하신 분이라면 능히 해결하실 수 있으리라 생각됩니다 ^^ 농담이고 앞서

설명드린 SpecialCells_Method 프로시저를 이해하신 분이라면 쉽게 적용하실 수 있어야 합니다

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 49: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Sub Specialcells_Method_2()

Dim rngMyRange As Range

Set rngMyRange = _

Worksheets(Sheet7)CellsSpecialCells(xlCellTypeFormulas)

rngMyRangeInteriorColorIndex = 6

MsgBox 수식이 입력된 모든 셀을 노란색으로 표시하였습니다 _

wwwiExcellercom

End Sub

End 속성

End 속성이라고 하니까 뭔지 정확히는 알 수 없지만 마지막과 관련된 것이 아닐까 하는 짐작은

어렴풋이 드시지요 바로 그렇습니다 End 속성은 영역의 마지막 셀을 구해주는 속성입니다 마지막

셀은 알겠는데 영역의 마지막 셀이란 무엇을 의미하는 것일까요 짐작하시겠지만 현재 셀을

기준으로 상하좌우 방향의 맨 끝에 있는 셀을 의미합니다 말로 하니까 이해가 될듯 말듯

하시지요 그러실 줄 알고 그림을 준비했습니다 다음 그림을 보세요

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 50: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

이 시점에서 수수께끼 하나 내 드릴까요

아니 VBA 공부하다 말고 집중력 떨어지게 왠 수수께끼 하시겠지요 다 이유가 있어 그런

것이니까 한번 맞춰 보세요

집집마다 4 개씩 가지고 있는데 동네를 다 털어도 4 개밖에 없고 온 나라를 다 뒤져도 4 개밖에 없는

것은 무엇일까~요

그것은 바로 동서남북 이랍니다 영역의 마지막 셀도 이와 비슷합니다 위 그림에서 D8 셀을

기준으로 해서 위쪽으로 마지막 셀은 D4 셀 아래쪽으로 마지막 셀은 D13 셀입니다 또한 왼쪽으로

마지막 셀은 B8 셀 오른쪽으로 마지막 셀은 F8 셀입니다 이것을 컴퓨터(엑셀)가 알아들을 수 있게

VBA 코드로 표현하면

Range(D8)End(xlUp)Select

Range(D8)End(xlDown)Select

Range(D8)End(xlToLeft)Select

Range(D8)End(xlToRight)Select

이렇게 됩니다 조금 응용을 해 봅니다 다음 코드를 실행해서 직접 확인해 보시면 아마도 End

속성에 대해서는 더 이상의 설명이 필요 없을 것입니다(물론 코드를 실행하기 전에 Sheet1 시트에

앞의 그림과 비슷한 형태의 데이터는 미리 만들어 두셔야 하겠지요)

Sub End_Property()

Dim rngStart As Range

Dim strAddress As String

Set rngStart = Sheets(Sheet1)Range(D8)

With rngStartEnd(xlUp)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 위쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlDown)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 51: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

columnabsolute=False)

MsgBox D8 셀의 아래 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToLeft)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 왼쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다 _

wwwiExcellercom

End(xlToRight)Select

strAddress = SelectionAddress(rowabsolute=False _

columnabsolute=False)

MsgBox D8 셀의 오른쪽 끝 셀인 [ amp strAddress amp ]셀을 선택하였습니다

End With

End Sub

ltEnd 속성의 인수 및 단축키 정리gt

이동 방향 인 수 단축 키

위쪽 끝 End(xlUp) ltCtrlgt + uarr

아래쪽 끝 End(xlDown) ltCtrlgt + darr

왼쪽 끝 End(xlToLeft) ltCtrlgt + larr

오른쪽 끝 End(xlToRight) ltCtrlgt + rarr

End 속성은 실무적으로 어떤 경우에 사용하면 좋을까요 여러 가지 경우에 적용할 수 있겠지만

다음과 같이 데이터를 추가적으로 입력해 나갈 때 마지막으로 입력된 셀이 어디인지를 파악하는

경우에 흔히 사용됩니다

Sub End_Property_2()

Range(A65536)End(xlUp)Offset(1 0)Select

MsgBox 데이터가 새로 입력될 위치는 amp SelectionAddress amp 입니다

End Sub

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 52: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

뿐만 아니라 특정한 영역을 지정하여 색상을 지정하고자 할 경우에도 사용할 수가 있겠습니다

아래와 같이 말입니다

Sub End_Property_3()

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 53: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Range(Range(E2) Range(E2)End(xlDown))Select

SelectionInteriorColorIndex = 3

SelectionFontColorIndex = 2

MsgBox 급여 영역의 데이터에 대한 서식 변경을 완료하였습니다 _

wwwiExcellercom

End Sub

VBA 입문강좌 Sub 프로시저와 Function 프로시저

bull Sub 프로시저와 Function 프로시저의 차이

bull Sub 프로시저

bull Function 프로시저

bull 사용자 정의 함수 예제

bull 사용자 정의 함수 범주 변경하기

bull 사용자 정의 함수 설명 추가하기

이번 시간에는 Sub 프로시저와 Function 프로시저의 차이점 그리고 Function 프로시저 즉 사용자

정의 함수의 기본 개념과 응용 예제들에 대해 살펴봅니다

Sub 프로시저와 Function 프로시저의 차이

우리가 VB Editor 에서 작성하는 VBA 코드는 보통 프로시저라고 부르며 가장 일반적인 프로시저는

Sub 프로시저와 Function 프로시저 입니다 이 두 가지 프로시저의 가장 큰 차이점은

Sub 프로시저 특정한 동작을 실행한다

Function 프로시저 특정한 계산을 수행하고 그 결과값을 돌려준다

김 판서가 두 명의 하인에게 똑같은 일거리를 주었습니다 페인트를 한통씩 주고 이제 봄이

되었으니 집 앞 담벼락에 페인트 칠을 해라하고 한 나절이 지났습니다 김 판서가 점검을 하러

나가 보았습니다 갑돌이에게 맡긴 담벼락은 색칠을 되어 있는데 갑돌이는 어디론가 사라져 버리고

보이지 않는데 삼돌이는 색칠을 마치고 주인에게 달려와서 결과를 보고합니다

저에게 주신 페인트 량은 100 리터였는데 담벼락의 넓이는 가로 10 미터 세로 2 미터로 20

평방미터였습니다 1 평방미터당 소요된 페인트 량이 03 리터였으므로 60 리터를 사용하여 현재 40

리터의 페인트 재고가 남아 있습니다

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 54: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

짐작하시겠지만 여기서 갑돌이는 Sub 프로시저 삼돌이는 Function 프로시저에 해당됩니다

어떻습니까 Function 프로시저가 Sub 프로시저보다 더 똑똑해 보이지요 앞으로는 똘똘한

Function 프로시저만 사용해야 되겠다는 생각이 드시나요

하지만 세상은 공평한 것 머리가 똑똑하면 얼굴이 받쳐주지 않고 외모가 되면 머리가 따라주지

않는 것이 보통이지요 머리도 똑똑하고 외모도 예술이면 하다 못해 성격이 괴팍하다거나 팔자가

드세다거나 하는 등 이 세상에 모든 것을 다 갖춘 사람은 없는 법이지요 Function 프로시저가 Sub

프로시저에 비해 지능은 뛰어난 반면 제약이 있습니다

Sub 프로시저

보통 여러분이 VBA 에서 작성하는 코드는 Sub 프로시저입니다 매크로 기록기를 이용해서 작성한

코드 역시 Sub 프로시저입니다 모든 Sub 프로시저는 Sub 라는 키워드로 시작해서 End Sub 라는

statement 로 끝을 맺습니다

Sub 안녕하세요()

MsgBox 안녕하세요 amp ApplicationUserName amp 님

End Sub

프로시저명 뒤에는 항상 한 쌍의 괄호가 붙습니다 보통의 경우 이 괄호 안에는 아무 것도 들어있지

않지만 필요한 경우 argument 즉 인수를 전달하여 실행을 할 수도 있습니다

Function 프로시저

Function 프로시저는 다른 말로 사용자 정의 함수라고도 부릅니다 모든 Function 프로시저는

Function 이라는 키워드로 시작해서 End Function 이라는 statement 로 끝을 맺습니다 사용자

정의 함수의 기본적인 작성 형식은 이러합니다

Function 함수명(인수 1 인수 2)

어쩌고

저쩌고

함수명 = 결과값

End Function

제곱근을 구해주는 사용자 정의 함수를 만들어 보면

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 55: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Function 제곱근(number n)

제곱근 = number ^ (1n)

End Function

여기서 number 는 제곱근을 구하고자 하는 값(숫자) n 은 몇 제곱근을 구할 것인지를 지정하는

인수입니다 예를 들어 위의 코드를 모듈시트에 작성한 다음 워크시트 내 임의의 셀에

=제곱근(22) 라고 입력하면 2 의 2 제곱근 값인 1414213 라는 결과값이 구해집니다

Function 즉 함수는 몇 개의 인수를 가질 수도 있고 전혀 가지지 않을 수도 있습니다(Today Now

Rand 등과 같이)

Function 프로시저는 딱 두 가지 방법에 의해서만 실행할 수 있습니다

(1) 다른 프로시저(Sub 혹은 Function 프로시저)에서 호출하는 방법

(2) 워크시트 내에서 수식의 형태로 사용하는 방법

반면 Sub 프로시저는 아주 다양한 방법으로 실행할 수 있는데 이것이 사람들로 하여금 Sub

프로시저를 더 많이 사용하게 하는 한 가지 이유가 되기도 합니다

(1) VBE 에서 표준 도구모음에 있는 Sub사용자 정의 폼 실행 아이콘 이용

(2) VBE 에서 실행-Sub사용자 정의 폼 실행 메뉴 이용

(3) VBE 에서 직접 실행 창에서 바로 실행 larr Sub 프로시저명 입력엔터

(4) 단축 키를 통해 실행(Ctrl + 단축 키) larr 단축 키가 미리 지정되어 있을 경우

(5) 다른 Sub 프로시저에서 호출하여 실행

(6) 워크시트에서 버튼이나 도형 등의 개체에 연결하여 실행

(7) 도구-매크로-매크로 메뉴를 통해 실행

(8) 도구 모음의 사용자 지정 단추에 연결하여 실행

(9) 사용자 지정 메뉴에 연결하여 실행

(10) 특정한 이벤트가 발생하였을 때 실행 larr 이벤트 프로시저에 연결하여

참으로 많은 방법이 있기도 하지요 이것 말고도 더 있을 지도 모릅니다 그리고 Function

프로시저는 Sub 프로시저에서 쉽게 할 수 있는 글꼴을 변경한다거나 셀의 색상을 변경한다거나 하는

작업은 할 수 없습니다

사용자 정의 함수 예제

(1) 인수를 하나도 가지지 않는 사용자 정의 함수

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 56: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

Function UserName()

UserName = ApplicationUserName

End Function

=UserName() 이라고 입력하면 현재 사용자의 이름이 표시됩니다

(2) 상여금 계산 사용자 정의 함수

아래과 같은 사원 기본정보가 있다고 할 때 직종에 따라 성과급을 차등 지급하는 사용자 정의

함수를 작성해 보겠습니다

Function 성과급(직종코드 연봉)

Select Case 직종코드

Case 1

성과급 = 연봉 01

Case 2 3

성과급 = 연봉 008

Case 4 To 7

성과급 = 1000000

Case Is gt 7

성과급 = 500000

End Select

End Function

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 57: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

이 함수를 실행하면 다음과 같은 결과를 얻을 수 있습니다

(3) 선택적 인수 Optional argument 를 가지는 사용자 정의 함수

특정한 범위 내에서 상위 5 개 값의 평균을 구해야 한다면 어떻게 해야 할까요 엑셀에는 그런

기능을 수행하는 함수가 따로 없기 때문에 다음과 같은 형태의 수식을 사용해야 할 것입니다

= (Large(영역 1) + Large(영역 2) + + Large(영역 5)) 5

물론 이 수식은 오류없이 제대로 작동합니다 하지만 그다지 좋은 해결 방법이라고 하기는

어렵습니다 왜냐고요 모로가도 어디로만 가면 되지 않느냐구요 그렇다면 만약 상위 10 개 값의

평균을 구해야 한다면 수식을

= (Large(영역 1) + Large(영역 2) + + Large(영역 10)) 10

이런 식으로 바꾸어 주실 것입니까 그러면 100 개 값의 평균은 어떻습니까 곤란하겠지요 이런

경우 사용자 정의 함수를 만들면 간단히 해결할 수 있습니다

Function 상위평균(rngX Optional n = 5)

Dim dblSum As Double

Dim i As Integer

For i = 1 To n

dblSum = dblSum + ApplicationWorksheetFunctionLarge(rngX i)

Next i

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 58: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

상위평균 = dblSum n

End Function

여기서 Optional 이라는 새로운 단어가 하나 나왔군요 우리가 잘 아는 Left 함수를 생각해 보면

Left(텍스트 추출할 문자 수)

이런 형식으로 사용됩니다 만약 추출할 문자 수 인수를 생략하면 엑셀이 알아서 1 로 간주합니다

즉 다음 두 수식은 같은 결과값을 돌려줍니다

= Left(A1 1)

= Left(A1)

이처럼 사용자 정의 함수에서 특정한 인수를 생략하면 기본적으로 어떤 값을 갖도록 설정할 때

사용하는 것이 Optional 키워드입니다

(4) 인수의 개수가 정해져 있지 않은 사용자 정의 함수

어떤 워크시트 함수는 인수의 개수가 미리 정해져 있지 않은 것이 있습니다 어떤 것이 있을까요

대표적인 것으로 Sum 함수가 있습니다

= Sum(number1 number2)

이런 식으로 30 개 까지의 인수를 가질 수 있습니다 여기서 첫번째 인수는 반드시 있어야 하지만

나머지 인수는 상황에 따라 변합니다 이런 함수는 어떻게 하면 만들 수 있을까요 ParamArray

키워드를 사용하면 가능합니다

Function MySum(ParamArray XXX() As Variant) As Double

Dim varX As Variant

For Each varX In XXX

MySum = MySum + varX

Next varX

End Function

ParamArray 키워드는 항상 Variant 데이터 타입이며 항상 선택적 인수 Optional argument 입니다 설령

Optonal 키워드를 사용하지 않았더라도 말입니다

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 59: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

사용자 정의 함수 범주 변경하기

기본적으로 사용자 정의 함수는 사용자 정의 범주에 포함되어 있습니다 VBA 를 이용하면 이 범주를

변경할 수 있습니다(왜 그렇게 만들었는지 이유를 알 수는 없지만 워크시트 상태에서 수작업으로는

바꾸어 줄 방법이 없습니다)

MacroOptions 메서드를 사용하여 다음과 같이 해 주면 상위평균이라는 사용자 정의 함수의 범주가

수학삼각함수 범주로 변경됩니다

Sub ChangeCategory()

ApplicationMacroOptions macro=상위평균 Category=3

End Sub

ltMacroOption 메서드의 기본 제공 범주gt

값 함수 범주

0 모두

1 재무

2 날짜시간

3 수학삼각

4 통계

5 찾기참조 영역

6 데이터베이스

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 60: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

7 텍스트

8 논리

9 정보

10 Commands(이 범주는 화면상에 표시되지 않습니다)

11 Customizing(이 범주도 숨겨져 있습니다)

12 Macro Control(이 범주도 숨겨져 있습니다)

13 DDEExternal(이 범주도 숨겨져 있습니다)

14 사용자 정의(Default)

15 공학(분석 도구를 추가 설치한 경우 나타납니다)

사용자 정의 함수 설명 추가하기

함수 마법사 대화상자에서 엑셀의 워크시트 함수를 선택해 보면 해당 함수에 대한 간단한 설명이

나타나는 것을 볼 수 있습니다 하지만 사용자 정의 함수에 대해서도 마찬가지로 이러한 설명이

나타나도록 할 수 있습니다

(1) 도구-매크로-매크로 메뉴를 선택하니다

(2) 매크로 이름 항목에 해당 함수의 이름을 입력합니다

(매크로 대화상자에는 사용자 정의 함수의 이름이 표시되지 않습니다)

(3) 옵션 버튼을 클릭합니다

(4) 설명 항목에 함수에 대한 자세한 설명을 기입합니다

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다

Page 61: VBA : Introducing VBA - cau.ac.krcau.ac.kr/~orist/2005_2/VB/VBA.pdf · VBA 입문강좌: Introducing VBA • BASIC & VB에 관한 기초 지식 • 그러면 VBA란 무엇인가?

(5) 확인 버튼을 클릭합니다

(6) 취소 버튼을 클릭합니다

새로운 함수 범주를 만들 수 있을까

함수 범주를 새로이 추가할 수는 없습니다 또한 사용자 정의 함수의 인수 argument 에 세부적인

설명을 추가할 수도 없습니다 대신 사용자 정의 함수의 인수 이름을 의미있는 것으로 지정해 주면

어느 정도는 직관적으로 이해할 수 있게 되므로 편리합니다