- 최초 작성일: 2001-12-12
- 최종 수정일: 2026-09-30
- 조회수: 20 회
- 작성자: 권현욱 (엑셀러)
- 강의 제목: VBA로 피벗 테이블 건들기 2
들어가기 전에
오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.
지난 시간에 이어서 피벗 테이블을 좀더 건드려(?) 보도록 하겠습니다. PivotCache, CreatePivotTable, PivotTableWizard 등과 같은 오브젝트들에 대해서 도움말을 참고하시라고 했는데 과연 몇 분이나 그렇게 하셨는 지 궁금합니다. Exceller가 하시라는 것을 해서 손해보는 일은 별로 없을 테니까 못 이기는 척하고 그때 그때 따라해 보시기 바랍니다.
지난 강좌에서는 피벗 테이블을 매크로 기록기를 사용하여 코드를 생성한 다음 이것을 보다 효율적인 코드가 되도록 수정하는 방법까지 설명을 드린 기억이 납니다. 이번 시간에는 여기서 한걸음 더 진도를 나아가 보도록 합니다. 버튼을 누르세요.
VBA로 피벗 테이블 건들기 2
핵심 요약: 피벗 테이블에 분기계 추가
CalculatedItems.Add로 월별 항목을 합산한 계산 항목을 만들고 Position 속성으로 위치를 조정하면 소스에 없는 분기계·반기계를 피벗 테이블에 표시할 수 있습니다.
- 1단계: 같은 이름의 PivotSheet가 있으면 지우고 새로 만듭니다.
- 2단계: PivotCache와 CreatePivotTable로 피벗 테이블을 만들고 필드를 배치합니다.
- 3단계: CalculatedItems.Add로 분기계를 만들고 Position으로 위치를 옮깁니다.
Step 1: 예제 데이터
아래 데이터로 피벗 테이블을 만듭니다. 이번에는 월 이름을 Jan, Feb, Mar… 로 입력하였고 1월부터 6월까지의 데이터가 들어 있습니다.
예제 데이터 펼쳐 보기 (Branch / BrandName / Month / Sales_AMT)
| Branch | BrandName | Month | Sales_AMT |
|---|---|---|---|
| 강동 | 아이오페 | Jan | 8700 |
| 강동 | 아이오페 | Feb | 500 |
| 강동 | 아이오페 | Mar | 5600 |
| 강동 | 라네즈 | Jan | 2800 |
| 강동 | 라네즈 | Feb | 6100 |
| 강동 | 라네즈 | Mar | 1000 |
| 강동 | 마몽드 | Jan | 6800 |
| 강동 | 마몽드 | Feb | 900 |
| 강동 | 마몽드 | Mar | 1700 |
| 강남 | 아이오페 | Jan | 1300 |
| 강남 | 아이오페 | Feb | 7500 |
| 강남 | 아이오페 | Mar | 300 |
| 강남 | 라네즈 | Jan | 10000 |
| 강남 | 라네즈 | Feb | 300 |
| 강남 | 라네즈 | Mar | 600 |
| 강남 | 마몽드 | Jan | 1400 |
| 강남 | 마몽드 | Feb | 6800 |
| 강남 | 마몽드 | Mar | 1300 |
| 영등포 | 아이오페 | Jan | 7400 |
| 영등포 | 아이오페 | Feb | 8500 |
| 영등포 | 아이오페 | Mar | 1200 |
| 영등포 | 라네즈 | Jan | 600 |
| 영등포 | 라네즈 | Feb | 3300 |
| 영등포 | 라네즈 | Mar | 6200 |
| 영등포 | 마몽드 | Jan | 8600 |
| 영등포 | 마몽드 | Feb | 9500 |
| 영등포 | 마몽드 | Mar | 900 |
| 종로 | 아이오페 | Jan | 4700 |
| 종로 | 아이오페 | Feb | 6000 |
| 종로 | 아이오페 | Mar | 4800 |
| 종로 | 라네즈 | Jan | 5500 |
| 종로 | 라네즈 | Feb | 5400 |
| 종로 | 라네즈 | Mar | 600 |
| 종로 | 마몽드 | Jan | 400 |
| 종로 | 마몽드 | Feb | 400 |
| 종로 | 마몽드 | Mar | 400 |
| 동대문 | 아이오페 | Jan | 5600 |
| 동대문 | 아이오페 | Feb | 5300 |
| 동대문 | 아이오페 | Mar | 4300 |
| 동대문 | 라네즈 | Jan | 2700 |
| 동대문 | 라네즈 | Feb | 6800 |
| 동대문 | 라네즈 | Mar | 7000 |
| 동대문 | 마몽드 | Jan | 2900 |
| 동대문 | 마몽드 | Feb | 4100 |
| 동대문 | 마몽드 | Mar | 1000 |
| 경서 | 아이오페 | Jan | 3400 |
| 경서 | 아이오페 | Feb | 3100 |
| 경서 | 아이오페 | Mar | 7400 |
| 경서 | 라네즈 | Jan | 6300 |
| 경서 | 라네즈 | Feb | 3900 |
| 경서 | 라네즈 | Mar | 6700 |
| 경서 | 마몽드 | Jan | 3500 |
| 경서 | 마몽드 | Feb | 100 |
| 경서 | 마몽드 | Mar | 6900 |
| 강동 | 아이오페 | Apr | 8700 |
| 강동 | 아이오페 | May | 500 |
| 강동 | 아이오페 | Jun | 5600 |
| 강동 | 라네즈 | Apr | 2800 |
| 강동 | 라네즈 | May | 6100 |
| 강동 | 라네즈 | Jun | 1000 |
| 강동 | 마몽드 | Apr | 6800 |
| 강동 | 마몽드 | May | 900 |
| 강동 | 마몽드 | Jun | 1700 |
| 강남 | 아이오페 | Apr | 1300 |
| 강남 | 아이오페 | May | 7500 |
| 강남 | 아이오페 | Jun | 300 |
| 강남 | 라네즈 | Apr | 10000 |
| 강남 | 라네즈 | May | 300 |
| 강남 | 라네즈 | Jun | 600 |
| 강남 | 마몽드 | Apr | 1400 |
| 강남 | 마몽드 | May | 6800 |
| 강남 | 마몽드 | Jun | 1300 |
| 영등포 | 아이오페 | Apr | 7400 |
| 영등포 | 아이오페 | May | 8500 |
| 영등포 | 아이오페 | Jun | 1200 |
| 영등포 | 라네즈 | Apr | 600 |
| 영등포 | 라네즈 | May | 3300 |
| 영등포 | 라네즈 | Jun | 6200 |
| 영등포 | 마몽드 | Apr | 8600 |
| 영등포 | 마몽드 | May | 9500 |
| 영등포 | 마몽드 | Jun | 900 |
| 종로 | 아이오페 | Apr | 4700 |
| 종로 | 아이오페 | May | 6000 |
| 종로 | 아이오페 | Jun | 4800 |
| 종로 | 라네즈 | Apr | 5500 |
| 종로 | 라네즈 | May | 5400 |
| 종로 | 라네즈 | Jun | 600 |
| 종로 | 마몽드 | Apr | 400 |
| 종로 | 마몽드 | May | 400 |
| 종로 | 마몽드 | Jun | 400 |
| 동대문 | 아이오페 | Apr | 5600 |
| 동대문 | 아이오페 | May | 5300 |
| 동대문 | 아이오페 | Jun | 4300 |
| 동대문 | 라네즈 | Apr | 2700 |
| 동대문 | 라네즈 | May | 6800 |
| 동대문 | 라네즈 | Jun | 7000 |
| 동대문 | 마몽드 | Apr | 2900 |
| 동대문 | 마몽드 | May | 4100 |
| 동대문 | 마몽드 | Jun | 1000 |
| 경서 | 아이오페 | Apr | 3400 |
| 경서 | 아이오페 | May | 3100 |
| 경서 | 아이오페 | Jun | 7400 |
| 경서 | 라네즈 | Apr | 6300 |
| 경서 | 라네즈 | May | 3900 |
| 경서 | 라네즈 | Jun | 6700 |
| 경서 | 마몽드 | Apr | 3500 |
| 경서 | 마몽드 | May | 100 |
| 경서 | 마몽드 | Jun | 6900 |
피벗 테이블이 생성되는데… 지난 시간에 만들었던 것과 비교해서 어떤 점이 다를까요?... 그렇습니다. 분기계, 상반기 데이터가 추가가 되었지요? 분명히 위의 소스 테이블에는 월별 데이터만 있고 분기, 반기별 데이터는 없는데 말입니다.
Step 2: CreatePivotTableByExceller2 프로시저
코드를 볼까요?
Sub CreatePivotTableByExceller2()
Dim pvtPCache As PivotCache
Dim pvtPTable As PivotTable
Dim shtSheet As Worksheet
Dim rngStart As Range, rngButton As Range
Set rngStart = Sheets("Preface").[A22]
'''변수를 선언하는 거야 어느 강좌에서나 그랬던 것처럼 별로 다를 것이 없습니다.
'''다만 PivotCache, PivotTable 등과 같이 낯선 변수 타입, 오브젝트 등이 나오면 항상
'''도움말을 참고해서 정리를 해 두시기 바랍니다. 오기(?)로 아직 도움말을 찾아보지
'''않은 분들! 아직 늦지 않았으니까 얼른 도움말을 찾아보세요!!!!
'''오기도 부릴 때 부려야지요! ^^;
For Each shtSheet In ThisWorkbook.Sheets
If shtSheet.Name = "PivotSheet" Then
MsgBox "같은 시트가 이미 있으므로 지웁니다!", , "동일 시트 발견//By Exceller"
Application.DisplayAlerts = False
shtSheet.Delete
Application.DisplayAlerts = True
End If
Next shtSheet
Worksheets.Add.Name = "PivotSheet"
'''PivotSheet라는 시트가 이미 있을 경우, 지우고 새로운 PivotSheet 시트를 만듭니다.
Set pvtPCache = ActiveWorkbook.PivotCaches.Add _
(SourceType:=xlDatabase, _
SourceData:=rngStart.CurrentRegion.Address)
Set pvtPTable = pvtPCache.CreatePivotTable _
(tabledestination:=Sheets("PivotSheet").[A1], _
tablename:="MyPivot1")
'''이 부분은 어제와 거의 같습니다. 엄밀히 말하면 약간 다르긴 한데… 어디가 다를까요?
'''눈썰미가 있거나 열심히 공부를 하시는 분이라면 금방 아실 터이므로 답은 생략! ^^
With pvtPTable
.PivotFields("BrandName").Orientation = xlPageField
.PivotFields("Branch").Orientation = xlRowField
.PivotFields("Month").Orientation = xlColumnField
.PivotFields("Sales_AMT").Orientation = xlDataField
.PivotFields("Month").CalculatedItems.Add "1/4분기", "= Jan+Feb+Mar"
.PivotFields("Month").CalculatedItems.Add "2/4분기", "= Apr+May+Jun"
.PivotFields("Month").CalculatedItems.Add "상반기", "= Jan+Feb+Mar+Apr+May+Jun"
'''CalculatedItem 라는 컬렉션 오브젝트를 사용하여 각각의 월을 합산하여 분기계,
'''또는 반기계를 구하였습니다.
.PivotFields("Month").PivotItems("1/4분기").Position = 4
.PivotFields("Month").PivotItems("2/4분기").Position = 8
.PivotFields("Month").PivotItems("상반기").Position = 9
'''1/4분기, 2/4분기의 위치를 3월 또는 6월 다음으로 이동시킵니다.
'''이 때 Pivot Table 개체의 Position 속성을 사용하는군요.
'''아래의 코드는 피벗 테이블이 있는 시트 상단에 돌아가기 버튼을 만들어 주기
'''위한 것입니다. 그동안 많이 다루어 왔으므로 크게 어려운 부분은 없을 것이므로
'''해설은 생략합니다.
End With
On Error Resume Next
Application.CommandBars("PivotTable").Visible = False
On Error GoTo 0
Set rngButton = ActiveSheet.[E1]
With rngButton
ActiveSheet.Buttons.Add(.Left, .Top, .Width * 2, .Height).Select
End With
With Selection
.Caption = "<<Go Back!!!"
.OnAction = "GoBack"
With .Characters(Start:=1).Font
.Name = "바탕"
.FontStyle = "보통"
.Size = 10
.ColorIndex = 3
End With
End With
rngButton.Select
End Sub
변수를 선언하는 거야 어느 강좌에서나 그랬던 것처럼 별로 다를 것이 없습니다. 다만 PivotCache, PivotTable 등과 같이 낯선 변수 타입, 오브젝트 등이 나오면 항상 도움말을 참고해서 정리를 해 두시기 바랍니다. 오기(?)로 아직 도움말을 찾아보지 않은 분들! 아직 늦지 않았으니까 얼른 도움말을 찾아보세요!!!! 오기도 부릴 때 부려야지요! ^^;
PivotSheet라는 시트가 이미 있을 경우, 지우고 새로운 PivotSheet 시트를 만듭니다. 그 다음 부분은 어제와 거의 같습니다. 엄밀히 말하면 약간 다르긴 한데… 어디가 다를까요? 눈썰미가 있거나 열심히 공부를 하시는 분이라면 금방 아실 터이므로 답은 생략! ^^
CalculatedItem 라는 컬렉션 오브젝트를 사용하여 각각의 월을 합산하여 분기계, 또는 반기계를 구하였습니다. 그리고 1/4분기, 2/4분기의 위치를 3월 또는 6월 다음으로 이동시키는데, 이때 Pivot Table 개체의 Position 속성을 사용하는군요. 아래쪽 코드는 피벗 테이블이 있는 시트 상단에 돌아가기 버튼을 만들어 주기 위한 것입니다. 그동안 많이 다루어 왔으므로 크게 어려운 부분은 없을 것이므로 해설은 생략합니다.
돌아가기 버튼에 연결된 GoBack 프로시저는 다음과 같이 원래 시트로 돌아가는 간단한 프로시저입니다.
Sub GoBack()
Sheets("Preface").Activate
End Sub
재미있지요? 읽다가 이해가 안되는 부분이나 피벗 테이블과 관련하여 궁금한 것이 있는 분은 질문을 주시기 바랍니다. 아무래도 현재 진행 중인 강좌와 관련있는 질문을 하시면 더 빠른 답변을 받으실 수 있을 것 같은 생각이 드시지요? ^^
아울러 최근에 Exceller의 개인 메일로 질문을 하신 분들은 아마 거의 답변을 받지 못하셨을 것입니다. 답변하기 싫어서 않는 것이 아니고 연말이 되니 이것 저것 신경을 쓸 일이 많아서 제대로 답변드리기가 힘이 들어서 입니다. 널리 이해하시고 질문은 가급적 Exceller 홈페이지의 Q&A 게시판을 이용해 주시기 바랍니다.
다음 시간에 또…
정리 — 피벗 계산 항목 핵심
| 구분 | 사용한 코드 | 역할 |
|---|---|---|
| 시트 준비 | Worksheets.Add.Name = "PivotSheet" | 피벗 테이블용 새 시트 |
| 피벗 생성 | pvtPCache.CreatePivotTable | 대상 위치 지정 |
| 계산 항목 | CalculatedItems.Add "1/4분기", "= Jan+Feb+Mar" | 월 항목 합산 |
| 위치 조정 | PivotItems("1/4분기").Position = 4 | 3월 다음으로 이동 |
| 돌아가기 | Buttons.Add / OnAction = "GoBack" | 원래 시트로 이동 |
자주 묻는 질문 (FAQ)
Q1. 소스 데이터에 없는 분기 데이터를 피벗 테이블에 넣을 수 있나요?
CalculatedItems.Add로 월 항목을 합산하는 계산 항목을 추가하면 분기계와 반기계를 만들 수 있습니다.
Q2. 계산 항목의 위치는 어떻게 바꾸나요?
PivotItem의 Position 속성에 원하는 위치 번호를 지정합니다.
Q3. 같은 이름의 시트가 이미 있으면 어떻게 하나요?
시트를 순환하며 이름을 확인해 있으면 지우고 새로 만드는 방식으로 처리합니다.
마치며
피벗 테이블의 계산 항목을 VBA로 다루면 소스에 없는 분기계와 반기계도 손쉽게 표시할 수 있습니다.