• 최초 작성일: 2023-08-21
  • 최종 수정일: 2023-08-21
  • 조회수: 2,364 회
  • 작성자: 권현욱 (엑셀러)
  • 강의 제목: VB0262 ㅡ 중복 값을 제거하는 VBA 코딩법 2가지

엑셀러 권현욱

들어가기 전에 ㅡ 개/고양이보단 나은 사람이 되고자 하였으나

'동물의 왕국'을 좋아하는 사람들이 많다. 40대 이상 중장년 남성층에서 특히 두드러진다. 이유는 다양하다. '동물은 배신하지 않아서', '자연의 순리를 깨달을 수 있어서', '우리 안에 내재된 공격성이 적나라하게 발현되므로' 등이다. 소수 의견으로 이런 것도 있다. '물소 떼가 연대해서 사자의 공격을 막아내는 통쾌한 역전이 있어서'(뭐지, 이건?)

지인이 동영상 링크를 하나 보내 줬다. 곰 한 마리와 할아버지(정확하게는 '푸바오'와 '강할부지')가 투닥거리는 영상이었다. 생각이 정리되지 않을 때마다 보면서 피식거리기도 하고 아무 생각 없이 빠져 들기도 했다. 추천 영상이 이내 곰으로 도배되기 시작했다.

로딩 중...

(이미지: 에버랜드 유튜브 채널에서 캡처)

유튜브를 처음 시작할 때 작은 다짐(혹은 기대)을 했다. '개나 고양이만도 못한 사람은 되지 말자'가 그것이었다. 개나 고양이를 능가하는 사람이 되기 어렵다는 걸 깨닫는 데는 그리 오랜 시간이 필요치 않았다(잠자고 물만 마셔도 몇 십만 뷰를 훌쩍 넘어가는 녀석들을 어떻게 이긴담?)

우리 사회가 푸바오에게 열광하는 것은 그만큼 힘들고 비정상적인 사회의 단면을 보여주는 게 아닐까 하는 생각이 들었다. 안타까운 사고가 수습되기도 전에 더 큰 사건으로 덮히고 있으니 왜 안 그렇겠는가.

사회가 정상을 되찾아서 '곰 영상'보다 '엑셀러TV' 같은 콘텐츠가 더 관심을 받는 날이 왔...으면 좋겠지만 그건 아마 힘들겠지?(푸바오의 인기는 이제 아이돌급이다. 톱스타들에게만 해준다는 지하철 생일 광고도 최근에 받았다)

동물을 보고 있으면 혈압이 떨어지고 심신이 안정된다는 연구 결과들도 있고, 반려동물과의 상호 교감을 통해 정신적 안정감을 주는 '애니멀 테라피'animal theraphy도 있다고 하니 이제 공연한 경쟁심은 접고 '덕심'을 발휘해 볼까나.



  • 이 콘텐츠는 '엑셀러TV' 멤버십 회원 '우선 공개' 콘텐츠입니다. 전체 대상으로는 8월 28일 오픈될 예정입니다.
  • 멤버십 회원에게는 예제 파일을 보내드립니다 ( 멤버십 보러 가기)
  • VBA에 익숙하지 않은 분들은 코드를 복사/붙여넣기하며 따라해 보세요.

사전 준비

얼마 전 강의에서 수식과 기본 기능을 이용하여 '중복된 항목 제거'하는 법에 대해 알아보았습니다. 4가지 방법으로 해결했었죠(수식 2가지 + 기본 기능 2가지).

VBA를 이용하여 해결할 수도 있습니다. VBA에 대해 알아야 하지만 훨씬 다양하고 복잡한 작업도 유연하게 처리할 수 있습니다. 어떻게 활용하는 지는 다른 강의에서 다루기로 하고, 이번 시간에는 기본기를 익히는 데 집중하도록 합니다.

이 강의는 아래 동영상 강의 내용과 보완 관계에 있습니다. 동영상과 함께 보시면 이해하기 더욱 쉽습니다.

워크시트 상태에서 ALT + F11 키를 눌러 Visual Basic Editor를 띄웁니다. [삽입] - [모듈] 메뉴를 선택해서 모듈 시트를 한 장 삽입하고 코딩을 시작합니다.

로딩 중...

코딩 준비

방법 1: 컬렉션 개체 이용

중복된 값이 있는 여러 항목 중에서 고유한 값만 추출할 때, 컬렉션 개체Collection object를 많이 사용합니다.

컬렉션 개체는 변수를 선언할 때 'New'라는 키워드를 붙여야 합니다다.

Dim oWords As New Collection

