• 최초 작성일: 2025-01-25
  • 최종 수정일: 2026-09-27
  • 조회수: 43 회
  • 작성자: 권현욱 (엑셀러)
  • 강의 제목: VBA 파워 코딩 254회 - 피평가팀 테이블 만들기

들어가기 전에

오래 전 엑셀 파일로 진행하던 강의를 웹 글로 복원한 것이라, "버튼을 눌러보세요"처럼 엑셀에서 직접 조작하라는 표현이 남아 있을 수 있습니다. 결과는 본문의 그림이나 표로 확인하실 수 있으며, 현재와 맞지 않는 내용은 보완하되 전반적인 스타일은 당시의 갬성(?)을 유지했습니다.

세상에서 제일 무서운 사람

세상에서 제일 무서운 사람은 "(그 분야의 책을) 딱 한 권만 열심히 읽은 사람"이라는 말이 있습니다. 자기가 알고 있는 것만이 진실이고 나머지 것은 부정하는 태도를 경계하는 의미라고 생각합니다. 어느 자기계발 책에 이런 구절이 나온다고 생각해 보세요.

이 책: '무엇'을 해야 할 지 모를 때에는 '뭔가를' 해야 한다.

저 책: '속도'보다 '방향'이 중요하다. 무턱대고 움직이기 전에 생각을 정립해야 한다.

'그래서 뭘 어쩌라는 거지? 움직이라는 거야, 움직이지 말라는 거야?'라는 생각이 듭니다.

서로 다른 조언을 하는 두 책의 구절을 나란히 놓은 그림
아이엑셀러

자신이 처한 위치와 상황에 따라 판단 기준은 달라집니다. 다른 것에 대한 수용성이 있는가, 유연하게 사고하는가가 중요하지, 읽은 책의 권 수가 중요하지 않은 법이지요.

살다 보면, '아, 이 책의 이 구절은 OXY가 꼭 읽고 개과천선 해 주었으면 좋으련만...' 하는 생각이 들 때가 있습니다. 여기서 OXY는 누구일까요? 그렇습니다! 여러분이 생각하시는 바로 '그 사람'입니다. OXY는 그 책을 읽을 가능성은 그다지 높지 않습니다. 그런 것들을 읽지 않고도 지금껏 잘 살아온 OXY는, 앞으로도 그럴 것으로 예상하기 때문입니다. 차라리 내가 마음을 바꿔먹는 게 훨씬 빠릅니다. 세상에서 내 맘대로 바꿀 수 있는 건 몇 가지 안 됩니다.

권현욱(엑셀러)
저자: 권현욱(엑셀러), 아이엑셀러 대표

필자는 Excel 컨설턴트, 작가, 그리고 크리에이터입니다. 현재 Microsoft Excel MVP이며, 『챗GPT+엑셀 업무자동화 정석』을 비롯한 10여 권의 도서를 집필했습니다. Excel 자동화 및 생산성 향상 분야에서 25년 넘는 경력을 보유하고 있습니다.

권현욱(엑셀러) 님의 최신 포스트:
  • 최신 글을 불러오는 중...


26년 경력 Microsoft MVP 권현욱(엑셀러) 대표 직강 1강 무료

🎁 파워툴스 마스터클래스 · 엑셀 바이브 코딩

AI에게 말로 지시해서 '나만의 엑셀 도구'를 만들고 리본에 장착합니다.

  • 코딩 지식 없이 시작 · 코드는 AI가 작성
  • 엑셀 리본에 내 탭과 버튼을 만들고 XLAM으로 공유
  • 1강 무료 수강 가능
수강 신청하기 강의 소개 보기

내부고객만족도 평가팀 테이블 만드는 Code

핵심 요약: Y 표시 표를 팀별 평가팀 목록으로 자동 변환하기

ChangeTableForm 프로시저가 원본 표의 각 행에서 Y가 표시된 열을 찾아 새 워크시트에 나열하고, 같은 팀명 셀을 병합한 뒤 테두리를 그립니다. 평가팀 이름은 EvalTeam 사용자 지정 함수로 구합니다.

  • 변환 대상: [표 1] (평가 관계를 Y로 표시) → [표 2] (팀별 평가팀 목록)
  • 메인 프로시저: ChangeTableForm (표 생성, 셀 병합, 테두리)
  • 사용자 지정 함수: EvalTeam(rngRow, rngLabel, iRow)
  • 난이도: 중급 이상 - 초보자는 로직 파악 위주로 보고 나중에 다시 보세요.

