- 최초 작성일: 2007-07-15
- 최종 수정일: 2026-09-30
- 조회수: 11 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 엑셀로 못하는게 머야 시리즈(5) - 로또번호 생성기
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
엑셀로 못하는게 머야 시리즈(5) - 로또번호 생성기
핵심 요약: 중복 없는 난수 생성기
From, To, How Many? 세 값을 입력하면 그 범위에서 중복 없는 숫자를 원하는 개수만큼 뽑아 주는 VBA 코드입니다. From에 1, To에 45, How Many?에 6을 입력하면 로또번호 생성기가 됩니다.
- 1단계: From부터 To까지의 숫자를 Collection 개체에 모두 담습니다.
- 2단계: Rnd 함수로 위치를 무작위로 골라 결과를 저장하고 컬렉션에서 제거합니다.
- 3단계: 결과를 셀에 표시하고 오름차순으로 정렬합니다.
Step 1: 어떤 질문이었을까요?
질문 하나
다름이 아니옵고 다른 어디를 뒤져봐도 없어서 이렇게 글을 남겨 봅니다. 이번에 10자리 정도 되는 난수 랜덤 하게 뿌려 지는 표를 만들려고 하는데 다들 알지를 못하고 책에도 대략 적으로뿐이 설명이 안나와서 질문을 드립니다.
A-Z 까지 1부터99999까지 의 숫자가 (또는 더큰 수) 합쳐져서 랜덤하게 10자리나 13자리 형식으로 겹치지 않고 랜덤하게 엑셀 표에 나오게 하고 싶습니다.
쉽게 이야기해드리면, 복권형식 스크래치 뒷면에 시리얼을 넣고서 이 시리얼을 가지고 포인트를 줄 생각입니다.
제말이 너무 어려웠나요? 알고싶습니다. 역량을 보여주세요 ^^
비슷한 질문
아무리 봐도 이해 못하는 초보인지라 과거 질문내용들과 강좌를 아무리 봐도 잘 모르겠습니다. 답변 부탁드릴께요
원하는 숫자의 범위를 선택하여 중복없이 난수로 몇개의 숫자를 출력하려 합니다. 즉 1 ~ 20 이란 숫자 중에 5개의 숫자를 무작위로 출력하려고 하는데 여기에서 1, 20, 5 이란 숫자를 직접 써넣구 출력하려합니다.
부탁드립니다. 건강하세요~
역량(?)을 발휘할 수 있을 지는 확신할 수 없지만… 한번 만들어 보도록 하지요. 사실은 '로또번호 생성기'라는 자극적인(?) 제목보다 '중복없는 난수 생성기'라는 표현이 더 맞을 것 같습니다.
Anyway… 적당한 숫자를 입력하고 아래의 '난수 추출하기' 버튼을 클릭해 보세요.
| From | To | How Many? |
|---|---|---|
| 1 | 50 | 8 |
버튼을 클릭하면 아래와 같이 중복 없이 뽑힌 숫자가 오름차순으로 표시됩니다. (예: 8, 9, 14, 18, 22, 23, 34, 38)
각 입력 칸은 다음과 같은 의미를 가집니다.
- From: 시작되는 숫자 입력
- To: 끝나는 숫자 입력
- How Many?: 생성할 숫자의 개수 입력(10개 이하로 지정하세요!)
From에 1, To에는 45, How Many? 부분에는 6을 각각 입력하면 바로… 로또번호 생성기가 되는 것입니다.
Step 2: 코드 살펴보기
코드의 내용을 살펴보도록 하지요.
Const strID As String = "www.iExceller.com"
Sub MakeRandomNum()
Dim X As New Collection
Dim i As Integer
Dim j As Integer
Dim intMin As Integer
Dim intMax As Integer
Dim intNum As Integer
Dim intStart As Integer
Dim intResult() As Integer
Dim intCount As Integer
Dim lngCount As Long
Dim strMsg As String
Dim rngResult As Range
'필요한 변수들을 선언합니다.
On Error GoTo ET
Randomize
Set rngResult = Range("From").Offset(6, -1)
Set rngResult = Range(rngResult, rngResult.End(xlDown))
rngResult.ClearContents
intStart = rngResult.Row - 1
'추출된 숫자가 표시될 영역을 지정합니다. 만약 이미 입력된 것이 있을 경우에는 삭제합니다.
Do
'만약 유효하지 않은 값이 입력되면 계속 입력되도록 하거나 혹은 프로시저를 종료합니다.
If Range("From") = "" Or Range("To") = "" Or Range("HowMany") = "" Then
MsgBox "입력값들을 확인하세요!", , strID
Exit Sub
End If
If Range("HowMany") > 10 Then
MsgBox "추출할 숫자의 갯수는 10개 이하로 지정하세요!", , strID
Exit Sub
End If
Loop While Range("From") = "" Or Range("To") = "" Or Range("HowMany") = ""
intMin = Range("From")
intMax = Range("To")
intNum = Range("HowMany")
ReDim intResult(1 To intNum, 1)
For i = intMin To intMax
X.Add i
Next i
For i = 1 To intNum
j = Int(Rnd * (intMax - intMin - i + 2)) + 1
intResult(i, 1) = X(j)
X.Remove j
'지정한 숫자 범위 내에서 난수를 발생시킵니다. 컬렉션 오브젝트의 값을 intResult 배열 변수에
'할당하고 나서 제거하는 과정입니다.
Next i
For i = 1 To intNum
'컬렉션 오브젝트에 담긴 값들을 지정한 위치에 표시합니다.
For intCount = 1 To intResult(i, 1)
Cells(intStart + i, 1) = intCount
Next intCount
For lngCount = 1 To 10000
'Doing Nothing
'속도 조절을 위한 더미 순환문(Dummy Looping) 입니다. 만약 PC 상황에 따라서 순환
'속도가 너무 느리면 이 부분을 제거하세요.
Next lngCount
Next i
rngResult.Sort key1:=rngResult, order1:=xlAscending
' 화면에 표시된 숫자값들을 오름차순으로 정렬합니다.
strMsg = intMin & " 에서 " & intMax & " 사이의 값 중에서 " & vbCr
strMsg = strMsg & intNum & " 개의 중복되지 않는 숫자를 추출하였습니다"
MsgBox strMsg, , strID
ET:
If Err.Number <> 0 Then
MsgBox Err.Description, , "오류 번호 : " & Err.Number
Err.Clear
End If
End Sub
원문 오류 수정:
- 원본 코드에서는
MsgBox에서strID를 사용하지만 이 상수의 선언이 빠져 있어 맨 위에Const strID를 추가했습니다. - 입력값이 비어 있을 때 메시지 상자만 계속 반복되는 구조여서, 메시지를 보여 준 다음
Exit Sub로 프로시저를 종료하도록 했습니다. - 원본에는
ET:레이블은 있는데On Error GoTo ET가 없어 오류 처리가 동작하지 않았습니다. 이를 추가했습니다. - 난수 발생기를 초기화하는
Randomize를 추가했습니다. 이 구문이 없으면 엑셀을 새로 실행할 때마다 똑같은 순서의 난수가 나옵니다.
코드의 핵심 원리: 먼저 From부터 To까지의 모든 숫자를 컬렉션에 담아 둡니다. 그다음 남아 있는 숫자 개수 안에서 무작위 위치를 하나 골라 결과 배열에 저장하고, 컬렉션에서 그 숫자를 제거합니다. 한 번 뽑힌 숫자는 컬렉션에서 사라지므로 중복이 생기지 않습니다. 추출한 숫자를 셀에 표시할 때 1부터 그 숫자까지 빠르게 세어 올라가는 연출을 넣은 것도 이 예제의 재미있는 부분입니다.
Microsoft 365 최신 버전에서는 함수만으로도 가능합니다. 동적 배열 함수를 지원하는 버전이라면 아래 수식으로 1~45 중 6개의 중복 없는 숫자를 뽑을 수 있습니다(F9 키를 누르면 새로 추출됩니다).
=SORT(TAKE(SORTBY(SEQUENCE(45), RANDARRAY(45)), 6))
'이런 것을 엑셀로 만들어 보았으면…' 하는 것이 있는 분은 알려주시기 바랍니다. '엑셀로 못하는게 머야 씨리즈'를 통해 다루어 보도록 하겠습니다.
다음에 또…
정리 — 중복 없는 난수 생성 코드 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 후보 숫자 담기 | X.Add i | From~To의 숫자를 컬렉션에 저장 |
| 난수 위치 | Int(Rnd * (intMax - intMin - i + 2)) + 1 | 남은 숫자 개수 안에서 위치 선택 |
| 중복 방지 | X.Remove j | 뽑은 숫자를 컬렉션에서 제거 |
| 난수 초기화 | Randomize | 실행할 때마다 다른 난수 발생 |
| 정렬 | rngResult.Sort key1:=rngResult | 결과를 오름차순 정렬 |
자주 묻는 질문 (FAQ)
Q1. 중복 없는 난수는 어떻게 만드나요?
후보 숫자를 컬렉션에 전부 담고, 무작위로 하나를 뽑을 때마다 컬렉션에서 그 숫자를 제거하면 됩니다. 이미 뽑힌 숫자는 다시 나올 수 없으므로 중복이 생기지 않습니다.
Q2. Randomize는 왜 필요한가요?
Rnd 함수는 난수 발생기를 초기화하지 않으면 실행할 때마다 같은 순서의 값을 만들어 냅니다. Randomize를 먼저 실행하면 매번 다른 난수가 나옵니다.
Q3. VBA 없이 수식으로도 만들 수 있나요?
동적 배열 함수를 지원하는 Microsoft 365에서는 SORTBY, RANDARRAY, SEQUENCE, TAKE 함수를 조합해 수식만으로 중복 없는 난수를 뽑을 수 있습니다.
마치며
로또번호 생성기라는 자극적인 제목보다는 중복 없는 난수 생성기라는 표현이 더 어울립니다. 컬렉션을 활용한 이 방법은 다양한 추첨 프로그램에 응용할 수 있습니다.