이 페이지에서
구문
= Sort2DArray ( 배열, 순번, [정렬방향], [가로방향정렬], [정렬시작지점], [정렬종료지점], [정렬한계값] )
인수구분
형식 설명
배열
필수
Variant
정렬할 2차원 배열입니다.
순번
필수
Long
배열을 정렬할 기준 열번호입니다.
배열의 열번호가 0부터 시작할 경우에는 0부터 증가하는 순번을, 1부터 시작할 경우에는 1부터 증가하는 순번을 입력합니다.
정렬방향
선택
Integer
1이면 오름차순 정렬합니다. 기본값은 -1 (=내림차순 정렬)입니다.
가로방향정렬
선택
Boolean
TRUE일 경우 가로방향으로 정렬합니다. 기본값은 FALSE 입니다.
정렬시작지점
선택
Long
정렬을 시작할 지점입니다. 기본값은 배열의 시작지점입니다.
정렬종료지점
선택
Long
정렬을 종료할 지점입니다. 기본값은 배열의 마지막 지점입니다.
정렬한계값
선택
Long
QuickSort와 InsertionSort를 구분할 한계점입니다. 기본값은 20입니다.
한계값은 데이터 구성에 따라 다르지만, 보통 10~20 사이의 정수가 적당합니다.
마스터 코드
복사한 코드는 VBA 편집기(Alt + F11) 새 모듈에 붙여넣어 사용하세요Function Sort2DArray(DB, ByVal Index As Long, Optional ByVal Order As Integer = -1, Optional ByVal ByColumn As Boolean = False, Optional ByVal lngStart As Long = 0, Optional ByVal lngEnd As Long = 0, Optional THRESHOLD As Long = 20)
'###############################################################
'오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com)
'수정 및 배포 시 출처를 반드시 명시해야 합니다.
'
'■ Sort2DArray 명령문
'■ 2차원 배열을 오름차순/내림차순 또는 내림차순으로 정렬합니다. 한계점을 설정하여 QuickSort 또는 InsertionSort로 보다 빠르게 정렬할 수 있습니다. 기본 한계점은 20입니다.
'■ 인수 설명
'_____________DB : 정렬할 배열입니다.
'_____________Index : DB를 정렬할 기준 순번입니다.
'_____________Order : [선택인수] 1 이면 오름차순 정렬합니다. 기본값은 -1 (=내림차순) 정렬입니다.
'_____________ByColumn : [선택인수] True 면 열방향(가로방향) 정렬입니다. 기본값은 FALSE 입니다.
'_____________lngStart : [선택인수] 정렬을 시작할 시작점입니다. 기본값은 배열의 시작지점입니다.
'_____________lngEnd : [선택인수] 정렬을 종료할 마지막점입니다. 기본값은 배열의 마지막지점입니다.
'_____________Threshold : [선택인수] QuickSort와 InsertionSort를 구분할 한계점입니다. 기본값은 20 입니다. Threshold 는 사용되는 데이터의 구성에 따라 다르지만 대부분 10-20 사이의 정수가 사용됩니다.
'■ 반환값
'_____________정렬된 배열을 반환합니다.
'본 명령문은 아래 링크를 참조하여 작성된 명령문입니다.
'https://www.vbforums.com/showthread.php?631366-RESOLVED-Quick-Sort-2D-Array
'###############################################################
Dim i As Long: Dim j As Long: Dim k As Long
Dim Pivot: Dim Temp
Dim Stack(1 To 64) As Long: Dim StackPtr As Long
If lngStart = 0 Then
If ByColumn = False Then lngStart = LBound(DB, 1) Else lngStart = LBound(DB, 2)
End If
If lngEnd = 0 Then
If ByColumn = False Then lngEnd = UBound(DB, 1) Else lngEnd = UBound(DB, 2)
End If
'가로방향 정렬
If ByColumn Then
ReDim Temp(LBound(DB, 1) To UBound(DB, 1))
Stack(StackPtr + 1) = lngStart
Stack(StackPtr + 2) = lngEnd
StackPtr = StackPtr + 2
Do
StackPtr = StackPtr - 2
lngStart = Stack(StackPtr + 1)
lngEnd = Stack(StackPtr + 2)
If lngEnd - lngStart < THRESHOLD Then
' 비교 대상의 첫번째 값과 마지막값 차이가 20 미만일 경우 Insertion Sort
For j = lngStart + 1 To lngEnd
For k = LBound(DB, 1) To UBound(DB, 1)
Temp(k) = DB(k, j)
Next
Pivot = DB(Index, j)
For i = j - 1 To lngStart Step -1
If Order >= 0 Then
If DB(Index, i) <= Pivot Then Exit For
Else
If DB(Index, i) >= Pivot Then Exit For
End If
For k = LBound(DB) To UBound(DB)
DB(k, i + 1) = DB(k, i)
Next
Next
For k = LBound(DB) To UBound(DB)
DB(k, i + 1) = Temp(k)
Next
Next
Else
' 비교 대상의 첫번째 값과 마지막값 차이가 20 이상일 경우 Quick Sort
i = lngStart: j = lngEnd
Pivot = DB(Index, (lngStart + lngEnd) \ 2)
Do
If Order >= 0 Then
Do While (DB(Index, i) < Pivot): i = i + 1: Loop
Do While (DB(Index, j) > Pivot): j = j - 1: Loop
Else
Do While (DB(Index, i) > Pivot): i = i + 1: Loop
Do While (DB(Index, j) < Pivot): j = j - 1: Loop
End If
If i <= j Then
If i < j Then
For k = LBound(DB) To UBound(DB)
Temp(k) = DB(k, i)
DB(k, i) = DB(k, j)
DB(k, j) = Temp(k)
Next
End If
i = i + 1: j = j - 1
End If
Loop Until i > j
If (lngStart < j) Then
Stack(StackPtr + 1) = lngStart
Stack(StackPtr + 2) = j
StackPtr = StackPtr + 2
End If
If (i < lngEnd) Then
Stack(StackPtr + 1) = i
Stack(StackPtr + 2) = lngEnd
StackPtr = StackPtr + 2
End If
End If
Loop Until StackPtr = 0
'세로방향 정렬
Else
ReDim Temp(LBound(DB, 2) To UBound(DB, 2))
' Stack 설정
Stack(StackPtr + 1) = lngStart
Stack(StackPtr + 2) = lngEnd
StackPtr = StackPtr + 2
Do
StackPtr = StackPtr - 2
lngStart = Stack(StackPtr + 1)
lngEnd = Stack(StackPtr + 2)
' 비교 대상의 첫번째 값과 마지막값 차이가 20 미만일 경우 Insertion Sort
If lngEnd - lngStart < THRESHOLD Then
For j = lngStart + 1 To lngEnd
For k = LBound(DB, 2) To UBound(DB, 2)
Temp(k) = DB(j, k)
Next
Pivot = DB(j, Index)
For i = j - 1 To lngStart Step -1
If Order >= 0 Then
If DB(i, Index) <= Pivot Then Exit For
Else
If DB(i, Index) >= Pivot Then Exit For
End If
For k = LBound(DB, 2) To UBound(DB, 2)
DB(i + 1, k) = DB(i, k)
Next
Next
For k = LBound(DB, 2) To UBound(DB, 2)
DB(i + 1, k) = Temp(k)
Next
Next
Else
' 비교 대상의 첫번째 값과 마지막값 차이가 20 이상일 경우 Quick Sort
i = lngStart: j = lngEnd
Pivot = DB((lngStart + lngEnd) \ 2, Index)
Do
If Order >= 0 Then
Do While (DB(i, Index) < Pivot): i = i + 1: Loop
Do While (DB(j, Index) > Pivot): j = j - 1: Loop
Else
Do While (DB(i, Index) > Pivot): i = i + 1: Loop
Do While (DB(j, Index) < Pivot): j = j - 1: Loop
End If
If i <= j Then
If i < j Then
For k = LBound(DB, 2) To UBound(DB, 2)
Temp(k) = DB(i, k)
DB(i, k) = DB(j, k)
DB(j, k) = Temp(k)
Next
End If
i = i + 1: j = j - 1
End If
Loop Until i > j
If (lngStart < j) Then
Stack(StackPtr + 1) = lngStart
Stack(StackPtr + 2) = j
StackPtr = StackPtr + 2
End If
If (i < lngEnd) Then
Stack(StackPtr + 1) = i
Stack(StackPtr + 2) = lngEnd
StackPtr = StackPtr + 2
End If
End If
Loop Until StackPtr = 0
End If
Sort2DArray = DB
End Function
Sub ArrayToRng(startRng As Range, Arr As Variant, Optional ColumnNo As String = "")
'###############################################################
'오빠두엑셀 VBA 사용자지정함수 (https://www.oppadu.com)
'▶ ArrayToRng 함수
'▶ 배열을 범위 위로 반환합니다.
'▶ 인수 설명
'_____________startRng : 배열을 반환할 기준 범위(셀) 입니다.
'_____________Arr : 반환할 배열입니다.
'_____________ColumnNo : [선택인수] 배열의 특정 열을 선택하여 범위로 반환합니다. 여러개 열을 반환할 경우 열 번호를 쉼표로 구분하여 입력합니다.
' 값으로 공란을 입력하면 열을 건너뜁니다.
'▶ 사용 예제
'Dim v As Variant
'ReDim v(0 to 1)
''v(0) = "a" : v(1) = "b"
'ArrayToRng Sheet1.Range("A1"), v
'▶ 사용된 보조 명령문
'Extract_Column 함수
'##############################################################
On Error GoTo SingleDimension:
Dim Cols As Variant: Dim Col As Variant
Dim X As Long: X = 1
If ColumnNo = "" Then
startRng.Cells(1, 1).Resize(UBound(Arr, 1) - LBound(Arr, 1) + 1, UBound(Arr, 2) - LBound(Arr, 2) + 1) = Arr
Else
Cols = Split(ColumnNo, ",")
For Each Col In Cols
If Trim(Col) <> "" Then
startRng.Cells(1, X).Resize(UBound(Arr, 1) - LBound(Arr, 1) + 1) = Extract_Column(Arr, CLng(Trim(Col)))
End If
X = X + 1
Next
End If
Exit Sub
SingleDimension:
Dim tempArr As Variant: Dim i As Long
ReDim tempArr(LBound(Arr, 1) To UBound(Arr, 1), 1 To 1)
For i = LBound(Arr, 1) To UBound(Arr, 1)
tempArr(i, 1) = Arr(i)
Next
startRng.Cells(1, 1).Resize(UBound(Arr, 1) - LBound(Arr, 1) + 1, 1) = tempArr
End Sub
'########################
' 배열에서 특정 열 데이터만 추출합니다.
' Array = Extract_Column(Array, 1)
'########################
Function Extract_Column(DB As Variant, Col As Long) As Variant
Dim i As Long
Dim vArr As Variant
ReDim vArr(LBound(DB) To UBound(DB), 1 To 1)
For i = LBound(DB) To UBound(DB)
vArr(i, 1) = DB(i, Col)
Next
Extract_Column = vArr
End Function
활용 예제
2차원 배열의 첫번째 열을 기준으로 내림차순 정렬
Sub Test1()
Dim DB As Variant
Dim i As Long: Dim j As Long
ReDim DB(0 To 5, 0 To 5)
For i = 0 To 5
For j = 0 To 5
DB(i, j) = Rnd() * 100
Next
Next
DB = Sort2DArray(DB, 0)
End Sub
2차원 배열의 첫번째 행을 기준으로 가로방향 오름차순 정렬
Sub Test2()
Dim DB As Variant
Dim i As Long: Dim j As Long
ReDim DB(0 To 5, 0 To 5)
For i = 0 To 5
For j = 0 To 5
DB(i, j) = Rnd() * 100
Next
Next
DB = Sort2DArray(DB, 0, 1, TRUE)
End Sub
안내사항
1차원 배열을 정렬해야 할 경우에는 SortArray 함수를 사용합니다.
정렬 한계값은 데이터 구성에 따라 조정할 수 있지만, 대부분의 경우 기본값을 그대로 사용해도 무방합니다.


