- 최초 작성일: 2001-03-21
- 최종 수정일: 2026-09-30
- 조회수: 15 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 중복없는 난수 만들기
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
0과 1사이의 임의의 수를 발생시키고자 할 때 Rnd 함수를 사용합니다. Rnd 함수는 VBA 함수이므로 워크시트 상태에서는 사용할 수가 없고 워크시트에서는 Rand 함수를 사용하면 됩니다. 아래의 버튼을 눌러 보세요.
중복없는 난수 만들기
핵심 요약: 중복 없는 난수
난수와 일련번호를 짝지어 난수 기준으로 정렬하면 일련번호가 중복 없이 무작위로 섞입니다.
- 1단계: Application.Caller로 배열 수식이 입력된 영역을 알아냅니다.
- 2단계: 셀 수만큼 Rnd 난수와 일련번호를 배열에 담고 난수로 정렬합니다.
- 3단계: 정렬된 일련번호를 영역 크기의 배열에 담아 돌려줍니다.
Step 1: 중복 없는 난수가 필요할 때
임의의 숫자가 셀에 표시되기는 하는데… 자세히 살펴보니까 중복되는 숫자가 눈에 띄는군요. 그렇다면 이런 의문을 가지는 분은 없으신지… 난수를 발생시키되 중복되지 않는 숫자들만 발생시키려면 어떻게 해야 하나요?
다시 아래의 버튼을 클릭한 다음 노란색 부분을 살펴 보세요.
원하시는 것처럼 임의의 정수들이 중복없이 나타났지요? 영역 내의 각 셀에는 {=makerandomnum()} 이런 수식이 들어있습니다. 일단 수식 좌우에 중괄호({})가 있는 것으로 보아서 배열수식이라는 것은 아시겠지요? 따라서 노란색 영역 부분을 범위로 지정한 다음, =makerandomnum() 이라고 입력하고 Ctrl + Shift + Enter키를 함께 타닥 입력한 것입니다.
Step 2: MakeRandomNum 사용자 정의 함수
여기서 MakeRandomNum이라는 것은 사용자 정의 함수입니다.
Function MakeRandomNum()
Dim rngTarget As Range
Dim varTemp1 As Variant, varTemp2 As Variant
Dim varMyVar1() As Variant, varMyVar2() As Variant
Dim i As Integer, j As Integer, k As Integer
Dim r As Integer, c As Integer
Dim lngCount As Long
Set rngTarget = Application.Caller
Randomize
'//변수를 선언합니다. 사용된 변수가 좀 많군요. ^^ rngTarget Range 오브젝트 변수에는
'//Application.Caller 즉, 이 함수를 호출하기 전에 지정한 영역을 할당해 주었습니다.
'//그 다음에 있는 Randomize는 난수 발생기를 초기화 시키는 명령입니다.
lngCount = rngTarget.Count
If lngCount > 1000 Then
MakeRandomNum = CVErr(xlErrNA)
Exit Function
End If
'//선택된 영역의 셀 수를 카운팅하여 lngCount에 담아두고, 그 수가 1000을 넘으면 #N/A
'//즉, Not Available 에러 코드를 리턴합니다.
r = rngTarget.Rows.Count
c = rngTarget.Columns.Count
ReDim varMyVar1(1 To r, 1 To c)
ReDim varMyVar2(1 To 2, 1 To lngCount)
'//선택된 영역에 대하여 행 수와 열 수를 카운팅하여 변수 r, c에 각각 저장해 두고,
'//동적 배열 변수인 varMyVar1, varMyVar2의 크기를 지정해 줍니다.
For i = 1 To lngCount
varMyVar2(1, i) = Rnd
varMyVar2(2, i) = i
Next i
'//임의의 숫자(난수)와 지정한 영역의 셀 수에 해당하는 일련의 숫자를 배열변수에
'//차례대로 담아둡니다.
For i = 1 To lngCount
For j = i + 1 To lngCount
If varMyVar2(1, i) > varMyVar2(1, j) Then
varTemp1 = varMyVar2(1, j)
varTemp2 = varMyVar2(2, j)
varMyVar2(1, j) = varMyVar2(1, i)
varMyVar2(2, j) = varMyVar2(2, i)
varMyVar2(1, i) = varTemp1
varMyVar2(2, i) = varTemp2
End If
Next j
Next i
'//좀 복잡해 보이지만 위 문장은 Random Number를 정렬하는 역할을 수행합니다.
'//순환문에 상수를 대입해가며 3~4차례만 순환문을 돌려보시면 이해하실 수 있을 것입니다.
For i = 1 To r
For j = 1 To c
k = k + 1
varMyVar1(i, j) = varMyVar2(2, k)
Next j
Next i
MakeRandomNum = varMyVar1
'//Random Number를 배열변수에 담은 다음 되돌려 줍니다.
End Function
Excel 365와 Excel 2021 이후에는 동적 배열 함수로 사용자 정의 함수 없이도 같은 결과를 얻을 수 있습니다. 예를 들어 1~56을 중복 없이 8행 7열로 섞어 배치하려면 =WRAPROWS(SORTBY(SEQUENCE(56),RANDARRAY(56)),7)을 입력하시면 됩니다(WRAPROWS는 Excel 365 기준).
논리 자체는 간단하지만 이것을 표현하는 방법 측면에 있어서 많은 것을 생각케 하는 예제가 아닌가 생각됩니다. 흰 종이를 한장 펼쳐두고 숫자를 하나씩 대입해 가며 잘 따져 보시기 바랍니다.
어디에 써먹나요?
이런 거는 배워서 어디에 써먹나요?
이런 의문을 가지는 분이 계시리란 생각이 듭니다. 아주 오래 전에 초간단 Slot Machine 게임에 대해 알려드린 적이 있습니다. 만약 여러분이 오락실 주인이라면 승률 조작(앗, 이건 아닌 것 같은데… ^^;)을 할 때에도 사용하실 수 있을 듯 하고… 그것 보다는 추첨같은 것을 할 때 활용하시면 되겠군요. 오락실 운운한 것은 취소!!!
마무리
다음 시간에 또…
정리 — 중복 없는 난수 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 호출 영역 | Set rngTarget = Application.Caller | 수식이 입력된 영역 |
| 난수 초기화 | Randomize | 난수 발생기 초기화 |
| 난수 생성 | varMyVar2(1, i) = Rnd | 0과 1 사이 난수 |
| 정렬 | If varMyVar2(1, i) > varMyVar2(1, j) Then | 난수 기준 정렬 |
| 결과 반환 | MakeRandomNum = varMyVar1 | 배열로 반환 |
자주 묻는 질문 (FAQ)
Q1. 중복되지 않는 난수를 만들려면 어떻게 하나요?
난수와 일련번호를 함께 배열에 담아 난수를 기준으로 정렬하면 일련번호가 중복 없이 무작위로 섞입니다.
Q2. 워크시트에서 난수를 발생시키는 함수는?
Rnd는 VBA 함수이므로 워크시트에서는 RAND 함수를 사용합니다.
Q3. 배열 수식으로 입력하는 이유는?
영역 전체에 결과를 한꺼번에 돌려주려면 Ctrl+Shift+Enter로 배열 수식을 입력해야 하기 때문입니다.
마치며
난수를 정렬하는 원리만 이해하면 추첨처럼 중복 없는 무작위 배치가 필요한 곳에 활용할 수 있습니다.