DataGridView添加汇总行最佳解决方案
新建1个类:
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Windows.Forms
Imports System.Data
Imports System.Drawing
Imports System.ComponentModel
Namespace OtherTools
Class DataGridViewAddSumRow
Private dgv As DataGridView = Nothing
Private dt As DataTable = Nothing
Private sc As String() = Nothing
Public Sub New()
End Sub
'
''' <summary>
''' 设置表格的数据源
''' </summary>
Public WriteOnly Property dataTableName() As DataTable
Set(ByVal value As DataTable)
Me.dt = value
End Set
End Property
'
''' <summary>
'''传递表格的名称
''' </summary>
Public WriteOnly Property DgvName() As DataGridView
Set(ByVal value As DataGridView)
dgv = value
End Set
End Property
Public WriteOnly Property SortColsName() As String()
Set(ByVal value As String())
sc = value
End Set
End Property
'
''' <summary>
''' 开始添加合计行
''' </summary>
Public Sub begin()
initDgv()
End Sub
Private Sub initDgv()
If dgv IsNot Nothing Then
AddHandler Me.dgv.DataSourceChanged, AddressOf dataGridView_DataSourceChanged
AddHandler Me.dgv.ColumnHeaderMouseClick, AddressOf dataGridView_ColumnHeaderMouseClick
AddHandler Me.dgv.CellValueChanged, AddressOf dataGridView_CellValueChanged
AddHandler Me.dgv.RowPostPaint, AddressOf dataGridView_RowPostPaint
Me.dgv.AllowUserToAddRows = False
dgv.DataSource = dt
End If
End Sub
'
''' <summary>
''' 计算合计算
''' </summary>
''' <param name="dgv">要计算的DataGridView</param>
Private Sub SumDataGridView(ByVal dgv As DataGridView, ByVal sortcols As String())
If dgv.DataSource Is Nothing Then
Exit Sub
End If
'DataTable dt = (DataTable)dgv.DataSource;
If dt.Rows.Count < 1 Then
Exit Sub
End If
Dim tal As Decimal() = New Decimal(dt.Columns.Count - 1) {}
Dim font As New Font(dgv.ColumnHeadersDefaultCellStyle.Font.FontFamily, dgv.ColumnHeadersDefaultCellStyle.Font.Size, FontStyle.Bold)
Dim ndr As DataRow = dt.NewRow()
'Dim talc As String = ""
Dim number As Integer = 0
For Each dr As DataRow In dt.Rows
'dr("@xu.Hao") = System.Math.Max(System.Threading.Interlocked.Increment(number), number - 1)
Dim n As Integer = 0
For Each dc As DataColumn In dt.Columns
'If talc = "" AndAlso dc.DataType.Name.ToUpper().IndexOf("STRING") >= 0 Then
' talc = dc.ColumnName
'End If
If Array.IndexOf(Of String)(sortcols, dc.ColumnName) = -1 Then
n += 1
Continue For
End If
If dc.DataType.IsValueType Then
Dim hej As String = dr(dc.ColumnName).ToString()
Try
If hej <> String.Empty Then
tal(n) += Decimal.Parse(hej)
End If
Catch generatedExceptionName As Exception
'if (hej != string.Empty) tal[n] += decimal.Parse(hej);
End Try
End If
n += 1
Next
Next
ndr.BeginEdit()
For i As Integer = 0 To dt.Columns.Count - 1
If tal(i) <> 0 Then
ndr(i) = tal(i)
End If
Next
'If talc <> "" Then
' ndr(talc) = "合计"
'End If
ndr.EndEdit()
dt.Rows.Add(ndr)
dgv.Rows(dgv.Rows.Count - 1).DefaultCellStyle.BackColor = Color.FromArgb(255, 255, 210)
dgv.Rows(dgv.Rows.Count - 1).DefaultCellStyle.Font = font
dgv.Rows(dgv.Rows.Count - 1).[ReadOnly] = True
If dgv.Tag Is Nothing Then
For Each dgvc As DataGridViewColumn In dgv.Columns
dgvc.SortMode = DataGridViewColumnSortMode.Programmatic
Next
End If
dgv.Tag = ndr
End Sub
Private Sub dataGridView_ColumnHeaderMouseClick(ByVal sender As Object, ByVal e As DataGridViewCellMouseEventArgs)
Dim sortDgv As DataGridView = DirectCast(sender, DataGridView)
Dim font As New Font(dgv.ColumnHeadersDefaultCellStyle.Font.FontFamily, dgv.ColumnHeadersDefaultCellStyle.Font.Size, FontStyle.Bold)
Dim fx As Integer = 0
If sortDgv.AccessibleDescription Is Nothing Then
fx = 1
Else
fx = Integer.Parse(sortDgv.AccessibleDescription)
fx = (If(fx = 0, 1, 0))
End If
sortDgv.AccessibleDescription = fx.ToString()
'If sortDgv.Columns(e.ColumnIndex).Name = "@xu.Hao" Then
' Exit Sub
'End If
Dim nCol As DataGridViewColumn = sortDgv.Columns(e.ColumnIndex)
If nCol.DataPropertyName = String.Empty Then
Exit Sub
End If
If nCol IsNot Nothing Then
sortDgv.Sort(nCol, If(fx = 0, ListSortDirection.Ascending, ListSortDirection.Descending))
End If
'--
Dim dr As DataRow = DirectCast(sortDgv.Tag, DataRow)
Dim dt As DataTable = DirectCast(sortDgv.DataSource, DataTable)
Dim ndr As DataRow = dt.NewRow()
ndr.BeginEdit()
For i As Integer = 0 To dt.Columns.Count - 1
ndr(i) = dr(i)
Next
dt.Rows.Remove(dr)
'if (e.ColumnIndex != 0)
If True Then
Dim n As Integer = 1
For i As Integer = 0 To sortDgv.Rows.Count - 1
Dim dgRow As DataGridViewRow = sortDgv.Rows(i)
Dim drv As DataRowView = DirectCast(dgRow.DataBoundItem, DataRowView)
Dim tdr As DataRow = drv.Row
tdr.BeginEdit()
tdr("@xu.Hao") = n
n += 1
tdr.EndEdit()
Next
sortDgv.Refresh()
sortDgv.RefreshEdit()
End If
ndr("@xu.Hao") = CInt((dt.Rows.Count + 1)).ToString()
ndr.EndEdit()
dt.Rows.Add(ndr)
sortDgv.Tag = ndr
'--
sortDgv.Sort(sortDgv.Columns("@xu.Hao"), ListSortDirection.Ascending)
sortDgv.Columns("@xu.Hao").HeaderCell.SortGlyphDirection = SortOrder.None
nCol.HeaderCell.SortGlyphDirection = If(fx = 0, SortOrder.Ascending, SortOrder.Descending)
sortDgv.Rows(sortDgv.Rows.Count - 1).DefaultCellStyle.BackColor = Color.FromArgb(255, 255, 210)
sortDgv.Rows(sortDgv.Rows.Count - 1).DefaultCellStyle.Font = Font
End Sub
Private Sub dataGridView_DataSourceChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim dgv As DataGridView = DirectCast(sender, DataGridView)
'DataTable dt = (DataTable)dgv.DataSource;
If dt Is Nothing Then
Exit Sub
End If
Dim tal As Decimal() = New Decimal(dt.Columns.Count - 1) {}
If dt.Columns.IndexOf("@xu.Hao") < 0 Then
Dim dc As New DataColumn("@xu.Hao", System.Type.[GetType]("System.Int32"))
dt.Columns.Add(dc)
dgv.Columns("@xu.Hao").DisplayIndex = 0
dgv.Columns("@xu.Hao").HeaderText = "序号"
dgv.Columns("@xu.Hao").SortMode = DataGridViewColumnSortMode.Programmatic
dgv.AutoResizeColumn(dgv.Columns("@xu.Hao").Index)
dgv.Columns("@xu.Hao").DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
dgv.Columns("@xu.Hao").Visible = False
End If
SumDataGridView(dgv, sc)
End Sub
Private Sub dataGridView_CellValueChanged(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs)
Dim dgv As DataGridView = DirectCast(sender, DataGridView)
If dgv.Tag Is Nothing OrElse e.RowIndex < 0 OrElse e.RowIndex = dgv.Rows.Count - 1 Then
Exit Sub
End If
Dim col As String = dgv.Columns(e.ColumnIndex).DataPropertyName
If col = String.Empty Then
Exit Sub
End If
If DirectCast(dgv.Rows(e.RowIndex).DataBoundItem, DataRowView).Row.Table.Columns(col).DataType.IsValueType Then
Dim tal As Decimal = 0
For Each dgvr As DataGridViewRow In dgv.Rows
If dgvr.Index <> dgv.Rows.Count - 1 Then
Dim hej As String = dgvr.Cells(e.ColumnIndex).Value.ToString()
If hej <> String.Empty Then
tal += Decimal.Parse(hej)
End If
End If
Next
If tal = 0 Then
dgv(e.ColumnIndex, dgv.Rows.Count - 1).Value = DBNull.Value
Else
dgv(e.ColumnIndex, dgv.Rows.Count - 1).Value = tal
End If
End If
End Sub
Private Sub dataGridView_RowPostPaint(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewRowPostPaintEventArgs)
Dim dgv As DataGridView = DirectCast(sender, DataGridView)
Dim font As New Font(dgv.ColumnHeadersDefaultCellStyle.Font.FontFamily, dgv.ColumnHeadersDefaultCellStyle.Font.Size, FontStyle.Bold)
Dim rectangle As Rectangle = New Rectangle(e.RowBounds.Location.X, e.RowBounds.Location.Y, dgv.RowHeadersWidth - 4, e.RowBounds.Height)
If e.RowIndex = dgv.Rows.Count - 1 Then
TextRenderer.DrawText(e.Graphics, "合计", font, rectangle, dgv.ColumnHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter Or TextFormatFlags.Right)
Else
TextRenderer.DrawText(e.Graphics, (e.RowIndex + 1).ToString(), dgv.RowHeadersDefaultCellStyle.Font, rectangle, dgv.RowHeadersDefaultCellStyle.ForeColor, TextFormatFlags.VerticalCenter Or TextFormatFlags.Right)
End If
End Sub
End Class
End Namespace
在DataGridView的窗体中:
'...
Imports getdywsd.OtherTools
'
da.Fill(dt)
Dim scol As String() = New String() {"销售数量", "码洋", "实洋"} '制定哪些列需要汇总
Dim ot As New DataGridViewAddSumRow
ot.SortColsName = scol
ot.dataTableName = dt
ot.DgvName = DataGridView1
ot.begin()
'
Imports getdywsd.OtherTools
'
da.Fill(dt)
Dim scol As String() = New String() {"销售数量", "码洋", "实洋"} '制定哪些列需要汇总
Dim ot As New DataGridViewAddSumRow
ot.SortColsName = scol
ot.dataTableName = dt
ot.DgvName = DataGridView1
ot.begin()
'