PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net | DataGridView,Excel,TextFile,Multi Projects

여러개의 프로젝트를 하나의 소루션에...

엑셀프로그래밍을 할때 VBA편집기는 프로젝트창이 하나밖에 없다
즉 하나의 프로젝트로 구성되는 소루션인 것이다
하지만 VB.Net 환경은 여러개의 프로젝트를 하나의 소루션으로
만든다
VB.Net은 하나의 프로젝트로 하나의 소루션이 되기도 하고
여러개의 프로젝트로 하나의 소루션이 되기도 한다
즉 비쥬얼스튜디오은 여러개의 프로젝트를 하나의 소루션으로 만든다
예를 들어서 엑셀의 VBA에 사용하려고 VB.Net으로 dll화일을 하나 만들었다고
치고, 이것을 우선 만들어 보자

엑셀이나 워드등 COM소루션의 VBA편집기에서 참조할수 있는 dll화일만들어보기

우선 만들어서 엑셀에 사용해 보고
이 프로젝트를 앞페이지에서 만든 소루션에 포함시켜보도록 하자
엑셀에서 사용할 dll화일이라는 것이 긴가민가 할것이다
하지만,종종 vba에서 자주 하였던 것을
기억할 것이다
아래의 그림과 같이 VBA편집기의 도구/참조메뉴에서
외부라이브러리를 참조하여 vba작업에 더욱 파워를 갖게 하는 것



특히 DAO,ADO,FileSystemObject 등을 사용할때
종종 하였었다
이것을 직접 VB.Net으로 만들어서 사용해 보자
우선 dll화일(ActiveX)화일을 만들려면 Visual Studio를 관리자모드로 열어야 한다



왜냐면 dll화일은 사용자컴퓨터의 Registery에 등록이 되기때문에
이곳의 등록은 안전을 위하여 관리자모드로 하게 되어 있다
그리고 새프로젝트를 템프릿창에서 Class 라이브러리 하나를 선택한다


화일명을 적절히 넣어주고, 여기에서는 UNOLibrary라고 주었다

그리고 Project속성창에서
Application탭의 [Assembly Information] 버튼을 크릭하여 나타나는 창에서
[Make Assembly COM Visible]을 체크해줘야 하고
Complile 탭에서 [Register COM interop] 을 체크해줘야 한다



Registery에 등록이 되기때문에
엑셀,워드등 COM 시스템의 VBA편집기의 도구/참조라이브러리에 나타나게 된다

그리고 Class1.vb명을 식별하기 좋은 이름으로 바꿔주고 여기에서는 myExcel.vb
그리고 Reference(라이브러리참조)를 한다
엑셀을 다루려고 하니, 엑셀 인터롭을 하나 참조시켜야 하는 것은 숙달되었을 것이고..



그리고 크래스모듈에 아래와 같이 간단하게 메소드를 하나 작성하자


'' 엑셀인터롭라이브러리를 imports시키고
Imports XL = Microsoft.Office.Interop.Excel

Public Class myExcel
    '' 간단한 행10개 열10개의 범위의 각각의 셀에
    '' 11에서99 사이의 난수를 발생시켜 작성하는 메소드를 하나 만들자
    Public Sub writeRandomNumber(shtX As XL.Worksheet)
        Dim oRandom As New Random

        For iX As Integer = 1 To 10
            For iY As Integer = 1 To 10
                shtX.Cells(iX, iY).value = oRandom.Next(11, 99)
            Next
        Next
    End Sub

End Class

그리고 빌드(build)를 하면 성공적으로 빌드가 된다
dll화일이 만들어지고
여러분의 시스템의 Registery에 dll이 등록되었다
이제 엑셀의 VBA창에서 이 dll화일을 참조하는지 보기 위하여 엑셀을 열고
VBA창으로 가서 도구/참조를 하여 참조대화상자에서 UNOLibrary를 찾아 보면..
잘 나타난다..



그런데..어라 이상하다..



아래와 같이 수정하고 다시..