컬렉션 개체에 구성원을 추가할 때에는 Add, 제거할 때에는 Remove 메서드를 사용합니다. 실제 코드를 보도록 하죠.

Sub getUniqueWords()
    ''' 변수 선언        
    Dim shtWord As Worksheet
    Dim rTbl As Range           
    Dim rWrite As Range
    Dim oWords As New Collection    ''' 컬렉션 개체
    Dim vX As Variant    ''' 컬렉션 개체의 각 구성원에 접근
    Dim rX As Range
    Dim iX As Integer
    
    On Error Resume Next    ''' 반드시 필요
    Set shtWord = Worksheets("연습")
    Set rTbl = shtWord.Range("B3").CurrentRegion
    Set rTbl = rTbl.Offset(1).Resize(rTbl.Rows.Count - 1)
        ''' B열에서 제목을 제외한 영역을 rTbl 변수에 재지정

    Set rWrite = rTbl.Cells(1).Offset(, 8)    
        ''' 결과를 표시할 위치(J4 셀)
    Range(rWrite, rWrite.End(xlDown)).Clear
        ''' 결과를 표시할 영역 주변 정리
    
    ''' 컬렉션 개체에 항목을 겹치지 않게 추가하는 과정
    ''' 세부 설명은 아래에서
    For Each rX In rTbl.Cells
        oWords.Add rX, rX
    Next

    ''' J4 셀부터 결과 표시(J5, J6,...)
    For Each vX In oWords
        rWrite.Offset(iX) = vX
        iX = iX + 1
    Next
End Sub

CODE

컬렉션 개체에 항목을 추가할 때에는 Add 메서드를 이용합니다. 이 때 다음과 같은 형식을 사용합니다.

oWords.Add item:=rX, key:=rX
(또는 oWords.Add rX, rX)

항목을 추가할 때, item과 key를 사용하는데, 만약 같은 key 값이 이미 있다면 오류가 발생하여 실행이 중단됩니다. 하지만 앞에서 On Error Resume Next 문을 추가해 두었으므로 작업이 계속 진행되고, 결과적으로 중복되지 않는 항목들이 컬렉션 개체에 저장됩니다.

프로시저 내부에 커서를 둔 채, [실행] 아이콘을 클릭하면 지정한 위치에 결과가 표시됩니다.

로딩 중...

방법 2: For ~ Next 문 이용

중복된 항목을 제거하려면 반드시 컬렉션 개체를 사용해야 하는 걸까요? 그렇지는 않습니다. 다른 방법도 가능합니다. 앞에서 작성한 코드를 조금 변형합니다. InStr 함수를 사용한 부분을 눈여겨 보세요.

InStr은 '한 문자열이 다른 문자열 내에서 처음 나타나는 위치'를 구해주는 VBA 함수로, 다음과 같은 형태로 사용합니다.

InStr ([시작], 문자열1 , 문자열2 , [비교])
[ ] 인수는 생략 가능
Sub getUniqueWords_2()
    Dim shtWord As Worksheet
    Dim rTbl As Range
    Dim rWrite As Range
    Dim rX As Range
    Dim iX As Integer
    Dim sWord As String     ''' 문자형 변수 추가
    
    On Error Resume Next
    Set shtWord = Worksheets("연습")
    Set rTbl = shtWord.Range("B3").CurrentRegion
    Set rTbl = rTbl.Offset(1).Resize(rTbl.Rows.Count - 1)
    Set rWrite = rTbl.Cells(1).Offset(, 9)
    Range(rWrite, rWrite.End(xlDown)).Clear

    For Each rX In rTbl.Cells
        If InStr(sWord, rX) = 0 Then
            ''' 이 조건이 True라는 것은 새로운 값이 등장했다는 뜻

            rWrite.Offset(iX) = rX    ''' J4 셀부터 결과 표시
            iX = iX + 1
            sWord = sWord & rX
                ''' 다음 비교를 위해 sWord에 rX 값을 계속 추가
        End If
    Next
End Sub

CODE

만약 결과값을 오름차순으로 정렬하려면 다음 한 줄을 프로시저 마지막에 추가하면 됩니다. 여기서부터는 VBA를 얼마나 알고 있느냐에 따라 활용도가 갈립니다.

Range(rWrite, rWrite.End(xlDown)).Sort key1:=rWrite, order1:=xlAscending, Header:=xlNo

내림차순으로 한다면 xlAscending 대신 xlDescending을 사용하면 됩니다.

이 밖에도 다른 방법들이 있을 수 있습니다. 응용력을 발휘하면 수식이나 엑셀 기본 기능으로는 할 수 없는 일들을 처리할 수 있습니다. 기회가 되면 다른 강의에서 다뤄보도록 하죠.