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

들어가기 전에

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

지난 일요일 아침에 평소보다 좀 많은 거리를 뛰었습니다. 한시간 정도 쉬지 않고 뛰었으니까 거리상으론 여의도 반 바퀴 정도는 되지 않을까 생각합니다. 어느 정도 뛰다보면 숨이 턱에까지 차오르고 그럴 때면 늘상 하는 생각이, '내가 앞으로 또 뛰면 성을 간다 갈어!!!' 하고 다짐을 합니다만 아침에 눈을 뜨고 정신을 차리면 어느새 운동화 끈을 매고 있는 자신을 발견하곤 씩~ 웃곤 합니다. 뜀박질에는 묘한 중독성(좋은 쪽 으로…)이 있는 것 같습니다.

여러분들은 생활을 하시면서 얼마나 많이, 자주 자신의 한계에 접하고 계신지요? 정신적, 육체적 극한 상황에 도달하면 새로운 많은 것들을 생각해 보게 됩니다. 책상머리에 앉아만 있을 때에는 생각지도 못했던 많은 생각을 하게 됩니다.

누구 말처럼 좋은 생각은 책상머리에 가만히 앉아있는데서 나오는 것은 아닌 것 같습니다. Excel도 좋고, Visual Basic도 좋지만 그보다 훨씬 더 중요한 것은 Sound Body임은 재론할 필요도 없을 것입니다. 여러분들도 부지런히 몸을 움직여 보시기 바랍니다.

사설은 이쯤에서 접고…

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

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

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


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

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

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

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

중복아이템 추려내기

핵심 요약: 중복 없이 고유 값 추출하기

각 셀을 그 위의 셀들과 비교해 같은 값이 없을 때만 출력하면 중복 없는 값을 얻을 수 있습니다.

  • 1단계: InputBox(Type:=8)로 대상 셀과 출력 기준 셀을 받습니다.
  • 2단계: 이중 반복문으로 위쪽 셀과 비교해 같으면 GoTo et로 건너뜁니다.
  • 3단계: 새로운 값이면 출력 위치에 기록하고 상태표시줄에 개수를 표시합니다.

Step 1: 결과 미리 보기

이번 시간에 설명드릴 내용은 강좌 제목 그대로 '중복되는 아이템들 중에서 유일한 것만 발췌해 내는 방법'에 대한 것입니다. "그게 뭐야?" 하시는 분들은 위의 버튼을 눌러서 예제를 한번씩 실행시켜 보고 돌아오시기 바랍니다. 이런 질문을 해오신 분들이 그동안 몇분 있었는데 그 분들에게 답변해 드린 내용을 약간 수정해서 설 명을 드리도록 하지요.

Step 2: 고급 필터가 있는데 왜 코딩할까?

여러 아이템들 중에서 중복되지 않는 값들만 추려내는 가장 손쉬운 방법은 아마도 "고급 필터" 기능을 사용하는 것이겠지요? 혹시 '고급 필터에 그런 기능이 어딨어?' 하시는 분이 있으신지? 언젠가 말씀을 드렸던 것 같은데 VBA로 프로그래밍을 하기 이전에 엑셀 본연의 기능 중에 비슷하거나 같은 기능이 있나없나를 먼저 살펴보아야 합니다. 그러기 위해서는 엑셀의 모든 기능들을 속속들이 깨 야 하는 것이겠지요?

각설하고, "고급 필터" 메뉴 중에서 "고유 레코드만" 이라는 항목이 있는데 여기를 선택하고 고급 필터링 을 하게되면 중복없이 고유한 값들만 발췌가 됩니다. 그러면 이런 의문을 가지시겠지요? 즉,

"좀전에는 프로그래밍을 하기 전에 엑셀의 기능을 잘 살펴본 다음, 그런 기능이 없으면 코딩을 하라고 해 놓고, 이제는 왜 고급 필터에 그런 기능이 있단걸 알면서도 프로그램을 짜려 합니까?"

아주 예리한 질문이군요(^^)! 아래의 대표적인 두 가지 이유 때문이지요.

(1) 고급 필터 기능을 사용할 수 없는 상황에 처했을 경우에 대비하기 위해서 입니다. 예를 들어 어떤 프로 그램을 짜서 다른 사람들에게 배포를 했는데 프로그램만 실행시켰다 하면, "워크시트로 빠져 나가서 고급 필터 메뉴에서 고유 레코드만 추출시킨 다음, 다시 돌아오세요!" 뭐 이런 메시지가 나타난다면 프로그램을 공들여서 힘들게 만들어 주고도 욕얻어 먹기 딱 좋겠지요 ^^.

(2) 그리고 또 한가지 이유는 프로그래밍 하는 논리적인 사고를 배양하기 위해서입니다.

Step 3: 코드 살펴보기

코드에 대해 설명을 드리도록 하지요.

