PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net | DataSet,DataTable

.Net FrameWork의 도구를 사용하여 분석하자..

엑셀에서의 분석기능을 사용하지 않고
.Net FrameWork의 다양한 정보를 다루는 도구를 사용하여 만들고 싶은대로
엑셀에 담겨있는 정보를 처리하는 일을 해보자
우리가 궁극적으로 사용하려는 도구는 LINQ, Extension Method,Lambda Expression등이지만
DataTable이라는 개체도 나름대로 분석할수 있는 기능을 갖고 있다
DataTable에 있는 기능들을 사용해 보자
그렇게 하면서 Windows의 컨트롤들을 런타임으로 생성해보면서 다양한 경험을 해보도록 하자
우선 지난 화일에서 Windows폼에 그냥 덜런 DataGridView 콘트롤하나만 잡아 넣었다
뭔가 콘트롤할수 있는 다른 컨트롤을 잡아 넣을 공간을 확보해보자
아래와 같이 하나 만들어보자



Windows의 콘트롤은 크게 3가지가 있다
하나는 다른 콘트롤들을 담아서 배치를 편하게 해주는 Container역할을 해주는 컨트롤이고
위에서 사용하는 경험을 갖게 하기 위한 것이
TableLayoutPanel콘트롤이고
다른 하나는
FlowLayoutPanel콘트롤이다
TableLayOutPanel콘트롤은 행과 열로 구분이 되어 전체적인
레이아웃을 편하게 해주고
행과열이 교차되는 하나의 셀속에는 다른 콘트롤을 하나밖에 넣을수 없다
그리고 FlowLayOutPanel콘트롤은
행방향이나 열방향으로 만들어 넣는 모든 컨트롤이 자동으로 자리를 잡는다
그래서 번거롭게 일일이 내용물이 되는 콘트롤의 위치를 지정하는 번거로운작업을
생략할수 있다

또 다른 종류의 콘트롤은 데이타의 집합체를 담아주는 콘트롤로서
위에서 사용한 콘트롤은
DataGridView,ComboBox가 데이타를 집합적으로 갖고 있고
데이타를 집합적으로 사용하는 콘트롤은 DataSource속성을 갖고 있다

나머지는 Button같은 일반적인 이벤트를 받아서 일을 열심히 해주는
사용자가 쉽게 보고 크릭하는 Interface용 콘트롤이다

콘테이너 콘트롤의 편리한 것은
폰트의 속성등을 콘테이너 콘트롤에서 해주면
나머지 구성하고 있는 콘트롤에도 모두 영향을 주기 때문에 코딩작업이 줄어든다

이 화일에서 코딩의 중요한 부분은..
콤보상자에 테이블의 어떤 열의 유일한 값만 골라서 넣어주는 부분을
전통적인 방법으로 한다면
아래와 같이 순환문을 열심히 돌려서 만들수 있다

Dim oList As New List(Of String)
For Each oRow As DataRow In oTable.Rows
	If Not oList.Contains(oRow.Item(1)) Then
		oList.Add(oRow.Item(1))
	End If
Next
oCombo1.DataSource = oList
  

하지만 .NetFrame work의 새로운 자원들을 활용한다면 LINQ를 사용한다
아래와 같이

 Dim sQ = From Q In oTable.AsEnumerable
               Select Q(1) Distinct

 oCombo1.DataSource = sQ.ToArray
 

