PROGRAMMING WORKSHOP

COMAddIns | VSTO

다른 페이지에서 VSTO 시리즈를 하고 있지만(진행중..)
이곳 COM AddIn코너에서 종합적으로 AddIn의 종류를 이야기 하고 있고
AddIn의 최신기술인 VSTO를 이야기 해 보도록 하자

VSTO에서는
Shared COMAddIn의 좋은 기능들이 그대로 구현되는 셈이다
그러나 기능을 손을 볼 필요없이 좀더 많이 알아서 처리해주는 것이(behind the scenes)
많아진 셈이다
그래서 프로젝트를 하나 만들면 아래와 같이 달랑 한장의 크래스모듈(ThisAddIn)이 나타난다



그것도 메소드가 달랑 두 개만 있다

하나는 StartUp ...추가기능 화일이 열릴때 초기화를 할수 있는 메소드
다른 하나는 ShutDown...추가기능 화일이 닫힐 때 정리정돈 청소 할수 있는 메소드
이렇게 두개다
Shared COMAddin에서는 아마도 5개 였을 것이다

Public Sub OnBeginShutdown(ByRef custom As System.Array) Implements ...
End Sub

Public Sub OnAddInsUpdate(ByRef custom As System.Array) Implements ...
End Sub

Public Sub OnStartupComplete(ByRef custom As System.Array) Implements ...
End Sub

Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements ...
End Sub

Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom As System.Array) Implements ...
End Sub

와 같이 5개 였다..
VSTO에서는 실은 이런 복잡한(실은 대단히 간단 한것이데도..VSTO에 비하여)
이것은 많은 것을 알아서 해줄 것이니..오피스, 엑셀개발자는
잡다한 것 잊으시고 업무에 필요한 로직만 신경쓰시라는 컨셉으로
만들어진 것이라고 보시면 된다

ThisAddIn이라는 크래스모듈을 중심으로..
일반 모듈, 크래스모듈,윈도우폼,각종자원화일등등을 추가하면서
만들고 싶은 것을 자유롭게 만들수 있는 개발환경이다
단지 아직 다양한 윈도우환경에서 설치상에 까다로움(주로 보안관련)
까다로움이란..설치하시는 분이 무엇을 설정하시고, 무엇을 확인하시고
그런 귀찮은 일들이 있는 것이지만..
버전업이 되면서 이런 문제들은 자연스럽게 해소 될 것이고
현재 VBA의 자유로움과 같이 정말 좋은 사무자동화도구를 만들수 있는
환상적인 도구가 될 것이다
그러니 먼저 배우는 놈이 장땡이다

VBA실력을 이곳에서 유감없이 발휘하면 된다
아래의 그림과 같이 새로운 프로젝트를 만든다



VisualBasic/Office/2007 에서 Excel 2007 AddIn 을 선택하면 된다
그리고 VSTO 추가기능의 장점은 리본메뉴를 편하게 디자인 할 수 있다는 점이다
아래와 같이 화일을 추가한다



리본창이 열린 상태가 된다
아래의 그림과 같이 버튼을 하나 끌어다 놓는다



이 버튼을 더블크릭하면 코딩할수 있는 크래스모듈이 열린다 이제 엑셀에 무슨 짓을 해도 된다
VBA에서 구현하던 것을 그대로 해도 좋고..그러면서 능력을
확장해 나가는 시작이 된다
.NetFrameWork를 기반으로 하는 VSTO 개발에서는 항상 라이브러리 참조에 대하여
가장 중요한 관심을 갖여야 한다
엑셀 VBA는 이미 엑셀이 갖고 있는 개체들만 사용하면 되지만
VB.Net에서의 개발환경에서는 라이브러리 참조와 여기에서 나오는 개체들의
조립인 셈이다
아래의 그림과 같이 프로젝트속성창에서 References창을 잘 관찰하는 것이 좋다
VSTO프로젝트로 Excel Addin을 만든다고 한다면
엑셀과 오피스개체들은 참조창에 줄줄이 자동참조하고 있다



리본에 삽입한 버튼을 더블크릭하면 아래와 같이 나타날 것이고

Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles Button1.Click End Sub

