반응형
S Y N O P S I S #모든 조합 뽑아내기2
- 구버전 에디터를 쓰다가 작성한 내용이 모두 날아갔다..(깊은 한숨..)
- 지난 포스팅(링크(새창))에 문의해주신 분에 대한 답으로 조합을 산출하는 매크로를 응용하는 코드를 작성해보았다.
- 문의내용의 요지는, 'n개의 집단 중에서 임의의 r개의 집단을 뽑는 nCr개의 조합을 산출하고, 각각의 조합에 대해 다시 하위요소들의 조합을 열거하는 것'이다.
- 예컨대, 4개의 집단(커피, 사이즈, 샷추가, 얼음추가) 중에서 2개의 집단을 뽑아내는 4C2개(6개)의 조합에 대해 모든 조합을 열거한다.
- 여기서 사용자가 임의로 변경해주어야 하는 부분은 2가지이다.
- 1) 전체 영역(여기서 n이 결정된다.), 2) 이 중에서 선정할 조합의 개수(여기서 r을 결정한다.)
- 참고로 조합을 산출하는 알고리즘은 고락가락 닷컴(링크(새창))을 참고했다.
- (코드 내에서 comb 함수)
매크로 Output
VBA Code
Option Explicit
Option Base 1
Dim rngSel As Range
Sub every_case()
Dim n As Long
Dim r As Long
Dim arrOfComb() As Variant
Set rngSel = Selection '선택영역 설정
n = rngSel.Columns.Count '열 갯수를 n으로 (nCr의 n)
'////// 바꿔줄 것 /////
r = 2 '조합 개수를 r로 (nCr의 r), 사용자가 임의로 바꿔줘야 함
'//////////////////////
ReDim Preserve arrOfComb(r + 1)
Call comb(arrOfComb, 1, n, r, 1) '재귀로 조합(Combination) 산출
End Sub
Public Function comb(ByRef arr() As Variant, ByVal idx As Integer, ByVal n As Integer, ByVal r As Integer, ByVal v As Integer)
If idx = r + 1 Then
Call prt(arr, rngSel)
ElseIf v = n + 1 Then '종결 조건
Exit Function
Else '종결 조건이 아니면
arr(idx) = v
Call comb(arr, idx + 1, n, r, v + 1)
Call comb(arr, idx, n, r, v + 1)
End If
End Function
Public Function prt(ByRef arr() As Variant, ByRef rngSel As Range) '프린트 함수
Dim oCol() As New Collection
Dim i As Long
Dim j As Long
Dim k As Long
Dim m As Long
Dim totalComb As Long
Dim crit As Double
Dim rsltVarStr As String
totalComb = 1
'////// 컬렉션에 데이터를 담는 과정; 배열을 써도 무방함
For j = 1 To UBound(arr) - 1
rsltVarStr = rsltVarStr & rngSel.Cells(1, arr(j)) & "-"
ReDim Preserve oCol(j) '열 갯수만큼 컬렉션 동적 생성
For i = 2 To rngSel.Rows.Count '행 갯수만큼 루프; 열머리가 없다면 1부터 시작하도록 변경
If Not IsEmpty(rngSel.Cells(i, arr(j))) Then '비어있는 셀은 제외
oCol(j).Add Item:=rngSel.Cells(i, arr(j)) '각 컬렉션에 삽입
End If
Next i
totalComb = totalComb * oCol(j).Count '조합해야 할 개수 산출
Next j
'////// 결과물을 보여줄 시트 생성
With Sheets.Add(, Sheets(Sheets.Count)) '결과를 출력할 시트 생성
.Name = rsltVarStr
End With
'////// 조합을 뽑는 과정
crit = totalComb
For j = 1 To UBound(arr) - 1
For m = 1 To totalComb / crit
For k = 1 To crit
Sheets(rsltVarStr).Cells(crit * (m - 1) + k, j) = oCol(j)(1 + Int((k - 1) / (crit / oCol(j).Count)))
Next k
Next m
crit = crit / oCol(j).Count
Next j
End Function
매크로 실행 동영상
Copyright (2021) Ruahneuma. All Rights Reserved.
반응형
'VBA Macro > VBA Excel' 카테고리의 다른 글
[엑셀 VBA] 짤막하고 유용한 사용자정의 함수 및 스니핏 (0) | 2021.02.02 |
---|---|
[엑셀 VBA] 숫자데이터의 구간별 빈도 빠르게 산출하기 (0) | 2021.01.26 |
[엑셀 VBA] 가능한 모든 조합 나열하기 (9) | 2020.05.18 |
[엑셀 VBA] 두 단어의 일치도(%) 산출 매크로 #2 (일반화된 방법) (2) | 2020.05.12 |
[엑셀 VBA] 셀 내용 보존하면서 셀 병합하기 (2) | 2018.07.28 |