rand(life)

[vba] 빈도 순위 높은 문자 찾기 본문

컴퓨터/엑셀

[vba] 빈도 순위 높은 문자 찾기

flogsta 2017. 7. 23. 17:32

지식인 질문에 대한 답. 다른 분의 답이지만 연구를 위해 가져왔다.


이런 구조에서, A와B열에서 가장 많이 나온 문자, 또는 두번째로 많이 나온 문자를 찾는 문제이다.

VBA로 해야한다.

코드 전체는 첨부화일을 참고하면 된다.

빈도순위찾기.xlsm

코드 중에서 오늘 살펴볼 부분은 아래 부분이다.

  v = Intersect(ws.UsedRange, 범위).Value
    For r = 1 To UBound(v, 1)
        For c = 1 To UBound(v, 2)
            d(v(r, c)) = d(v(r, c)) + 1         
        Next
    Next

그 중에서도 파란색으로 표시한 부분이 제일 어려웠다. 여기서 d는 지난 포스트에서 설명한 Scripting.Dictionary이다.

오랜 시간동안 F8키를 누르면서 살펴보았는데, 결론은 다음과 같다.


위의 그림 상황에서 저 코드까지 실행시키면, d의 item과 key는 다음과 같다

즉, key는 중복되지 않게 추가되는 항목이름(숫자)이며

item은 그 항목의 숫자이다.


            d(v(r, c)) = d(v(r, c)) + 1         가 하는 일은

Silent Method를 이용한 것인데,

d(key) = item

이렇게하면 key가 존재하지 않으면 추가하고, key가 존재하면 item을 수정한다.


즉,

d(v(r, c)) = d(v(r, c)) + 1   

여기서 v(r,c)라는 키가 처음 나오는 것이라면 1을 item으로, v(r,c)를 key로 등록한다.


d(v(r,c))가 처음 등록될때는 item은 0이다.

(원래는 d.add key, item 처럼 등록되어야하는데, d(v(r,c))가 처음 등록될때는 아직 item이 없으므로)

(즉, d( ) 괄호 안에 있는 것이 key로, 등호 (=) 뒤에 있는 것이 item으로 등록된다)


for 순환문을 돌다가 이미 d안에 존재하는 key가  v(r,c)에서 또 나온다면,

기존의 key에 배당되어있는 item에 1을 더한다


이런 식으로 모든 범위를 돌고 나면, d안에 key는 중복된 것없이 쌓이고,

해당 key가 몇번 나왔는지가 item으로 등록된다.


이 item이 해당 key가 나오는 빈도수이므로,

   Let dItems = d.Items

의 구문으로 dItems라는 배열에 해당 item 배열을 집어넣고


이 배열을 이용해서

        n = wf.Large(dItems, nNo) 와 같은 구문으로 빈도순위를 구한다.


주의할 점은, VB편집기에서 지역창을 열어보면 위와 같이 나오는데,

Item 1이라고 쓰여있는 것의 Item Number는 0이다. (Dictionary Object는 0부터 시작하므로)


그리고 "값"이라고 나와있는 것들은 Key이다.


Item은 여기에 표시되지 않는데, 직접 실행창에서

? d(key)

와 같은 방식으로 실행하면 item을 출력한다. 예를 들어, ? d("가") 를 실행하면 3이 출력된다.