빈탕이다...
처음 만나는 VSTO에서 엑셀을 다루려고 하니..뻐하다!!!
무엇을 어떻게 해야 할지 좀 황당하다
우선 앞페이지에서 Class모듈로 Application개체를 만들어서 사용하였던 것을
기억해 보시기 바란다
여러개의 통합문서를 다루는 종합사령실을 차려 놓은 셈이다
그렇다면 가장 먼저 접근하여야할 개체가 무엇일까???를 생각하면 된다
그렇지!!! 엑셀의 최상위 개체 Application개체에 접근하면 된다
그렇다면 추가 기능화일이 열러고 위의 리본버튼을 크릭하면
활성화된 워크시트에 어떤 정보를 뿌리고 싶다!!라고 치자

Dim iX As Integer,iY As Integer For iX=1 To 10 For iY=1 To 10 Activesheet.Cells(iX,iY)=Int(Rnd()*100)+1 Next Next

라고 하는 것은 쉽고도 쉬운 순환문으로 100개의 셀에 난수를
뿌리는 것이다
이것을 그대로 리본버튼을 크릭하면 시트에 뿌려주게 하면 된다

그런데 VSTO환경에서 어떻게 워크시트에 접근할 것인가???
이것이 문제인 것이다
이것만 알면 만사 형통이다..엑셀 VBA에서 활용하던 실력을 발휘하면 된다

우선 가장 중요한 것이 Globals 라는 개체다
이 Globals는 추가기능화일의 최상위 개체이다
이 녀석이 엑셀의 Application을 관리하고 있다

아래의 그림과 같이 Globals 라고 치고 쩜찍으면 현재 소루션이 갖고있는
자원이 나타난다
Global{} 이라는 NameSpace와 헷갈리지 마시고 Globals라는 개체이다



여기에서 ThisAddIn이라는 속성이 나타나고 이것이 현재 ThisAddIn크래스모듈에서
생성된 개체가 되는 것이고
이 개체가 엑셀의 Application 개체를 갖고 있는 것이다
모든 것을 이미 만들어서 보관하고 있는 것이다
그래서 엑셀의 최상위 개체 Application개체에 접근은
Globals.ThisAddIn.Application 인것이다
이것만 알면 그냥 엑셀인 것이다
이제 워크시트개체를 담을 변수를 만든다고 치자

Dim shtX As Worksheet

라고 엑셀 VBA에서는 하였었다
그러나 VSTO는 Worksheet라는 것을 이해 못한다!!!
언놈이 갖고 있는 개체냐????라고 의아해 한다
당연한 것이다 .NetFrameWork환경에서 엑셀은 외계인인 것이다
그래서 프로젝트속성창의 References(참조)탭창의 Imported NameSpace목록을
보면..아래의 그림과 같이 VSTO가 엑셀을 Import시켜놓은 상태이다



그래서 별도로 크래스모듈이나 일반모듈 선언부에

Import XL=Microsoft......

와 같이 선언할 필요가 없다
그냥 알아서 끌어다가 놓은 것을 사용하면 된다
그래서 아래와 같이 작성하면 된다

Dim oSheet As Excel.Worksheet = Globals.ThisAddIn.Application.ActiveSheet

한가지만 더 알아두자
oSheet.Cells(iX,iY).Value=Int(Rnd()*100)+1
를 작성하려고 하는데 어라..아래의 그림과 같이 목록에 속성이 안보이네???



엑셀에서 VBA에서와는 달리 남의 집에 와서(.NetFrameWork환경) 신세지는 것이라서
예의가 밝아야 한다...VBA에서 Value속성같은 것은 Default로 작성하지 않아도
알아서 처리가 되었다..그러나 남의 집에서는 명함을 제대로 잘 내놓아야 한다
그런 정도의 예의는 아는지라 Value속성을 넣으려고 하는데
목록이 기분이 나쁘다!!!!
value라고 입력해도 첫문자가 대문자로 바뀌지도 않는다
그냥 그렇게 넣어도 에러는 나지 않는다, 그렇지만 기분 나쁜것 이다
왜그럴까???
Cells() 속성을 .NetFrameWork에서 알아채지 못하고 있는 것이다
그래서 명시적으로 나는 이런 개체다!!라는 것을 밝히는 것이 좋다
아래와 같이 종종 개체타입을 알려 주는 것이 좋은 것이다

CType(oSheet.Cells(iX, iY), Excel.Range).Value = Int(Rnd() * 100) + 1