이번 강좌는 조금 난이도가 있습니다. VBA에 익숙하지 않은 초보님들은 '이런 것도 있군' 정도로 생각하면서 진행되는 로직을 파악하는데 치중하셨다가 나중에 VBA에 익숙해졌을 때 다시 보셔도 됩니다.

[표 1]을 [표 2]로 바꾸려면?

"내부고객만족도 평가" 진행을 담당하고 있는 직원이 열심히 일하는 모습을 보면서 생각이 떠올라서 만들어 보았습니다. [표 1]과 같은 테이블이 있습니다.

[표 1]
각 팀이 어느 팀에게 평가받는지 Y로 표시한 표 1
아이엑셀러

영업1팀부터 재무팀까지 9개 팀이 있는데, 각 팀은 다른 부서로부터 내부고객만족도 평가를 받게 됩니다. 예를 들어 영업1팀은 '마케팅팀/홍보팀/기획팀/인사팀/총무팀/재무팀'으로부터 평가를 받고, 신채널팀은 '기획팀/인사팀/총무팀/재무팀' 등 4개 팀으로부터 평가를 받는 식입니다.

이와 같은 로직으로 [표 2]와 같은 형태로 테이블 모양을 변경하려면 어떻게 해야 할까요? 참고로, 지금까지는 밝은 눈과 재빠른 손을 이용한 노동집약적 방식을 사용하고 있었습니다.

[표 2]
팀별로 평가팀을 세로로 나열한 표 2
아이엑셀러

버튼 하나로 테이블 만들기

예제 파일을 열고 '피평가팀 테이블 만들기' 버튼을 클릭해 보세요. 위의 [표 2]와 같은 테이블이 자동으로 휘리릭~~ 만들어집니다.

피평가팀 테이블 만들기 버튼을 클릭하면 새 워크시트에 표 2가 만들어지는 모습
아이엑셀러

'피평가팀 테이블 만들기' 버튼에 연결된 코드

'피평가팀 테이블 만들기' 버튼에 연결된 코드입니다.

