PROGRAMMING WORKSHOP

VB.Net | System.IO ...VBA의 IO함수에 해당하는 것들

VB언어를 사용하여 실버라이트다 WPF다..표현도구가 다양하다 ,
엑셀과 떨어진 다른 것도 좋지만 엑셀을 중심으로 하는
VSTO로 같은 System.IO 관련 개체들을 구현 해보자!!

VSTO를 통하여 VB.net을 익히시고 각자의 취향과 용도에 따라서
WPF나 실버라이트나 윈도우폼이나 확장하여 나갈수 있을 것이다
너무 욕심이 많아서 이것 저것 죄다 구현하려고 노력하여 보나..
욕심대로 되지 않는다
VB.Net을 VSTO에 중심을 잡고 나가기로 하자..

엑셀중심, VSTO중심,Office중심으로..

앞에서 WPF에 표현하였던 System.IO 의 내용을 VSTO로 다시 시작하자..

Visual Studio 2008(2010도 마찬가지요령)에서
새 프로젝트를 엑셀 2007 Add-in으로 선택하여 만들고
Visual Studio는 하나의 소루션내에 여러개의 프로젝트가 만들어 질수 있으나
지금 만든 것은 하나의 소루션에 하나의 엑셀프로젝트가 들어 있는 셈이다
하나의 프로젝트에 여러개의 소루션이 아니고
하나의 소루션에 여러개의 프로젝트라는 이야기다
엑셀통합문서에서 VBA로 작업을 할때 하나의 통합문서에는 하나의 VBA프로젝트가
들어있다..소루션창이라고 하지 않고 프로젝트창이라고 하였었던것을
상기하시면..아하..Visual Studio는 여러개의 프로젝트를 종합적으로
모아서 하나의 소루션을 꾸밀수 있구나..라는 것을 접수하시면 된다
아무튼 하나의 소루션에 하나의 프로젝트를 만들었다

Add-In이니까 열면 빈탕이다..뭔가 시작할수 있는 시각적 장치가 있어야 한다
이때 리본개체..(2007이후 부터의 메뉴시스템)이 필요하게 된다

MS에서 2007에 골때리게 복잡하게 만든 리본은 실은
VSTO를 겨냥하여 만든것이라고 할수 있는 것이다
리본은 VBA로 다루지 않고(VBA에서는 기존의 명령줄) VSTO에서 VB로 다룬다
물론 VBA로서 처리할수 있으나 XML문서를 풀고 묶고..
한마디로 배보다 배꼽이 더 큰 작업질을 해야 한다
VBA로는 그냥 기존의 명령줄을 활용하는 것이 공연히 힘빼지 않고 좋다

소루션창에서 엑셀Add-in프로젝트를 오른쪽마우스로 선택하고
추가/새아이템을 하여 리본을 선택하면 리본이 삽입된다
Visual Studio 에서는 마치 윈도우폼을 메뉴에 사용하는 것과 같은 요령이 된다
그냥 버튼 끌어다가 놓고 크릭이벤트프로시져에 적절한 하고 싶은
일을 코딩해주면 되는 것이다



리본에 도구상자에서 버튼을 끌어다 놓고
Group상자와 버튼의 속성값을 속성창에 각각 입력하고
중요한 것은 버튼의 Click 이벤트프로시져에 이제 원하는 작업을 하면 된다
버튼을 크릭하면
새로운 시트가 하나 생성되고 이름을 "FileSystem"이라고 지어준다
그리고 Add-in이 실행되는 컴퓨터의 드라이브명만 리스팅해보자

소루션창에서 모듈시트를 또 한장 추가하고 이름을 modFileSys라고 지어주고
모듈의 내용을 아래와 같이 작성한다