이것이 무슨 말이냐 하면 ...아직 무슨 타입의 개체인지 모를 Cells을
CType 함수 ..Change Type 함수를 사용하여 Excel.Range 타입으로 변환시키는 것이다
그러면 쩜찍으면 Range개체의 자원목록이 기분좋게 나타나는 것이다
VBA에서 다른 개발환경에 가서 가장 낯섫고, 손에 익숙지 않은 것이
개체의 타입의 정의를 항상 잘해주어야 한다는 것만 알면 된다
그러니 엑셀프로그래밍을 VBA로 하면서 항상 어떤 속성은 어떤 타입의 개체를
만들어 주고 있구나!!!!라는 것을 의식하면서 하는 것이 좋다

Imports Microsoft.Office.Tools.Ribbon

Public Class Ribbon1
    Private Sub Ribbon1_Load(ByVal sender As System.Object, ByVal e As RibbonUIEventArgs) Handles MyBase.Load
    End Sub
	Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles Button1.Click
Dim oSheet As Excel.Worksheet = Globals.ThisAddIn.Application.ActiveSheet
        For iX As Integer = 1 To 10
            For iY As Integer = 1 To 10
                CType(oSheet.Cells(iX, iY), Excel.Range).Value = Int(Rnd() * 100) + 1
            Next
        Next
    End Sub
End Class

위와 같이 한후 디버그실행(F5키)시키면 엑셀이 열릴 것이고
버전에 따라서 에러가 날수도 있을 것이다..
대개의 경우 2003버전과 2007버전을 같이 사용할때 2003버전을 열어 놓고
하면 에러가 난다
2003버전을 닫아 놓고 하시면 된다
엑셀이 열리면 리본에 버튼이 만들어 졌음을 볼수 있고
이것을 크릭하면 위의 Button1_Click이 실행되어 행열에 난수가 뿌려짐을
볼수 있다..
이제 된 것이다..
이런 요령으로 VBA에서 얻은 것을 활용하면 된다
추가한다면 WindowForm을 추가 할때 WindowForm에 대한 지식이 것이고
또한 WindowForm의 지식은 Custom Task Pane이라는 오른쪽에 창을
만드는 것으로 연장 되는 것이다
또 확장하여 .NetFrameWork의 크래스들에 대한 지식일 것이다
최소한 여러분의 VBA에서 구현하던 것은 모두 진행할수 있을 것이다
VBA모듈에 작성하는 대신 VB.Net의 크래스모듈에 작성하는 것이 다른 것이다

이제 위의 Button1_Click에서 빨강색 부분을 보면
Dim oSheet As Excel.Worksheet = Globals.ThisAddIn.Application.ActiveSheet
Globals.ThisAddIn.Application ..참 길다
이런 것들때문에 일반모듈시트가 하나 필요할 것이다
어떤 프로젝트나 일반 모듈시트 한장은 필수적으로 삽입하는 습관이 좋다
프로젝트에서 Item추가하여 모듈시트를 삽입하고..이름을 modMain이라고 지어주고

Module modMain
    Public oApp As Excel.Application = Globals.ThisAddIn.Application

End Module

라고 작성해 주면 프로젝트내에서 어느 곳에서나
Globals.ThisAddIn.Application 이라는 긴 코딩 보다는
oApp라는 변수로 접근하기가 쉬우 질 것이다
그래서 위의 리번버튼에서

Dim oSheet As Excel.Worksheet = Globals.ThisAddIn.Application.ActiveSheet

와 같이 한 것을 아래와 같이 하면 될 것이다

Dim oSheet As Excel.Worksheet = oApp.ActiveSheet

그러나 위의 방법보다는 항상 추가기능화일이 로딩이 될때 모든 준비작업을
초기화 시켜주는 습관이 좋다
위의 내용을 아래와 같이 하여 주는 것이 좋을 것이다

모듈시트에서 변수 선언만 해두고
Module modMain
    Public oApp As Excel.Application

End Module
추가기능의 메인 크래스인 ThisAddIn에서 초기화한다
Public Class ThisAddIn
	Private Sub ThisAddIn_Startup() Handles Me.Startup 
	modMain.oApp = Globals.ThisAddIn.Application

    End Sub
	Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
	End Sub
End Class

만들다 보면 수도 없이 변수가 만들어지고..헷갈리기 시작하는 것을
방지하는 좋은 방법은 어느 한곳에서 초기화를 해주는 ..즉 변수등을 관리해주는
형식이 바람직 한 것이기 때문이다
이름그대로 ThisAddIn개체의 StartUp() 메소드속에 출발준비작업을 하는 것이 좋은 것이다

