• 최초 작성일: 2000-07-12
  • 최종 수정일: 2026-09-30
  • 조회수: 10 회
  • 작성자: 권현욱 (엑셀러)
  • 강의 제목: 유저폼 상에서의 중복아이템 추려내기

들어가기 전에

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

이미 예고해 드린 바와 같이 이번 시간에는 여러 아이템 중에서 중복되는 것은 제외하고 유일한 아이템 (Unique Items)들을 추려내는 또다른 방법에 대해 살펴보도록 하겠습니다. 아마 VB 코드를 좀 짠다고 하는 분들은 대개 지난 시간(VB0028)에 설명드린 것과 비슷한 방법을 사용하실 것입니다.

이번에는 거기서 한 걸음 더 나아가서 컬렉션 개체(Collection Object)를 사용해 보도록 하지요. 오늘 내용은 "Visual Basic Programmer's Journal"의 J.G.Hussey님 아이디어를 응용해 본 것입니다. 위의 버튼을 눌러 예제 프로그램을 실행해 보고 오세요.

잘 되지요? 오늘은 새로운 개념이 하나 나오니까 잘 따라 오시기 바랍니다.

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

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

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


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

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

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

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

유저폼 상에서의 중복아이템 추려내기

핵심 요약: Collection으로 중복 제거하기

Collection.Add에서 Key가 중복되면 에러가 발생하는 성질을 이용하면 On Error Resume Next와 함께 중복 없는 항목만 모을 수 있습니다.

  • 1단계: 셀 값을 X.Add 값, CStr(값)으로 컬렉션에 추가합니다.
  • 2단계: 중복이면 에러가 나므로 On Error Resume Next로 건너뜁니다.
  • 3단계: For Each로 컬렉션의 항목을 리스트박스에 추가합니다.

Step 1: 유저폼 만들기

(1) VB Editor 상태에서(Alt+<F11>) UserForm을 하나 삽입합니다. (2) 아래의 그림을 참조하여 유저폼에 예제와 같은 컨트롤 들을 삽입합니다.

Label 2개, 리스트박스, OK/닫기 버튼이 있는 유저폼
아이엑셀러

(3) 각각의 속성을 다음과 같이 바꾸어 줍니다. 사용된 컨트롤은 세 종류(ListBox, CommmandButton, Label), 5개 입니다.

① Label 컨트롤

컨트롤명변경할 속성변경 내용
Label1없음없음
Label2없음없음

지금까지는 레이블 컨트롤의 캡션을 변경할 때 속성창에서 직접 바꾸어 주었는데 오늘은 프로그램 상의 코딩작업을 통해 변경하도록 하겠습니다.

② ListBox 컨트롤

컨트롤명변경할 속성변경 내용
ListBox1없음없음

리스트박스 컨트롤도 속성을 변경할 필요가 없습니다. 그냥 크기나 적당히 조절하시면 되겠습니다.

③ 명령버튼(CommandButton)

컨트롤명변경할 속성변경 내용
CommandButton1NamecmdOK
CaptionOK
CommandButton2NamecmdClose
Caption닫기

Step 2: 코드 작성하기

(1) OK 버튼

(4) 이제 각 컨트롤들에 대해 필요한 지능을 부여하는 작업을 해 주어야 겠지요? 먼저, OK 버튼을 더블클릭합니다. 그러면 Private Sub cmdOK_Click()이라는 이벤트가 나타나게 되는데 아래의 코드를 입력합니다. "복사-붙여 넣기"를 해도 되겠지만 가급적 직접 손으로 입력해 보는 것이 좋을 것입니다.