Private Sub CommandButton1_Click()
    '이 프로시저를 실행하기 전에 별도로 Sorting을 한다거나 하는 작업은 필요가 없습니다.
    Dim intNum As Integer
    Dim intNum1 As Integer
    Dim intNum2 As Integer
    Dim rngSource As Range
    Dim rngTarget As Range
    Dim strDefault As String
    Dim lngLast As Long
    Dim strActiveCell As String
    '늘 그래왔듯이 변수, 즉 등장인물을 지정합니다.

    Const str1 = "대상 영역의 첫 셀을 선택하세요." & vbCr & _
        "A2 셀을 선택하시는 것이 좋겠군요"
    Const str2 = "어느 셀에서부터 출력할까요?" & vbCr & _
        "B2 셀을 선택하세요!"
    'Const에 대해서는 설명을 드렸던가요? Dim은 변수를 선언할 때 사용하는 반면, Const는 변수가
    '아닌 상수를 지정할 때 쓰는 선언문입니다.

    strActiveCell = ActiveCell.Address
    strDefault = Range("a2").Address
    On Error Resume Next
    Set rngSource = Application.InputBox(str1, "대상셀 선택//Exceller", Type:=8)
    Set rngTarget = Application.InputBox(str2, "출력기준셀 선택//Exceller", strActiveCell, Type:=8)
    'Excel 함수인 InputBox() 함수를 써서 추출할 대상이 되는 셀과 추출한 다음 출력할 기준이 되는
    '셀의 위치를 지정합니다.

    If rngSource Is Nothing Or rngTarget Is Nothing Then Exit Sub
    '만약 실행도중 에러가 발생하더라도 계속 실행을 하라는 문장이지요?
    lngLast = rngSource.Parent.Cells(rngSource.Parent.Rows.Count, rngSource.Column).End(xlUp).Row - rngSource.Row

    For intNum = 0 To lngLast
    '여기서부터 이제 본격적인 중복자료 추출작업에 들어갑니다. rngSource.CurrentRegion.Rows.Count
    '이므로 추출할 대상이 되는 셀에 잇닿아 있는 주변 셀들의 행의 개수만큼 순환문이 반복되겠군요.

        For intNum1 = 0 To intNum - 1
            If rngSource.Offset(intNum, 0) = rngSource.Offset(intNum1, 0) Then GoTo et
            '그런 다음 또 한번의 For~Next 문을 사용해서 추출할 대상이 되는 셀이 한간씩 아래로 이동할 때
            '마다 바로 그 위의 셀들의 값을 일일이 비교를 하게 됩니다. 그래서 같은 값이 나오면 GoTo et 즉,
            'et 부분으로 이동합니다. 여기서 et는 아무 작업도 하지 않도록 설정해 준 하나의 분기점입니다.
            '비록 et에서는 아무 작업도 하지 않지만 일단 갔다가 돌아오면 intNum1은 값이 하나 증가하므로
            '그 아래 셀로 이동하여 비교를 하게 되겠지요?
        Next intNum1

        rngTarget.Offset(intNum2, 0) = rngSource.Offset(intNum, 0)
        '그래서 만약 위 셀의 값과 아래 셀의 값이 다르다면 그것은 새로운 아이템이므로 지정한 셀에 그 값을
        '뿌려주는 것이지요.

        intNum2 = intNum2 + 1
        '그 다음, intNum2의 값을 1씩 증가시켜 주었네요. 여기서 intNum2는 중복없이 아이템을 추출할 때마다
        '셀을 한간씩 아래로 이동시켜 출력하기 위한 변수입니다.

        Application.DisplayStatusBar = True
        Application.StatusBar = intNum2 & "개의 Item 추출..."
        If intNum2 > 15 Then ActiveWindow.SmallScroll down:=1
        '위 세 라인은 프로그램의 실행과는 직접적인 연관이 없이, 사용자의 편의를 돕기 위한 보너스입니다.
        '새로운 항목이 하나씩 추출될 때마다 상태표시줄에 현재까지 몇 개의 아이템이 출력되었는지를 알려
        '주고, 또 추출 아이템이 15개 이상일 경우 화면을 스크롤 시켜줌으로써 사용자가 조금이라도 덜 지루
        '해 하도록 하기 위한 작은 배려인 셈이지요.

et:
    Next intNum
    Application.StatusBar = ""
    MsgBox "총 " & intNum2 & "개의 Item을 추출하였습니다", , "//Exceller"
    '작업이 모두 끝났으면 총 몇 개의 아이템이 추출되었는지를 메시지 박스를 통해 다시 한번 사용자에게
    '알려주고 프로그램을 종료합니다.
End Sub

마무리

별로 어려운 부분이 없을 것입니다. 그런데 한 가지 문제가 있습니다. 뭐냐하면 검색할 자료가 얼마 없을 때에는 괜찮은데 검색해야 할 대상이 몇 천건 정도 된다면 이 프로그램을 실행할 때 시간이 엄청나게 많이 소요가 될 것입니다. 레코드가 많으면 많을수록 더욱 그러하지요. 그렇다면 어떻게 해야 할까요?

그 해결책에 대해서는 다음 시간에 설명을 드리겠습니다.

또한 응용력을 조금 발휘를 해서 UserForm 상에서 리스트 박스를 띄울 때 중복 아이템들을 제거하고 나 타나도록 하는 방법에 대해서도 알아보도록 하지요.

오늘은 여기까지…

정리 — 고유 값 추출 핵심

구분 사용한 코드 역할
범위 입력 Application.InputBox(..., Type:=8) 셀 범위 선택
상수 선언 Const str1 = ... 변하지 않는 메시지
중복 비교 rngSource.Offset(intNum, 0) = rngSource.Offset(intNum1, 0) 위쪽 셀과 비교
건너뛰기 GoTo et 중복이면 다음으로
진행 표시 Application.StatusBar 추출 개수 표시

자주 묻는 질문 (FAQ)

Q1. 고급 필터가 있는데 왜 VBA로 만드나요?

고급 필터를 사용할 수 없는 상황에 대비하고, 프로그래밍의 논리적 사고를 기르기 위해서입니다.

Q2. 데이터가 많으면 어떤 문제가 있나요?

비교 횟수가 늘어나 대상이 수천 건이면 실행 시간이 매우 오래 걸립니다. 그 해결책은 다음 강좌에서 다룹니다.

Q3. Const와 Dim은 어떻게 다른가요?

Dim은 변수를 선언하고, Const는 변하지 않는 상수를 지정하는 선언문입니다.

마치며

엑셀 본연의 기능이 있는지 먼저 살펴본 다음, 필요할 때 코딩하는 습관을 들이시기 바랍니다.