2021. 2. 22. 14:39

엑셀 Addin 작성시 툴바 및 메뉴 생성 / 제거 코드

엑셀에서 Addin을 작성할때, 엑셀의 툴바 및 툴바 버튼, 메뉴를 추가하기 위한 코드
- 모든 작업은 ThisWorkbook 개체에서 작업한다.
- 되도록이면 작업하기 전에 On Error Resume Next 를 걸어줘서 오류를 없애는 편이 나을 것임

- Workbook_AddinInstall 이벤트에 아래와 같은 코드 추가
    ' 툴바에 버튼 올리기
    Application.CommandBars.Add "툴바이름"
    Application.CommandBars("툴바이름").Visible = True
    Set btnCmd = Application.CommandBars("툴바이름").Controls.Add(msoControlButton)
    btnCmd.OnAction = "클릭시 실행할 모듈 상의 함수이름1"
    btnCmd.Caption = "버튼이름1"
    btnCmd.FaceId = 64   ' 버튼 아이콘
    btnCmd.Style = msoButtonIcon  ' 버튼 모양
    Set btnCmd = Nothing
   
    Set btnCmd = Application.CommandBars("툴바이름").Controls.Add(msoControlButton)
    btnCmd.OnAction = "클릭시 실행할 모듈 상의 함수이름2"
    btnCmd.Caption = "버튼이름2"
    btnCmd.FaceId = 104   ' 버튼 아이콘
    btnCmd.Style = msoButtonIcon  ' 버튼 모양
    Set btnCmd = Nothing

    ' 메뉴에 삽입하기
    Set cmdBar = Application.CommandBars("worksheet menu bar")
    With cmdBar.Controls.Add(Type:=msoControlPopup)
        .Caption = "상위메뉴이름"
        With .Controls.Add(Type:=msoControlButton)
            .Caption = "메뉴항목이름1"
            .OnAction = "메뉴항목클릭시 실행할 모듈상의 함수 이름1"
            .BeginGroup = True   ' 새로운 가로선을 넣을지 여부
            .FaceId = 64             ' 메뉴상에 표시할 아이콘 번호
        End With
       
        With .Controls.Add(Type:=msoControlButton)
            .Caption = "메뉴항목이름2"
            .OnAction = "메뉴항목클릭시 실행할 모듈상의 함수 이름2"
            .FaceId = 301
        End With
    End With
    Set cmdBar = Nothing


- 툴바 삭제시 Workbook_AddinUninstall 이벤트에 아래와 같은 코드 추가
    ' 툴바 삭제
    Dim cmdBar As CommandBar
   Application.CommandBars("툴바이름").Visible = False   ' 툴바이름은 위에서 생성한 툴바 이름임
   Application.CommandBars("툴바이름").Delete

   ' 메뉴 삭제
    Set cmdBar = Application.CommandBars("worksheet menu bar")
    cmdBar.Controls("상위메뉴이름").Delete
    Set cmdBar = Nothing

 

- 오피스 2016에서 돌려보니 가끔 오류도 나오고 오류는 안나는데 추가기능 쪽의 메뉴가 나오지 않는 현상이 발생하는 경우가 있음. 이때에는 Addin이 Open 될 때 메뉴를 추가해주고 BeforeClose 일때 메뉴를 삭제해주는 방법을 사용한다.

이 때, 화면에 메뉴가 두개씩 나오는 나오는 경우가 발생할 수 있기 때문에 Workbook_AddinInstall 함수에서 기존 버튼이 있는지 확인하는 과정이 필요하다

Private Sub Workbook_AddinInstall()
    ' 이거 추가한다고 엑셀 열때마다 오류가 나면 짜증나니 이렇게 호출
    On Error Resume Next
    ' 기존에 해당 버튼이 있는지 확인
    If Application.CommandBars("버튼명") Is Nothing Then
        Application.CommandBars.Add "버튼명"
        Application.CommandBars("버튼명").Visible = True
        Set btnCmd = Application.CommandBars("버튼명").Controls.Add(msoControlButton)
        btnCmd.OnAction = "호출함수"
        btnCmd.Caption = "버튼명"
        btnCmd.FaceId = 1394   ' 버튼 아이콘
        btnCmd.Style = msoButtonIcon  ' 버튼 모양
        Set btnCmd = Nothing
    End If
	
End Sub

' 열릴 때 마다 툴바가 추가되면, 지속적으로 버튼만 늘어나기 때문에
' (install 할 때 기존에 버튼이 있는지 확인하기 때문에 그럴 리는 없지만 보험용도)
' 닫을 때 툴바를 없애줌(MS에서 이렇게 하라고 하였음)
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Workbook_AddinUninstall
End Sub

