PROGRAMMING WORKSHOP

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

Filtering - 같은 결과 다양한 방법..

앞페이지에서 DataGridView, ComboBox,Button, Container Control등을
생성하여 엑셀 데이타를 폼에 올려 놓았다
이제 버튼을 좀더 갯수를 추가하여
콥모상자에서 선택한 조건에 맞게 DataGridView에 나타난 정보를
휠터링 해보자
같은 조건의 같은 결과의 작업이지만 방법이 다양하다는 점에 유의해서 보자
아래 그림과 같이 버튼을 크릭할때마다 같은 이벤트프로시져를 사용하여
해당버튼마다 작업방법을 달리 하면서 관찰해보자



위의 작업을 위한 윈도우폼 인터페이스를 만들기 위하여..
순환문을 사용하여 버튼을 5개 생성추가하자
버튼을 5개를 달려고 일일이 작업하면 바보..


  '' 5번 순환하면서 버튼을 5개 달자..
For iX As Integer = 1 To 5
	Dim oBtn As New Windows.Forms.Button
	oBtn.Text = {"휠터-Table.Select", "휠터-DataGridView", "휠터-LINQ", "휠터-Looping", "원래대로.."}(iX - 1)
	oBtn.AutoSize = True
	oBtn.BackColor = Windows.Forms.Button.DefaultBackColor
	oBtn.Name = "btn_" & iX
	oFlow.Controls.Add(oBtn)

	''////////////////////////////////////////////////////////////////////
	'AddHandler oBtn.Click, New EventHandler(Sub() MsgBox("현재 화일에서는 콤보상자에 정보를 채우는 것을" & vbNewLine & _
	'                                                     "LINQ를 사용함과 콘트롤의 활용을 보시고 다음 작업을 다음화일에서..."))


	'' 위의 내용을 아래와 같이 수정한다, 프로시져작업내용이 많으니 이벤트프로시져를 별도로 만드는 것이 좋겠지..
	'AddHandler oBtn.Click, New EventHandler(AddressOf button_click)
	' 위의 것이 정식표현이고 아래가 약식표현이다
	AddHandler oBtn.Click, AddressOf button_click
Next
 

DataGridView콘트롤에서 보여주는 데이타를 휠터링한다는 의미는 무엇일까?
DataGridView콘트롤은 그냥 데이타를 보여주고 있을뿐
실제 Data는 DataTable이라는 개체가 메모리속에 갖고 있다
그러니 DataTable의 원본에서 휠터링을 해야 할 것이다
그런데 실은 DataTable의 원본은 손상되면 안된다
그대로 유지하고 View를 만들어서 휠터된 내용을 DataGridView에 다시 연결해주면 되는 것이다
실은
DataTable.DataSource=DataTable

DataTable.DataSource=DataTable.DefaultView
를 약식으로 표현한 것이다
DefaultView속성은 DataTable의 연결관계를 유지하는 View인 DataView개체를 만들어 주는것
DataTable이 직접 붙는 것이 아니고 DataView가 붙는 것이다
View는 억세스DB에서 Query테이블 같은 것이다
View나 Query테이블은 내용은 없고 원본을 어떻게 가져오는지에 대한
표현식이 숨어 있을 뿐이다
억세스DB에서 쿼리테이블을 이해하셨다면 되는 것
아마도 엑셀에서 PivotTable을 만들때
PivitTable은 단순히 보여주는 창이고
실제 데이타원본은 PivotCache 라는 메모리속의 저장창고에 숨겨져 있는 것이나 마찬가지다
그래서 이 PivotCache 개체에서 다양하게 여러개의 PivotTable을 만들어 내듯이
모든 데이타의 원리가 그런 것..

