- 최초 작성일: 2000-08-10
- 최종 수정일: 2026-09-30
- 조회수: 8 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: 시트 정렬하기
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
Excel에서 작업을 하다보면 경우에 따라서는 작업 시트가 10개, 20개, 마구 불어나고 나중에는 이 시트들을 사전순으로 정렬을 해 주어야 하는 경우가 생길 것입니다. 예를 들어 시트가 30개 정도 된다면 이들 중에서 자기가 원하는 시트로 이동하려면 어떻게 할까요?
물론 시트이동 탭을 오른쪽 마우스 버튼으로 눌러서 (그나마) 좀 쉽게 이동하는 방법도 있지만 그것도 시트 가 많다면 시트 이름이 한번에 다 나타나지 않아 불편할 것입니다. 먼저, 이 워크북에 있는 여러 시트들의 위 치를 무작위로 흩어놓은 다음, 아래의 버튼을 누르세요.
잘 되지요? 이번 강좌에서는 이렇게 시트를 이름순으로 정렬하는 방법에 대해 설명을 드리겠습니다. 코드를 보시기 전 에 '어떻게 하면 이런 것이 가능할 것인가?' 머리속에서 한번 생각해 보시는 것이 좋을 것입니다.
시트를 정렬하는 것도 아마 여러 가지 방법이 있을 것으로 생각이 됩니다만 제가 주로 사용하는 두 가지 방 법에 대해 소개해 드리지요. 혹시라도 다른 기발한 방법이 있는 분은 알려주시기 바랍니다.
시트 정렬하기
핵심 요약: 시트를 이름순으로 정렬하기
시트 이름을 정렬한 결과대로 Move 메서드로 시트 위치를 바꾸면 이름순 정렬이 됩니다.
- 방법 1: Temp 시트의 A열에 시트 이름을 적고 Sort한 뒤 순서대로 Move합니다.
- 방법 2: 배열에 이름을 담고 버블 소트로 인접한 이름을 교환합니다.
- 핵심: 두 값을 바꿀 때는 임시 저장공간을 사용합니다.
방법 1: 시트 이름을 셀에 적고 정렬하기
(방법 1) 각 시트의 이름을 워크시트에 표시한 다음 Sorting을 활용하는 방법
Sub SheetSortByName2()
Dim sht As Worksheet
Dim rngCell As Range
Dim intNum As Integer
Dim intCount As Integer
Dim strTemp As String
'//먼저 등장인물(변수)을 설정해 줍니다.
Application.DisplayAlerts = False
Worksheets.Add.Name = "Temp"
'//보통 시트를 삭제하려고 하면 "시트를 정말로 삭제할까요 말까요?…"하고 물어오는데 "Application.
'//DisplayAlerts=False"라고 지정을 하면 묻지 않고 바로 지웁니다.
'//그리고 나서 워크시트를 한 장 삽입한 다음, 시트이름을 "Temp"라고 정해줍니다.
For Each sht In Worksheets
intCount = intCount + 1
Cells(intCount, 1) = sht.Name
Next sht
'//각 워크시트를 돌면서 시트의 이름을 좀전에 삽입한 워크시트의 A1셀부터 아래로 가면서 차례로 적어
'//둔 다음,
Columns(1).Sort key1:=Range("A1"), order1:=xlAscending, Header:=xlNo
'//첫번째 열을 기준으로 오름차순 정렬을 합니다. 그러면 시트의 이름들이 사전순으로 나열되겠지요?
For Each rngCell In Range("a1").CurrentRegion.Columns(1).Cells
intNum = intNum + 1
strTemp = rngCell.Value
Sheets(strTemp).Move before:=Sheets(intNum)
Next rngCell
'//For~Next 순환문을 돌면서 Temp 시트의 A열에 있는 각 셀들의 값을 strTemp라는 변수에 저장을
'//하고 시트의 위치를 바꾸어 줍니다. 이 과정을 시트 수만큼 반복해 주면 사전순 배열이 될 것입니다.
'//왜 그렇게 되냐고요? 종이에다가 intNum값을 하나씩 증가시켜 가면서 위의 순환문을 한바퀴씩 돌려
'//보세요. 그러면 금방 답이 나옵니다 ^^.
Sheets("Temp").Delete
'//이렇게 해서 정렬이 끝난 다음에는 Temp라는 임시 작업공간 시트는 삭제를 해 주어야 겠지요?
'//만약 이것을 삭제하지 않을 경우, 다음 번에 이 프로시저를 다시 실행하게 되면 에러가 나겠지요?
'//왜냐하면 프로시저 초반부에 Worksheets.Add.Name="Temp"라는 구문 때문이지요.
End Sub
방법 2: 버블 소트 알고리즘 사용하기
버블소트 알고리즘 이라고 하니까 겁부터 나시지요? ^^;
아래와 같이 한 셀에는 "토끼"라는 값이 입력되어 있고, 다른 셀에는 "거북이"라는 값이 들어 있습니다. 그렇다면 이 두 값을 서로 바꾸어 주려면 어떻게 해야 할까요? 즉 토끼가 든 셀은 거북이로, 거북이가 든 셀은 토끼로 바꾸어 주려면 말입니다.
먼 말인지 이해가 안 가시지요? ^^ 아래의 "토끼/거북이 바꾸기" 버튼을 눌러 보세요.
어떻습니까? 버튼을 한번 누를 때마다 두 셀의 값이 서로 바뀌지요? 어떻게 하면 이렇게 될까요? 알고보면 간단합니다.
- (1) 먼저 "토끼"라는 값을 임시 저장공간에다가 담아둡니다.
- (2) "거북이"라는 값을 가져와서 "토끼"위에 엎어씁니다.
- (3) 원래 "거북이"가 들어있든 셀을 (1)에서 임시 저장공간에 담아두었던 토끼로 대치합니다.
이렇게 3단계 작업을 하면 되겠지요? 논리적으로는 아주 간단합니다. 코끼리를 냉장고에 넣는 3단계와 흡사한 것도 같지요? 하하하!! 농담입니다.
Sub SwapCells()
Dim varTemp
varTemp = Range("B77").Value
Range("B77").Value = Range("D77").Value
Range("D77").Value = varTemp
End Sub
이것은 버블소트 라고는 할 수는 없겠지만 이 아이디어를 약간 응용한 것이 버블소트 알고리즘입니다. 코드를 살펴 볼까요?
Sub SortByBubbleSort()
Dim i As Integer
Dim j As Integer
Dim varTemp
Dim strName() As String
'//변수를 선언하는 것은 보통 때와 똑같은데… strName()이라고 하는 배열변수를 하나 선언한 것이
'//조금 다르군요. 배열변수에 대해서는 설명을 드렸던가요? 드렸군요. 예전에 셀을 병합하는 방법에
'//대해 설명을 드릴 때 (동적) 배열변수를 사용해서 해결을 했었지요? 기억이 안나는 분들은 다시
'//살펴보시기 바랍니다. 어짜피 반복학습이 중요한 것이니까…
i = Sheets.Count
ReDim strName(1 To i)
'//현재 시트의 수를 카운팅 한 다음, 다시 strName() 배열변수의 크기(정확히 말하자면 차원의 크기)
'//를 다시 지정해 주었습니다.
'//ReDim문은 Dim문에 의해 이미 선언된 동적 배열의 크기를 지정(또는 재확정)할 때 사용합니다.
'//배열의 요소나 차원의 개수를 바꾸고자 할 경우, ReDim문을 여러 번 반복해서 사용할 수도 있으나
'//배열변수의 타입이 Variant가 아니라면 데이터 타입 자체를 바꿀 수는 없습니다. 보다 자세한 사항은
'//도움말을 참고하시도록…
For i = LBound(strName()) To UBound(strName())
strName(i) = Sheets(i).Name
Next i
'//배열과 관련하여 새로운 것이 하나 나왔군요. Ubound()는 배열에서 지정된 차원의 최대범위를 돌려
'//줍니다.(누구 기죽일려고 작정을 했나? 지정된 차원의 최대범위를 어쩐다구?!@#$) ^^;)
'//쉽게 말해서 strName(1 to 10, 1 to 5)라고 하게 되면 이것은 2차원 배열이 됩니다. 가로/세로 방향으
'//로 있으니까 2차원인 것이지요. 그리고 차원의 최대범위라는 것은 그냥 해당 차원이 갖는 제일 큰 값
'//이라고만 생각해 두세요. (Lbound()는 Ubound()와는 반대의 특징을 갖는 것이겠지요?)
'//즉 For LBound(strName())=1 To Ubound(strName())에서 최대범위는 얼마일까요? ReDim strName(I)
'//에 의해서 현재 워크북의 워크시트 수만큼이 되겠지요? 지금 보시는 파일에서 시트수가 몇 개 입니까?
'//7개 이지요. 따라서 Ubound()는 7인 것이지요.
For i = UBound(strName()) - 1 To LBound(strName()) Step -1
'//여기서 Ubound(strName())-1을 해 준 이유는 아시겠지요? 현재 시트를 다른 시트들과 비교를 해야
'//하므로 당연히 현재 시트와 현재 시트를 비교할 필요는 없겠지요? 그래서 -1을 해 준 것입니다.
For j = 1 To i
If strName(j) > strName(j + 1) Then
varTemp = strName(j)
strName(j) = strName(j + 1)
strName(j + 1) = varTemp
Sheets(varTemp).Move after:=Sheets(strName(j))
'//이 단계에서 버블소트를 사용하였지요? 현재 시트의 이름을 그 다음 시트 이름과 비교를
'//해서 현재 시트 이름이 크면(크다는 말은 사전순으로 따졌을 때 뒷부분이라는 얘기이지요!)
'//(1) 현재 시트 이름을 임시 저장공간에 담아두고, (2) 다음 시트의 이름을 현재 시트 이름으로
'//바꾸어 주고, (3) 다음 시트의 이름을 임시 저장공간에 있는 이름으로 바꾸어 주는 것입니다.
'//말이 좀 엉킨 것 같은데, 위에서 설명드린 토끼/거북이를 서로 바꾸는 방법과 비교를 해 보시
'//기 바랍니다. 똑같은 논리적 구조이니까요.
'//그 다음에는 현재 시트를 다음 시트의 위치로 이동 시켜주면 되는 것이지요.
End If
Next j
Next i
End Sub
마무리
코끼리를 냉장고에 넣는 방법과 비슷합니까?(하나도 안 비슷하다고요?!@#$) 논리적인 개념을 잘 정리해 두시기 바랍니다. 아마 여러 분야에서 응용이 가능할 것입니다.
그럼…
정리 — 시트 정렬 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 임시 시트 | Worksheets.Add.Name = "Temp" | 정렬용 작업 공간 |
| 정렬 | Columns(1).Sort key1:=Range("A1") | 이름 오름차순 |
| 시트 이동 | Sheets(strTemp).Move before:=Sheets(intNum) | 순서대로 배치 |
| 배열 크기 | ReDim strName(1 To i) | 시트 수만큼 확보 |
| 교환 | varTemp = strName(j) | 임시 저장 후 교환 |
자주 묻는 질문 (FAQ)
Q1. 임시 시트를 마지막에 삭제하는 이유는 무엇인가요?
삭제하지 않으면 다음에 프로시저를 실행할 때 같은 이름의 Temp 시트를 추가하려다 오류가 발생합니다.
Q2. Application.DisplayAlerts = False는 무슨 역할을 하나요?
시트를 삭제할 때 나타나는 확인 메시지를 표시하지 않고 바로 삭제하도록 합니다.
Q3. UBound와 LBound는 무엇인가요?
배열의 지정한 차원에서 가장 큰 첨자와 가장 작은 첨자를 돌려줍니다.
마치며
논리적인 개념을 잘 정리해 두면 여러 분야에 응용할 수 있습니다.