PROGRAMMING WORKSHOP

COMAddIns | Excel AddIn

COM 라이브러리
Excel COM AddIn을 하면서 엑셀자체화일로 만드는 Excel Addin화일을
하나 먼저 만들어 보는 것이 순서인데 빼 먹었다
VSTO를 하기 전에 엑셀 AddIn을 만들어 보도록 하자
그래야 다음에 할 VSTO버전까지 하면 모두 살펴보는 셈이 된다
Excel AddIn으로 만들어야 할 대상이 과연 무엇이 있을까?
이런 차원에서 생각을 해보신 적이 있다면 엑셀 추가기능화일을
만들어 보아야 한다
이것은 순수한 VBA로 만들어진다

복잡하게 만들면 이야기하고자 하는 핵심에서 벗어날 것 같으니
간단한 것으로 하도록 하자
엑셀이 열려있을때 하나의 통합문서만 열고 사용하지 않을 것이다
여러개의 통합문서를 열어 놓고 작업을 한다
각각의 통합문서에는 몇장의 시트가 들어 있고
이 각각의 시트를 쉽게 왔다 갔다하는 메뉴를 하나 만드는 것은
별 문제가 없을 것이다
그런데 새로운 문서가 열릴때 어디에선가 새로운 문서가 열렸다는
신호를 보내주어야 할 것이다
그 신호를 받아서 메뉴를 갱신해야 AddIn화일로서 가치가 있을 것이다
또 여러개의 통합문서중 어느 것이 닫혔다면 역시
마찬가지로 닫힌 상태에서 열린 것만 메뉴를 다시 구성해야 한다

일반 모듈시트에 아래와 같이 작성하고

'//메뉴버튼의 작성
Sub CreateMyBar()
Dim oBar As CommandBar
Dim oPopup_ As CommandBarPopup
Dim oPopup As CommandBarPopup
Dim oButton As CommandBarButton
Set modMain.oMain = New clsMain
Set modMain.oMain.App = Application
Set oBar = Application.CommandBars(modMain.Main_Bar)
Set oPopup = oBar.Controls.Add(Office.msoControlPopup)
oPopup.Caption = modMain.MY_MENU
Dim oBook As Workbook
Dim oSheet As Worksheet
For Each oBook In Workbooks
    If oBook.Name <> modMain.sBookToKill Then
    Set oPopup_ = oPopup.Controls.Add(Office.msoControlPopup)
    oPopup_.Caption = oBook.Name
    For Each oSheet In oBook.Worksheets
        Set oButton = oPopup_.Controls.Add(Office.msoControlButton)
        oButton.Caption = oSheet.Name
        oButton.Parameter = oBook.Name
        oButton.OnAction = "ThisWorkbook.ButtonClick"
    Next
    End If
Next
End Sub
'//메뉴버튼의 제거
Sub DeleteMyBar()
On Error Resume Next
Application.CommandBars(Main_Bar).Controls(MY_MENU).Delete
End Sub

위와 같이 작성후 ThisWorkBook..즉 Addin화일이 될 통합문서의
ThisWorkBook 모듈시트에서 아래와 같이 작성하면


Private Sub Workbook_BeforeClose(Cancel As Boolean)
modMain.DeleteMyBar 
End Sub

Private Sub Workbook_Open()
On Error Resume Next
modMain.DeleteMyBar
modMain.CreateMyBar
End Sub

Sub ButtonClick()
Dim oButton As CommandBarButton
Dim oPop As CommandBarPopup
Set oButton = Application.CommandBars.ActionControl
Application.Goto Workbooks(oButton.Parameter).Worksheets(oButton.Caption).Range("A1")
End Sub

화일이 열리고 닫힐때마다 위의 내용들이 실행되어
열때는 메뉴가 나타나고 닫으면 메뉴가 사라지게 된다



그러나 위의 것은 좀 문제가 있는 것이다
위의 화일이 열려 있다고 해도 기존의 통합문서를 또 열거나
닫거나 할때 메뉴가 갱신되지 않는다
그리고 새로운 통합문서를 생성해도 역시 메뉴는 갱신되지 않는다
오직 해당 문서(AddIn화일이 통합문서)가 열리고 닫혀야만 갱신된다
이런 답답한 일이 있나???
왜냐면 Application 레벨에서의 통제기능이 없기 때문이다
위의 것은 통합문서단위에서의 일만 한다

이때 필요하게 되는 것이 크래스모듈의 활용이다
크래스모듈에 엑셀의 Application개체를 심어서
Application개체의 이벤트를 사용할수 있게 만드는 것이다



VB.Net에 재미가 들리신분들에게는 크래스모듈에서
Public WithEvents App As Excel.Application
이라는 구문이 낯섫지 않고 친근하게 느껴질 것이다

Application이 갖고 있는 모든 Event에 접근할수 있게 되고
특정한 통합문서의 Worksheet의 이벤트를 Application레벨에서
모든 통합문서의 시트를 통제가 가능해지는 것이다
여기에서 새로운 시트가 삽입되거나, 삭제 될때마다
메뉴가 갱신되어야 한다는 문제..
새통합문서가 삽입되거나, 닫히거나, 기존의 문서가 열리거나
닫히거나 모든 것의 움직임을 통제하는 콘트롤 타워를 장악하게 되는 것이다

아래 화일을 열고 통합문서를 새로 추가하거나, 닫거나
기존의 문서를 열거나, 시트를 삭제하거나..등등을 해보시면
항상 메뉴는 현상황을 갱신하고 유지하고 있음을 볼수 있을 것이다
(프로그래밍적으로 추가되는 문서나 시트는 제외된다)
이것은 일반 통합문서이지만 이것을 [다른 이름으로 저장하기]/[추가기능화일]로
저장하면 추가기능 화일이 되는 것이니, 이것은 각자 그렇게 저장해서
사용해 보시기 바란다

***[LOG-IN]***