• 최초 작성일: 2008-05-19
  • 최종 수정일: 2008-05-19
  • 조회수: 39,982 회
  • 작성자: 엑셀러 권현욱
  • 강의 제목: 리본에 새로운 탭 추가하기

엑셀러 권현욱

들어가기 전에

얼마 전에 읽은 글 중에 이런 것이 있었습니다.

당신이 원하든 원하지 않든 간에
자기가 내뱉은 말 한마디가
남 앞에 자신의 초상화를 그려놓는 것이다.
사람들은 그가 하는 말로써 그를 판단한다.
부정의 이미지가 아니라
긍정의 이미지가 떠올려지는 사람이 돼라.

ㅡ 이비즈네트워크 CEO 최윤규

우리는 흔히 남들이 나를 몰라준다고 야속해 합니다. 나의 본 모습은 그게 아닌데 사람들에게 잘못 인식되어 있다며 마음 아파합니다. 실체가 없으면 그림자 또한 존재할 수 없는 법입니다. 평소에 내가 한 말 한마디, 작은 행동 하나가 상대방의 뇌리에 조금씩 조금씩 흔적을 남기어 결국에는 '나'란 존재가 각인되는 것이겠지요.



리본과 관련된 이번 강의는 VBA 입문용이라고 하기에는 좀 무리가 있습니다만 별도 섹션으로 구분하기도 뭐하고 해서 그냥 이 범주에 포함시켰습니다. VBA를 처음 접하는 분이라면 '이런 것도 있군' 하는 정도로 부담 없이 읽고 넘어가셔도 됩니다.

- 이번 강의 콘텐츠는 "엑셀 2007 매크로와 VBA 날개달기"(디지털북스)에서 편집/인용하였습니다.

지난 강의 말미에 'Custom UI Editor’와 친해져야 한다고 했었는데 많이 사용해 보셨나요? 그러셨으리라 믿고...

이번에는 다음 그림과 같이 3개의 그룹을 가진 ‘Power Tools’라는 탭을 추가해 보겠습니다. 앞에서 소개해 드린 Custom UI Editor를 이용하여 작성하도록 하지요.

BASIC

완성 예

Step 1: 리본X 코드 작성

1. 새로운 통합 문서를 하나 만든 다음 '리본X_탭추가.xlsm'이라는 이름으로 저장합니다. 다른 이름으로 저장해도 상관없으나 파일 형식은 'Excel 매크로 사용 통합 문서(*.xlsm)' 형식으로 지정하세요.

2. Custom UI Editor를 실행하고 방금 저장한 통합 문서를 엽니다. 새로운 탭을 생성하는 것 자체는 간단합니다. 다음과 같은 리본X 코드를 작성합니다. 직접 입력하기 어려우면 아래 내용을 긁어다 붙여 넣으세요.

<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'>
    <ribbon>
    <tabs>
    <tab id="MyTab" label="Power Tools"> 
    </tabs>
    </ribbon>
</customUI>

CODE

BASIC

3. 엑셀로 가서 '리본X_탭추가.xlsm' 파일을 열어보면 ‘Power Tools’ 탭이 만들어져 있음을 확인할 수 있습니다. 그룹이나 아이콘이 빠져 있기는 하지만...

BASIC

Step 2: 빈 탭에 지능심기

허우대 뿐인 Power Tools 탭에 지능을 심어 볼까요? Custom UI Editor를 실행한 다음 그룹과 컨트롤을 추가하는 리본X 코드를 입력합니다. 처음 보는 분이라면, '아니, 뭐가 이렇게도 복잡한 것이 다 있나?' 하며 현기증이 날 법도 합니다만 코드의 세세한 부분까지는 알 필요가 없습니다. 여기서는 그저 반복되는 패턴만 눈으로 익혀두는 것으로 충분합니다. 코드는 붙여넣기만 하세요.

<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'>
    <ribbon>
    <tabs>
    <tab id="MyTab" label="Power Tools ">
    <group id="Group1" label="Memo Tool">
    <control idMso="ReviewNewComment" label="Insert Memo" />
    <control idMso="ReviewShowOrHideComment" label="Show or Hide Memo" />
    <control idMso="ReviewDeleteComment" label="Delete Memo" />
    <control idMso="ReviewShowAllComments" label="Show All Memo" />
    <control idMso="ReviewPreviousComment" label="Previous Memo" />
    <control idMso="ReviewNextComment" label="Next Memo" />
    </group>

    <group id="Group2" label="Built-in Tool">
    <control idMso="FileNew" label="New" size="large" />
    <control idMso="FileOpen" label="Open" size="large" />
    <control idMso="FileSaveAsOtherFormats" label="Save As..." size="large" />
    <control idMso="FilePrint" label="Print" size="large" />
    <control idMso="FilePrintPreview" label="Preview" size="large" />
    <separator id="MySep1" />
    <control idMso="Calculator" label="Calculator" size="large" />
    </group>

    <group id="Group3" label="Power Tool">
    <button id="MyBtn1"
        label="New Style Memo"
        onAction="AddComment"
        imageMso="CreateEmail" />
    <button id="MyBtn2"
        label="Cell Merge"
        onAction="CellMerge"
        imageMso="FieldsMenu" />
    <checkBox id="Checkbox1"
        label="Page Breaks"
        onAction="TogglePageBreakDisplay"
        getPressed="GetPressed"
        getEnabled="GetEnabled"/>
    <separator id="MySep2" />
    <button id="MyBtn4"
        label="Versatile Print Manager"
        size="large"
        onAction="ShowPrint"
        imageMso="FileDocumentManagementInformation" />
    </group>
    </tab>
    </tabs>
    </ribbon>
