• 최초 작성일: 2001-11-21
  • 최종 수정일: 2026-09-30
  • 조회수: 20 회
  • 작성자: 권현욱 (엑셀러)
  • 강의 제목: 지정한 행마다 합계 구하기

들어가기 전에

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

PC가 완전히 맛이 가서 AS Center 보냈다가 일요일에 찾았습니다. 엎어진 김에 쉬어 간다고, 이 참에 아예 하드 디스크를 밀어 버렸습니다. 시원하게… T.T 해서 아주 오래간만에 하드 디스크 파티션에... 포맷까지 하였습니다. OS도 윈도우 XP로 깔고 아주 새로운 기분에 자판을 두들기고 있습니다. PC를 새로 설정을 할 때에는 죽을 맛이었는데 막상 하드를 밀고 모든 것을 새로 세팅하고 나니 이렇게 개운할 수가 없군요.

어짜피 컴퓨터라는 것은 에러를 전제로 하는 물건입니다. PC가 자주 다운이 된다거나 상태가 좀 이상하다 싶으면 괜히 열받지 마시고 화끈하게(또는 시원하게 ^^) 새로 시작해 보시기 바랍니다.

참! 지난 주 후반쯤에 PowerTools 패스워드를 알려달라고 요청하신 분은 다시 한번 메일을 보내주시기 바랍니다. 하드를 밀어버리는 통에 그동안 하드 디스크에 저장해 두었던 일부 메일들도 함께 사라졌습니다.

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

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

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


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

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

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

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

지정한 행마다 합계 구하기

핵심 요약: N행마다 합계 행 삽입

사용자가 입력한 행 수마다 빈 행을 삽입하고 그 위 구간의 합계를 넣으며, 남는 데이터 처리와 총 합계까지 코드로 처리합니다.

  • 1단계: InputBox로 2~10 사이의 행 수를 입력받고 0이면 합계를 제거합니다.
  • 2단계: CountA로 남은 데이터 수를 확인하며 EntireRow.Insert로 행을 삽입하고 구간 합계를 넣습니다.
  • 3단계: 마지막에 총 합계를 입력하고, 제거할 때는 Find와 FindNext로 "합계" 행을 삭제합니다.

Step 1: 이번 시간의 질문

일정 행마다 합계계산을 해서 행을 삽입할 수 있나여?
1,2,3번 행의 내용을 4번 행을 새로 추가해서 합계가 계산되도록 할 수
있나요? 물론 자료가 많아서 일일이 수작업 하기가 번거로와서요

'지정 행마다 합계 구하기"라고?? 그것은 예전에 Excel 강좌에서 배열 수식을 사용하면 된다고 해놓고선…' 그 동안 강좌를 열심히 공부하신 분 중에는 이렇게 생각을 하시는 분이 계실 듯 합니다. 건성건성으로 따라오신 분이라면 먼 소리를 하는 줄도 모르실 것이고… ^^

이런 질문에 대해, "부분합을 사용" 하시라는 좀 무성의한(^^;) 답변을 드린 것으로 기억합니다. 그런데 가만히 보보니까 Range 오브젝트에 대해 많은 것을 생각해 보게 하는 아주 재미있는 예제가 될 것 같아서 VBA 강좌시간에 다루어 보도록 합니다.

아래의 버튼을 눌러서 오늘의 예제 파일을 실행시켜 보고 오시기 바랍니다.

잘 되지요? 코드를 볼까요? 먼저, 예제 시트를 만드는 코드입니다.

Step 2: 예제 시트 만들기 (MakeTestSheet)