Private Sub cmdOK_Click()
    Dim intNum As Integer
    Dim str As String
    '//언제나 그렇듯이 변수를 지정해 줍니다.
    '//intNum은 리스트 박스 내에서 몇 번째 항목이 선택되었는지를 받기 위한 변수이고,
    '//str은 사용자에게 메시지를 보여주기 위한 변수입니다.

    With ListBox1
        intNum = .ListIndex
        If ListBox1.ListIndex < 0 Then
            MsgBox "메뉴를 선택하세요!!", vbInformation, "//Exceller"
            Exit Sub
            '//ListIndex 속성값은 항상 0부터 시작이 된다고 지난 번에 설명을 드렸는데 기억하고 계시지요?
            '//따라서 ListIndex 속성이 0보다 작다는 것은 아무 것도 선택되지 않았다는 것이니까 이런 경우
            '//에는 에러 메시지를 출력하고 프로시저를 빠져 나가도록 조치합니다.

            '//여기서 vbInformation이라는 못보던 것이 하나 나왔지요? 이것을 MsgBox 상수라고 부르며,
            '//vbOKOnly, vbYesNo, vbQuestion, vbExclamation, vbCritical 등 20여 가지가 있습니다. 또한
            '//두 개 이상의 상수들을 조합해서 vbExclamation + vbOKOnly 등과 같이 사용할 수도 있습니다.
            '//그 밖의 상수들에 대해서는 도움말을 참조하세요. 한 20여 가지 정도 될 것입니다.
        End If

        str = .List(intNum) & "을(를) 선택하셨군요!" & vbCr & vbCr & _
        "대단한 안목이십니다!!!"
        '//선택된 리스트 박스의 목록에 다가 다른 문자열 등을 첨가하여 새로운 문자열을 하나 만듭니다.
    End With
    MsgBox str, , "//Exceller"
End Sub

(2) 닫기 버튼

(5) Shift + <F7>을 눌러 유저폼을 불러온 다음, Cancel 버튼을 더블클릭 하여 코드창에 유저폼을 종료하기 위한 다음의 코드를 입력합니다. 이 코드는 이제 눈감고도(!) 입력하시겠지요?

Private Sub cmdClose_Click()
    Unload Me
End Sub

자, 이제 여기까지가 워밍업 이었습니다 ^^. 심호흡을 하시고… 계속 진행하도록 하지요.

(3) 컬렉션으로 중복 제거하기

(6) "삽입-모듈" 메뉴를 선택하여(또는 도구모음을 사용하셔도 되겠지요?) 모듈 시트를 하나 삽입합니다. 그 다음에 다음의 코드를 입력하세요. 이 부분이 오늘의 핵심입니다.