이런 저런 필요한 기능 붙인다고 치고..
여기에서는 그냥 싱거운 테스트자동화만 했다
이제 회사의 영업부직원들에게 혹은 전체회사에 이 추가기능을 사용하게 하고 싶다
회사에 화일써버가 있다면 써버에 게시(Publish) 하고 설치(Install)하게 할수도 있고
회사에 웹써버가 있다면 웹써버에 같은 방식으로 게시할수도 있다
기본적으로 여러사람이 같은 추가기능을 사용할수 있게 되고
개발자인 여러분이 회사의 방침에 따라서 어떤 계수등이 바뀌거나
업무 절차가 바뀌어 사용중인 추가기능화일을 업데이팅하고 싶다면
그냥 개발자가 변경내용을 자동화하여 같은 경로에 그냥 Publish(게시)버튼만
눌러 주면 되는 것이다
바로 이것이 VSTO소루션의 파워가 되는 것이다
각 사용자가 사용중인 추가기능화일은 버전체크가 자동으로
이루어져(게시할때 설정한 시간이나 기간에 따라서) 항상
같은 방식의 업무를 추가기능 화일을 통하여 아무 탈없이 진행 될수 있는 것이다
화일을 주고 받고, 어쩌고 할 일이 없는 것이다
버전이 다르니, 같으니 어쩌구 분쟁의 소지가 없게 되는 셈이다
그야 말로 전회사의 일관성있는 자동화가 이루어지는 셈이다
아무쪼록 VBA로 내공을 쌓고 , 종국에는 VSTO소루션으로 전체가 자동화되는것을
이루시기 바란다
저희 회사는 뭐 이렇다할 로직도 없고 ..그냥 문서작성이나 하구
그러니까..필요 없겠네..할수도 있을 것이다...
요따위 생각이 발전과 성장을 못하게 한다
기본적으로 양식을 통일성있게 사용할 수 있을 것이다
양식을 다양한 형식으로 버튼 하나만 누르면 일관성있는 양식을
사용할 수 있을 것이다...최소한..!!

이제 사용자에게 배포를 해야 할 것이다
개발자의 입장에서는 디버깅을 한번 한 상태가 되면
엑셀을 열면 계속 개발자의 화일경로의 AddIn화일을 물고 열리지만
이것은 정식으로 설치된 것은 아니다
정식으로 설치를 하거나, 다른 사용자에게 배포를 위한다면
배포를 위한 작업은 프로젝트속성창에서 Publish(게시)탭에서
아래의 그림과 같이 하게 된다



Publish(게시)버튼을 최초로 크릭하면
Publish 폴더가 만들어지고 화일의 내용이 만들어지고
다시 버전업시킨 내용을 Publish(게시)하면 Publish 폴더내에
새버전이 아래의 그림과 같이 계속 추가된다
Publish폴더내의 VSTO확장자의 화일을 더블크릭하면 설치 되는 것이다



새로운 버전이 게시될때 변하는 것은
Publish 폴더의 자식폴더인 Application Files 폴더에 새로운 버전의
폴더가 계속 만들어지게 된다
각각의 버전속의 화일내용중 VSTO확장자의 화일이 해당버전을 찾아가는
화일이다 ..이 화일과 똑같은 화일이
Publish 폴더에도 하나가 있다..이것은 Application Files폴더내의 각버전폴더의
VSTO화일과 같은 것이다
만약 버전 10이 최근 버전인데 버전 3으로 다시 바꾸고 싶다면
버전 3내의 VSTO화일을 Publish 폴더의 VSTO화일로 바꿔주면
사용자의 버전은 모두 버전 3으로 갱신된다
그러니까..버전을 꺼꾸로도 바꿔줄수 있다는 이야기다
그러니까 Publish 폴더와 하부화일을 모두 사용자에게 주면
설치가 된다
이것은 웹써버나, 화일써버 없을때는 소루션에 셋업프로젝트(MSI화일)을
추가하여 셋업프로젝트를 생성한후..만들어지는 msi화일(Window Installer화일)을 배포하는 것이
좋을 것이다
VSTO소루션은
개발자가 웹써버나 화일써버에 게시(Publish)하고 설치(Install)하는
방식이 가장 바람직한 방법일 것이다


***[LOG-IN]***