</customUI>

CODE

코드 작성이 끝났으면 Custom UI Editor의 [Validate] 아이콘을 클릭해 보세요. XML 파일이 제대로 작성되었다면 'Custom UI XML is well formed!'라는 대화상자가 나타납니다.

Step 3: 콜백 프로시저 작성

1. 리본X 코드에서 호출하는 콜백 프로시저를 작성할 차례입니다. [Generate Callbacks] 아이콘을 클릭하면 콜백 프로시저명이 나타나는데 범위를 지정한 다음 마우스 오른쪽 버튼을 클릭하고 [Copy] 메뉴를 선택합니다.

2. 엑셀로 돌아와서 해당 파일을 엽니다. VB Editor 상태에서 모듈을 하나 삽입하고, 1 에서 복사한 콜백 프로시저들을 붙여넣습니다.

BASIC

콜백 프로시저를 붙여넣기 한 모습

전체적인 흐름을 이해하는 것이 중요하므로 콜백 프로시저의 코드 내용은 뒷 부분에서 한꺼번에 설명드리겠습니다.

Step 4: 외부 프로시저 작성

‘Power Tool’ 그룹에 있는 4개의 컨트롤에 연결된 콜백 프로시저 및 콜백 프로시저에서 호출하는 외부 프로시저들을 작성합니다.

1. MyBtn4 프로시저에서 호출하는 사용자 정의 폼을 작성합니다 (반드시 사용자 정의 폼을 먼저 작성해야 하는 건 아닙니다).

BASIC

2. ‘Power Tool’ 그룹에 있는 4개의 컨트롤에 연결된 콜백 프로시저 및 콜백 프로시저에서 호출하는 외부 프로시저들을 작성합니다. 다시 한 번 강조하지만 지금 단계에서는 코드 내용을 이해하는 것은 하나도 중요하지 않습니다. 진행되는 흐름을 잘 따라오시면 됩니다.

Option Explicit
Public MyRibbon As IRibbonUI

Sub AddComment(control As IRibbonControl)
' New Style Memo 컨트롤에 연결된 코드
    Dim Msg As String
    Msg = InputBox("메모내용을 입력하세요: ", "메모 입력")

    If Msg = "" Then
        MsgBox "아무 것도 입력하지 않았으므로 종료합니다"
        Exit Sub
    End If
    With ActiveCell
        .AddComment
        .Comment.Visible = True
        .Comment.Text Text:=Msg
    End With
    ActiveCell.Comment.Shape.Select
    With Selection
        .VerticalAlignment = xlCenter
        .Font.Size = 9
        .Font.Name = "Arial"
        .Font.ColorIndex = 2
        .AutoSize = True
        With .ShapeRange.Line
            .Weight = 0.25
            .ForeColor.SchemeColor = 10
        End With
        .Interior.ColorIndex = 3
    End With
    ActiveCell.Comment.Visible = False
End Sub
'--------------------
Sub CellMerge(control As IRibbonControl)
' Cell Merge 컨트롤에 연결된 코드
    Dim strTemp As String
    Dim strCell() As String
    Dim i As Integer
    Dim intNum As Integer
    Dim bytResult As Byte
    Dim rngTarget As Range
    Application.DisplayAlerts = False
    On Error GoTo ET

    Set rngTarget = Application.InputBox("병합할 영역을 선택하세요", _
    "영역 선택", Type:=8, _
    Default:=Selection.Address)
    intNum = rngTarget.Cells.Count
    ReDim strCell(intNum)

    With rngTarget
        If .Areas.Count <> 1 Then
            MsgBox Msg, , "범위 지정 오류"
            Exit Sub
        End If
    End With

    For i = 1 To intNum
        strTemp = strTemp & rngTarget.Cells(i)
        strCell(i) = rngTarget.Cells(i)
    Next i

    rngTarget.Merge
    rngTarget = strTemp
    bytResult = MsgBox("자료가 합쳐졌지요?" & vbCr _
    & "셀을 원래대로 돌릴까요?", vbYesNo, "작업 상태 확인")
    If bytResult = vbNo Then Exit Sub

    With rngTarget
        .UnMerge
        For i = 1 To intNum
            .Cells(i) = strCell(i)
        Next i
    End With