Imports XL = Microsoft.Office.Interop.Excel
''InteropServices는 VB.Net에서 확장된 COM개체와의 중간 Interop의 역할을 위한 개체들을 갖고있는 네임스페이스
Imports System.Runtime.InteropServices
''크래스 속성(Attribute)를 하나 붙여준다
''이것은 VB.Net dll을 COM dll로 사용하도록 하라는 정보를 주는 것
<ClassInterface(ClassInterfaceType.AutoDual)>
Public Class myExcel
    '' 간단한 행10개 열10개의 범위의 각각의 셀에
    '' 11에서99 사이의 난수를 발생시켜 작성하는 메소드를 하나 만들자
    Public Sub writeRandomNumber(shtX As XL.Worksheet)
        Dim oRandom As New Random

        For iX As Integer = 1 To 10
            For iY As Integer = 1 To 10
                shtX.Cells(iX, iY).value = oRandom.Next(11, 99)
            Next
        Next
    End Sub

End Class

위와 같이 크래스의 속성을 붙여준후 빌드를 하여
엑셀의 VBA에서 작성하면 아래와 같이 개체의 멤버목록이 나타난다



나머지 작성하지 않았는데 나타나는 멤버는
VB.Net의 개체들이 기본적으로 갖고 있는(Default)멤버들이니
그냥 사용하셔도 되고, 무시하셔도 된다

이렇게 COM dll로 만들어서 사용할수 있다고 하는 것의 의미는
VBA로 작성한 코드가 보안이 불안전하여(쉽게 남들이 열어보는..)
감추어 버리고 싶다면, Visual Basic에서 dll을 만들어
응용할수 있다는 이야기
이 프로젝트는 윈도우창이 열리는 것이 아닌 소스코드만 있는 것이라서
자체적으로 실행할수 없다
다른 소루션에서 참조하여 사용하는 프로젝트이다
아래 그림과 같이 Application타입이 Class 타입인것이다



아래 화일을 관리자모드로 여신후(관리자모드가 아니면 에러!!) 빌드시킨후
빌드가 성공적이면, 엑셀을 여시고 엑셀의 VBA 창에서 도구/참조에서
UNOLIbrary를 찾아서 체크한후 아래와 같이 VBA모듈에서 작성하고 실행해보시면
아하...모두 이해가 될 것이다

Sub testUnoLibrary()
Dim oUno As New UNOLibrary.myExcel
On Error Resume Next

oUno.writeRandomNumber ActiveSheet
oUno.ShowWindow
End Sub

만약 엑셀 VBA에서 위의 dll을 참조한 상태에서
위의 프로젝트에서 프로시져등을 추가하거나 수정을 하고
또 다시 빌드를 한다고 하면 에러가 난다는 점도 이해하셔야 한다
왜냐면 레지스터에 등록된 dll을 이미 다른 곳에서 연결하여(참조하여)사용하는데
빌드를 한다면(변경을 한다면) 다른 곳에서 연결이 되어있다는
에러가 당연히 난다는 점..상식적으로 이해하셔야 한다
아래 화일을 열어서 사용할때는 반드시 관리자모드로 여셔야 한다

***[LOG-IN]***

사용자정의 개체를 사용하는 소루션에서 참조하여 사용..

위에서 만든 dll프로젝트를 맨처음 만들었던 소루션화일에서 참조하여
사용하자
앞페이지에서 만든 소루션화일도 [관리자모드]로 열어야 한다
그리고 소루션창에서 소루션명을 오른쪽 마우스로 크릭하여 Add메뉴
그리고 Exist Project메뉴를 선택하면 화일열기창이 열리고 여기에서
앞에서 작성한(다운받으신 UNOLibrary 소루션화일)을 폴더를 찾아서
폴더를 열고 vbproj 확장자의 화일을 선택하면 아래의 그림과 같이
본래의 프로젝트와 더불어 프로젝트가 하나 더 생긴 셈이된다



하나의 소루션화일에 프로젝트가 두개가 생긴 것이다
vb.net 소루션은 하나의 소루션에 여러개의 프로젝트를 만들어서(혹은 기존 프로젝트를 참조)
사용할수 있다는 점