홈페이지에 작성되었던 코드에 문제가 있어 바로 수정했습니다. :)
확인해주셔서 감사합니다!
근데 엑셀 2차원 배열 정렬 :: Sort2DArray 에서 문자 정렬 말고 숫자로 정렬을 할 수는 없나요?
도와 주세요 ^^
https://www.oppadu.com/%ec%97%91%ec%85%80-sortarray-%ed%95%a8%ec%88%98/
위 링크를 참고하여 명령문을 적절히 수정해보세요.
Sort2DArray 는 문자 와 숫자 구별 없이 그냥 숫자로 정렬 되는 거 아닌가요??
제가 필요한 건 숫자 입니다. 그래서 Sort2DArray 를 실행했는데 아래와 같이 나옵니다. ㅠ.ㅠ
예) 1, 10, 11, 2, 21, 22, 3, 4 ...
그리고 링크 주신 건 문자와 숫자 구별을 IsNumeric 함수로 구별해서 하는데 전 그냥 숫자정렬이면 됩니다.
근데 제가 생각하기에는 Sort2DArray 가 숫자로 되는 것 같은데 실제 작동은 문자로 됩니다.
도움 부탁드립니다. ^^
숫자 오름/내림차순 정렬이 잘 되는지 궁금하시다면, 게시글 상단의 '다운로드' 버튼을 클릭해서 완성파일을 한번 확인해보시길 바랍니다.
만약 사용중인 데이터가 1,11,2,21.. 순으로 정렬된다면 원본데이터의 데이터형식이 문자로 되어있어서 그럴 수 있습니다.
원본 데이터를 숫자 데이터로 올바르게 변경 후 코드를 다시 실행해보세요