Sub ChangeTableForm()
    Dim rTable As Range          ' 작업 대상 영역을 지정하기 위한 변수
    Dim rTeamName As Range       ' A열에서 평가받을 팀을 지정하기 위한 변수
    Dim rResult As Range         ' 결과가 표시될 위치를 지정하기 위한 변수
    Dim rCell As Range           ' For Each ~ In ~ Next 문에서 사용될 Flag 변수
    Dim iCol1 As Integer         ' 피평가팀 수를 카운팅 하기 위한 변수
    Dim iCol2 As Integer         ' 평가팀 수를 카운팅 하기 위한 변수
    Dim iRow As Integer          ' For ~ Next 문에서 사용될 Flag 변수
    Dim i As Integer             ' For ~ Next 문에서 사용될 변수
    Dim iX As Integer            ' For ~ Next 문에서 사용될 변수
    Dim iTemp1 As Integer        ' 동일값을 가진 셀 병합 시 사용될 변수
    Dim iTemp2 As Integer        ' 동일값을 가진 셀 병합 시 사용될 변수
    Dim iNum As Integer          ' rResult 영역의 셀 수를 카운팅 하기 위한 변수

    Application.DisplayAlerts = False
                            ' 셀 병합을 할 때마다 경고 메시지 표시하지 않도록 설정
    Set rTable = Range("Start").CurrentRegion   ' 원본 테이블 전체 영역을 지정
    Set rTeamName = rTable.Columns(1)   ' 원본 테이블의 팀명(세로) 지정
    Worksheets.Add                      ' 새로운 워크시트 추가
    Range("A1:C1") = Array("팀명", "평가팀 수", "피평가팀")
                                 ' A1:C1 영역에 새로 만들어질 테이블의 제목 입력

    Set rResult = ActiveSheet.Range("A2")   ' 결과 값을 표시할 시작 위치 지정
    With rResult                        ' 결과를 표시할 셀에 대하여...
        For Each rCell In rTeamName.Cells   ' 피평가팀 영역의 각 셀에 차례로 접근
            If rCell <> "" Then         ' 셀 값이 공란이 아닌 경우에만 아래 구문 실행
                .Offset(i) = rCell      ' 피평가팀을 지정한 위치에 표시
                iCol1 = rTable.Columns.Count - 1  ' 원본 테이블의 열 수를 변수에 할당
                iCol2 = rCell.EntireRow.SpecialCells(xlTextValues).Count - 1
                               ' 각 셀의 행에 몇 개의 값이 있는지 구해서 변수에 할당
                For iRow = 1 To iCol2   ' iCol2 변수 값만큼 For ~ Next문 반복
                    .Offset(i, 0) = rCell   ' 피평가팀을 행 방향으로 이동하면서 표시
                    .Offset(i, 1) = "평가팀" & iRow   ' 몇 번째 평가팀인지 B 열에 표시
                    .Offset(i, 2) = EvalTeam(rCell.Offset(, 1).Resize(, iCol1), rTable.Rows(1), iRow)
                                  ' 사용자 지정함수 EvalTeam 실행 결과를 C열에 표시
                                  ' 이 때 세 가지 정보를 매개 변수로 함께 전달
                    i = i + 1     ' 다음 행으로 이동을 위해 변수 값 1만큼 증가
                Next
            End If
        Next
    End With

    Set rResult = rResult.CurrentRegion.Columns(1)
                                        ' [표 2] 영역의 첫 번째 열을 변수에 지정
    iNum = rResult.Cells.Count          ' rResult 영역의 셀 수를 변수에 지정

    For Each rCell In rResult.Cells     ' 선택 영역의 각 셀에 차례로 접근
        iTemp1 = iTemp1 + 1             ' 이미 검색한 셀의 수는 하나씩 증가
        iTemp2 = iNum - iTemp1          ' 아직 검색하지 않은 셀의 수는 하나씩 감소

        If Len(rCell) > 0 Then   ' 대상 셀의 값이 공란이 아닌 경우에만 아래 구문 실행
            iX = 0                      ' 변수 값 초기화

            For i = 1 To iTemp2   ' 아직 검색하지 않은 셀 수만큼 For ~ Next 문 반복
                If rCell.Offset(i, 0) = rCell Then
                                        ' 현재 셀 내용과 아래 셀 내용이 같으면...
                    iX = iX + 1         ' 변수 값 1 증가
                Else
                    Exit For            ' For ~ Next 문에서 탈출
                End If
            Next

            If iX > 0 Then Range(rCell, rCell.Offset(iX, 0)).Merge
                     ' 변수 iX 값이 0보다 크다는 것은 같은 값을 가진 셀이 2개 이상 있다는
                     ' 의미가 되므로 이런 경우에는 Merge 메서드를 이용하여 셀 병합
        End If
    Next rCell

    With rResult.CurrentRegion     ' 선택한 영역을 대상으로 괘선 그리기
        .BorderAround xlSolid
        .Borders(xlInsideHorizontal).LineStyle = xlSolid
        .Borders(xlInsideVertical).LineStyle = xlSolid
    End With

    Application.DisplayAlerts = True   ' 경고 메시지 표시 상태 초기화
End Sub

참고: 원문 코드 수정

원문 코드에서 실행에 문제가 되는 두 곳을 고쳤습니다. 첫째, 결과 위치를 Set iResult = ActiveSheet.Range("A2")로 지정했는데 이후에는 rResult를 사용하므로 Set rResult = ...로 바로잡았습니다. 원문 그대로면 With rResult 구문에서 개체 변수가 설정되지 않아 오류가 발생합니다. 둘째, 표 제목을 입력하는 Range("A1:C1") = Array(...)가 새 워크시트를 추가하는 Worksheets.Add보다 앞에 있어서 제목이 새 시트가 아닌 원래 시트에 입력되므로, Worksheets.Add 뒤로 옮겼습니다. 이 밖에 주석의 오타("갈 셀" → "각 셀")도 바로잡았습니다.

사용자 지정 함수 EvalTeam