ET:
    If Err.Number <> 0 Then
        MsgBox Err.Description, , "Error 발생"
        Application.DisplayAlerts = True
        On Error GoTo 0
        Err = 0
    End If
End Sub
'--------------------
Sub TogglePageBreakDisplay(control As IRibbonControl, pressed As Boolean)
' Page Breaks 컨트롤에 연결된 코드
    On Error Resume Next
    ActiveSheet.DisplayPageBreaks = pressed
End Sub
'--------------------
Sub GetPressed(control As IRibbonControl, ByRef returnedVal)
' Page Breaks 컨트롤에 연결된 코드
    On Error Resume Next
    returnedVal = ActiveSheet.DisplayPageBreaks
End Sub
'--------------------
Sub GetEnabled(control As IRibbonControl, ByRef returnedVal)
' Page Breaks 컨트롤에 연결된 코드
    returnedVal = TypeName(ActiveSheet) = "Worksheet"
End Sub
'--------------------
Sub ShowPrint(control As IRibbonControl)
' Versatile Print Manager 컨트롤에 연결된 코드
    frmPrint.Show
End Sub

CODE

3. 마지막으로 ‘Versatile Print Manager’ 컨트롤에 연결되어 있는 2개의 프로시저를 작성합니다. 앞에서와 마찬가지로 코드 내용을 이해하려고 할 필요는 없습니다. 왜? 지금 단계에서는 그게 중요한 게 아니니까요!

Sub ReverseOrderPrint(ByVal OK As Boolean, Optional ByVal EvenOrOdd As Byte)
    Dim intTotalPage As Integer
    Dim i As Integer
    intTotalPage = ExecuteExcel4Macro("get.document(50)")

    If intTotalPage Mod 2 = 0 Then intTotalPage = intTotalPage - 1
    If EvenOrOdd = 1 Then
        For i = intTotalPage To 1 Step -2
            ActiveSheet.PrintOut from:=i, To:=i, preview:=OK
        Next i
    ElseIf EvenOrOdd = 2 Then
        For i = intTotalPage + 1 To 1 Step -2
            ActiveSheet.PrintOut from:=i, To:=i, preview:=OK
        Next i
    Else
        For i = intTotalPage + 1 To 1 Step -1
            ActiveSheet.PrintOut from:=i, To:=i, preview:=OK
        Next i
    End If
End Sub
'--------------------
Sub GeneralOrderPrint(ByVal OK As Boolean, Optional ByVal EvenOrOdd As Byte)
    Dim intTotalPage As Integer
    Dim i As Integer
    intTotalPage = ExecuteExcel4Macro("get.document(50)")

    If EvenOrOdd = 1 Then
        For i = 1 To intTotalPage Step 2
            ActiveSheet.PrintOut from:=i, To:=i, preview:=OK
        Next i
    ElseIf EvenOrOdd = 2 Then
        For i = 2 To intTotalPage Step 2
            ActiveSheet.PrintOut from:=i, To:=i, preview:=OK
        Next i
    Else
        For i = 1 To intTotalPage
            ActiveSheet.PrintOut from:=i, To:=i, preview:=OK
        Next i
    End If
End Sub

CODE

이것 말고도 몇 개의 프로시저가 더 있습니다. 이와 관련해서는 예제 파일을 열어 직접 살펴보시기 바랍니다.

엑셀 2007에서 리본을 사용자화하는 작업은 이전 버전에서 커맨드 바 오브젝트를 이용하던 것과 비교하면 상당히 까다롭습니다. 따라서 특별한 경우가 아니라면 커맨드 바 오브젝트를 이용하는 것이 더욱 편리할 수 있다는 점을 염두에 두시기 바랍니다. 커맨드 바 오브젝트에 대한 사항은 예전에 소개해 드린 VBA 강좌들을 참고하세요. 단, 커맨드 바 오브젝트를 사용하면 다음과 같은 단점은 있습니다. 전문 용어(?)로 '뽀대'는 좀 덜 납니다. (^^)

  • 모든 컨트롤이나 명령이 '추가 기능' 탭 아래에 표시된다.
  • 도구 모음을 만들 수 없다(이것은 리본X 코드를 작성하더라도 마찬가지).
  • 실행되지 않고 무시되는 속성이나 메서드가 있을 수 있다

이러한 점을 염두에 두고 사전에 테스트를 통해 확인을 한다면 커맨드 바 오브젝트는 엑셀 2007 버전에서도 여전히 하나의 대안이 될 수 있을 듯 합니다.