본문 바로가기

엑셀VBA

엑셀 VBA 딕셔너리(Dictionary) 기능 사용하기

반응형

딕셔너리 사용: 참조 추가

먼저 엑셀 VBA 사용해서 특정 셀에 값 넣기 에서 살펴본 것처럼 엑셀 VBA를 켜고 module을 삽입한다. 딕셔너리 사용을 위한 참조 변경딕셔러리 기능을 사용하기 위해서는 윈도우에서 제공하는 참조 라이브러리를 추가해야 한다. 오피스 추가기능을 가져오는 건데 컴퓨터에 내장되어 있는 것을 가져온다고 생각하면 된다. 아래 그림 1과 같이 추가하면 되고 추가하는 라이브러리 이름은 Microsoft Scripting Runtime이다.

그림1: 딕셔너리 사용을 위한 참조 추가

 

딕셔너리 정의하기

딕셔너리를 사용하기 위해서는 딕셔너리를 하나의 객체로 정의해야 한다. 따라서 아래와 같이 "딕셔너리"라는 변수를 Object로 정의하고 CreateObject 함수를 사용해서 Scripting.Dictionary 객체를 생성한 다음 그 객체를 "딕셔너리"변수에 할당해 준다. 이렇게 하면 이제 "딕셔너리"는 Dictionary의 객체가 된다.

Sub 딕셔너리연습()

Dim 딕셔너리 As Object
Set 딕셔너리 = CreateObject("Scripting.Dictionary")

End Sub

 

딕셔너리 데이터 구성

아래 그림과 같은 예시 데이터로 간단한 딕셔너리(Dictionary)를 만들고 값을 불러내보자. 

그림2: 연습용 데이터

키값과 항목값 추가(Add, Exists)

우리가 사전을 찾을 때 A에 apple, advertisement 등과 같은 단어들이 나오듯이 딕셔너리 데이터도 하나의 key 값에 item 이 종속되어 있는 형태이다. 따라서 딕셔너리에 데이터를 추가할 때는 딕셔너리 객체에 Add 함수를 사용해서 key, item 쌍으로 값을 추가해 준다. 

Sub 딕셔너리연습()

Dim 딕셔너리 As Object
Set 딕셔너리 = CreateObject("Scripting.Dictionary")

' Row 1부터 마지막 7번 Row까지 데이터로 딕셔너리 생성 작업
For i = 2 To 7
    ' 위 그림 2에서 첫번째 컬럼이 종목코드
    코드 = Worksheets("dict").Cells(i, 1)
    ' 위 그림 2에서 두번째 컬럼이 종목명
    종목명 = Worksheets("dict").Cells(i, 2)
    ' 위 그림 2에서 세번째 컬럼이 가격
    가격 = Worksheets("dict").Cells(i, 3)
    ' 딕셔너리 객체에 key는 코드, item 은 종목명을 추가해서 딕셔너리 만드는 코드
    딕셔너리.Add 코드, 종목명
Next

End Sub

 

그런데 사전에 A, B, C... 등과 같은 key 값은 하나씩만 존재하듯이 하나의 딕셔너리에서 key 값은 유일한 값이어야 한다. 위 그림 2에서 종목코드 "463290"이라는 코드가 중복되므로 위 코드를 실행하면 아래와 같은 오류가 발생한다. 

그림3: 딕셔너리 데이터 추가시 Key값 중복될 경우 오류

따라서 딕셔너리 객체에 데이터를 추가할 때는 key 값 중복이 발생하는지를 Exists함수를 통해서 확인해야 한다. 아래와 같이 if 문을 조합해서 추가하려는 코드와 동일한 key 값이 존재하면 아무것도 하지 않고, 그 외의 경우만 key, item을 추가하면 된다.

Sub 딕셔너리연습()

Dim 딕셔너리 As Object
Set 딕셔너리 = CreateObject("Scripting.Dictionary")

For i = 2 To 7
    코드 = Worksheets("dict").Cells(i, 1)
    종목명 = Worksheets("dict").Cells(i, 2)
    가격 = Worksheets("dict").Cells(i, 3)
    If 딕셔너리.Exists(코드) Then
    	'key 값과 동일한 코드가 추가될 경우 pass
    Else
        딕셔너리.Add 코드, 종목명
    End If
Next

End Sub

 

여러 항목 배열로 추가(Add & Array)

item에 여러 항목을 추가하고 싶을 때는 Array로 item들을 묶어내면 된다. 

딕셔너리.Add 코드, Array(종목명, 가격)

 

딕셔너리 데이터 활용

딕셔너리 객체의 key 값들은 딕셔너리. Keys()와 같은 형태로 Keys 함수를 통해서 하나씩 불러올 수 있다. For each 형태와 조합한다면 각 key 별로 데이터를 불러내서 "results" 시트에 순서대로 기록하는 코드를 아래와 같이 구현할 수 있다. 기억할 점은 Array 값을 불러올 때 Array에 기록한 순서대로 종목명은 0번째(0), 가격은 1번째(1) 값으로 불러오면 된다는 것이다.

Sub 딕셔너리연습()

Dim 딕셔너리 As Object
Set 딕셔너리 = CreateObject("Scripting.Dictionary")

...(생략)...

'results 시트에 데이터를 넣는 작업을 시작하는 row
workrow = 2
'딕셔너리 key 값들을 i 에 넣어서 하나씩 작업
For Each i In 딕셔너리.keys()
    'key 값을 첫번째 컬럼에 넣기
    Worksheets("results").Cells(workrow, 1) = i
    'key 값에 해당하는 item 값 array 에서 첫번째 값
    Worksheets("results").Cells(workrow, 2) = 딕셔너리(i)(0)
    'key 값에 해당하는 item 값 array 에서 두번째 값
    Worksheets("results").Cells(workrow, 3) = 딕셔너리(i)(1)
    'results 시트에 데이터를 넣는 작업을 한 row 완료했으니까 +1
    workrow = workrow + 1
Next

End Sub

 

전체적으로 아래 코드와 같이 "dict"시트의 코드, 종목명, 가격을 순서대로 입수해서 코드 중복 없이 딕셔너리를 만들고 이를 "results"시트에 기록하는 코드를 아래와 같이 만들 수 있다.

Sub 딕셔너리연습()

'results 텝의 데이터 마지막행을 구해서 범위를 정한 뒤 내용 삭제(clearcontents)
results데이터마지막행 = Worksheets("results").UsedRange.Rows.Count + 1
Worksheets("results").Range(Worksheets("results").Cells(2, 1), Worksheets("results").Cells(results데이터마지막행, 3)).ClearContents

Dim 딕셔너리 As Object
Set 딕셔너리 = CreateObject("Scripting.Dictionary")

For i = 2 To 7
    코드 = Worksheets("dict").Cells(i, 1)
    종목명 = Worksheets("dict").Cells(i, 2)
    가격 = Worksheets("dict").Cells(i, 3)
    If 딕셔너리.Exists(코드) Then
    
    Else
        딕셔너리.Add 코드, Array(종목명, 가격)
    End If
Next

workrow = 2
For Each i In 딕셔너리.keys()
    Worksheets("results").Cells(workrow, 1) = i
    Worksheets("results").Cells(workrow, 2) = 딕셔너리(i)(0)
    Worksheets("results").Cells(workrow, 3) = 딕셔너리(i)(1)
    workrow = workrow + 1
Next

End Sub

 

추가적으로 최종 작업 파일을 첨부한다.

240803_딕셔너리연습파일.xlsm
0.02MB

반응형