' 툴바가 자동으로 추가가 안되기 때문에 열릴때 마다 추가
Private Sub Workbook_Open()
    Workbook_AddinInstall
End Sub

 

 

2018. 4. 10. 18:05

엑셀 Addin 작성시 마우스 오른쪽 메뉴 생성 방법

MS쪽 사이트에 있는 코드를 그대로 가져와 설명만 붙여봄


Sub AddToCellMenu(),

    Dim ContextMenu As CommandBar,

    Dim MySubMenu As CommandBarControl,

,

    ' 중복 제거를 위해서 미리 메뉴를 삭제해 줌,

    Call DeleteFromCellMenu,

,

    ' CommandBars("Cell")로 지정하면 ContextMenu를 접근할 수 있음,

    Set ContextMenu = Application.CommandBars("Cell"),

,

    ,

    ' 내장되어 있는 메뉴를 추가(ID = 3 -> Save),

    ' 내장되어 있는 메뉴를 추가하기 위해선 아래의 한줄이면 끝,

    ' before는 순서,

    ContextMenu.Controls.Add Type:=msoControlButton, ID:=3, before:=1,

,

,

    ' 1단짜리 메뉴 추가. 일반 툴바에 버튼 추가하는 것과 같은데 순서 지정하는 부분이 있음,

    ' OnAction에는 동작할 함수가, FaceId는 아이콘이, Caption의 경우 Text로 표시할 부분이, Tag에는 기타 정보가 들어감,

    ' 삭제시에 Tag정보를 바탕으로 버튼을 삭제할 수 있음,

    With ContextMenu.Controls.Add(Type:=msoControlButton, before:=2),

        .OnAction = "'" & ThisWorkbook.Name & "'!" & "ToggleCaseMacro",

        .FaceId = 59,

        .Caption = "대문자/소문자/적절한 문자로 전환",

        .Tag = "My_Cell_Control_Tag",

    End With,

,

    ' Add a custom submenu with three buttons.,

    ' 서브메뉴가 있는 경우 추가 방법,

    ' 일단 메뉴를 하나 만들고, 그 아래 버튼을 넣는 방식,

    ' 메뉴를 추가할때 Type을 보면 msoControlPopup임. 버튼일 경우는 Type이 msoControlButton임,

    ' 일단 버튼을 만든 이후에는 일반 메뉴와 똑같음,

    Set MySubMenu = ContextMenu.Controls.Add(Type:=msoControlPopup, before:=3),

,

    With MySubMenu,

        .Caption = "문자메뉴",

        .Tag = "My_Cell_Control_Tag",

,

        With .Controls.Add(Type:=msoControlButton),

            .OnAction = "'" & ThisWorkbook.Name & "'!" & "UpperMacro",

            .FaceId = 100,

            .Caption = "대문자",

        End With,

        With .Controls.Add(Type:=msoControlButton),

            .OnAction = "'" & ThisWorkbook.Name & "'!" & "LowerMacro",

            .FaceId = 91,

            .Caption = "소문자",

        End With,

        With .Controls.Add(Type:=msoControlButton),

            .OnAction = "'" & ThisWorkbook.Name & "'!" & "ProperMacro",

            .FaceId = 95,

            .Caption = "적절한문자",

        End With,

    End With,

,

    ' 아래 명령어로 중간 구분자를 넣을 수 있음,

    ContextMenu.Controls(4).BeginGroup = True,

End Sub,

,

Sub DeleteFromCellMenu(),

    Dim ContextMenu As CommandBar,

    Dim ctrl As CommandBarControl,

,

    ' CommandBars("Cell")로 지정하면 ContextMenu를 접근할 수 있음,

    Set ContextMenu = Application.CommandBars("Cell"),

,

    ' Delete the custom controls with the Tag : My_Cell_Control_Tag.,

    ' 모든 콘트롤들을 보면서 Tag가 My_Cell_Control_Tag 인 항목을 찾아서 지워줌,

    ' 이렇게 하면 원하는 모든 걸 한번에 지울 수 있으니 이 방법을 쓰면 좋을 것임,

    For Each ctrl In ContextMenu.Controls,

        If ctrl.Tag = "My_Cell_Control_Tag" Then,

            ctrl.Delete,

        End If,

    Next ctrl,

,

    ,

    On Error Resume Next,

    ' 내장 기능에 대한 삭제는 아래와 같은 방법으로 사용,

    ContextMenu.FindControl(ID:=3).Delete,

    On Error GoTo 0,

End Sub,