Module modFileSys Public Const SHT_FILE_SYS As String = "FileSystem" Public shtFileSys As Excel.Worksheet Public Sub ListDriverNames(ByVal oSht As Excel.Worksheet) Dim iNextDrive As Integer = 0 With oSht.Range("B3") For Each oX As System.IO.DriveInfo In System.IO.DriveInfo.GetDrives .Offset(iNextDrive).Value = oX.Name iNextDrive += 1 Next End With End Sub Public Function IsSheetExist(ByVal sShtName As String) As Boolean Dim oSht As Excel.Worksheet = Nothing Try oSht = Globals.ThisAddIn.Application.Worksheets(sShtName) Catch ex As Exception Return False Finally If Not IsNothing(oSht) Then oSht.Cells.Clear() End If shtFileSys = oSht End Try Return True End Function Public Sub CreateSheet(ByVal sShtName As String) shtFileSys = Globals.ThisAddIn.Application.Worksheets.Add With shtFileSys.Cells .Font.Size = 11 .Font.Name = "맑은 고딕" .Parent.name = sShtName End With Globals.ThisAddIn.Application.ActiveWindow.DisplayGridlines = False End Sub End Module

Import System.IO
를 선언해주고 사용하면

For Each oX As System.IO.DriveInfo In System.IO.DriveInfo.GetDrives
    .Offset(iNextDrive).Value = oX.Name
    iNextDrive += 1
Next

구문상의 빨강색은 생략해도 되지만..
아무튼 작업편한대로 하면 된다
실은 선언부에
Import System.IO
를 해주는 것이 좋겠지만..간단하면 위와 같이 직접 작성해도 된다

위와 같이 하고 위의 내용을
리번의 버튼에서 호출하여 사용하자

리번의 버튼의 Click이벤트프로시져에서 modFileSys에 있는 자원을
활용한다

Private Sub btnSystemIO_Click(ByVal sender As System.Object, ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) Handles btnSystemIO.Click If Not modFileSys.IsSheetExist(modFileSys.SHT_FILE_SYS) Then modFileSys.CreateSheet(modFileSys.SHT_FILE_SYS) End If modFileSys.ListDriverNames(modFileSys.shtFileSys) End Sub

위의 구문에서 해당시트가 존재하는지 확인하고
없으면 새로 시트를 만들어서 사용하고 있으면 있는 것을 청소하여 사용한다
그리고 System.IO의 개체들을 활용하여
드라이브를 시트에 뿌려주는 프로시져 ListDriverNames프로시져를
호출하면..
즉 버튼을 크릭하면 아래와 같이 시트에 드라이브명만 달랑나타나게 될 것이다



위의 리번버튼의 크릭이벤트의 구문을 보면..
쪼끔 의아하게 생각할 것이 있을 것이다

With modFileSys
....
....
....
End With

와 같이 With ~ End With문을 사용하면 간단 할 것을 매번 모듈명을
앞에 붙여서 사용하여야 하나????
모듈시트는 어쩔수 없이 그런 녀석이다..
표현식에는 모듈명을 사용할 수 없는 것이다
그럼 방법이 없을까????

그래서 VB에서 제공하는 것이 무엇인지를 알아야 할 것이다

어떤 편리한 무엇이 있는지 보자!!
많이 사용하지 않은 분들에게는 뭔가 여전히 좀 껄끄러운
크래스모듈이 자연스럽게 필요해지고..
모듈시트는 어떤곳에 사용하고 크래스모듈은 어떤 것에 사용되는지
알게 된다
하나도 껄끄러울 것이 없다
크래스모듈에 위의 일반모듈의 것을 잡아 넣고
그냥 크래스모듈을 개체선언만 하면 되는 것이다
아하...별것 아니고 편리한 것이구나...!!!
라는 것을 알게 된다면 엄청난 소득이다

Class모듈을 하나 삽입하시고
이름을 clsFileSys라고 지으시고
크래스모듈내에 모듈시트내의 것을 모두 복사하여
옮긴다

아래와 같이..

Imports System.IO Public Class clsFileSys Public SHT_FILE_SYS As String = "FileSystem" Public shtFileSys As Excel.Worksheet Public Sub ListDriverNames(ByVal oSht As Excel.Worksheet) Dim iNextDrive As Integer = 0 With oSht.Range("B3") For Each oX As DriveInfo In DriveInfo.GetDrives .Offset(iNextDrive).Value = oX.Name iNextDrive += 1 Next End With End Sub Public Function IsSheetExist(ByVal sShtName As String) As Boolean Dim oSht As Excel.Worksheet = Nothing Try oSht = Globals.ThisAddIn.Application.Worksheets(sShtName) Catch ex As Exception Return False Finally If Not IsNothing(oSht) Then oSht.Cells.Clear() End If shtFileSys = oSht End Try Return True End Function Public Sub CreateSheet(ByVal sShtName As String) shtFileSys = Globals.ThisAddIn.Application.Worksheets.Add With shtFileSys.Cells .Font.Size = 11 .Font.Name = "맑은 고딕" .Parent.name = sShtName End With Globals.ThisAddIn.Application.ActiveWindow.DisplayGridlines = False End Sub End Class

