배움터  
  HOME > 배움터 > 무료강좌
무료강좌
 
엑셀, 곽승주님의 오튜공구함 제작으로 배워보는 VBA 이야기, Excel

2. 도구 모음 만들기-Ⅱ

이제부터는 코드를 하나하나 뜯어보겠습니다.

Const USER_TAG As String = "UserToolbar"
Const CBO_TAG As String = "UserCombo"
Const TOOL_NAME As String = "오튜공구함"

"_TAG"로 끝나는 상수는 개체를 식별하기 위한 것입니다. 지난 메뉴에서도 보았을 겁니다.

TOOL_NAME 상수는 도구모음의 이름입니다. 이 이름은 [보기(V)]-[도구모음(T)] 을 클릭하거나 메뉴와 도구표시줄의 빈곳에서 마우스 오른쪽 버튼을 클릭하면 볼 수 있습니다.
 

 

 

 

Sub CreateUserToolbar()
     Dim cmdbarUser As CommandBar
도구모음을 만들기 위한 CommandBar개체를 선언합니다.

     On Error GoTo ErrHandler
에러 핸들러입니다. 불의의 에러를 받게 되면 "ErrHandler"라고 Label을 붙인 곳으로 이동하라는 의미입니다. 프로그램의 작성에서 에러에 대한 처치는 중요합니다. 99% 완성후 나머지 1%를 채우지 못해 미완으로 남는 경우가 많습니다. 이 1%가 버그가 없는 프로그램을 만드는 것이고 이를 위해서는 에러핸들러를 만들어 두셔야 합니다. VBA에서는 에러처치를 위한 여러 방법을 준비하고 있는데 On Error과 관련한 구문은 다음과 같습니다.

  • On Error GoTo line or label 제가 위에서 사용한 구문입니다.
  • On Error Resume Next 에러가 난 문장의 다음부터 시작하라는 의미입니다.
  • On Error GoTo 0 모든 에러핸들러를 사용못하도록 합니다.

     Set cmdbarUser = Application.CommandBars.Add(Name:=TOOL_NAME,
     Position:=msoBarTop)

중요한 부분입니다. 앞서 선언한 CommandBar개체변수에 새로운 개체를 추가하고 있습니다. 이름은 상수로 이미 만든 것을 부여하고 위치는 도구모음들이 자주 모이는 곳(?) 인 메뉴밑의 화면상단으로 정했습니다. 위에서 보면 CommandBars는 CommandBar 가 여럿 모인 개체컬력션입니다. 따라서 CommandBars개체의 Add메소드를 사용한다는 것은 CommandBar를 하나 더 추가하겠다는 의미입니다. 이와 비슷한 경우가 아래에도 더 있습니다.

     CreateUserButton cmdbarUser
     CreateUserCombo cmdbarUser
도구모음에 버튼과 콤보상자를 만드는 프로시져를 실행합니다.

     cmdbarUser.Visible = True

               <완성된 오튜 공구함>

간단하지만 "오튜공구함" 이라는 도구모음이 생겼습니다. 그러나 그건 어디까지나 내부적으로입니다. 실제로 화면에 보이게 하려면 위에서 처럼 VIsible속성를 TRUE로 변경해주어야 합니다.

     Set cmdbarUser = Nothing
이제 사용한 개체변수를 메모리에서 풀어 줍니다.

     Exit Sub
이는 에러핸들러와 관련한 것입니다. 그 의미는 현재의 Sub프로시져를 빠져 나오라는 의미입니다. 만일 이 문장이 없다면 아래의 에러핸들러까지 실행될 겁니다. 그러므로 에러핸들러를 사용하게 되면 Exit Sub문을 사용합니다. 그러나 Function 프로시져라면 Exit Function을 사용합니다.

ErrHandler:
Label이라는 것입니다. 큰 의미는 없고 프로그램의 흐름을 바꾸는 경우에 이용됩니다.

     DeleteUserToolbar
"오튜공구함" 도구모음을 삭제하는 프로시져를 살행합니다.

     Resume
에러가 발생한 곳부터 다시 시작하라는 의미입니다. Resume은 세개의 유형으로 사용할 수 있습니다.

  • Resume 에러가 간 곳에서 다시 시작하라는 의미
  • Resume Next 에러가 난 다음 문장부터 시작하라는 의미
  • Resume line or label label로 이동하여 다시 시작하라는 의미

 위에서 제가 에러핸들러를 달아 둔 이유는, 가령 Sub CreateUserToolbar()가 이미 실행한 상태에서 실수등으로 다시 한번 실행하는 경우를 대비하기 위한 것입니다. 따라서 도구모음을 지우고 다시 시작하도록 하였습니다.
