|

มาดูวิธีการคิด ...
1. โหลดข้อมูลจาก MS Access เข้าสู่ DataGridView1 (A)
2. โหลดข้อมูลจาก Excel เข้าสู่ DataGridView2 (B)
3. สมมุติฐานคือให้ B เป็น Subset ของ A นั่นคือสมาชิกทุกตัวของ B จะต้องเป็นสมาชิกของ A
4. วนรอบแถวทั้งหมดจาก DataGridView1 (A) เป็นหลัก เพื่อทำการเปรียบเทียบค่าในแต่ละแถว DataGridView2 (B) โดยทำการเปรียบเทียบจากหลัก 0 หากมีค่าตรงกัน เช่น 'E' = 'E' ก็ให้ทำการบวกค่าในแต่ละหลักของทั้ง 2 ตารางกริดเข้าหากัน
5. นำผลลัพธ์ที่ได้ไปแสดงผลใน DataGridView3 (C)
6. เลือกทำการบันทึกข้อมูลจาก DataGridView3 ลงไปในไฟล์ MS Access ต้นฉบับ หรือเลือกบันทึกไฟล์ใหม่
(หมายเหตุ: DataGridView4 แอดมินเพิ่มเติมให้ในทำการ Intersection คือการหาสมาชิกทั้งหมดที่เหมือนกันในเซตต้นแบบ)
มาดูโค้ดฉบับเต็มกันเถอะ ...
- Imports System.Data.OleDb
- Imports System.IO
- Public Class frmCompareDataGridView
- Private Sub frmCompareDataGridView_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
- Call LoadDataFromAccess()
- Call LoadDataFromExcel()
- '// --------------------------------------------------------------------------------------
- '// ยึดค่าตาม DataGridView1 เพราะ DataGridView2 เป็น Subset ของ DataGridView1
- '// นั่นคือสมาชิกทุกตัวของ DataGridView2 จะต้องเป็นสมาชิกของ DataGridView1
- Call CompareDataGridView1()
- '// ยึดค่าตาม DataGridView2 หรือการทำ Intersection
- Call CompareDataGridView2()
- '// --------------------------------------------------------------------------------------
- '// Initialized All DataGridView
- Call SetupGridView(DataGridView1)
- Call SetupGridView(DataGridView2)
- Call SetupGridView(DataGridView3)
- Call SetupGridView(DataGridView4)
- End Sub
- '// --------------------------------------------------------------------------------------
- '// โหลดข้อมูลจาก MS Access เข้าไปที่ DataGridView1
- Private Sub LoadDataFromAccess()
- Dim Conn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyPath(Application.StartupPath) & "\MyData.accdb")
- Dim sql As String = "SELECT * FROM Table1"
- Dim Cmd As OleDbCommand
- Dim DR As OleDbDataReader
- Cmd = New OleDbCommand(sql, Conn)
- With DataGridView1.Columns
- .Add("c1", "Name")
- .Add("c2", "SCB")
- .Add("c3", "KTB")
- .Add("c4", "TMB")
- .Add("c5", "UOB")
- End With
- Try
- If Conn.State = ConnectionState.Open Then Conn.Close()
- Conn.Open()
- DR = Cmd.ExecuteReader
- DataGridView1.Rows.Clear()
- While DR.Read
- DataGridView1.Rows.Add(DR(0), DR(1), DR(2), DR(3), DR(4))
- End While
- Catch ex As Exception
- MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
- Finally
- Cmd.Dispose()
- Conn.Close()
- End Try
- End Sub
- '// --------------------------------------------------------------------------------------
- '// โหลดข้อมูลจาก Excel เข้าไปที่ DataGridView2
- Private Sub LoadDataFromExcel()
- Dim Conn As OleDbConnection
- Dim Cmd As OleDbCommand
- Dim DA As New OleDbDataAdapter
- Dim strConn As String = _
- " Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & _
- MyPath(Application.StartupPath) & "MyData.xlsx" & ";" & _
- " Extended Properties=""Excel 12.0 Xml; HDR=YES"";"
- Try
- Me.DataGridView2.DataSource = Nothing
- Dim DT As New DataTable
- Conn = New OleDbConnection
- Conn.ConnectionString = strConn
- Cmd = New OleDbCommand
- '/ เสมือน Sheet เป็น Table ในฐานข้อมูล
- Cmd.CommandText = "Select * FROM [Sheet1$]"
- Cmd.Connection = Conn
- DA.SelectCommand = Cmd
- DA.Fill(DT)
- DataGridView2.DataSource = DT
- '//
- Catch ex As Exception
- MessageBox.Show(ex.Message)
- Finally
- Conn = Nothing
- Cmd = Nothing
- DA = Nothing
- End Try
- End Sub
- '// --------------------------------------------------------------------------------------
- '// จะทำการลูปตามจำนวนแถวของ DataGridView1 เพื่อเปรียบเทียบกับค่าในแถวของ DataGridView2
- '// หากหลักแรก (Index = 0) มีค่าตรงกัน เช่น 'A' = 'A' ก็จะทำการบวกค่าในแต่ละหลักของแถวที่ตรงกันไปแสดงผลที่ DataGridView3
- Private Sub CompareDataGridView1()
- DataGridView3.Rows.Clear()
- DataGridView3.Columns.Clear()
- '// สร้างคอลัมน์ใน DataGridView3
- With DataGridView3.Columns
- .Add("Name", "Name")
- .Add("SCB", "SCB")
- .Add("KTB", "KTB")
- .Add("TMB", "TMB")
- .Add("UOB", "UOB")
- End With
- '// วนลูปผ่าน DataGridView1
- For Each row1 As DataGridViewRow In DataGridView1.Rows
- If row1.IsNewRow Then Continue For '<-- ข้ามแถวว่างสุดท้าย ถ้าไม่ได้ปิด AllowUserToAddRows = False
- '// ใช้การอ้างอิงหลักผ่าน Index แทนการระบุชื่อ
- Dim name1 As String = row1.Cells(0).Value.ToString()
- Dim scb1 As Integer = Convert.ToInt32(row1.Cells(1).Value)
- Dim ktb1 As Integer = Convert.ToInt32(row1.Cells(2).Value)
- Dim tmb1 As Integer = Convert.ToInt32(row1.Cells(3).Value)
- Dim uob1 As Integer = Convert.ToInt32(row1.Cells(4).Value)
- '// ค่ารวมจาก DataGridView2
- Dim scb2 As Integer = 0
- Dim ktb2 As Integer = 0
- Dim tmb2 As Integer = 0
- Dim uob2 As Integer = 0
- '// วนลูปผ่าน DataGridView2 เพื่อตรวจสอบจากหลัก 0 ที่ตรงกัน เช่น 'A' = 'A'
- For Each row2 As DataGridViewRow In DataGridView2.Rows
- If row2.IsNewRow Then Continue For
- Dim dname As String = row2.Cells("dName").Value.ToString()
- If dname = name1 Then
- scb2 += Convert.ToInt32(row2.Cells("SCB").Value)
- ktb2 += Convert.ToInt32(row2.Cells("KTB").Value)
- tmb2 += Convert.ToInt32(row2.Cells("TMB").Value)
- uob2 += Convert.ToInt32(row2.Cells("UOB").Value)
- End If
- Next
- '// รวมค่า
- Dim totalSCB = scb1 + scb2
- Dim totalKTB = ktb1 + ktb2
- Dim totalTMB = tmb1 + tmb2
- Dim totalUOB = uob1 + uob2
- '// เพิ่มข้อมูลเข้า DataGridView3
- DataGridView3.Rows.Add(name1, totalSCB, totalKTB, totalTMB, totalUOB)
- Next
- End Sub
- '// --------------------------------------------------------------------------------------
- '// จะทำการลูปตามจำนวนแถวของ DataGridView2 เพื่อเปรียบเทียบกับค่าในแถวของ DataGridView1
- '// หากหลักแรก (Index = 0) มีค่าตรงกัน เช่น 'A' = 'A' ก็จะทำการบวกค่าในแต่ละหลักของแถวที่ตรงกันไปแสดงผลที่ DataGridView4
- Private Sub CompareDataGridView2()
- '// คัดลอกคอลัมน์จาก DataGridView2 (เพราะยึดจาก DGV2)
- For Each col As DataGridViewColumn In DataGridView2.Columns
- DataGridView4.Columns.Add(DirectCast(col.Clone(), DataGridViewColumn))
- Next
- '// วนลูปแถวใน DataGridView2
- For Each row2 As DataGridViewRow In DataGridView2.Rows
- If row2.IsNewRow Then Continue For
- Dim resultRow As New List(Of Object)
- Dim name2 As String = row2.Cells(0).Value.ToString()
- '// คัดลอกค่าเดิมจาก DataGridView2 ลง resultRow
- resultRow.Add(name2)
- For i As Integer = 1 To 4
- resultRow.Add(Val(row2.Cells(i).Value))
- Next
- '// ตรวจสอบชื่อกับ DataGridView1 และบวกค่าหากเจอ
- For Each row1 As DataGridViewRow In DataGridView1.Rows
- If row1.IsNewRow Then Continue For
- Dim name1 As String = row1.Cells(0).Value.ToString()
- If name2 = name1 Then
- For i As Integer = 1 To 4
- Dim currentVal As Decimal = Convert.ToDecimal(resultRow(i))
- Dim addVal As Decimal = Val(row1.Cells(i).Value)
- resultRow(i) = currentVal + addVal
- Next
- Exit For '// เจอแล้วหยุด
- End If
- Next
- '// เพิ่มข้อมูลรวมลงใน DataGridView4
- DataGridView4.Rows.Add(resultRow.ToArray())
- Next
- End Sub
- '// --------------------------------------------------------------------------------------
- '// บันทึกข้อมูลจาก DataGridView3 ลงไปยังไฟล์ MS Access ที่ถูกสร้างขึ้นใหม่
- Private Sub btnSaveNewFile_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveNewFile.Click
- '// ==== 1. เลือกชื่อและตำแหน่งไฟล์ Access ที่จะสร้างใหม่ ====
- Dim SaveDialog As New SaveFileDialog()
- With SaveDialog
- .InitialDirectory = MyPath(Application.StartupPath)
- .Filter = "Access Database (*.accdb)|*.accdb"
- .Title = "บันทึกข้อมูลเป็น Access Database"
- .FileName = "Data_" & DateTime.Now.ToString("ddMMyyyy_HHmmss") & ".accdb"
- End With
- If SaveDialog.ShowDialog() <> DialogResult.OK Then Exit Sub
- '// ตำแหน่งไฟล์และชื่อไฟล์+นามสกุล
- Dim DbPath As String = SaveDialog.FileName
- '// ชื่อไฟล์+นามสกุล
- Dim DbFileName As String = System.IO.Path.GetFileName(SaveDialog.FileName)
- '// ==== 2. สร้างไฟล์ .accdb ใหม่ ====
- If File.Exists(DbPath) Then File.Delete(DbPath)
- Dim strConn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DbPath & ";Jet OLEDB:Engine Type=5;"
- Dim Cat = CreateObject("ADOX.Catalog")
- Cat.Create(strConn)
- '// ==== 3. สร้างตารางใหม่โดยอิงจากคอลัมน์ของ DataGridView1 ====
- Dim TableName As String = "Table1"
- Using Conn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DbPath)
- Conn.Open()
- '// สร้างคำสั่ง SQL สำหรับสร้างตาราง
- Dim Sql As String = "CREATE TABLE [" & TableName & "] ("
- For i As Integer = 0 To DataGridView1.Columns.Count - 1
- Dim colName = DataGridView1.Columns(i).HeaderText
- If i = 0 Then
- Sql &= "[" & colName & "] TEXT(255),"
- Else
- Sql &= "[" & colName & "] SMALLINT,"
- End If
- Next
- '// ลบ comma สุดท้าย และปิดวงเล็บ
- Sql = Sql.TrimEnd(","c) & ")"
- Using Cmd As New OleDbCommand(Sql, Conn)
- Cmd.ExecuteNonQuery()
- End Using
- '// ==== 4. Insert ข้อมูลจาก DataGridView3 ไปเก็บไว้ใน MS Access ====
- For Each row As DataGridViewRow In DataGridView3.Rows
- If row.IsNewRow Then Continue For
- Dim ColNames As New List(Of String)
- Dim values As New List(Of String)
- For i As Integer = 0 To DataGridView1.Columns.Count - 1
- ColNames.Add("[" & DataGridView1.Columns(i).HeaderText & "]")
- Dim val = If(IsDBNull(row.Cells(i).Value), "0", row.Cells(i).Value.ToString())
- '// เพิ่มเครื่องหมาย ' ' แค่คอลัมน์แรก (Name)
- If i = 0 Then
- values.Add("'" & val.Replace("'", "''") & "'") '// ป้องกัน single quote ในชื่อ
- Else
- '// ตรวจสอบว่าเป็นตัวเลข ถ้าไม่ใช่ ให้เป็น 0
- If Not Integer.TryParse(val, Nothing) Then val = "0"
- values.Add(val)
- End If
- Next
- Dim InsertSql As String = "INSERT INTO [" & TableName & "] (" & String.Join(",", ColNames) & ") VALUES (" & String.Join(",", values) & ")"
- Using Cmd As New OleDbCommand(InsertSql, Conn)
- Cmd.ExecuteNonQuery()
- End Using
- Next
- Conn.Dispose()
- Conn.Close()
- End Using
- MessageBox.Show("บันทึกข้อมูลเรียบร้อยแล้ว: " & DbFileName, "Report Status", MessageBoxButtons.OK, MessageBoxIcon.Information)
- End Sub
- '// --------------------------------------------------------------------------------------
- '// บันทึกข้อมูลจาก DataGridView3 ลงไปยังไฟล์ MS Access เดิม (MyData.accdb)
- Private Sub btnSaveExistFile_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveExistFile.Click
- Dim DbFileExist As String = "MyData.accdb"
- Dim DbPath As String = MyPath(Application.StartupPath) & DbFileExist
- Dim TableName As String = "Table1"
- '// เชื่อมต่อฐานข้อมูล Access ที่มีอยู่
- Dim strConn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DbPath
- Using Conn As New OleDbConnection(strConn)
- Conn.Open()
- '// ===== 1. ลบข้อมูลเดิมในตาราง =====
- Dim DeleteSql As String = "DELETE FROM [" & TableName & "]"
- Using Cmd As New OleDbCommand(DeleteSql, Conn)
- Cmd.ExecuteNonQuery()
- End Using
- '// ===== 2. เตรียมรายชื่อคอลัมน์ =====
- Dim FieldNames As New List(Of String)
- For i As Integer = 0 To DataGridView3.Columns.Count - 1
- FieldNames.Add(DataGridView3.Columns(i).Name)
- Next
- '// --------------------------------------------------------------------------------------
- '// ใช้ Parameterized Query
- '// สมมุติว่า ...
- '// TableName = "Table1"
- '// FieldNames = {"Name", "SCB", "KTB"}
- '// Placeholders = {"?", "?", "?"}
- '// ดังนั้นจะได้ ...
- '// InsertSql = "INSERT INTO [Table1] ([Name],[SCB],[KTB]) VALUES (?,?,?)"
- Dim Placeholders = Enumerable.Repeat("?", FieldNames.Count).ToArray()
- '// คำสั่ง SQL สำหรับการ INSERT ข้อมูลแบบหลายคอลัมน์ โดยใช้ String.Format()
- Dim InsertSql As String = String.Format("INSERT INTO [{0}] ({1}) VALUES ({2})", _
- TableName, _
- String.Join(",", FieldNames.Select(Function(f) "[" & f & "]").ToArray()), _
- String.Join(",", Placeholders))
- '// ===== 3. เพิ่มข้อมูลใหม่จาก DataGridView3 เข้าไปไว้ใน MS Access =====
- Using Cmd As New OleDbCommand(InsertSql, Conn)
- For Each row As DataGridViewRow In DataGridView3.Rows
- If row.IsNewRow Then Continue For
- Cmd.Parameters.Clear()
- For i As Integer = 0 To FieldNames.Count - 1
- Dim value = If(IsDBNull(row.Cells(i).Value), DBNull.Value, row.Cells(i).Value)
- Cmd.Parameters.AddWithValue("?", value)
- Next
- Cmd.ExecuteNonQuery()
- Next
- End Using
- Conn.Close()
- End Using
- MessageBox.Show("อัปเดตข้อมูลเรียบร้อยแล้วใน " & DbFileExist, "Report Status", MessageBoxButtons.OK, MessageBoxIcon.Information)
- End Sub
- Private Sub frmCompareDataGridView_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
- Me.Dispose()
- GC.SuppressFinalize(Me)
- Application.Exit()
- End Sub
- Private Sub btnExit_Click(sender As System.Object, e As System.EventArgs) Handles btnExit.Click
- Me.Close()
- End Sub
- #Region "FUNCTION"
- Function MyPath(ByVal AppPath As String) As String
- '/ Return Value
- MyPath = AppPath.ToLower.Replace("\bin\debug", "").Replace("\bin\release", "").Replace("\bin\x86\debug", "").Replace("\bin\x86\release", "")
- '// If not found folder then put the \ (BackSlash) at the end.
- If Microsoft.VisualBasic.Right(MyPath, 1) <> Chr(92) Then MyPath = MyPath & Chr(92)
- End Function
- #End Region
- #Region "DATAGRIDVIEW"
- '// Initialized DataGridView.
- Private Sub SetupGridView(ByRef DGV As DataGridView)
- With DGV
- .RowHeadersVisible = False
- .AllowUserToAddRows = False
- .AllowUserToDeleteRows = False
- .AllowUserToResizeRows = False
- .MultiSelect = False
- .SelectionMode = DataGridViewSelectionMode.FullRowSelect
- .ReadOnly = True
- '// Data rows
- .Font = New Font("Tahoma", 10)
- .RowTemplate.MinimumHeight = 27
- .RowTemplate.Height = 27
- '// Autosize Column
- .AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
- '// Header
- With .ColumnHeadersDefaultCellStyle
- .BackColor = Color.RoyalBlue
- .ForeColor = Color.White
- .Font = New Font(DGV.Font, FontStyle.Bold)
- End With
- .ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing
- .ColumnHeadersHeight = 36
- '/ Accept changes to the header's background color.
- .EnableHeadersVisualStyles = False
- '// Even-Odd Color of Rows.
- .AlternatingRowsDefaultCellStyle.BackColor = Color.Beige
- '// Even-Odd Color of Columns.
- For iCol As Integer = 0 To DGV.Columns.Count - 1
- '// If any integer Mod by 2 and gets the answer is 0 so even number, 1 is an odd number.
- If iCol Mod 2 = 1 Then
- DGV.Columns(iCol).HeaderCell.Style.BackColor = Color.BlueViolet
- Else
- DGV.Columns(iCol).HeaderCell.Style.BackColor = Color.SeaGreen
- End If
- Next
- End With
- End Sub
- #End Region
- End Class
คัดลอกไปที่คลิปบอร์ด
ดาวน์โหลดโค้ดต้นฉบับ VB.NET (2010) ได้ที่นี่ ...
|
ขออภัย! โพสต์นี้มีไฟล์แนบหรือรูปภาพที่ไม่ได้รับอนุญาตให้คุณเข้าถึง
คุณจำเป็นต้อง ลงชื่อเข้าใช้ เพื่อดาวน์โหลดหรือดูไฟล์แนบนี้ คุณยังไม่มีบัญชีใช่ไหม? ลงทะเบียน
x
|