어라 순환도 하지 않으면서 어떻게 값을 찾아서 집합체에 넣는 것이지??!!
순환문을 작성하지 않을뿐, LINQ라는 엔진이 스스로 뒤에서
순환을 하는 작업을 대신 해주는 것
개발자는 어떻게 어떤 값을 주욱 찾아서 집합체에 넣어라!!
라는 한줄의 명령을 해주면 되는 것이고, 이것이 LINQ 언어이다


            '' 윈도우폼은 많은 콘테이너 컨트롤을 갖고 있다
            '' container control은 직접 하는 일은 없지만, 다른 콘트롤을
            '' 보기좋게 혹은 기능적으로 배치하기 좋게 하는 레이아웃팅 콘트롤이다
            '' 가장 많이 사용하는 TableLayoutPanel콘트롤을 하나 생성하여 붙이자..
            '' TableLayOutPanel의 행은 2개 열은 한개짜리로 만든다
            '' 그리고 행의 폭은 첫행은 80%, 두번째 행은 20%로 폼의 사이즈가 변경되어도
            '' 항상 같은 비율로 크기가 조정된다
            Dim oPanel As New Windows.Forms.TableLayoutPanel
            '' Dock속성은 부모(여기에서는 폼전체)에게 어떻게 배치될것인지를 결정한다
            '' DockStyle.Fill로 하면 폼을 마우스로 크기를 조정하면 자동으로
            '' TableLayoutPanel도 연동되어 움직인다

            oPanel.Dock = DockStyle.Fill
            oPanel.RowCount = 2
            oPanel.ColumnCount = 1
            '' TableLayoutPanel콘트롤은 열과 행의 갯수를 원하는대로
            '' 만들어 넣을수 있다
            '' 이때 RowStyles나 ColumnStyles에 행과 열을 원하는 만큼
            '' 추가 시킨다
            '' 여기에서는 열은 1개 행은 2개 이므로
            '' 행을 두개 추가한다..추가하는 요령은 아래와 같고..
            oPanel.RowStyles.Add(New RowStyle(SizeType.Percent, 80%))
            oPanel.RowStyles.Add(New RowStyle(SizeType.Percent, 20%))
            oPanel.Dock = DockStyle.Fill

            '' 전체 콘테이너 콘트롤에 서식을 해주면 
            '' 나머지 자식 콘트롤에도 영향을 주니까, 가장 상위콘테이너콘트롤에서 해주면
            '' 코딩이 간단하다
            oPanel.Font = New Font("맑은 고딕", 9)

            Me.Controls.Add(oPanel)

            '' 버튼과 콤보상자를 담을 콘테이너 콘트롤을 하나만들어서
            '' 위의 TableLayoutPanel콘트롤의 두번째 행에 추가한다
            '' FlowLayoutPanel콘트롤은 자식 콘트롤의 위치를 지정하는 번거로움없이
            '' 자동으로 추가하는대로 자리를 잡는다
            Dim oFlow As New Windows.Forms.FlowLayoutPanel
            '' 자식콘트롤들이 자동으로 왼쪽에서 오른쪽으로 차례대로 배치되게 한다
            oFlow.FlowDirection = FlowDirection.LeftToRight
            '' FlowLayout을 처음에 만든 전체 콘테이너 콘트롤인 TableLayoutPanel의 Controls집합체에 추가한다
            '' 이때 TableLayoutPanel은 행과 열로 구성이 되어 있어서
            '' 행위치와 열위치를 지정해주어야 한다
            '' 
            oPanel.Controls.Add(oFlow, 0, 1)
            oFlow.Dock = DockStyle.Fill


            '' DataTable을 표현할 DataGridView콘트롤을 하나 만들어서
            '' 위의 TableLayoutPanel콘트롤의 첫째 행에 넣는다
            '' 위에서 엑셀정보를 가져다가 DataTable개체에 넣고
            '' 이 DataTable을 DataGridView의 DataSource로 사용한다
            Dim oDGV As New Windows.Forms.DataGridView
            oDGV.DataSource = oTable
            oDGV.Dock = DockStyle.Fill
            oDGV.AllowUserToAddRows = False
            oDGV.Font = New Font("맑은 고딕", 9)
            oPanel.Controls.Add(oDGV, 0, 0)

            '' 콤보상자하나를 생성한다
            '' 이 콤보상자의 정보는 DataTable의 두번째열의 내용을
            '' 유일한 값만 골라서 채운다
            '' 이때 LINQ 언어를 사용한다
            Dim oCombo1 As New Windows.Forms.ComboBox

            '' 아래 두개를 비교하세요./////////////
            ''//////////////////////LINQ를 사용하는 경우////////////
            '' LINQ를 사용하여, DataTable의 2번째열의 내용을 유일한 값만 골라내어
            '' 집합체를 만든다..
            Dim sQ = From Q In oTable.AsEnumerable
                    Select Q(1) Distinct


            '' 이집합체는 ComboBox의 DataSource로 쓸수 없다
            '' 그래서 배열로 변환하여 전달하면 된다
            oCombo1.DataSource = sQ.ToArray
            '/////////////////////////////////////////////////////

            ''//////////////////기존의 순환문을 돌리는 경우/////////////////
            'Dim oList As New List(Of String)
            'For Each oRow As DataRow In oTable.Rows
            '    If Not oList.Contains(oRow.Item(1)) Then
            '        oList.Add(oRow.Item(1))
            '    End If
            'Next
            'oCombo1.DataSource = oList
            ''//////////////////////////////////////////

            '' 콤보상자콘트롤을 FlowLayoutPanel의 Controls집합체에 추가하고
            oFlow.Controls.Add(oCombo1)

            '' 콤보상자 두번째 것도 같은 요령이다, 이것은 DataTable의 3번째열의 내용을
            '' 유일한 값(Distinct)을 얻어서 연결한다
            Dim oCombo2 As New Windows.Forms.ComboBox

            '' 역시 위의 경우와 마찬가지로 전통적인 순환방법과 LINQ처리 방법의 비교
            '' 아래의 sZ는 어떤 타입인지 명시적으로 표현하지 않은 것은
            '' Dim sZ As IEnumerable(Of Object) 의 As 이하를 생략한 것이다

            Dim sZ = From Q In oTable.AsEnumerable
                   Select Q(2) Distinct
           
            oCombo2.DataSource = sZ.ToArray

            'oList = New List(Of String)
            'For Each oRow As DataRow In oTable.Rows
            '    If Not oList.Contains(oRow.Item(2)) Then
            '        oList.Add(oRow.Item(2))
            '    End If
            'Next
            'oCombo2.DataSource = oList
            ''//////////////////////////////////////////

            ''두번째콤보상자도 역시 콘테이너 콘트롤인 FlowLayoutPanel의 Controls집합체에 넣고
            oFlow.Controls.Add(oCombo2)
          

            '' 버튼개체를 하나 만든다

            Dim oBtn As New Windows.Forms.Button
            oBtn.Text = "휠터"
            oBtn.AutoSize = True
            oBtn.BackColor = Windows.Forms.Button.DefaultBackColor

            '' AddHandler는 버튼의 이벤트에 어떤 작업을 할지 프로시져를 포인팅한다..
            '' 여기에서는 그냥 Inline으로 표현했다
            '' AddressOf 대신에 아래와 같이 Inline으로 표현하는 것을 Lambda expression 이라고 한다
            '' 이것은 나중에 자세히 또 나올 것이다
            AddHandler oBtn.Click, New EventHandler(Sub() MsgBox("현재 화일에서는 콤보상자에 정보를 채우는 것을" & vbNewLine & _
                                                                 "LINQ를 사용함과 콘트롤의 활용을 보시고 다음 작업을 다음화일에서..."))

            '' 역시 생성된 버튼도 FlowLayoutPanel의 Controls집합체에 추가하고
            oFlow.Controls.Add(oBtn)

            '' FlowLayoutPanel의 편리한 점은
            '' 그냥 콘트롤을 추가하는대로 차례대로 위치를 자동으로 잡아준다
            '' 번거롭게 일일이 위치를 계산하지 않아도 되는 셈..
            
            '' 윈도우폼의 폭을 정해주고
            Me.Width = 900

***[LOG-IN]***