그런 원리를 알고 휠터링을 하는 표현을 보자
첫번째 버튼..


 ''DataTable개체의  Select 메소드를 활용한다
 '' 즉 원본에서 조건에 맞는 행만 뽑아서, DataRow개체(엑셀의 행에 해당한다)를 담는 배열을 만들어서
 '' 왜냐면 Select메소드의 Return값의 타입이 DataRow이고 배열로 반환하니까..
 '' 항상 값을 받는 변수의 형식은 사용하는 함수즉 메소드의 결과값의 형식과 맞아야 하는 것은 상식이다!!!
 '' 조건식..어떤 언어이던 논리를 다루는 언어, 즉 컴퓨터언어는 논리식과 논리값이 생명이다
 '' 그러니 이 논리식 감각이 없으면 Excel과 VBA에서 확실하게 자리를 잡고 오시면 된다
 '' 그런다면 아래의 한줄의 표현식(여기에서 문자열로 전달한다..)은 그냥 당연히 이해가 된다
Dim oRows() As DataRow = oTable.Select(oTable.Columns(3).ColumnName & "='" & sCriteria1 & "' AND " & oTable.Columns(2).ColumnName & "='" & sCriteria2 & "'")
'' oRows변수에 들어온 DataRow 개체 갯수를 확인하여 0이면 해당행이 하나도 없는 것..
'' 0보다 크다면...이 결과를 DataGridView의 DataSource에 주면 된다
'' 그런데 배열을 직접전달할수는 없다
'' 왜냐면 DataSource속성이 받는 값은 DataTable의 View버전인 DataView를 받아야 하니까.
'' 배열의 속성중에 CopyToDataTable이라는 것이 있다
'' 물론 이 배열은 VBA의 배열과는 다른 .NetFrame Work가 제공하는 배열
'' 다양한 속성과 메소드가 있다
'' 그중의 하나가 CopyToDataTable 인것이고 DataTable이 DataSource에 속성에 전달된다고 
'' 하는 것은 CopyToDataTable에서 배열을 DataTable로 변환한 것의 DefaultView(즉 DataView)가
'' 전달되는 것
'' 아무것도 없을때는 DataGridView의 DataSource를 Nothing으로 지워버리고..
If oRows.Count > 0 Then
	oDGV.DataSource = oRows.CopyToDataTable
Else
	oDGV.DataSource = Nothing
End If
 

위의 것은 DataTable이 제공하는 파워를 활용한 것이고..
두번째 버튼에서는
DataTable이 아니고, DataView라는 개체에는 뭔 기능이 없을까???
물론 이놈도 뭔가 갖고 있다
아래와 같이 하면..


'' DataView개체타입 변수를 하나 만들고
'' DataView를 DataTable개체에서 만들어내는 것
Dim oDataView As DataView
'' New DataView(....)라는 개체 생성프로시져에서 직접 만들어내는 것
'' 첫째매개변수는 DataTabe, 
'' 두번째매개변수는 조건 표현식...
'' 표현식의 내용은 위의 첫째버튼과 같은것이고..
'' 세번째는 어떤열을 정렬을 할까라는 행이름으로 오름차,내림자를 전달하고
'' 네번째는 DataViewRowState.CurrentRows 는 DataTable에 행이 추가되던 ,삭제되던
'' 현재의 상태를 기준으로 한다는 매개변수, Default값은 CurrentRows이다
'' 이렇게 하여 DataView를 만들어내고
'' 이것을 DataGridView의 DataSource 속성에 주면된다
''
oDataView = New DataView(oTable, oTable.Columns(3).ColumnName & " = '" & sCriteria1 & "' AND " & oTable.Columns(2).ColumnName & "= '" & sCriteria2 & "'", oTable.Columns(0).ColumnName & " DESC", DataViewRowState.CurrentRows)
If oDataView.Count > 0 Then
	oDGV.DataSource = oDataView
Else
	oDGV.DataSource = Nothing
End If

세번째가 가장 자주 사용하여야 할 LINQ 언어로 작성하기..


