- 최초 작성일: 2000-12-15
- 최종 수정일: 2026-09-30
- 조회수: 9 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 여러 조건을 만족하는 자료 추출하기
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
약 한달쯤 전 강좌(VB0063)에서 "콤보박스를 통한 자료추출" 방법에 대해 설명드린 적이 있습니다. 그 이후로 여러 건의 질문 메일을 받았는데 요약을 하자면,
"한 가지 조건을 만족하는 자료에 대해서는 알겠는데… 그렇다면 두 가지 또는 그 이상의 조건을 충족하는 자료들을 추려내는 방법은 없습니까?"
하는 것이었습니다. 없을 리가 없겠지요? ^^
강좌에서 사용한 WorkPlace 시트의 데이터는 다음과 같은 형태입니다(위쪽 6건만 표시했습니다).
| 품목 | 브랜드 | 수량 | 단가 | 금액 |
|---|---|---|---|---|
| 화장품 | 아이오페 | 6 | 60000 | 385000 |
| 냉장고 | RF1 | 10 | 10000 | 102000 |
| 세탁기 | CM1 | 4 | 4000 | 16000 |
| 세탁기 | CM2 | 4 | 4000 | 17000 |
| 냉장고 | RF1 | 7 | 7000 | 50000 |
| 화장품 | 설화수 | 20 | 20000 | 402000 |
초등학교때 구구단을 제대로 배워두면 나중에 미분이나 적분, 통계 등에서 두루 써먹을 수 있는 것처럼, 프로그래밍도 마찬가지입니다. 몇 가지 안되는 공식(프로그래밍의 경우에는 오브젝트, 속성, 방법)을 가지고 이렇게도 쓰고 저렇게도 응용하는 것입니다. 만약 VB0063 강좌에서 설명드린 내용을 완전히 소화해서 내 것으로 만들었다면 위와 같은 질문은 없어야…
하여튼 질문에 답변을 드려야겠군요. 똑같이 하면 재미가 없으니까 이번 시간에는 유저폼을 인터페이스로 사용해 보도록 하지요.
여러 조건을 만족하는 자료 추출하기
핵심 요약: 여러 조건으로 자료 추출
콤보박스 목록을 Collection으로 중복 없이 채우고, 선택된 두 조건을 And로 비교해서 일치하는 행만 새 시트로 복사합니다.
- 1단계: 유저폼에 콤보박스 두 개와 OK 버튼을 배치합니다.
- 2단계: Activate 이벤트에서 Collection으로 중복 없는 목록을 콤보박스에 채웁니다.
- 3단계: OK 클릭 시 If 문에 And로 조건을 결합해 일치하는 행을 복사합니다.
Step 1: 유저폼에 컨트롤 그리기
(1) VB Editor 상태에서 유저폼을 하나 삽입하고 아래와 같이 필요한 컨트롤들을 그려 넣습니다. 두 가지 조건을 받기 위해 두 개의 콤보박스를 사용합니다.
Step 2: Activate 이벤트에서 콤보박스 채우기
(2) 유저폼의 빈 공간을 더블클릭하고 우측 상단의 이벤트 선택 목록상자에서
Activate 이벤트를 선택하고 아래의 코드를 작성합니다.
Private Sub UserForm_Activate()
Dim rngCell As Range
Dim rngFirst As Range
Dim rngSecond As Range
Dim sht As Worksheet
Dim X As New Collection
Dim Y As New Collection
Dim varItem As Variant
Dim varItem2 As Variant
On Error Resume Next
'//변수를 선언해 줍니다. 이번 시간에는 다른 강좌에 비해 좀 많은 수의 변수를 선언해
'//주었습니다. 또한 Dim X As New Collection 이라고 한 것으로 보아 컬렉션 오브젝트를
'//사용하려나 봅니다. ^^
'//컬렉션 오브젝트란 말을 처음 들으시나요? 아니지요? 아주 오래 전에 여러 번 설명을
'//드렸는데 무슨 작업을 할 때 였는지 기억이 나시는지… "중복 아이템"을 추려낼 때
'//사용했었습니다. 기억이 안 나거나 가물가물하신 분들은 VB0029, 30 강좌를 다시 한번
'//살펴보시기 바랍니다. 어차피 이번 시간에는 컬렉션 오브젝트를 아셔야 진도를 계속
'//나갈 수 있으니까요.
'//그리고 반드시 On Error Resume Next 구문을 넣어주어야 에러가 발생하지 않습니다.
Set sht = Sheets("WorkPlace")
Set rngFirst = sht.Columns(1).SpecialCells(xlTextValues)
Set rngSecond = sht.Columns(2).SpecialCells(xlTextValues)
'//WorkPlace 시트의 1열과 2열 중 값이 들어있는 모든 셀을 rngFirst, rngSecond 변수에
'//담아두고…
For Each rngCell In rngFirst
X.Add rngCell.Value, CStr(rngCell.Value)
'//여기서 컬렉션 오브젝트가 사용되었습니다. 컬렉션 오브젝트는
'//object.Add item, key, before, after
'//여기서 key argument가 사용되면 반복되는 값이 나타날 경우 error를 발생시키게
'//됩니다. 그런데 위에서 On Error Resume Next라는 구문을 넣어 주었으므로 계속
'//작업을 진행하게 되는 것이지요. 즉 의도적인 에러 발생이라고 할 수 있습니다.
Next rngCell
For Each varItem In X
If varItem <> "품목" Then Me.cmbCriteria1.AddItem varItem
'//위에서 추가된 컬렉션 오브젝트를 AddItem 속성을 통해 콤보박스의 아이템으로
'//추가해 줍니다.
Next varItem
'//아래는 두번째 콤보박스의 내용을 중복되지 않는 브랜드명으로 채워넣기 위한 것으로
'//위에서 설명드린 것과 같은 내용입니다.
For Each rngCell In rngSecond
Y.Add rngCell.Value, CStr(rngCell.Value)
Next rngCell
For Each varItem2 In Y
If varItem2 <> "브랜드" Then Me.cmbCriteria2.AddItem varItem2
Next varItem2
End Sub
On Error Resume Next로 중복 키 오류를 일부러 무시하는 이 방법은 예전부터 쓰던 고전적인 방식입니다. 요즘에는 Scripting.Dictionary의 Exists 메서드로 중복을 검사하거나, 최신 엑셀의 UNIQUE 함수를 이용하는 방법도 많이 사용합니다.
Step 3: OK 버튼에서 두 조건으로 자료 추출하기
(3) Shift + <F7>키를 눌러 유저폼을 다시 호출하고, OK 버튼을 더블클릭하여 Click 이벤트를 발생시킨 다음, 아래와 같은 코드를 작성합니다.
Private Sub btnOK_Click()
Dim strCriteria1 As String
Dim strCriteria2 As String
Dim Msg As String
Dim rngTarget As Range
Dim rngCell As Range
Dim sht As Worksheet
Dim r As Long
Application.DisplayAlerts = False
For Each sht In ThisWorkbook.Sheets
If sht.Name = "ExtractData" Then sht.Delete
Next sht
'//현재 워크북 파일 중에서 "ExtractData"라는 시트가 있을 경우 삭제합니다.
'//Application.DisplayAlerts=False로 하여 시트를 삭제할 때 "… 지울까요?"하는
'//메시지를 나타나지 않게 설정합니다.
Set rngTarget = Sheets("WorkPlace").Columns(1).SpecialCells(xlTextValues)
strCriteria1 = Me.cmbCriteria1.Value
strCriteria2 = Me.cmbCriteria2.Value
'//두 콤보박스로부터 선택된 항목의 값을 strCriteria1과 strCriteria2라는 문자열 변수에
'//담아둡니다.
Worksheets.Add after:=Sheets("WorkPlace")
ActiveSheet.Name = "ExtractData"
Set sht = Worksheets("ExtractData")
'//워크시트를 하나 삽입하고 "ExtractData"라고 이름을 정해 줍니다.
For Each rngCell In rngTarget
If rngCell.Value = strCriteria1 And rngCell.Offset(0, 1) = strCriteria2 Then
'//바로 이 부분이 핵심입니다. 첫번째 콤보박스에서 선택된 목록과 rngCell의 값,
'//그리고 두번째 콤보박스의 목록과 rngCell에서 오른쪽으로 한 간 이동한 셀의
'//값이 서로 같은지를 비교합니다. 그래서 같은 경우에만 행 전체를 복사해서
'//ExtractData 시트에 붙여 넣습니다.
'//만약 세 가지, 네 가지 또는 그 이상의 조건을 비교하려면 이 부분에 And를
'//사용해서 조건을 추가해 주시면 되겠지요?
rngCell.EntireRow.Copy
Application.Goto sht.Range("a1"), True
Range("a1").Offset(r, 0).Select
ActiveSheet.Paste
r = r + 1
End If
Next rngCell
'//작업이 다 끝난 다음에 서식을 꾸미는 과정입니다.
Rows(1).EntireRow.Insert
Range("a1") = "품목"
Range("b1") = "브랜드"
Range("c1") = "수량"
Range("d1") = "단가"
Range("e1") = "금액"
Range("a1").Select
Selection.AutoFormat Format:=xlRangeAutoFormatList1, Number:=True, Font:= _
True, Alignment:=True, Border:=True, Pattern:=True, Width:=True
Unload Me
If r < 1 Then
Msg = "지정하신 조건에 해당되는 자료가 없습니다." & vbCr
Msg = Msg & "조건을 다시 확인하세요!"
Else
Msg = "총 " & r & " 건의 자료가 추출되었습니다"
End If
Application.DisplayAlerts = True
MsgBox Msg, , "자료 추출 완료//Exceller"
End Sub
마무리
다음 시간에 또…
정리 — 다중 조건 추출 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 목록 채우기 | UserForm_Activate | 폼이 열릴 때 콤보박스 초기화 |
| 중복 제거 | X.Add rngCell.Value, CStr(rngCell.Value) | 키 중복 오류를 이용 |
| 텍스트 셀 찾기 | Columns(1).SpecialCells(xlTextValues) | 값이 있는 셀만 대상 |
| 다중 조건 | If A = 조건1 And B = 조건2 Then | 두 조건 모두 만족 |
| 결과 복사 | rngCell.EntireRow.Copy | 행 전체를 새 시트에 붙여넣기 |
자주 묻는 질문 (FAQ)
Q1. Collection 개체로 중복을 어떻게 제거하나요?
Add 메서드에 key 인수를 지정하면 같은 값이 다시 추가될 때 오류가 발생하는데, On Error Resume Next로 이를 무시하면 고유한 값만 남습니다.
Q2. 조건을 세 개 이상으로 늘리려면 어떻게 하나요?
비교하는 If 문에 And를 이용해 조건을 계속 추가하면 됩니다.
Q3. 유저폼이 열릴 때 콤보박스를 채우려면 어떤 이벤트를 쓰나요?
UserForm의 Activate 이벤트 프로시저에서 AddItem으로 항목을 추가합니다.
마치며
한 가지 조건 추출을 이해했다면 And로 조건을 늘리는 것만으로 여러 조건 추출도 어렵지 않습니다.