- 최초 작성일: 2008-07-28
- 최종 수정일: 2026-09-30
- 조회수: 16 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 나만의 Vlookup 함수 만들기 2 - n번째 값 가져오기
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
질문 하나
안녕하세요. VBA강좌를 보다가 많은 도움을 받았습니다. 그런데 한가지 안풀리는 의문이 있는데요 VBA 를 통하여 vlookup의 효과를 볼수 있는지 궁금합니다. 제가 Vlookup을 사용하는 이유가 참조값에 의해서 지정한 자리에 data가 찍혀야하기 때문이거든요 그래서 그 자료를 가지고 또 다른 함수를 사용해서 가공을 합니다.
제 질문이 좀 뒤죽박죽이면 vba로 vlookup과 같은 기능을 할 수 있는 예제가 있으면 알려주세요 감사합니다.
위 질문만으로는 정확히 하시려는 바를 이해하기는 어렵습니다만, 'vba로 vlookup과 같은 기능을 할 수 있는 예제'라는 부분에 착안하여 생각해 보도록 하죠.
나만의 Vlookup 함수 만들기 2 - n번째 값 가져오기
핵심 요약: 같은 값 중 n번째 것을 가져오는 MyVlookup2
Vlookup은 같은 값이 여러 개일 때 항상 맨 위의 값만 돌려줍니다. Optional 인수를 하나 더 받는 사용자 정의 함수를 만들면 몇 번째 값을 가져올지 지정할 수 있습니다.
- 1단계: 찾을 값, 참조 테이블, 열 번호에 몇 번째인지를 나타내는 Optional 인수를 더합니다.
- 2단계: Find 메서드로 첫 번째 일치 셀을 찾고, After 인수를 이용해 n번째 셀까지 이동합니다.
- 3단계: 값이 없으면 No Data!!를, 있으면 지정한 열의 값을 돌려줍니다.
Step 1: MyVlookup2 함수로 n번째 값 가져오기
<F9> 키를 누를 때마다 '결과값'이 어떻게 바뀌는지 살펴보세요.
| 분류1 | 분류2 |
|---|---|
| a | a1 |
| a | a2 |
| a | a3 |
| a | a4 |
| b | b1 |
| b | b2 |
| c | c1 |
| a | a5 |
| b | b3 |
| c | c2 |
| c | c3 |
| d | d1 |
| c | c4 |
| d | d2 |
| d | d3 |
| a | a6 |
| 찾을 값 | 몇번째? | 결과값 |
|---|---|---|
| a | 2 | a2 |
| b | 0 | No Data!! |
| c | 0 | No Data!! |
| d | 2 | d2 |
참고: 예제 파일에서 '몇번째?' 열은 =INT(RAND()*6) 수식으로 0~5 사이의 값을 만들기 때문에 <F9> 키를 누를 때마다 값이 바뀌고, 그에 따라 '결과값'도 달라집니다. 위 표는 그중 한 번의 결과입니다. 0처럼 1보다 작은 값이 들어가거나 n번째 값이 존재하지 않으면 'No Data!!'가 표시됩니다.
Vlookup 함수는 같은 값이 여러 개 있을 경우, 맨 위에 있는 하나의 값만 가져옵니다. '분류1'에서 a라는 값이 여러 개 있습니다. 만약 '=VLOOKUP("a",$B$29:$C$44,2,FALSE)' 라고 하면 항상 'a1'이라는 결과값을 돌려줍니다.
하지만 이번 시간에 만들어 볼 'MyVlookup2' 함수는 같은 값이 여러 개 있을 경우 그 중에서 몇번째 것을 가져올 것인지 지정할 수 있습니다.
Step 2: 함수 사용하는 방법
F29 셀에는 다음과 같은 수식이 들어있습니다. 물론 myvlookup2라는 것은 엑셀에서 제공하는 함수가 아니라 사용자가 필요에 따라 만든 '사용자 정의 함수'입니다.
=myvlookup2(D29,$B$28:$C$44,2,E29)
Step 3: MyVlookup2 함수 코드 살펴보기
myvlookup2 함수의 내용을 살펴볼까요.
Function MyVlookup2(rngX As Range, rngRefTable As Range, intCol As Integer, Optional intXXX As Integer = 1)
'MyVlookup2 함수는 4개의 인수를 가집니다. rngX는 '찾을 값', rngRefTable은 '참조 테이블'
'intCol은 참조 테이블에서 '몇번째 열'의 값을 가져올 지를 각각 지정합니다.
'여기까지는 지난 시간에 보았던 MyVlookup 함수와 비슷한데… 뒤에 intXXX 라는 것이 하나 더
'붙어 있습니다. 그것도 앞에 Optional 어쩌구… 하는 요상한(?) 것을 데리고 말입니다.
'우리가 자동차를 살 때, 에어컨이나 카오디오 등과 같이 기본적으로 딸려 나오는 것이 있나 하면
'에어백이나 선루프, 자동변속기 등과 같은 선택사양이 있습니다.
'Optional 키워드는 선택사양과 비슷한 역할을 수행합니다. 즉, 특정한 인수를 생략하면 기본적으로
'어떤 값을 갖도록 설정할 때 사용합니다. 여기서는 이 인수를 특별히 지정하지 않으면 '1'이라는
'값을 갖도록 하였습니다.
Dim rngFound As Range
Dim rngSource As Range
Dim i As Integer
Dim strAddress As String
Dim rngTarget As Range
If intXXX < 1 Then
'intXXX 변수 값으로 1보다 작은 것이 입력되면 오류 메시지를 보여주고 프로시저를 종료합니다.
MyVlookup2 = "No Data!!"
Exit Function
End If
Set rngSource = rngRefTable.Columns(1)
Set rngFound = rngSource.Find(rngX, , xlValues, xlWhole)
'Find 메서드를 사용하여 rngSource 영역 내에 rngX 변수값과 같은 것이 있는지 찾습니다.
If Not rngFound Is Nothing Then
'Not rngFound Is Nothing이라는 것을 말 그대로 해석해 보면
''rngFound 변수가 아무 것도 아닌 것이 아니라면'이라는 이중부정 형태입니다.
'이것을 달리 표현하면, '뭔가 값을 찾았다면'이라는 의미입니다.
If intXXX > 1 Then
'intXXX 변수값이 1보다 크면 아래의 구문을 실행합니다.
strAddress = rngFound.Address
For i = 2 To intXXX
'intXXX, 즉 같은 값이 여러 개 있을 경우, 사용자가 지정한 위치의 것을 가져오기 위해
'For~Next 순환문을 사용하였습니다. 같은 값을 계속 찾으면 안되니까 Find 메서드의
'after 파라미터(여기서는 rngFound)를 지정해 주었습니다.
Set rngFound = rngSource.Find(rngX, rngFound, xlValues, xlWhole)
If rngFound.Address = strAddress Then
Set rngFound = Nothing
Exit For
End If
Next i
End If
End If
If rngFound Is Nothing Then
MyVlookup2 = "No Data!!"
Else
MyVlookup2 = rngFound.Offset(, intCol - 1)
'지정한 횟수만큼 순환문을 돌린 다음 intCol - 1 위치에 있는 결과값을 MyVlookup2 함수의
'결과값으로 돌려줍니다. 왜 1을 빼주었는지는… 잘 생각해 보세요. Offset 프로퍼티의 성질을
'잘 떠올려 보시면…? 0부터 시작하는지 1부터 시작하는지… ^^
End If
End Function
오늘 질문에 대한 것은 이것으로 어느 정도 해결이 될 듯 합니다. 즉 Vlookup 함수와 비슷한 역할을 VBA로 구현하려면 Find와 FindNext 메서드를 적절히 사용하면 되니 말입니다. 오류 트랩에 대한 부분은 별도로 추가하지 않았는데, 이것은 여러분의 필요에 따라 적당히 추가해서 사용하세요.
참고 - 수식으로 n번째 값을 가져오려면? Microsoft 365나 엑셀 2021처럼 FILTER 함수를 쓸 수 있는 버전이라면 =INDEX(FILTER($C$29:$C$44,$B$29:$B$44=D29),E29)처럼 수식만으로도 같은 결과를 얻을 수 있습니다. 매크로를 사용할 수 없는 환경이라면 이 방법도 고려해 보세요.
다음 시간에…
정리 — MyVlookup2 함수 핵심
| 구분 | 내용 |
|---|---|
| 인수 | rngX(찾을 값), rngRefTable(참조 테이블), intCol(열 번호), intXXX(몇 번째, 생략하면 1) |
| Optional 키워드 | 인수를 생략하면 기본값(여기서는 1)을 사용하도록 지정 |
| n번째 찾기 | Find 메서드의 After 인수에 직전 결과를 넘겨 다음 일치 셀로 이동 |
| 값이 없는 경우 | 한 바퀴 돌아 처음 셀로 돌아오거나 1보다 작은 값이 입력되면 No Data!! |
| 결과값 | rngFound.Offset(, intCol - 1)의 값 |
자주 묻는 질문 (FAQ)
Q1. n번째 값이 없으면 어떻게 되나요?
예를 들어 a가 6개인데 7번째 값을 요청하면 Find가 한 바퀴 돌아서 처음 셀로 돌아오게 되고, 코드는 이를 감지해 No Data!! 문자열을 돌려줍니다. 0이나 음수처럼 1보다 작은 값을 지정한 경우에도 마찬가지입니다.
Q2. 마지막 인수를 생략하면 어떻게 동작하나요?
Optional 인수의 기본값이 1이므로 생략하면 첫 번째 값을 가져옵니다. 즉 일반 Vlookup 함수와 같은 결과가 나옵니다.
Q3. VLOOKUP 함수만으로 n번째 값을 가져올 수는 없나요?
보조 열에 =B29&COUNTIF($B$29:B29,B29)처럼 항목명과 순번을 이어 붙인 키를 만들어 두면 VLOOKUP으로도 n번째 값을 찾을 수 있습니다. FILTER 함수를 쓸 수 있는 최신 버전에서는 INDEX와 FILTER 조합도 가능합니다.
마치며
Optional 인수 하나만 더해도 함수의 쓰임새가 훨씬 넓어집니다. Find 메서드의 특성을 잘 이해해 두면 다양한 검색 함수를 직접 만들 수 있으니, 여러분의 업무에 맞게 응용해 보세요!