PROGRAMMING WORKSHOP

VSTO|
ActionsPane과 CustomTaskPane

VSTO를 사용하면서 얻어지는 좋은 점은
.NetFramwWork의 자원을 마음대로 사용할수 있는 것은 말할 것도 없고
시각적으로 당장 눈에 보이는 것은
Ribbon메뉴바를 마음대로 만들어서 사용할수 있다는 점과
통합문서를 열면 오른쪽에 패널이 하나 만들어져서 다양한 콘트롤들을
쎄련되게 배치하고 사용할수 있다는 점일 것이다

VSTO로 만들어지는 엑셀 소루션은 두가지가 있다
하나는 통합문서독립적인 소루션(WorkBook Level Solution)을 만드는 경우와
다른 하나는 엑셀 Application상의 추가기능(Applicaiton Level Solution)으로
구분 할 수 있다

통합문서단위의 VSTO를 만들어 보자



통합문서단위의 VSTO는 위의 그림과 같이 두가지 옵션이 있다
하나는 새통합문서에 VSTO작업을 하는 것이고
다른 하나는 이미 사용하던 통합문서에 VSTO작업을 하는 것

사용자의 명령버튼을 사용하는 것은 VBA 에서는 시트에 버튼을 달던가
UserForm을 사용하던가..메뉴를 사용하던가 하였었다
VSTO에서는 Ribbon이라는 것을 사용할수 있고, 붙박이 ActionsPane을
사용할수 있고, UserForm대신에 지능높은 윈도우폼을 그대로 사용할수 있다
이 페이지에서는 ActionsPane의 삽입과 활용방법을 보도록 한다
통합문서에서 사용되는 ActionsPane은 실은 VBA에서 사용하던
CommandBar(명령줄)을 활용하는 것이다
지금 사용하시는 엑셀의 VBA편집기의 직접실행창에 가셔서
아래와 같이 명령을 해 보시기 바란다
?commandbars("Task Pane").visible
그럼 False라는 결과가 나타난다..눈에 보이지 않는 것이다
또 아래와 같이 해보시면
?commandbars("Task Pane").name
Document Actions 이라는 결과가 나타난다
그럼 아래와 같이 CommandBar이니까..눈에 보이게 해볼까??!!라고 엔터키를 치면
commandbars("Task Pane").Visible=True
아무일도 벌어지지 않는다
이것은 CommandBar에 들어 있기는 하나..VBA로 컨트롤 할수 없는
명령줄인 것이다
그럼 어디서 사용할수 있나?
실은 이 CommandBars("Task Pane")에 윈도우시스템의 컨트롤을
만들어 넣어야 눈에 보인다
그래서 VSTO에서 사용할수 있는 것이다
Commandbars("Task Pane")은 빈탕..껍데기(Container)뿐이다
만들어진 내용(윈도우컨트롤)을 Commandbar("Task Pane")속에 넣어주어야
눈에 보이게 되는 것이다
바로..이 뭔가 만들어주는 것을 VSTO에서 만들수 있다는 것이다
아래의 그림과 같이 Task pane에 들어갈 내용물을
UserControl(윈도우프로그램중의 하나의 컨트롤)이라는 콘트롤로 만든다



UserControl이라는 것을 하나 삽입하면 그냥 회색바탕의
아무것도 없는 맹탕으 것이 하나 만들어진다
이것은 정말 아무짝에도 쓸모없는 것이다
이것에 다양한 콘트롤을 삽입하면 되는 것이다
VBA에서 UserForm의 맨탕과 같다..이것에 다양한 콘트롤을
그려넣듯이 도구상자에서 그려 넣으면 된다
간단하게 버튼 하나 그려 넣어보자
아직 버튼에는 아무 지능도 심어주지 말고
프로젝트창에서 ThisWorkBook개체를 선택하여 코드보기를 연다
아래와 같이 빈탕의 두개의 이벤트프로시져가 나타난다
하나는 통합문서가 열리면서 발생하는 것..
다른 하나는 통합문서가 닫히면서 발생하는 이벤트
시작 이벤트에 아래와 같이 몇줄 적어 보자

Public Class ThisWorkbook
	Private Sub ThisWorkbook_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup
	Dim oCtl As New UserControl1
        Me.ActionsPane.Controls.Add(oCtl)
	With Globals.ThisWorkbook.Application.CommandBars("Task Pane")
            .Position = Microsoft.Office.Core.MsoBarPosition.msoBarRight
            .Width = 200
        End With
 	End Sub
	Private Sub ThisWorkbook_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown
	
	End Sub
End Class

위와 같이 한후 F5키를 눌러서 디버깅런을 하면
오른쪽에 예쁘게 창이 하나 만들어 질것이다..
창에는 현재 버튼 하나만 달랑 있다



이 버튼을 크릭하여 뭔일을 시켜보자

Public Class UserControl1
  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  Static iX As Integer
  iX += 1
  If iX > 4 Then iX = 0
  Try
    With Globals.ThisWorkbook.Application.CommandBars("Task Pane")
      Select Case iX
        Case 0
            .Position = Microsoft.Office.Core.MsoBarPosition.msoBarBottom
        Case 1
            .Position = Microsoft.Office.Core.MsoBarPosition.msoBarFloating
        Case 2
            .Position = Microsoft.Office.Core.MsoBarPosition.msoBarLeft
        Case 3
            .Position = Microsoft.Office.Core.MsoBarPosition.msoBarRight
        Case 4
            .Position = Microsoft.Office.Core.MsoBarPosition.msoBarTop
      End Select
		End With
  Catch ex As Exception
  End Try
  End Sub
End Class