Sub MakeTestSheet()
    Dim r As Integer
    Dim rngCell As Range
    Worksheets.Add after:=Sheets("Preface")
    '''Preface 시트 뒤에 새로운 워크시트를 한 장 삽입합니다.

    Set rngCell = [A1].Offset(0, 5)

    For r = 1 To 257
        Cells(r, 2) = Int(Rnd * 1000)
        '''순환문을 돌면서 임의의 숫자를 B열에 뿌려 줍니다. 여기서 257이라는 숫자는
        '''어떤 의미가 있을까요?... 아무 뜻도 없습니다. ^^ 그저 1과 자기 자신 이외의
        '''어떤 수로도 나누어지지 않는 수, 즉 임의의 솟수일 따름입니다.

    Next r
    With rngCell
        With ActiveSheet.Buttons.Add(.Left, .Top, .Width * 2, .Height)
            .OnAction = "MakeConditionalSum"
            .Caption = "Click Me!!!"
            '''버튼을 하나 만들고 프로시저를 연결합니다.

        End With
    End With
End Sub

Step 3: 지정한 행마다 합계 구하기 (MakeConditionalSum)

버튼에 연결된 MakeConditionalSum 프로시저는 다음과 같습니다.

Sub MakeConditionalSum()
    Dim shtSheet As Worksheet
    Dim lngSubTotal As Long, lngTotal As Long
    Dim i As Integer, intOffset As Integer, intNew As Integer
    Dim r As Integer, intStart As Integer
    Dim Msg As String
    Dim blnOK As Boolean
    Application.ScreenUpdating = False
    Set shtSheet = ActiveSheet
    '''필요한 변수와 타입을 정의해 준 다음, ScreenUpdating 속성을 False로 지정하여
    '''프로그램의 수행 속도가 조금이라도 빠르도록 설정합니다.

    If TypeName(Selection) <> "Range" Then
        MsgBox "유효하지 않은 범위입니다//By Exceller"
        Exit Sub
    End If
    '''셀이 아닌 다른 오브젝트 등이 선택되어 있을 경우, 에러 메시지를 나타내고…

    Do
        Msg = Space(0)
        Msg = Msg & " 몇 행마다 합계를 구할까요?" & vbCr & vbCr
        Msg = Msg & "0을 입력하면 합계 부분을 제거합니다"
        i = Val(InputBox(Msg, "2~10 사이의 숫자를 입력하세요!//By Exceller"))
        If i = 0 Then: DelConSum: Exit Sub
        '''몇 행마다 합산을 할 것인 지 기준을 사용자로부터 입력받습니다.
        '''이 때 2~10 이내의 숫자만 입력이 가능하도록 Do~Loop 문을 사용하였습니다.
        '''만약 사용자가 0을 입력할 경우, 기존의 소계 부분을 제거합니다.

    Loop While i < 2 Or i > 10

    DelConSum
    intOffset = i + 1
    r = intOffset
    With shtSheet
        Do
            If IsEmpty(.Cells(r, 2)) Then blnOK = True
            '''blnOK 변수가 True 값을 가질 때까지 Do~Loop 문을 계속 실행합니다.
            '''그러면 blnOK 변수는 언제 True 값을 가지는가? B열의 값이 공란이 나올 때까지
            '''반복문을 계속 실행하게 됩니다.
            '''만약 이 문장이 없으면 언제까지나 계속 실행되는 무한 루프문이 됩니다.

            If r = intOffset Then intStart = 1
            intNew = Application.CountA(.Range(.Cells(intStart, 2), .Cells(r - 1, 2)))
            If intNew < intOffset - 1 Then r = intStart + intNew
            '''여기서부터는 종이를 한 장 펴놓고 각 변수에 직접 숫자를 대입해 가면서
            '''살펴보시면 이해가 빠릅니다. 말로 간단하게 설명을 드리자면, 사용자가
            '''지정한 수(변수 i에 담겨져 있는 값)만큼 셀의 값을 intNew 변수에 담아둡니다.
            '''그 아래에 있는 코드는 데이터의 맨 마지막 부분에 남게 되는 값들의 처리를
            '''위한 것입니다. 즉 데이터 수가 257개인데 10개씩 Grouping을 하게되면
            '''마지막에 7개의 데이터가 남지요? 이 부분의 처리를 위한 것입니다.

            '''나머지 아래의 코드는 별로 어려운 부분이 없을 것입니다. 사용자가 지정한
            '''간격마다 빈 행을 하나씩 삽입하고 부분 합계를 넣어주는 것입니다.

            .Cells(r, 1).EntireRow.Insert
            With .Cells(r, 1)
                .Value = "구간 합계"
                .Font.ColorIndex = 3
            End With

            lngSubTotal = Application.Sum(.Range(.Cells(intStart, 2), .Cells(r - 1, 2)))
            lngTotal = lngTotal + lngSubTotal
            .Cells(r, 2) = lngSubTotal
            intStart = r + 1
            r = r + intOffset
        Loop Until blnOK

        With .Cells(Application.CountA(.Columns(2)) + 1, 2)
            .Value = lngTotal
            .Offset(0, -1) = "총 합계"
        End With
    End With
    Application.ScreenUpdating = True
    MsgBox "이제 지정하신 " & i & " 행씩 합계를 구하였습니다", , "작업 완료//By Exceller"
End Sub

필요한 변수와 타입을 정의해 준 다음, ScreenUpdating 속성을 False로 지정하여 프로그램의 수행 속도가 조금이라도 빠르도록 설정합니다. 셀이 아닌 다른 오브젝트 등이 선택되어 있을 경우에는 에러 메시지를 나타냅니다. 몇 행마다 합산을 할 것인지 기준은 사용자로부터 입력받는데, 이때 2~10 이내의 숫자만 입력이 가능하도록 Do~Loop 문을 사용하였고, 사용자가 0을 입력할 경우 기존의 소계 부분을 제거합니다.

blnOK 변수가 True 값을 가질 때까지 Do~Loop 문을 계속 실행합니다. 그러면 blnOK 변수는 언제 True 값을 가지는가? B열의 값이 공란이 나올 때까지 반복문을 계속 실행하게 됩니다. 만약 이 문장이 없으면 언제까지나 계속 실행되는 무한 루프문이 됩니다. 여기서부터는 종이를 한 장 펴놓고 각 변수에 직접 숫자를 대입해 가면서 살펴보시면 이해가 빠릅니다. 말로 간단하게 설명을 드리자면, 사용자가 지정한 수(변수 i에 담겨져 있는 값)만큼 셀의 값을 intNew 변수에 담아둡니다. 그 아래에 있는 코드는 데이터의 맨 마지막 부분에 남게 되는 값들의 처리를 위한 것입니다. 즉 데이터 수가 257개인데 10개씩 Grouping을 하게되면 마지막에 7개의 데이터가 남지요? 이 부분의 처리를 위한 것입니다. 나머지 아래의 코드는 별로 어려운 부분이 없을 것입니다. 사용자가 지정한 간격마다 빈 행을 하나씩 삽입하고 부분 합계를 넣어주는 것입니다.

Step 4: 구간 합계 제거하기 (DelConSum)

마지막으로, 이미 존재하는 구간 합계 부분을 제거하는 코드를 보도록 합니다. 몇 강좌 전에 살펴본 Find와 FindNext 메서드를 사용하였지요? Find 메서드가 무엇인지, 어떤 곳에 사용하는 것인지 헷갈리는 분은 VB0125 강좌를 다시 살펴보고 오시기 바랍니다.

Sub DelConSum()
    Dim shtSheet As Worksheet
    Dim rngFindData As Range
    Set shtSheet = ActiveSheet

    With shtSheet.Columns(1)
        Set rngFindData = .Find("합계", LookIn:=xlValues, LookAt:=xlPart)
        If Not rngFindData Is Nothing Then
            Do
                rngFindData.EntireRow.Delete
                Set rngFindData = .FindNext
            Loop While Not rngFindData Is Nothing
        End If
    End With
End Sub

오늘은 여기까지…

정리 — 구간 합계 삽입 핵심

구분 사용한 코드 역할
간격 입력 Do ~ Loop While i < 2 Or i > 10 2~10 범위 입력 강제
남은 데이터 수 Application.CountA(...) 마지막 구간 처리
행 삽입 .Cells(r, 1).EntireRow.Insert 합계 행 추가
구간 합계 Application.Sum(...) 구간별 합계
합계 제거 .Find("합계") / .FindNext 합계 행 삭제

자주 묻는 질문 (FAQ)

Q1. 지정한 행마다 합계 행을 넣는 다른 방법이 있나요?

부분합 기능이나 배열 수식으로도 가능하지만 VBA를 사용하면 Range 오브젝트를 이용해 원하는 간격으로 유연하게 처리할 수 있습니다.

Q2. 257이라는 숫자는 무슨 의미인가요?

특별한 의미는 없으며 1과 자기 자신 이외의 수로 나누어지지 않는 임의의 소수일 뿐입니다.

Q3. 삽입한 합계 행을 없애려면?

입력 상자에 0을 입력하면 DelConSum이 실행되어 1열에서 "합계"가 들어간 행을 모두 삭제합니다.

마치며

부분합으로도 할 수 있는 작업이지만 Range 오브젝트를 다양하게 다뤄 볼 수 있는 재미있는 예제입니다.