PROGRAMMING WORKSHOP

.Net FrameWork,VB.Net |DataTable,DataGridView,LINQ

BindingSource를 통하여 휠터를 더 다양하게

RunTime으로 컨트롤 붙이고 좀더 많은 조건으로 휠터링하기

지난 화일에서 날자만 사용하여 BindingSource의 휠터기능을 활용하였습니다
이번에는 데이타테이블의 모든 휠드를 조건을 주어 보도록 해볼까요
조건을 주려면, 해당휠트의 어떤 조건값을 줄것인지 사용자가
선택하기 편안한 콘트롤을 사용하는 것이 좋을 것입니다
이때 컨트롤의 대상이 될 만한것이 CheckBox도 있을 것이지만
아이템이 많으면 조잡해질수 있으니,
아래의 그림같이 ListBox콘트롤을 사용하도록 해보도록 합니다



Sub addMoreFilterCriteriaControls()
	Dim oGroup As GroupBox
	Dim iNext As Integer = 0
	Dim iGap As Integer = 6
	Dim oListBox As ListBox
	Dim iStartX As Integer = oCalEnd.Left - 50
	Dim iStartY As Integer = oCalEnd.Top + oCalEnd.Height + iGap

	''그룹상자 3개와 그룹상자안에 목록상자를 하나씩 만든다
	For Each sFld As String In {"지역", "영업사원", "품목"}
		Dim sFldName As String = sFld

		'' LINQ 활용, 지역휠드, 유일한 값만 모으기..
		'' 순환변수(sFld)로 LINQ 구문에 사용할수 없다
		'' 그래서 지역변수(sFldName)에 담아서 전달한다
		
		''LINQ로 테이블에서 해당목록상자에 담을 해당휠드의 유일한 아이템을 얻어내어
		''집합체에 담는다
		''아래의 구문은
		''테이블을 Enumerable타입(LINQ언어를 사용할수 있는 형식의 데이타로 변환 oTable.AsEnumerable)하여 
		''어떤 휠드(sFldName)에서 유일한 값(Distinct)을 찾아낸 결과를
		''결과가 Object타입일수도 있으니까..안전하게 Ctype(Q(sFldName),String) 문자열로 변환하여
		''모두 가져와 (Select) 집합체(IEnumerbel(Of String)에 담는다
			
		Dim oList As IEnumerable(Of String) = From Q In oTable.AsEnumerable
				Select CType(Q(sFldName), String) Distinct

		oGroup = New GroupBox With {.Left = iStartX + iNext * (110 + iGap), .Text = sFld & " 선택", _
				.Top = iStartY, .Height = 100, .Width = 110}

		oListBox = New ListBox With {.Top = iGap * 2, .Left = iGap, .Width = 100, .Height = 90, _
				.SelectionMode = SelectionMode.MultiSimple, .Name = "lst_" & sFld}

		

		''아래와 같이 하여도 되지만, 위와 같이 하는 것이 간결하겠지요////////////////////////////
		'oGroup = New GroupBox

		'oGroup.Left = iStartX + iNext * (110 + iGap) ' oCalEnd.Left - 50
		'oGroup.Text = sFld & " 선택"
		'oGroup.Top = iStartY ' oCalEnd.Top + oCalEnd.Height + iGap
		'oGroup.Height = 110
		'oGroup.Width = 110

		'oListBox = New ListBox
		'oListBox.Top = iGap * 2
		'oListBox.Left = iGap
		'oListBox.Width = 100
		'oListBox.Height = 90
		'oListBox.SelectionMode = SelectionMode.MultiSimple
		'oListBox.Name = sFld
		
		''위의 LINQ에서 만든 집합체를 목록상자의 아이템으로 담는다
		For Each sX In oList
			oListBox.Items.Add(sX)
		Next
		oGroup.Controls.Add(oListBox)
		Me.Controls.Add(oGroup)
		iNext += 1
	Next
End Sub

LINQ가 없으면 테이블을 행별로 순환하면서 해당휥드의 유일한 값을
하나,하나 수집하여야 하겠지만,LINQ가 숙달되면, 그냥 말하듯이 두어줄 적어주면 된다
물론 LINQ가 숙달되지 않아도 순환하면서 처리해도 상관없지만..
새로운 것은 챙겨서 자신의 것으로 만드는 것이 좋을 것이고, 이 강좌의 목적이 새로운 것을
익숙하시도록 하기 위함이니까..

위와 같이 하면 그림과 같이 3개ㅢ 그룹상자와 목록상자가 만들어지고
테이블에서 원하는 조건으로 주고 휠터를 하면 되는 지능을 심으면 된다
지난 페이지에서 휠터를 위한 날짜의 조건식을 문자열로 주었던 것을
확장하면 된다
각,목록상자에서 사용자가 선택한 아이템을 조건으로 주기 위한 조건식..
VBA에서 조건식은 이미 충실히 마스터들 하였으니 별문제가 없을 것이지만
BindingSource개에의 Filter 속성에 문자열로 엮어서 전달하여야
하는 점...
결국은 조건식에 능숙하고
문자열정보의 작성에 능숙하여야 한다는 이야기다


''각 목록상자를 순환하면서 
''선택된 아이템을 읽어서 문자열로 조립힌다
	For Each sX As String In {"지역", "영업사원", "품목"}
		oListBox = Me.Controls.Find("lst_" & sX, True)(0)
		If oListBox.SelectedItems.Count > 0 Then
			sFilter &= "("
			For Each sItem As String In oListBox.SelectedItems
				sFilter &= sX & "='" & sItem & "' OR "
			Next
			sFilter = sFilter.Substring(0, sFilter.Length - " OR ".Length) & ") AND "
		End If

	Next

	sFilter &= "(주문일자>=#" & datStart & "# AND 주문일자<=#" & datEnd & "#)"

''sFilter변수에 
''순환하면서 작성된 문자열로 된 조건식을 BindingSource개체의 Filter속성에 전달한다
	oBS.Filter = sFilter

휠터버튼을 크릭할때마다 그림과 같이 작성된 조건식을 메시지박스에 띄게 하였으니
관찰하시면서 좋겠다..



BindingSource에 연결된 모든 콘트롤을 휠터가 되는 것은 당연하고..
참 지능이 많은 개체들이다



***[LOG-IN]***

DataTable.Compute(..)

휠터를 하게 되면..
휠터된 내용을 합계를 내던..
평균을 내던..요약된 값을 뽑아 보고 싶어지는 것은 당연한 순서
위의 화일에서 휠터된 내용의 합계를 보이도록 하기 위하여
Label콘트롤을 하나더 추가하고..
DataGridView컨트롤이 보여주고 있는 테이블의 내용을
(휠터가 되었던, 휠터가 되지 않았던..)
요약한 값을 보여주도록 하자



텍스트문서의 데이타원본상에 합계열이 없고 단가와 수량열만 있다
그래서 DataTable을 만들때, 단가와 수량을 곱한 합계열을 하나더 추가하는 점을
잘 살펴보시고...
왜 합계열을 만들어야 하냐면..
DataTable의 Compute 메소드의 요약함수가 포함된 문자열 표현식에
Sum(단가*수량) 이라는 표현(있을법한데...),
두개의 휠드를 곱하는 것은 유효한 표현이 아니기때문
DataTable에 합계열을 폼이 초기화될때 만든후
Compute메소드의 표현식을
Sum(합계) 와 같이 하나의 휠드만 사용하도록 하기 위함
휠터는 BindingSource의 Filter속성을 사용하고
요약값은 DataTable의 Compute 메소드를 사용하였다
첨부화일에 설명을 달아 놓았습니다

***[LOG-IN]***

휠터된 내용 엑셀로 보내기..

엑셀개체를 만들어서
윈도우폼상의 휠터된 내용을 엑셀로 보내는 작업을 해보자
엑셀작업을 하려면 엑셀라이브러리를 참조시킨다는 것
자꾸 해보다 보면 습관이 되어 모든 것이 자연스러워진다
버튼 하나 Runtime으로 생성하여 붙이고




'' 엑셀라이브러리를 참조후 아래와 같이 Imports 시킨다
'' 이때 XL 이라는 별명으로 항상 쉽게 참조할수 있게 한다
Imports XL = Microsoft.Office.Interop.Excel

Public Class Form1
'' WithEvents키워드를 사용하여 전역변수로 콘트롤을 선언하면
    WithEvents oToXLButton As Button
''아래의 해당콘트롤의 이벤트프로시져를 사용할수 있다, 간단한 경우는
'' AddHandler oToXLButton.Click, AddressOf....... 를 사용하지 않아도 된다

    Private Sub oToXLButton_Click(sender As Object, e As System.EventArgs) Handles oToXLButton.Click

        Dim oApp As XL.Application = New XL.Application
        Dim oBook As XL.Workbook = oApp.Workbooks.Add
        Dim oSheet As XL.Worksheet = oBook.Worksheets(1)

        '' WindowForm이 엑셀위에 항상 위치하도록...//////
        Me.TopMost = True
        ''.////////////////////////////////////////////
        Try
            Dim iRow As Integer = 1
            oApp.Visible = True
            Dim iCol As Integer = oDGV.Columns.Count

            With oSheet
''열머리 휠드명은 DataGridView의 Column의 Name값으로 얻을수 있다
                For iY As Integer = 0 To iCol - 1
                    .Range("A" & iRow).Offset(, iY).Value = oDGV.Columns(iY).Name
                Next
''행방향 순환..DataGridView의 Rows집합체를 각각의 행인 DataGridViewRow 개체로 순환한다				
                For Each oRow As DataGridViewRow In oDGV.Rows
                    iRow += 1
''하나의 행에서 열방향으로 순환하면서 해당 DataGridViewRow의 Cells집합체의 각각의 Cell값을 얻어서 넣는다					
                    For iY As Integer = 0 To iCol - 1
                        .Range("A" & iRow).Offset(, iY).Value = oRow.Cells(iY).Value
                    Next
                Next
                .UsedRange.Columns.AutoFit()
            End With
        Catch ex As Exception
        End Try

    End Sub
	...
	...
	...
End Class

아주 고전적 방법으로 행순환, 열순환하면서 값을 옮겼다
실은 다른곳에서 엑셀에 값을 옮길때는 배열등으로 한꺼번에 옮기는 것 보다는
하나,하나 옮기는 것이 좋다
이유는 배열등으로 옮기면 데이타타입을 하나하나의 열에 맞추어서 전달하지 못하니까..
나중에 이 데이타를 정상적으로 변환하는 것이 시간을 더 소비할수도 있다

아래의 화일을 보시도록...

***[LOG-IN]***

한코너로 계속 가면 지루하니, 코너를 바꿔서
TreeView 콘트롤을 중심으로 하여 지금까지 하였던
DataTable,DataGridView그리고 폼의 다른 컨트롤들을
다시 다른 시각에서 복습하도록 하자
VB.Net(.NetFrameWork)은 어느 것을 딱 떼어서 설명하기가 곤란하다

모든 개체들이 복잡하게(실은 원리를 알면 간단하지만) 연관성을 갖고 있기 때문에..
방법은 각개체를 줌심으로 반복하여 다른 개체들에 대한 이야기를 해나가게 되니까..
반복하면 모든 것이 여러분들의 것이 자연스럽게 될 것이다