두 개의 표를 날짜에 따라 맞춰서 표시하기(2) - Dictionary
1. Dictionary의 개념
Dictionary는 키와 값이 한 쌍으로 된 구조로
Json파일의 Key, Value와 비슷합니다.
그런데 Json 파일을 다룰 때는 주로 Value 관점에서 접근했는데,
Dictionary는 그동안 사용한 경험으로는 고윳값을 만들기 위해 Key 위주로 사용합니다.
Dictionary의 가장 큰 특징은 Key가 하나뿐이 존재하지 않는다는 것으로, 중복된 데이터를 거르는데 많이 사용하고, 속도도 매우 빠릅니다.
2. Dictionary 선언 방식에 따른 비교
VBA에서 Dictionary를 사용할 때는 참조를 지정해서 이용하는 방식과 참조를 지정하지 않고 VBA의 Object 라이브러리를 이용하는 두 가지 방법이 있으며, 추천은 첫 번째 도구 - 참조 방식인데 이것의 단점은 다른 PC에도 참조를 사용한다고 체크가 되어 있어야 한다는 점이고, 장점은 구문 자동 완성이 지원된다는 것입니다.
두 개를 개괄적으로 비교하면 아래와 같습니다.
구분 | 도구 - 참조 방식 | Object 이용 방식 |
시작 | 도구 - 참조를 클릭한 후 Microsoft Scripting Runtime를 찾아서 체크 | 참조 체크 필요 없음 |
Dictionary 선언 | Dim myDic as New Scriting Dictionary | Dim myDic As Object set myDic = CreateObject("Scripting.Dictionary) |
키, 값 추가 | myDic.Add Key, Value | |
키가 있는지 체크 | If myDic .Exists("Apples") Then | |
Dictionary 순환 | Dim key As Variant For Each key In myDic .Keys Debug.Print key, myDic(key) Next key | |
키, 값 불러오기 | Dim i As Long For i = 0 To myDic .Count - 1 Debug.Print myDic .Keys(i), myDic .Items(i) Next i | Dim i As Long For i = 0 To myDic .Count - 1 Debug.Print myDic .Keys()(i), myDic .Items()(i) Next i |
이 부분의 차이가 중요하고, 첨자가 0부터 시작하고 myDic.Count - 1 인 것도 주의 |
도구 - 참조가 필요 없는 Object 방식으로 먼저 해보고, 다음으로 도구 - 참조 방식으로 해보겠습니다.
3. 매크로 작성하기
가. Object 방식
도구 - 참조를 설정할 필요가 없으니 바로 코드를 작성하면 됩니다.
Sub objDic()
Dim dicA As Object
'Dictionary 선언
Set dicA = CreateObject("scripting.dictionary")
End Sub
나. 도구 - 참조 방식
(1) 도구 - 참조 선택
① 도구- 참조를 클릭합니다.
② Microsoft Script Runtime을 클릭합니다.
위에 Microsoft Script Control 1.0이 보이는데 이것이 아니고, Microsoft Scripting Runtime입니다.,
왼쪽 체크 박스에 체크하고 확인 버튼을 누릅니다.
그러면 Microsoft Scripting Runtime이 위쪽에 배치됩니다.
③ Dictionary 선언
단 한 줄이면 됩니다.
Sub refDic()
Dim dicA As New Scripting.Dictionary
End Sub
(2) 구문 자동 완성
도구 - 참조 방식을 사용하면 Dictonary와 관련된 구문의 자동 완성이 지원되기 때문에 코딩하기가 편리합니다.
예를 들어 아래와 같이 dim dicA as new s까지 입력하면 scripting이 선택되고, 탭키를 누르고
점(.)을 찍으면 Dictiionary가 표시됩니다. 다시 탭 키를 눌러 완성합니다.
4. 코드 비교
가. Object 방식
Sub objDic()
Dim arrA, arrB
Dim dicA As Object
Dim i As Long
'범위를 배열에 저장
arrA = Range("A4:C" & Range("C5").End(xlDown).row)
arrB = Range("E4:G" & Range("G5").End(xlDown).row)
'Dictionary 선언
Set dicA = CreateObject("scripting.dictionary")
'배열에서 일자 추출해서 합침
Call ArrayToDict(arrA, dicA)
Call ArrayToDict(arrB, dicA)
For i = 0 To dicA.Count - 1
Debug.Print (dicA.keys()(i)) & "," & dicA.items()(i)
Next
End Sub
Sub ArrayToDict(arrName, dicName)
'배열에서 일자를 추출
Dim i As Long
Dim n As Long
For i = 2 To UBound(arrName)
If Not dicName.exists(arrName(i, 1)) Then
dicName.Add arrName(i, 1), n
n = n + 1
End If
Next
End Sub
나. 도구 - 참조 방식
Sub refDic()
Dim arrA, arrB
Dim dicA As New Scripting.Dictionary
Dim i As Long, n As Long
'범위를 배열에 저장
arrA = Range("A4:C" & Range("C5").End(xlDown).row)
arrB = Range("E4:G" & Range("G5").End(xlDown).row)
'배열에서 일자 추출해서 합침
Call ArrayToDict(arrA, dicA)
Call ArrayToDict(arrB, dicA)
For i = 0 To dicA.Count - 1
Debug.Print (dicA.keys(i) & "," & dicA.items(i))
Next
End Sub
5. 실행
아래와 같이 E16셀의 값을 1/12에서 1/13으로 바꾸고
실행하면 결과는 같습니다.
6. 참고 사항 - 저장 시 공유 위반 발생
Object 방식과 도구 - 참조 방식으로 작성한 코드를 하나의 파일에 저장하려고 했더니
V3가 파일을 삭제하고, 엑셀은 아래와 같이 '공유 위반'오류를 발생시키니 반드시 한 가지 방식으로만 코드를 작성해야 합니다.
따라서, 각각 저장한 파일을 첨부합니다.