본문 바로가기
  • Welcome!
VBA, VB.NET For Creo

개발 요청] 치수 변경, 간섭 체크, 최단 거리 값 구하기 #2

by ToolBOX01 2024. 11. 27.
반응형

가능한 모든 조합 나열하기 

 

[엑셀 VBA] 가능한 모든 조합 나열하기

개인적으로 필요해서 SPSS의 집단별 통계 기능을 엑셀로 만들고 있는 중이다. 이 매크로는 그 과정의 시작 단계라 할 수 있겠다. 집단별 변수값에 따라 만들 수 있는 모든 조합을 나열한다. 예를

ruahneuma.tistory.com

 

□ Collection 함수

VBA에서 Collection은 객체나 값의 그룹을 관리하기 위해 제공되는 가변 길이 데이터 구조입니다. 간단히 말해, 여러 데이터를 하나의 묶음으로 다룰 수 있는 데이터 타입입니다. 배열(Array)과 유사하지만, 더 많은 기능을 제공하며, 특히 동적이고 다양한 데이터를 처리할 때 유용합니다.

Collection의 주요 특징
1. 가변 크기:
Collection의 크기는 고정되어 있지 않으며, 데이터를 추가하거나 삭제할 수 있습니다.
배열과 달리 ReDim이 필요 없습니다.

2.다양한 데이터 유형:
한 컬렉션에 서로 다른 데이터 유형(예: 숫자, 문자열, 객체)을 저장할 수 있습니다.

3.키를 사용한 항목 식별:
컬렉션의 항목은 **키(Key)**와 **인덱스(Index)**로 접근할 수 있습니다.
키를 사용하면 데이터 검색 속도가 빠르고, 보다 직관적인 코드 작성이 가능합니다.

4.동적 데이터 관리:
데이터 추가(Add) 및 삭제(Remove)를 쉽게 처리할 수 있습니다.

5.루프를 통한 데이터 접근:
For Each...Next 구문을 사용해 컬렉션의 항목을 쉽게 순회할 수 있습니다.

▷ Collection의 기본 사용법

1. Collection 선언 및 초기화

Dim myCollection As New Collection


2. 데이터 추가
데이터를 컬렉션에 추가하려면 Add 메서드를 사용합니다. 키(Key)를 지정하여 항목을 추가할 수도 있습니다.

myCollection.Add Item:="First Item"            ' 인덱스만 사용
myCollection.Add Item:="Second Item", Key:="2" ' 키(Key)를 사용
myCollection.Add Item:=100                     ' 숫자 추가


3. 데이터 읽기
인덱스를 사용해 항목을 가져올 수 있습니다.

MsgBox myCollection(1)  ' 첫 번째 항목 가져오기
MsgBox myCollection("2") ' 키(Key)를 사용하여 항목 가져오기


4. 데이터 삭제
항목을 삭제하려면 Remove 메서드를 사용합니다.
인덱스나 키(Key)를 기준으로 삭제 가능합니다.

myCollection.Remove 1   ' 첫 번째 항목 삭제
myCollection.Remove "2" ' 키 "2"에 해당하는 항목 삭제


5. 루프를 사용한 데이터 접근
For Each 구문으로 컬렉션의 모든 항목을 순회합니다.

Dim item As Variant
For Each item In myCollection
    MsgBox item
Next item

▷ Collection의 한계

1. 인덱스 기반 접근 속도:
컬렉션은 인덱스 기반으로 순차 접근해야 하므로, 대량 데이터 처리에서 성능이 저하될 수 있습니다.

2.정렬 불가:
기본적으로 정렬 기능을 제공하지 않습니다. 정렬이 필요할 경우 배열을 사용하거나 직접 구현해야 합니다.

3.키(Key)의 중복 불허:
같은 키를 가진 항목은 추가할 수 없습니다. 키가 중복되면 오류가 발생합니다.

▷ Collection의 실사용 예제

1. 숫자와 문자열 저장

Sub Example1()
    Dim myCollection As New Collection
    myCollection.Add "Apple"
    myCollection.Add "Banana"
    myCollection.Add 100

    Dim item As Variant
    For Each item In myCollection
        Debug.Print item
    Next item
End Sub

 

2.객체 저장
워크시트(Worksheet) 객체를 컬렉션에 저장하여 쉽게 관리할 수 있습니다.

Sub Example2()
    Dim sheetCollection As New Collection
    Dim ws As Worksheet
    
    ' 모든 워크시트를 컬렉션에 추가
    For Each ws In ThisWorkbook.Sheets
        sheetCollection.Add ws
    Next ws
    
    ' 컬렉션의 각 워크시트 이름 출력
    Dim item As Worksheet
    For Each item In sheetCollection
        Debug.Print item.Name
    Next item
End Sub

 

3. 키를 사용한 데이터 접근

Sub Example3()
    Dim myCollection As New Collection
    myCollection.Add "First Item", "Key1"
    myCollection.Add "Second Item", "Key2"
    
    ' 키로 데이터 접근
    MsgBox myCollection("Key1")
    
    ' 키로 항목 삭제
    myCollection.Remove "Key2"
End Sub

 

▷입력한 값들을 조합하여 표시 하는 기능

Sub GenerateAllCombinations()
    Dim oCol() As New Collection
    Dim rngSel As Range
    Dim totalComb As Long
    
    '// 현재 선택한 영역을 범위로 설정
    Set rngSel = Worksheets("FingerCheck").Range("B6", "G8")
    totalComb = 1
    
    Debug.Print rngSel.Count
    
    '// 데이터를 컬렉션에 저장하고 총 조합 수 계산
    InitializeCollections rngSel, oCol, totalComb
    
    '// 결과 시트 생성
    CreateResultSheet "result"
    
    '// 조합 생성 및 결과 출력
    OutputCombinations oCol, rngSel.Columns.Count, totalComb
End Sub

'// 데이터를 컬렉션에 저장하고 총 조합 수를 계산하는 서브루틴
Private Sub InitializeCollections(rngSel As Range, oCol() As Collection, ByRef totalComb As Long)
    Dim i As Long, j As Long
    
    For j = 1 To rngSel.Columns.Count
        ReDim Preserve oCol(1 To rngSel.Columns.Count) ' 배열 크기 동적 설정
        Set oCol(j) = New Collection                   ' Collection 초기화
        
        For i = 1 To rngSel.Rows.Count
            If Not IsEmpty(rngSel.Cells(i, j)) Then
                oCol(j).Add rngSel.Cells(i, j).Value   ' 값을 Collection에 추가
            End If
        Next i
        totalComb = totalComb * oCol(j).Count          ' 조합 수 계산
    Next j
End Sub

'// 결과 시트를 생성하는 서브루틴
Private Sub CreateResultSheet(sheetName As String)
    On Error Resume Next
    Application.DisplayAlerts = False
    Worksheets(sheetName).Delete '//기존 시트 삭제
    Application.DisplayAlerts = True
    On Error GoTo 0
    
    Worksheets.Add(After:=Sheets(Sheets.Count)).Name = sheetName
End Sub

'// 모든 조합을 생성하여 결과 시트에 출력하는 서브루틴
Private Sub OutputCombinations(oCol() As Collection, colCount As Long, totalComb As Long)
    Dim crit As Double
    Dim j As Long, k As Long, m As Long
    Dim sheetName As String
    
    crit = totalComb
    sheetName = "result"
    
    For j = 1 To colCount
        For m = 1 To totalComb / crit
            For k = 1 To crit
                Worksheets(sheetName).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 Sub

 

입력한 값

 

 프로그램 실행 결과