End Sub
이번에 도구모음을 삭제하는 프로시져를 살펴보죠
Sub DeleteUserToolbar()
     Dim cmdbarUser As CommandBar

     On Error GoTo ErrHandler

     Set cmdbarUser = Application.CommandBars(TOOL_NAME)
"오튜공구함" 도구모음의 개체를 받아 cmdbarUser에 할당한다.

     cmdbarUser.Delete
받자마자 없애버립니다.
     Set cmdbarUser = Nothing
     Exit Sub

ErrHandler:
     Exit Sub
End Sub
크게 설명할 게 없군요. 이미 앞에서 다했던 부분이라 설명은 생략합니다.
이번에는 도구모음에 여러 버튼을 붙이는 프로시져를 설명하겠습니다.
Sub CreateUserButton(cmdbarUser As CommandBar)
프로시져의 매개변수로 CommandBar개체를 받습니다. 이 개체는 "오튜공구함"을 대신하는 개체변수로 여기에 버튼을 추가하게 됩니다. 그래서 이 프로시져를 호출하는 경우엔 다음과 같이 CommandBar개체변수를 넘겨줍니다.
        CreateUserButton cmdbarUser
        CreateUserCombo cmdbarUser

     Dim i As Byte
     Dim cmdctlUser As CommandBarButton
cmdctlUser개체는 CommandBarButton개체변수로서 CommandBarButton개체변수는 도구모음의 버튼을 의미합니다.

     Dim NameFaceIDMacroOfCmdBtn
지난 강의에서 메뉴를 생성하기 위해 필요한 데이터를 워크시트에 저장하고 불러들였습니다. 이번에 워크시트가 아니라 Array()함수를 사용하여 메모리에 적재한 후 읽어 들이는 방식으로 버튼을 만들려고 합니다. 그래서 이를 담기 위한 NameFaceIDMacroOfCmdBtn 변수를 선언했습니다.

     NameFaceIDMacroOfCmdBtn = Array( _
     "otHELP", 49, "sbShowHelp", False, _
     "otABOUT", 625, "sbShowAbout", True, _
     "otEXIT", 358, "sbExit", True _
     )

Array()함수는 Variant 형식의 변수에 위와 같이 배열을 만들어 줍니다. 이배열은 1차원배열입니다. 다만 배열의 입력순서를 주의해서 보시길 바랍니다. 먼저 버튼의 이름(화면에서는 툴팁으로 나오는 것임)을 입력하고 그다음엔 FaceID, 버튼을 클릭하는 경우 실행할 프로시져이름, 그룹여부등을 입력한니다.

     For i = LBound(NameFaceIDMacroOfCmdBtn) To
           Bound(NameFaceIDMacroOfCmdBtn) Step 4
배열을 다루다 보면 LBound()와 UBound()함수를 자주 사용합니다. 배열을 사용해본 분들은 아실테지만 VB/VBA에서는 0부터 배열의 인덱스가 시작됩니다. 가령 10개의 배열을 Dim OneArray(10)처럼 선언하면 0부터 시작하여 10까지 11개의 변수로 이루어진 배열이 만들어 집니다. 물론 Option Base1을 코딩의 처음부분에 두면 1부터 시작합니다. BASIC의 배열선언은 많이 세련되어졌습니다. PASCAL처럼 Dim OneArray(1 To 10) 처럼 선언할 수 있는데, 배열의 상하 차원을 지정할 수 있습니다. LBound()와 UBound()는 배열의 하위 인덱스와 상위 인텍스를 돌려줍니다.

     Set cmdctlUser = cmdbarUser.Controls.Add(Type:=msoControlButton,
        before:=1)

이번에 cmdctlUser변수에 도구모음의 버튼콘트롤을 추가합니다. 그리고 그위치는 1번으로 둡니다.

     With cmdctlUser
        .Caption = NameFaceIDMacroOfCmdBtn(i)

NameFaceIDMacroOfCmdBtn()배열의 첫요소는 버튼의 이름이라고 정의했습니다. 그래서 Caption속성에 이를 할당합니다.

        .FaceId = NameFaceIDMacroOfCmdBtn(i + 1)