Sub ExtractOneItem2()
    '이 예제는 J.G. Hussey님의 아이디어에서 힌트를 얻어 만들어 본 것입니다//By Exceller
    Dim rngAll As Range
    Dim rngCell As Range
    Dim X As New Collection
    Dim varItem
    Dim sht As Worksheet
    '//등장인물과 배역을 지정해 주었습니다.
    '//rngAll은 아이템들이 있는 전체 영역을 지정하기 위한 Range 오브젝트 변수,
    '//rngCell은 rngAll 내에 있는 각 셀들에 접근하기 위한 오브젝트 변수입니다.
    '//그 다음에 Dim X As New Collection이라는 보도듣도 못한 새로운 것이 하나 나왔지요?
    '//이것이 바로 컬렉션 오브젝트 입니다. 이것을 통해 새로운 아이템들을 담아둘 수 있는데 아래에서
    '//설명을 드리겠습니다.

    Set sht = Sheets("Sheet2")
    Set rngAll = sht.Columns(1).SpecialCells(xlTextValues)
    '//sheet2를 sht라는 시트 오브젝트 변수에 담아두고, rngAll에는 sheet2의 1번째 열 중에서 문자열이
    '//들어있는 모든 셀이 포함이 됩니다. 즉 문자열이 연속되지 않아도 되는 것이지요.

    On Error Resume Next
    '//On Error Resume Next는 "에러가 발생했을 경우 계속해서 그 다음 문장을 실행하라"는 뜻이라는 건
    '//다들 아실테고… 한 가지 주의하셔야 할 점은, 오늘의 컬렉션 오브젝트를 사용하기 위해서는 이 구문
    '//을 반드시 적어주어야 한다는 것입니다. 그 이유는… 아래에서 설명드립니다.

    For Each rngCell In rngAll
        X.Add rngCell.Value, CStr(rngCell.Value)
        '//컬렉션 오브젝트의 기본적인 사용형태는
        '//[오브젝트명.Add Item, key, (before), (after)] 입니다.
        '//여기서 key 요소(정식 용어로는 argument라고 하지요)는 unique한 텍스트, 즉 중복되지 않는
        '//텍스트일 경우에만 유효합니다.
        '//먼 말이냐 하면, 만약에 위에서 나왔던 값을 밑에서 또 만나면 에러가 발생하게 되고, 따라서
        '//아이템에 추가가 되지 않는다는 말입니다. 이러한 성질머리를 최대한 활용해서 오늘의 과제를
        '//를 해결하는 것이지요.

        '//다시 한번 정리를 해 보면, key라는 argument가 사용되면 반복되는 값이 나타날 때 에러가 발생
        '//합니다. 에러가 발생되면 당연히(!) 아이템이 추가가 되지 않을 것입니다. 그렇지만 위에서 On
        '//Error Resume Next라는 구문을 써 주었으므로 프로그램 자체를 종료하지는 않고 그 다음 아이
        '//템을 계속 돌면서 새로운 아이템이 발견될 경우 이를 추가하게 되는 것이지요.

        '//즉, 에러가 발생되면 아이템이 추가가 되지 않지만 "이것이 바로 우리가 원하는 바"이지요. 기특
        '//하게도…

        '//이해 하시겠습니까?
    Next rngCell
    On Error GoTo 0

    UserForm1.ListBox1.Clear
    For Each varItem In X
        UserForm1.ListBox1.AddItem varItem
        '//컬렉션 오브젝트인 X에 저장된 아이템(들)에 대해 순환문을 돌려서 UserForm1에 있는 리스트
        '//박스에 아이템을 하나씩 하나씩 추가해 나갑니다.
    Next varItem

    With UserForm1
        .Label1.Caption = "발췌된 아이템數: " & X.Count
        .Label2.Caption = "총 아이템數: " & rngAll.Count
        .Show
        '//지금까지는 유저폼 내에 있는 레이블 컨트롤의 속성을 바꾸어 줄 때 속성창을 사용하여 수정을
        '//해 주었었지요? 그렇지만 이렇게 코딩을 통해 고쳐줄 수도 당연히 있습니다. 적어도 손으로 작업
        '//이 가능하다면 프로그래밍을 통해 자동화를 할 수 있다는 얘기가 되지요.
    End With
    '//이러한 일련의 과정을 통해 중복 아이템들이 걸러진 Unique한 Item들을 리스트 박스에 추가한 다음,
    '//이것을 유저폼의 Show 메서드(Method)에 의해 화면상에 표시합니다.
End Sub

마무리

이렇게 해주면 됩니다. 생각만큼 복잡하지는 않을 것입니다. 다음에 또…

정리 — Collection 중복 제거 핵심

구분 사용한 코드 역할
컬렉션 선언 Dim X As New Collection 고유 항목 보관
항목 추가 X.Add rngCell.Value, CStr(rngCell.Value) Key로 중복 방지
에러 무시 On Error Resume Next 중복 시 다음으로
목록 채우기 UserForm1.ListBox1.AddItem varItem 고유 항목 표시
개수 표시 X.Count / rngAll.Count 추출 수와 전체 수

자주 묻는 질문 (FAQ)

Q1. Collection에서 중복이 제거되는 원리는 무엇인가요?

Key 인수가 유일한 텍스트일 때만 유효하므로, 이미 있는 Key로 추가하면 에러가 발생하여 항목이 추가되지 않습니다.

Q2. On Error Resume Next를 꼭 써야 하나요?

네. 중복 Key에서 발생하는 에러로 프로그램이 멈추지 않고 다음 항목으로 넘어가게 하려면 반드시 필요합니다.

Q3. MsgBox 상수는 무엇인가요?

vbInformation, vbYesNo, vbQuestion 등 메시지 상자의 아이콘과 버튼 형태를 지정하는 상수이며, vbExclamation + vbOKOnly처럼 조합할 수 있습니다.

마치며

새로운 개념이 하나 나오니 차분히 따라 해 보시기 바랍니다.