버튼크릭이벤트에 위의 내용을 넣고 실행하고
버튼을 크릭할때 마다 Action Pane이 위치를 좌우상하로
이동하는 것을 볼수 있을 것이다
와우..!! 많은 확장 가능성을 볼 수 있을 것이다
여러분의 가치 상승의 기회가 된다
아래 화일의 모듈의 주석으로 설명을 추가하였다

***[LOG-IN]***

다음은 위의 통합문서소루션과 대별하여 Application레벨소루션
즉 Add-In 소루션에서 위와 모양은 같은것이지만 개체가 다른
CustomTaskPane을 만들어 보자
Add-In타입 소루션은 아래의 그림과 같이



Excel2007 AddIn 템프릿을 선택한후
위의 통합문서소루션과 같은 요령으로
프로젝트창에서 오른쪽 마우스크릭하여 Usercontrol을 하나 삽입하고
버튼하나 그려넣는다
이 UserControl을 잡아 넣는 Container가 통합문서와는 다른 것이다
프로젝트창에서 ThisAddin.vb를 코드보기로 열면

Public Class ThisAddIn
    Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup

    End Sub

    Private Sub ThisAddIn_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown

    End Sub
End Class

와 같이 이벤트프로시져가 두개가 나타난다
하나는 시작하는 이벤트프로시져, 다른 하나는 종료하는 이벤트프로시져
Class명은 통합문서에서는 ThisWorkBook이였으나
AddIn에서는 ThisAddIn이라는 크래스명으로 나타난다
이곳에 UserControl을 어떻게 생성하고 어디에 담는지 보자

Public Class ThisAddIn
    Public oCtl As New UserControl1
    
    Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Startup
        Dim oCTP As Microsoft.Office.Tools.CustomTaskPane = _
        	 Me.CustomTaskPanes.Add(oCtl, "UNO_VSTO Sample")
        With oCTP
            .DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionRight
            .Width = 300
            .Visible = True
        End With
    End Sub

    Private Sub ThisAddIn_Shutdown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shutdown
	End Sub
End Class

AddIn 애서는 CustomTaskPane이라는 개체를 만들어 낸다
이것을 CustomTaskPanes라는 집합체에 담는 것
그러니까..UserControl을 생성하고
CustomTaskPane개체를 생성할때
Me.CustomTaskPanes이라는 집합체의 Add메소드에 UserControl과 TaskPane창의
캡션용 문자열정보를 전달하면 CustomTaskPane이 만들어진것
이개체의 필요한 속성정보를 ,위치,폭,눈에 보이게 등의 값을 준다
이러면 끝이다

문제는 UserControl에 얼마나 기능이 빵빵한 내용을 만들어 넣느냐의 문제!!
디버그실행을 하면 ..



너무 싱거우니까..
VBA에는 없는 기능을 하나 만들어 넣어보자
Timer개체라는 것이 있다
예를 들어서 매100초마다 어떤 작업을 해라..
매 1분마다 어떤 작업을 해라!!
라는 일을 해주는 기특한 Timer개체를 사용해 보자
여기에서는
활성화된 셀, 선택하는 셀에 현재시간이 일정한 간격으로 갱신되게
해보자

그리고 UserControl의 버튼을 크릭하면 Timer를 중단시키기도 하고
다시 크릭하면 Timer가 다시 돌아가게도 해보자
그럼 UserControl+Task Pane+.NetFrameWork의 개체+엑셀을 조합시켜본
간단한 쌤플이 되는 것
나머지는 각자 VBA와 Excel실력을 바탕으로 .NetFrameWork의
개체를 얼마나 이해하느냐에 따라서 하늘을 훨훨나는 소루션을
만들어 낼 수 있을것이다

프로젝트창(소루션창이라고하는 것이 더 좋을 것이다)에서
UserControl1.vb 화일을 코드보기로 열어서
아래와 같이 작성한다
WithEvents라는 키워드는 VBA에서 크래스모듈의 전력이 있으면..
아하..이곳에서도 사용되는 구나!!! 낯섫지 않을 것이다

Public Class UserControl1
		'#####
		'# Timer개체 생성
		'#########################
    WithEvents oTimer As New Timers.Timer
		
		' UserControl이 Load될때의 이벤트
    Private Sub UserControl1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    		' Timer 시간간격설정
        oTimer.Interval = 100
        ' Timer 시작시키기
        oTimer.Start()
    End Sub
    
    ' 위에서 Timer개체를 WithEvents로 생성하여 만들어진 이벤트프로시져에..
    Private Sub oTimer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles oTimer.Elapsed
        Try
        ' 엑셀시트의 활성화셀에 Date.Now.Tostring 값을 전달..
        ' Timer이벤트가 발생할때마다 이 짓을 하게 된다
            Globals.ThisAddIn.Application.ActiveCell.Value = Date.Now.ToString
        Catch ex As Exception

        End Try

    End Sub
		
		' 버튼크릭이벤트
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Try
        ' 시트를 청소하고
            Globals.ThisAddIn.Application.ActiveSheet.cells.clear()
        ' Timer 정지
            If Button1.Text = "Timer Stop" Then
                oTimer.Stop()
                Button1.Text = "Timer Start"
        ' Timer 시작
            Else
                oTimer.Start()
                Button1.Text = "Timer Stop"
            End If
        Catch ex As Exception

        End Try

    End Sub
End Class

아래의 그림과 같이 싱거운 짓을 한다



VSTO는 이런 기본적인 틀만 잡아놓으면 나머지는 VBA의 능력으로만으로도
충분히 VBA로 작성하던것을 옮겨 놓을수 있고
워크샵에서 진행하는 WPF,Window폼의 각각의 콘트롤들에 대한 지식을
UserForm에 잡아 넣거나, 독자적인 윈도우폼을 띄우가면서
할수도 있는것...

***[LOG-IN]***