다음은 위의 'ChangeTableForm' 프로시저에서 호출한 사용자 지정 함수입니다. 세 가지 파라미터를 함께 전달하여 실행합니다.

  • rngRow: 평가팀(B:J열)
  • rngLabel: 피평가팀(여기서는 4행의 각 셀)
  • iRow: 현재 행 번호
Function EvalTeam(rngRow As Range, rngLabel As Range, iRow As Integer)
    Dim rCell As Range         ' For Each ~ In ~ Next 문에서 사용될 Flag 변수
    Dim iCount As Integer

    For Each rCell In rngRow.Cells   ' B:J 열의 각 셀에 대해 반복
        If rCell = "Y" Then          ' 해당 열의 각 셀 값이 "Y"이면...
            iCount = iCount + 1      ' 변수 값을 1만큼 증가

            If iCount = iRow Then    ' iCount와 iRow 변수 값이 같으면...
               EvalTeam = Intersect(rCell.EntireColumn, rngLabel)
                                     ' 두 영역이 교차하는 지점에 있는 셀의 값을
                                     ' 사용자 지정 함수의 결과값으로 돌려주고
               Exit Function         ' 사용자 지정 함수 탈출
            End If
        End If
    Next
End Function

눈으로만 보지 말고 VBA의 디버깅 툴을 이용하거나 빈 종이에 각 변수의 증가되는 값을 기록해 가며 순환문을 몇 바퀴 돌려보면 이해하게 되는 순간이 옵니다. 중간에 포기하지 말고 도전해 보시기 바랍니다.

참고: 이미지에 대하여

이 글은 원래 네이버 포스트에 게재되었던 글로, 네이버 포스트 서비스 종료로 네이버 블로그로 옮기는 과정에서 원본 이미지가 소실되었습니다. 위 이미지는 본문 설명을 바탕으로 당시 화면 구성을 재구성한 예시 이미지이며, 실제 엑셀 화면과 세부 디자인(버전별 UI)은 다를 수 있습니다. 특히 [표 1], [표 2]의 팀 구성과 평가 관계는 본문에 나온 영업1팀과 신채널팀의 예를 제외하면 예시로 만든 것입니다.

정리 — 평가팀 테이블 만들기 코드의 구성

구성 요소 역할
ChangeTableForm 새 워크시트에 [표 2]를 만들고 셀 병합과 테두리까지 처리하는 메인 프로시저
EvalTeam 행에서 n번째 Y가 있는 열을 찾아 해당 열의 팀명을 돌려주는 사용자 지정 함수
셀 병합 반복문 아래 셀과 값이 같은 만큼 세어 Merge 메서드로 병합
Application.DisplayAlerts 병합 시 경고 메시지가 뜨지 않도록 False로 설정했다가 끝나면 True로 복원

자주 묻는 질문 (FAQ)

Q1. Y로 표시된 표를 팀별 목록 형태로 자동 변환할 수 있나요?

VBA로 가능합니다. 각 행에서 Y가 표시된 열을 차례로 찾아 해당 열의 제목을 새 워크시트에 나열하고, 같은 팀명이 연속된 셀은 병합하면 됩니다.

Q2. 셀을 병합할 때 경고 메시지가 계속 나타나는데 어떻게 하나요?

코드 앞부분에서 Application.DisplayAlerts = False로 경고 메시지를 끄고, 작업이 끝난 뒤 Application.DisplayAlerts = True로 되돌려 놓으면 됩니다.

Q3. 코드가 어려워서 이해가 안 될 때는 어떻게 하나요?

VBA의 디버깅 도구로 한 줄씩 실행하거나, 빈 종이에 각 변수 값이 증가하는 과정을 적어 가며 반복문을 몇 바퀴 따라가 보면 이해하게 되는 순간이 옵니다.

마치며

조금 어려워도 반복문을 한 바퀴씩 따라가다 보면 어느 순간 이해가 됩니다. 포기하지 말고 도전해 보세요!
VBA에 대한 기초 지식을 공부하실 분은 아이엑셀러 닷컴 사이트 정문 왼쪽에 있는 'VBA 강좌 - VBA 입문강좌'를 읽어보시면 이해가 빠릅니다.