[VB.NET] การสร้างกราฟ หรือ Chart และส่งข้อมูลจากตารางกริดออกไปยัง Excel
http://www.g2gnet.com/webboard/images/vbnet/ChartExportExcel.pngบทความนี้แอดมินขอเหมารวบยอดไปเลยทีเดียวนะครับ กรณีของ การส่งข้อมูลจากตารางกริดไปยัง Excel จะใช้วิธีแบบ Line By Line ซึ่งแน่นอนว่าจะเกิดการทำงานที่ล่าช้ามาก หากกรณีที่มีข้อมูลเยอะๆ ส่วนการทำกราฟ หรือ Chart ก็จะอาศัยข้อมูลที่เกิดจากการสุ่มค่าตัวเลขแบบทศนิยมลงไปในตารางกริด โดยที่แอดมินใช้วิธีการที่ชื่นชอบก็คือ สั่งแบบ @Run Time แต่เพื่อความสะดวก แอดมินจะลาก Chart Control เข้ามาวางบนฟอร์มเอาไว้ก่อน ส่วนป้าย Legend และ Series หรือกราฟที่แสดงผลนั้น จะใช้การเขียนโค้ดเพื่อสร้างมันขึ้นมาแบบอัตโนมัติ นั่นคือเราจะเรียนรู้คุณสมบัติต่างๆของ Chart Control ด้วยโค้ดแทน และด้วยวิธีการนี้มันเกิดความยืดหยุ่นสูงในการปรับแต่งเพื่อไปใช้ในงานอื่นๆต่อไป ...
การส่งข้อมูลออกไป Excel จะทำต้อง References ตัว Microsoft Excel 14.0 Library Object เข้ามาก่อน โดยเลือกจาก COM (Component Object Model) ... (OFFICE 2010) ...
http://www.g2gnet.com/webboard/images/vbnet/RefExcel14.png
http://www.g2gnet.com/webboard/images/vbnet/RefExcel.png
โค้ดในส่วนของการสุ่มข้อมูลเพื่อนำมาใส่ลงในตารางกริด ...
' / --------------------------------------------------------------------------
Private Sub FillData()
Dim dt As New DataTable
dt.Columns.Add("Item")
dt.Columns.Add("Value1")
dt.Columns.Add("Value2")
dt.Columns.Add("Value3")
dt.Columns.Add("Average")
Dim RandomClass As New Random()
Dim MyMonth As String() = New String() {("ม.ค."), ("ก.พ."), ("มี.ค."), ("เม.ย."), ("พ.ค."), ("มิ.ย."), ("ก.ค."), ("ส.ค."), ("ก.ย."), ("ต.ค."), ("พ.ย."), ("ธ.ค.")}
For i As Byte = 0 To 11
Dim dr As DataRow = dt.NewRow()
dr(0) = MyMonth(i)
dr(1) = FormatNumber(RandomClass.Next(100, 1000) + RandomClass.NextDouble(), 2)
dr(2) = FormatNumber(RandomClass.Next(100, 1000) + RandomClass.NextDouble(), 2)
dr(3) = FormatNumber(RandomClass.Next(100, 1000) + RandomClass.NextDouble(), 2)
'// CDbl = Convert to Double
dr(4) = Format((CDbl(dr(1)) + CDbl(dr(2)) + CDbl(dr(3))) / 3, "#,##0.00")
dt.Rows.Add(dr)
Next
dgvData.DataSource = dt
Label1.Text = "Total : " & dt.Rows.Count.ToString("#,##") & " Records."
End Sub
โค้ดในส่วนของการสร้างกราฟ หรือ Chart
' / --------------------------------------------------------------------------------
Private Sub btnChart_Click(sender As System.Object, e As System.EventArgs) Handles btnChart.Click
If dgvData.RowCount <= 0 Then Return
'//
Chart1.Titles.Clear()
'// Clear Legends & Series
Chart1.Series.Clear()
Chart1.Legends.Clear()
'// Clear Points
For Each xSeries In Chart1.Series
xSeries.Points.Clear()
Next
'// Create Legends
Dim Legend1 As Legend = New Legend()
Legend1.Name = "Legend1"
Chart1.Legends.Add(Legend1)
'// Create Series
Dim Series1 As Series = New Series()
Dim Series2 As Series = New Series()
Dim Series3 As Series = New Series()
Dim Series4 As Series = New Series()
'// Add Series
With Chart1
.Series.Add(Series1)
.Series.Add(Series2)
.Series.Add(Series3)
.Series.Add(Series4)
End With
'//
Try
Dim myFont As New Font("Tahoma", 14, FontStyle.Bold)
Chart1.Titles.Add("Sample Chart")
Chart1.Titles(0).Font = myFont
'// Define Chart Type.
For Each xSeries In Chart1.Series
Select Case cmbChartType.Text
Case "Column"
xSeries.ChartType = SeriesChartType.Column
Case "Line"
xSeries.ChartType = SeriesChartType.Line
Case "Point"
xSeries.ChartType = SeriesChartType.Point
End Select
'// Show Legend
If chkShowLegend.Checked Then
xSeries.IsVisibleInLegend = True
Else
xSeries.IsVisibleInLegend = False
End If
'// View the value of a chart point on mouse over.
xSeries.ToolTip = "#VAL{0.00}"
Next
'//
With Chart1
.Series(0).LegendText = "Value 1"
.Series(1).LegendText = "Value 2"
.Series(2).LegendText = "Value 3"
.Series(3).LegendText = "Average"
End With
'// Show all Axis Label
Chart1.ChartAreas(0).AxisX.Interval = 1
'//
With Chart1.ChartAreas("ChartArea1")
.AxisX.MajorGrid.LineWidth = 1
.AxisY.MajorGrid.LineWidth = 1
End With
'// LOOP DISPLAY
For CountData As Integer = 0 To dgvData.Rows.Count - 1
With Chart1
'// 0 = Month, 1 = Value1, 2 = Value2, 3 = Value3, 4 = Average
.Series(0).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(1, CountData).Value)
.Series(1).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(2, CountData).Value)
.Series(2).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(3, CountData).Value)
.Series(3).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(4, CountData).Value)
End With
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
โค้ดในส่วนของการส่งข้อมูลออกไป Excel
' / --------------------------------------------------------------------------------
'// Export data to Excel.
Private Sub btnExportExcel_Click(sender As System.Object, e As System.EventArgs) Handles btnExportExcel.Click
'// ไม่มีข้อมูลในตารางกริด ก็สั่งให้เด้งหนีออกไป
If dgvData.Rows.Count <= 0 Then Exit Sub
'// พิจารณาการเลือกใช้ชนิดข้อมูล (Data Type) ให้เหมาะสม
Dim MaxRow As Integer, MaxCol As Short
Dim nRow As Integer, nCol As Short
Dim xlsApp As New Excel.Application
Dim xlsWorkBook As Excel.Workbook = xlsApp.Workbooks.Add
Dim xlsWorkSheet As Excel.Worksheet = CType(xlsWorkBook.Worksheets(1), Excel.Worksheet)
'// S T A R T
Try
xlsApp.Visible = True
'// หาค่าจำนวนแถว
MaxRow = dgvData.RowCount
'// หาค่าจำนวนหลัก
MaxCol = dgvData.Columns.Count - 1
With xlsWorkSheet
.Cells.Select()
.Cells.Delete()
'// Header
For nCol = 0 To MaxCol
.Cells(1, nCol + 1).Value = dgvData.Columns(nCol).HeaderText
Next nCol
'// ไล่ตามจำนวนแถว
For nRow = 0 To MaxRow - 1
For nCol = 0 To MaxCol
.Cells(nRow + 2, nCol + 1).value = dgvData.Rows(nRow).Cells(nCol).Value
Next nCol '// Nested Loop
'// หากชุดคำสั่งที่อยู่ใน Nested Loop
'// การให้ตัวแปรต่อท้าย Next จะช่วยให้เรารู้ว่ามันอยู่ใน Loop ไหน
Next nRow
'// กำหนดรูปแบบใน WorkSheet
.Rows("1:1").Font.FontStyle = "Bold"
.Rows("1:1").Font.Size = 10
'//
.Cells.Columns.AutoFit()
.Cells.Select()
.Cells.EntireColumn.AutoFit()
.Cells(1, 1).Select()
End With
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
xlsApp = Nothing
'// Release memory.
ReleaseObject(xlsApp)
ReleaseObject(xlsWorkBook)
ReleaseObject(xlsWorkSheet)
End Sub
โค้ดฉบับเต็มทั้งหมด ...
' / --------------------------------------------------------------------------
' / Developer : Mr.Surapon Yodsanga (Thongkorn Tubtimkrob)
' / eMail : thongkorn@hotmail.com
' / URL: http://www.g2gnet.com (Khon Kaen - Thailand)
' / Facebook: https://www.facebook.com/g2gnet (For Thailand)
' / Facebook: https://www.facebook.com/commonindy (Worldwide)
' / Purpose: Create data into DataGridView for make the Chart and Export data to Excel @Run Time.
' / Microsoft Visual Basic .NET (2010) + MS Excel 14.0
' /
' / This is open source code under @CopyLeft by Thongkorn Tubtimkrob.
' / You can modify and/or distribute without to inform the developer.
' / --------------------------------------------------------------------------
Imports System.Windows.Forms.DataVisualization.Charting
Imports Excel = Microsoft.Office.Interop.Excel
Public Class frmChartExportExcel
Private Sub frmPlotGraph_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Label1.Text = ""
'// Chart Type
'// https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datavisualization.charting.seriescharttype?view=netframework-4.7.2
cmbChartType.Items.Add("Column")
cmbChartType.Items.Add("Line")
cmbChartType.Items.Add("Point")
cmbChartType.SelectedIndex = 0
'// Setup DataGridView
Call InitializeGrid()
'// Generate Data
Call btnGenData_Click(sender, e)
'//
End Sub
Private Sub btnGenData_Click(sender As System.Object, e As System.EventArgs) Handles btnGenData.Click
Call FillData()
End Sub
' / --------------------------------------------------------------------------
Private Sub FillData()
Dim dt As New DataTable
dt.Columns.Add("Item")
dt.Columns.Add("Value1")
dt.Columns.Add("Value2")
dt.Columns.Add("Value3")
dt.Columns.Add("Average")
Dim RandomClass As New Random()
Dim MyMonth As String() = New String() {("ม.ค."), ("ก.พ."), ("มี.ค."), ("เม.ย."), ("พ.ค."), ("มิ.ย."), ("ก.ค."), ("ส.ค."), ("ก.ย."), ("ต.ค."), ("พ.ย."), ("ธ.ค.")}
For i As Byte = 0 To 11
Dim dr As DataRow = dt.NewRow()
dr(0) = MyMonth(i)
dr(1) = FormatNumber(RandomClass.Next(100, 1000) + RandomClass.NextDouble(), 2)
dr(2) = FormatNumber(RandomClass.Next(100, 1000) + RandomClass.NextDouble(), 2)
dr(3) = FormatNumber(RandomClass.Next(100, 1000) + RandomClass.NextDouble(), 2)
'// CDbl = Convert to Double
dr(4) = Format((CDbl(dr(1)) + CDbl(dr(2)) + CDbl(dr(3))) / 3, "#,##0.00")
dt.Rows.Add(dr)
Next
dgvData.DataSource = dt
Label1.Text = "Total : " & dt.Rows.Count.ToString("#,##") & " Records."
End Sub
' / --------------------------------------------------------------------------------
'// การตั้งค่าเริ่มต้นให้กับตารางกริดในแบบ @Run Time
Private Sub InitializeGrid()
With dgvData
.RowHeadersVisible = False
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
.AllowUserToResizeRows = False
.MultiSelect = False
.SelectionMode = DataGridViewSelectionMode.FullRowSelect
.ReadOnly = True
.Font = New Font("Tahoma", 9)
' จัดความกว้างของแต่ละหลัก
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
.AutoResizeColumns()
' Adjust Header Styles
With .ColumnHeadersDefaultCellStyle
.BackColor = Color.Navy
.ForeColor = Color.White
.Font = New Font("Tahoma", 9, FontStyle.Bold)
End With
End With
End Sub
' / --------------------------------------------------------------------------------
Private Sub btnChart_Click(sender As System.Object, e As System.EventArgs) Handles btnChart.Click
If dgvData.RowCount <= 0 Then Return
'//
Chart1.Titles.Clear()
'// Clear Legends & Series
Chart1.Series.Clear()
Chart1.Legends.Clear()
'// Clear Points
For Each xSeries In Chart1.Series
xSeries.Points.Clear()
Next
'// Create Legends
Dim Legend1 As Legend = New Legend()
Legend1.Name = "Legend1"
Chart1.Legends.Add(Legend1)
'// Create Series
Dim Series1 As Series = New Series()
Dim Series2 As Series = New Series()
Dim Series3 As Series = New Series()
Dim Series4 As Series = New Series()
'// Add Series
With Chart1
.Series.Add(Series1)
.Series.Add(Series2)
.Series.Add(Series3)
.Series.Add(Series4)
End With
'//
Try
Dim myFont As New Font("Tahoma", 14, FontStyle.Bold)
Chart1.Titles.Add("Sample Chart")
Chart1.Titles(0).Font = myFont
'// Define Chart Type.
For Each xSeries In Chart1.Series
Select Case cmbChartType.Text
Case "Column"
xSeries.ChartType = SeriesChartType.Column
Case "Line"
xSeries.ChartType = SeriesChartType.Line
Case "Point"
xSeries.ChartType = SeriesChartType.Point
End Select
'// Show Legend
If chkShowLegend.Checked Then
xSeries.IsVisibleInLegend = True
Else
xSeries.IsVisibleInLegend = False
End If
'// View the value of a chart point on mouse over.
xSeries.ToolTip = "#VAL{0.00}"
Next
'//
With Chart1
.Series(0).LegendText = "Value 1"
.Series(1).LegendText = "Value 2"
.Series(2).LegendText = "Value 3"
.Series(3).LegendText = "Average"
End With
'// Show all Axis Label
Chart1.ChartAreas(0).AxisX.Interval = 1
'//
With Chart1.ChartAreas("ChartArea1")
.AxisX.MajorGrid.LineWidth = 1
.AxisY.MajorGrid.LineWidth = 1
End With
'// LOOP DISPLAY
For CountData As Integer = 0 To dgvData.Rows.Count - 1
With Chart1
'// 0 = Month, 1 = Value1, 2 = Value2, 3 = Value3, 4 = Average
.Series(0).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(1, CountData).Value)
.Series(1).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(2, CountData).Value)
.Series(2).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(3, CountData).Value)
.Series(3).Points.AddXY(dgvData.Item(0, CountData).Value, dgvData.Item(4, CountData).Value)
End With
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
' / --------------------------------------------------------------------------------
'// Export data to Excel.
Private Sub btnExportExcel_Click(sender As System.Object, e As System.EventArgs) Handles btnExportExcel.Click
'// ไม่มีข้อมูลในตารางกริด ก็สั่งให้เด้งหนีออกไป
If dgvData.Rows.Count <= 0 Then Exit Sub
'// พิจารณาการเลือกใช้ชนิดข้อมูล (Data Type) ให้เหมาะสม
Dim MaxRow As Integer, MaxCol As Short
Dim nRow As Integer, nCol As Short
Dim xlsApp As New Excel.Application
Dim xlsWorkBook As Excel.Workbook = xlsApp.Workbooks.Add
Dim xlsWorkSheet As Excel.Worksheet = CType(xlsWorkBook.Worksheets(1), Excel.Worksheet)
'// S T A R T
Try
xlsApp.Visible = True
'// หาค่าจำนวนแถว
MaxRow = dgvData.RowCount
'// หาค่าจำนวนหลัก
MaxCol = dgvData.Columns.Count - 1
With xlsWorkSheet
.Cells.Select()
.Cells.Delete()
'// Header
For nCol = 0 To MaxCol
.Cells(1, nCol + 1).Value = dgvData.Columns(nCol).HeaderText
Next nCol
'// ไล่ตามจำนวนแถว
For nRow = 0 To MaxRow - 1
For nCol = 0 To MaxCol
.Cells(nRow + 2, nCol + 1).value = dgvData.Rows(nRow).Cells(nCol).Value
Next nCol '// Nested Loop
'// หากชุดคำสั่งที่อยู่ใน Nested Loop
'// การให้ตัวแปรต่อท้าย Next จะช่วยให้เรารู้ว่ามันอยู่ใน Loop ไหน
Next nRow
'// กำหนดรูปแบบใน WorkSheet
.Rows("1:1").Font.FontStyle = "Bold"
.Rows("1:1").Font.Size = 10
'//
.Cells.Columns.AutoFit()
.Cells.Select()
.Cells.EntireColumn.AutoFit()
.Cells(1, 1).Select()
End With
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
xlsApp = Nothing
'// Release memory.
ReleaseObject(xlsApp)
ReleaseObject(xlsWorkBook)
ReleaseObject(xlsWorkSheet)
End Sub
Private Sub frmPlotGraph_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
Me.Dispose()
Application.Exit()
End Sub
Private Sub btnClose_Click(sender As System.Object, e As System.EventArgs) Handles btnClose.Click
Me.Close()
End Sub
'// เวลากด Enter ในแถวของตารางกริด จะไม่เกิดการเลื่อนตำแหน่ง
Private Sub dgvData_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles dgvData.KeyDown
If e.KeyCode = Keys.Enter Then e.SuppressKeyPress = True
End Sub
' / ------------------------------------------------------------------
'// คืนหน่วยความจำกลับคืนสู่ระบบ
Public Sub ReleaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
'// GC = Garbage Collection
GC.Collect()
End Try
End Sub
End Class
ดาวน์โหลดโค้ดต้นฉบับแบบเต็ม VB.NET (2010) ได้ที่นี่ ...
หน้า:
[1]