FaceID속성에 NameFaceIDMacroOfCmdBtn()배열의 en 번째 요소를 할당합니다.
        .OnAction = NameFaceIDMacroOfCmdBtn(i + 2)
이번에는 버튼을 클릭할 경우 실행할 프로시저를 지정합니다.
        If NameFaceIDMacroOfCmdBtn(i + 3) Then .BeginGroup = True
여기에선 그룹을 지정하는 여부를 결정합니다. 사실 NameFaceIDMacroOfCmdBtn()배열에 그룹은 TRUE/FALSE로 지정하므로 굳이 If문을 사용할 필요는 없습니다.
.BeginGroup=NameFaceIDOfCmdBtn(I+3) 으로 하면 됩니다.

      End With
    Next i
    Set cmdctlUser = Nothing
End Sub

이번에 보게될 프로시져는 도구모음에 콤보상자를 만드는 것입니다. [서식도구모음]을 보면 글꼴과 크기를 콤보상자를 이용하여 선택할 수 있습니다. 다음의 것도 그런 콤보박스입니다.

Sub CreateUserCombo(cmdbarUser As CommandBar)
     Dim cmdctlUser As CommandBarComboBox
콤보상자를 대표하는 변수를 CommandBarComboBox 데이터형으로 선언했습니다.

     Set cmdctlUser = cmdbarUser.Controls.Add(Type:=msoControlComboBox,
        Id:=1, before:=1)
새로운 콤보박스개체를 추가하여 cmdctlUser 게체변수에 할당합니다.

     With cmdctlUser
        .Caption = "Date-Format Selector"
        .OnAction = "cmdcboUserAction"
        .BeginGroup = True
        .AddItem Text:="Select any Date-Format"
       .AddItem Text:="YYYY-MM-DD"
       .AddItem Text:="YY-MM-DD"
       .AddItem Text:="YY.MM.DD"

콤보박스에서 선택할 요소를 입력합니다.
        .Width = 150
콤보박스의 크기를 지정합니다
        .ListIndex = 1
콤보박스에서 처음 보이는 항목을 지정합니다. 첫번쨰 항목을 지정하고 잇으므로 실행하면 "Select any Date-Format" 라는 문구가 보일 것입니다.
        .Tag = CBO_TAG
     End With
     Set cmdctlUser = Nothing
End Sub

여기는 위의 콤보박스와 연결되는 프로시져로서 콤보박스선택에 따라 무언가를 보여주도록 하였습니다. 물론 이 프로시져는 연습으로 만들어 본 것인데 실제로 하는 경우에는 선택내용에 따라 여기서 다시 다른 프로시져를 호출해야 할 것입니다.

Sub cmdcboUserAction()
     Dim cmdctlUser As CommandBarComboBox

     Set cmdctlUser = Application.CommandBars(TOOL_NAME) _
        .FindControl(Type:=msoControlComboBox, Tag:=CBO_TAG)
위에서 설명을 생략했지만 사용자정의 콤보상자에 붙인 CBO_TAG라는 꼬리표를 찾아 개체를 돌려줍니다. 이걸 보니 공항에서 도착후 꼬리표를 보고 수하물을 찾던 생각이 나는군요. 그러고 보면 프로그래밍의 세계는 실제 세계와 많이 닮은 듯합니다.

     MsgBox "You Selected! " & vbCrLf & cmdctlUser.Text, vbInformation
선택한 내용을 메시지박스를 통해 보여줍니다. 위에서도 언급했지만 위의 문장은 무얼 선택햇는가를 보여주려는 예입니다. 실제에서 다음과 같이 할 겁니다.
Select Case cmdctlUser.Text
Case "xxxxx":
     실행할 프로시져
Case "xxxxx":
     실행할 프로시져

End Select
아직 프로시져를 만들지 않은 관계로 여기에서 이것을 나중으로 미뤄 둡시다.

End Sub

자 이제 끝날 때가 된 것 같군요. 실제 여러 유형의 버튼이 있지만 실제 사용안되는 것도 있어 가능한 것만 골라 보여드렸습니다. 가령 [서식도구모음]의 괘선버튼, 배경색상버튼 같은 것은 저도 아직 구현하지 못했습니다. 언젠가 알게 되면 알려드리죠. 혹시 지금 아시는 분 있으시면 저에게도 귀뜸을 해주시길 바랍니다.
 

목차 | 이전 | 다음