위에서는 System.IO NameSpace 를 선언부에 Import시켜주었다
마찬가지지만 이렇게 해주는 것이 자판두들기는 시간을 절약하겠지

그리고 이것을 사용할때 위의 크래스모듈을 개체로 생성만 시키면
마음대로 With ~ End With 문을 사용할수 있다

위와 같이 하여 시트상에 사용하는 컴퓨터의 드라이브명을 뿌렸고
이제 이 드라이브명을 다블크릭하면 해당 드라이브상의 폴더명을
모두 뿌리게 해보자



엑셀프로그래밍을 시작하여 VB.Net으로 넘어오시는 분들은 거저먹는 것이고
VB.Net을 하다가 엑셀프로그래밍을 하시는 분들은 눈만 껌뻑거려야 되는 순간이다
워크시트를 더블크릭하면 어떤 이벤트가 발생하지???여기에서 부터 막힌다
그러나 엑셀부터시작한 분들은 SheetBeforeDoubleClick이벤트프로시져라는 것을 안다
실은 엑셀프로그래밍을 했었어도 크래스모듈을 삽입하고
Application레벨의 이벤트를 다루어 본 적이 없다면 엑셀에서 왔어도 헷갈릴것이다
엑셀의 이벤트는 워크시트레벨에서의 이벤트
통합문서레벨에서의 이벤트, 한 단계 더 높이 올라가서
Application레벨에서의 이벤트(엑셀VBA편집기에서도 크래스모듈을 삽입하고 하여야 사용)
를 VSTO의 엑셀 Add-in에서는 [Application레벨이벤트]에서 모든 것을 콘트롤하게 된다
엑셀프로그래밍에서 우노가 공연히 크래스모듈을 사용하세요..사용하세요..
하였던 것이 아니다
이런 좀더 쎄련된 소루션을 만들때 핵심적으로 필요하게 되는 것이라서
그런 것이다..감각을 잃지 마시라는 의미에서!!
아무튼..아래의 그림과 같이 SheetBeforDoubleClick이벤트프로시져를 찾아서
이곳에 원하는 작업내용을 작성하면 더블크릭할때마다 이 놈이 실행되는 것



Try~Catch문을 아래와 같이 항상 잘 활용하도록 하여야 하는 것이 좋은 습관이다..
왜냐면 Add-in단위에서의 에러는 사용자의 여러개의 통합문서상에서도
문제가 생기게 하는 치명적일수 있는 것이니까..
Application레벨상의 소루션이라는 점 잊지 말아야 한다
Event를 다룰때의 치명적으로 중요한 점들이다...


아래의 그림과 같이 계속 홀더를 크릭하면 하위 홀더가 열리고
해당 홀더의 화일목록도 같이 갖여 오는 것을 최종결과물로 해보자
엑셀의 지식과 VB.Net을 조합하는 셈이다




***[LOG-IN]***

System.IO.DriveInfo--------------------------------화일시스템정보개체
System.IO.DriveInfo.GetDrives----------------------화일시스템내의 드라이브정보
System.IO.DriveInfo.GetDirectories-----------------화일시스템내의 홀더정보
System.IO.DriveInfo.GetDirectories.GetFiles--------홀더내의 화일정보
와 같이 간단하고 파워풀한 개체를 엑셀의 개체들과 적절히
조합하여 재미있게 만들어 보았다
엑셀시트의 범위개체들이 없는 다른 인터페이스, 윈도우폼이나
WPF폼등을 사용하면 TreeView나 ListBox같은 콘트롤 같은데 잡아넣어야하는
피곤한 작업을 하지만 엑셀시트는 창의적인 작업을 마음대로
하기 좋은 놀이터이다..
엑셀은 역시 좋다!!