그런데 중요한 것이 또 하나 있다
본래 있던 프로젝트에서 새로 소루션에 추가된 프로젝트의 dll을 참조하지 않으면
허당이다..
어떤 프로젝트이던지 다른 프로젝트의 것을 사용할때는 참조시켜야 한다
같은 소루션속에 있는 프로젝트라고 해도
참조를 시키지 않는다면 아무 상관도 없이 그냥 같은 소루션속에 있는 것이다
참조를 시키지 않는다면, 아무 의미가 없다!!
아래와 같이 참조시킨다



하나의 소루션에 프로젝트를 추가 하기도 하고
외부에 이미 만들어진 프로젝트를 갖여다 사용하기도 한다
소루션에 추가하면 새로운 프로젝트폴더가 소루션폴더에 눈에 보이지만,
위에서 외부의 프로젝트를 가져다 사용하는 것은 해당프로젝트에서 생성되는 dll화일만
참조하는 셈이다..예를 들어서 위에서와 같이 외부 UNOLibriary라는 프로젝트를
추가하여 사용하면서 해당프로젝트에 새로운 프로시져를 추가하면
당초원본 프로젝트의 화일이 변경되는 셈이다
아래의 프로시져를 추가된 프로젝트 UNOLibrary의 myExcel.vb 화일에 아래의
프로시져를 추가하고 빌드하고 실행시켜본후
당초 UNOLibrary 원본으로 가서 보시면 새프로시져가 추가되었음을 볼수 있을 것이다
그러니 소루션에서 외부기존프로젝트를 끌어다가 사용하면 이것은 그 외부프로젝트의 껍데기일뿐
원본은 외부에 있는 셈이다


'' 아래의 프로시져를 추가
'' DataTable개체를 매개변수로 전달받아
'' 엑셀통합문서의 시트에 DataTable의 내용을 옮기는 작업
Public Sub saveDataTableToExcel(oDataTable As DataTable)
	''excel application 개체생성
	Dim oXL As New XL.Application
	''새로운 통합문서를 만들고
	Dim oBook As XL.Workbook = oXL.Workbooks.Add
	'' 작업할 시트를 해당통합문서의 첫째시트로 하여
	Dim oSheet As XL.Worksheet = oBook.Worksheets(1)
	Dim iColSize As Integer = oDataTable.Columns.Count
	Dim iRow As Integer = 1
	Dim iCol As Integer = 1
	'' 매개변수로 전달받은 DataTable의 열을 순환하면서 테이블의 열머리 만들고
	For Each oCol As DataColumn In oDataTable.Columns
		oSheet.Rows(1).cells(iCol).value = oCol.ColumnName
		iCol += 1
	Next
	'' 테이블 열머리를 만들고 
	'' 행별로 순환하면서
	For Each oDataRow As DataRow In oDataTable.Rows
		iRow += 1
		''각각의 행에서 열별로 순환하면서 값을 옮긴다
		For iC As Integer = 0 To iColSize - 1
			'' DataTable의 각행의 각셀은 Item에 접근하여 값을 얻는다
			oSheet.Rows(iRow).cells(iC + 1).value = oDataRow.Item(iC)
		Next
	Next
	''시트명 써주고
	oSheet.Name = "DataTableToXL"
	'' Excel은 버전이 많으니, FileFormat 매개변수에 적절한 상수를 선택하여야 한다
	oBook.SaveAs(Filename:=My.Computer.FileSystem.SpecialDirectories.Desktop & "\myExcelFromVBNet.xlsx",
				 FileFormat:=XL.XlFileFormat.xlOpenXMLWorkbook)
	''통합문서 닫고
	oBook.Close(False)
	''엑셀프로그램 닫는다
	oXL.Quit()

End Sub

앞페이지의 소루션 화일에
위의 UNOLibrary화일을 프로젝트추가하시고,
소루션창에 추가된 내용의 myExcel.vb에 위의 프로시져를 추가하고
실행하셔보시기 바랍니다

***[LOG-IN]***