티스토리 뷰

VBA

[Excel][VBA] 배열을 이용한 셀영역 Shuffle

어린왕자1234 2021. 11. 14. 20:01

■ 셔플 개념

CODE
Sub shuffle_data()

'PURPOSE OF CODE
'TO RANDOMLY SHUFFLE CONTENTS OF AN ARRAY
'SIZE AND TYPE OF ARRAY DOES NOT MATTER
'FOR THIS EXAMPLE I WILL USE A 9 ELEMENT ARRAY OF INTEGERS

    Dim i, rnum, Temp, b(9) As Integer 'dimension array with 9 integer elements
    
    'populate array element i with integer i
    For i = 0 To 9
        b(i) = i
    Next i
    
    'intialize random number generator
    Randomize Timer 
        
    'swap array element i with a random element
    For i = 0 To 9
         'generate random number and store as variable rnum
         'rnum = CLng(Rnd * (UBound(b) - LBound(b)) + LBound(b))  과 동일 결과
         rnum = Int(Rnd * (UBound(b) - LBound(b) + 1) + LBound(b)) 
         'temporarily store array element i to a variable called temp
         Temp = b(i) 
         'set array element i equal to random array element rnum
         b(i) = b(rnum) 
         'set array element rnum to old value of array element i stored as temp
         b(rnum) = Temp 
    Next i
     
    'test that array elements were shuffled
    For i = 0 To 9
        Debug.Print b(i)
    Next i
    
End Sub
 
 

 

■ 셔플함수 구현

     배열 변수(1~10수)  shuffle하여 배열로 반환

CODE
Option Explicit    

Function ShuffleArray(InArray As Variant) As Variant()

    Dim i, j, N As Long
    Dim Temp, Arr() As Variant
    
    Randomize Timer 
    ReDim Arr(LBound(InArray) To UBound(InArray))
    For i = LBound(InArray) To UBound(InArray)
        Arr(i) = InArray(i)
    Next i     
    
    For j = LBound(Arr) To UBound(Arr)
        N = Int(((UBound(Arr) - LBound(Arr) + 1) * Rnd) + LBound(Arr))
        Temp = Arr(j)
        Arr(j) = Arr(N)
        Arr(N) = Temp
    Next j
    ShuffleArray = Arr
    
End Function
Sub Test()
    Dim Arr1, Arr2 As Variant   ' Dim Arr1, Arr2() As Variant 도 가능
    Dim i As Integer

    Arr1 = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    Arr2 = ShuffleArray(Arr1)
    Debug.Print ("[result]")
    For i = LBound(Arr2) To UBound(Arr2)
        Debug.Print (Arr2(i))
    Next i
        
End Sub

 

■ 선택영역 Shuffle

CODE
Option Explicit

Private Sub shuffle_Click()
    Dim r, rng As Range
    Dim Arr, Temp As Variant
    Dim i, j, cnt, w As Integer
    
    '셔플할 영역 설정
    Set rng = Worksheets("sheet1").Range("b4:d15")
    
    cnt = rng.Cells.Count
    ReDim Arr(cnt - 1)
    
    i = 0
    For Each r In rng
        Arr(i) = r
        'Debug.Print (Arr(i))
        i = i + 1
    Next r
    
    '랜덤 index 생성하여 배열을 순차적으로 shuffle
    Randomize Timer 'intialize random number generator
    For i = 0 To cnt - 1
        j = CLng(((UBound(Arr) - 0 +1) * Rnd) + 0)
        Temp = Arr(i)
        Arr(i) = Arr(j)
        Arr(j) = Temp
        'Debug.Print (Arr(i))
    Next i
        
    '셔플데이터를 셀에 대입  rng = Arr 은 불가
    For i = 1 To rng.Rows.Count
        For j = 1 To rng.Columns.Count
            w = (rng.Columns.Count) * (i - 1) + (j - 1)
            rng.Cells(i, j) = Arr(w)
            'Debug.Print (w)
        Next j
        
    Next i     
    
End Sub
 

shuffle.xlsm
0.03MB

 

■ 특정 범위를 이용하여 Suffle데이터 출력

     - 위의 수식만큼 완벽한 결과 구현 불가 => 배열의 특성 때문

 

1. 아래의 함수를 모듈에 붙여 넣는다.

CODE
Function ShuffleRange(ByVal rng As Range) As Variant
       
    Dim a, i, r, k As Integer
    Dim j, Temp, arr() As Variant
    
    
    i = 0
    For Each j In rng
        ReDim Preserve arr(i)
        arr(i) = j
        i = i + 1
    Next j
    
    Randomize Timer
    For a = 0 To UBound(arr)
        r = Int(Rnd * (UBound(arr) + 1))
        Temp = arr(a)
        arr(a) = arr(r)
        arr(r) = Temp

    Next a
    
    ShuffleRange = arr
    
End Function

2. 사용자 지정 함수에서 아래의 수식을 입력하여 배열수식과 일반수식의 결과 차이를 확인한다.

shuffle_test.xlsm
0.02MB