'' LINQ를 하려면 LINQ언어가 작업할수 있는 타입이어야 한다
'' DataTable개체를 Enumerable개체로 바꾸기 위하여 DataTable의 AsEnumerable 속성을 사용하면 된다
'' 아래의 내용을 말로 풀자면
'' [In] ---여러행을고 구성된 테이블의 집합체 속에 있는 모든 행을...
'' [From] Q --여기에서 Q는 LINQ내의 변수라고 보시면 된다
'' 이 변수에 순환되는 행을 잡아 넣는 것이다.. 그리고 해당순환된 행을 조건식으로 따지면 된다
'' [Where] ---- 이것이 순환된 행 Q변수를 조건식으로 판단하는 것..조건식은 VBA에서 항상 하는 조건식이다..
'' [Select] Q -- 이것은 조건에 맞는 행즉 Q 행을 선택하여 oQ라는 집합체에 줄줄이 담는 것이다
'' 키워드 몇개 챙기면 집합체에서 찾고 싶은 것을 마음대로 찾을수 있고
'' 코딩도 뭔가 있어 뵈이지 않는가??!!!
'' DB에서 SQL 언어를 사용하였다면, 아하..별것아니네..하실수 있는 것이 LINQ..
'' 앞으로 주로 이것을 사용하게 될 것이니, 숙달시키셔서 광빨잡으시기를...

 Dim oQ = From Q In oTable.AsEnumerable
		Where Q.Item(3) = sCriteria1 And Q.Item(2) = sCriteria2
		Select Q
		If oQ.Count > 0 Then
			oDGV.DataSource = oQ.CopyToDataTable
		Else
			oDGV.DataSource = Nothing
		End If
'' 실은 순환문이 위의 한줄의 표현식 속에 숨어있는 것
'' 내부적으로 순환하는 것은 마찬가지지만, 순환을 위한 알고리즘이 좀더 최적화되어
'' 우리가 일반적으로 하는 순환문 보다 발전 된것..

네번째 버튼은
일반적인 순환문으로는 안되나???궁금하실 것이니..일반적인 For~Next문을 사용해보자


'' 엑셀에서 Range개체를 행별로 순환할때는
'' 결과값을 Collection개체에 담던가, 배열에 담던가 아니면
'' Union방법을 사용하여 Range개체에 담았었다
'' 여기에서는 DataTable은 DataRow로 구성이 되어 있으니
'' DataRow개체(행)을 배열에 담도록 하면 되겠다
'' 몇개의 행이 조건에 맞을지 모르니 동적배열로 하여야 할 것이고
'' 동적배열을 조건이 맞을때마다 배열에 주어 담고

Dim oRows() As DataRow = Nothing
Dim iX As Integer = 0
For Each oRow As DataRow In oTable.Rows
	If oRow.Item(3) = sCriteria1 And oRow.Item(2) = sCriteria2 Then
		ReDim Preserve oRows(iX)
		oRows(iX) = oRow
		iX += 1
	End If
Next
'' 배열을 DataGridView개체의 DataSource속성에 주려면
'' 역시 또 데이타형식이 맞아야 한다
'' 배열에는 CopyToDataTable이 있다고 위에서 이야기했다, 같은 요령으로...
If oRows IsNot Nothing Then
	oDGV.DataSource = oRows.CopyToDataTable
Else
	oDGV.DataSource = Nothing
End If

한가지 목적을 찾아가는 길은 다양한 것이니, 한가지만 고집하시면 안된다
위의 경우에서 최근의 기술이 LINQ이니 바짝 챙겨나가도록 하자

세상은 급변하여
정보가 넘쳐난다
기하급수적으로 정보가 쌓여 갈 것이다
문제는 과연 어떤 조건에 맞게 휠터링을 하느냐가 문제가 되는 셈이다
휠터링을 하는 조건식의 개념은 프로그래밍을 하지 않더라고 챙기고 가야할 미래의
필수도구로 보아도 될 것이다
아무 정보다 마구 줏어먹으면 배탈난다, 자신이 원하는 조건식을 항상 돌려본다는
생각을 프로그래밍언어에서 훈련될수 있을 것이다

***[LOG-IN]***

다음 페이지에서는 Binding의 개념을 살펴보자
Binding의 개념을 알면 , 코딩의 노력을 많이 효과적으로 줄일수 있다
또한 Binding을 하여주는 개체를 통한 휠터링도 역시 다음 페이지에서 챙기도록 하자