1.去重检测
使用 LINQ 可以更简洁地实现这个功能。我们可以通过 LINQ 将 DataGridView
的行数据按指定列进行组合并去重。以下是使用 LINQ 实现的示例代码:
Public Function IsDuplicateExists(gdv As DataGridView, columns As List(Of String)) As Boolean
' 列名集合が空の場合、False を返す
If columns Is Nothing OrElse columns.Count = 0 Then
Return False
End If
' gdv から全ての行を取得し、新規行は除外する
Dim rows = gdv.Rows.Cast(Of DataGridViewRow)().Where(Function(row) Not row.IsNewRow)
' 指定された列に基づいてキーを作成し、重複をチェックする
Dim uniqueRows = rows.Select(Function(row) String.Join(",", columns.Select(Function(col) If(row.Cells(col).Value IsNot Nothing, row.Cells(col).Value.ToString(), String.Empty)))).Distinct()
' 重複がある場合、uniqueRows の件数が元の行数より少なくなる
Return uniqueRows.Count() < rows.Count()
End Function
代码说明:
gdv.Rows.Cast(Of DataGridViewRow)()
:使用Cast
方法将DataGridViewRowCollection
转换为可枚举的IEnumerable(Of DataGridViewRow)
,这样可以使用 LINQ 查询。Where(Function(row) Not row.IsNewRow)
:过滤掉新行(IsNewRow
为True
),以避免处理用户新输入的空行。Select(Function(row) String.Join(",", ...)
:使用 LINQ 的Select
方法来构建每一行的唯一键,按指定的列进行组合。Distinct()
:通过Distinct
方法去除重复的键。uniqueRows.Count() < rows.Count()
:比较去重前后的行数,如果Distinct
之后的行数少于原始行数,表示有重复行,返回True
。
优点:
- 使用 LINQ 简洁地实现了按指定列组合和去重的逻辑。
Distinct
方法有效地去除重复项,使代码逻辑清晰。- 通过
Where
和Select
方法,LINQ 提供了高效的数据操作和过滤机制。
这样使用 LINQ 的方式不仅简化了代码,而且对去重操作较为直观。
Public Function IsDuplicateExists(gdv As DataGridView, columns As List(Of String)) As Boolean
' 列名集合が空の場合、False を返す
If columns Is Nothing OrElse columns.Count = 0 Then
Return False
End If
' gdv から全ての行を取得し、新規行は除外する
Dim rows = gdv.Rows.Cast(Of DataGridViewRow)().Where(Function(row) Not row.IsNewRow)
' 指定された列に基づいてキーを作成し、重複をチェックする
Dim uniqueRows = rows.Select(Function(row) String.Join(",", columns.Select(Function(col) If(row.Cells(col).Value IsNot Nothing, row.Cells(col).Value.ToString(), String.Empty)))).Distinct()
' 重複がある場合、uniqueRows の件数が元の行数より少なくなる
Return uniqueRows.Count() < rows.Count()
End Function
Private Sub butCheckGrdList_Click(sender As Object, e As EventArgs) Handles butCheckGrdList.Click
Try
' 重複チェックを行う列名リストを作成
Dim columnsToCheck As New List(Of String) From {"TRI_NAME", "TRI__NAME_RYAKU", "TRI_ADDRESS1", "TRI_TEL"}
' 列名リストが空かどうかを確認する
If columnsToCheck Is Nothing OrElse columnsToCheck.Count = 0 Then
MessageBox.Show("重複データをチェックする列が指定されていません。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Return
End If
' IsDuplicateExists メソッドを呼び出し、DataGridView と列名リストを渡す
Dim hasDuplicates As Boolean = IsDuplicateExists(grdList, columnsToCheck)
' 重複データがあるかどうかの結果に基づいてメッセージを表示
If hasDuplicates Then
MessageBox.Show("重複データが存在します!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Else
MessageBox.Show("重複データはありません。", "情報", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
Catch ex As Exception
End Try
End Sub
2.对grdList去重返回DataTable
进一步优化 GetDistinctDataTable
方法
我们将采用以下步骤:
- 确保所有列值正确处理,即使它们包含空值。
- 使用更明确的唯一性检查,以避免遗漏任何唯一行数据。
- 提供更详细的错误信息,以便调试。
以下是优化后的代码:
Public Function GetDistinctDataTable(gdv As DataGridView, columns As List(Of String)) As DataTable
' 如果列名集合为空或不存在,返回一个空的 DataTable
If columns Is Nothing OrElse columns.Count = 0 Then
Return New DataTable()
End If
' 创建一个新的 DataTable 来存储结果
Dim resultTable As New DataTable()
' 根据传入的列名创建 DataTable 的列,所有列的数据类型都设为 String
For Each colName In columns
resultTable.Columns.Add(colName, GetType(String))
Next
' 使用 HashSet 来存储唯一的行数据字符串
Dim uniqueValues As New HashSet(Of String)()
' 从 DataGridView 中获取所有非新行
Dim rows = gdv.Rows.Cast(Of DataGridViewRow)().Where(Function(row) Not row.IsNewRow)
' 遍历每一行,提取指定列的值
For Each row In rows
' 构建唯一的行数据字符串(列值用逗号分隔)
Dim rowData As String = String.Join(",", columns.Select(Function(col)
Dim cellValue = row.Cells(col).Value
Return If(cellValue IsNot Nothing, cellValue.ToString().Trim(), String.Empty)
End Function))
' 检查 rowData 是否已经存在于 HashSet 中
If uniqueValues.Add(rowData) Then
' 将唯一的行数据添加到 DataTable 中
resultTable.Rows.Add(rowData.Split(","c))
End If
Next
' 返回去重后的 DataTable
Return resultTable
End Function
关键改进点
-
修正列值处理:
- 使用
Trim()
方法移除列值的前后空格,确保比较的一致性。
- 使用
-
String.Join
拼接:- 确保列值拼接的字符串格式一致,以便进行准确的去重。
-
确保
HashSet
去重逻辑正确:HashSet
自动处理重复数据,确保每一条唯一数据只添加一次。
调试和验证
-
验证数据:
- 确保
DataGridView
中的数据按预期显示,列名和数据类型都正确。
- 确保
-
检查列名:
- 确保
columns
列表中的列名在DataGridView
中实际存在。
- 确保
-
调试信息:
- 你可以在代码中添加调试信息来检查每一步是否按预期工作。例如,可以在循环中打印每一行的数据字符串。
调试示例
For Each row In rows
' 构建唯一的行数据字符串(列值用逗号分隔)
Dim rowData As String = String.Join(",", columns.Select(Function(col)
Dim cellValue = row.Cells(col).Value
Return If(cellValue IsNot Nothing, cellValue.ToString().Trim(), String.Empty)
End Function))
' 打印调试信息
Debug.WriteLine($"Processing row: {rowData}")
' 检查 rowData 是否已经存在于 HashSet 中
If uniqueValues.Add(rowData) Then
' 将唯一的行数据添加到 DataTable 中
resultTable.Rows.Add(rowData.Split(","c))
End If
Next
这段代码将帮助你查看每一行的数据,并检查哪些数据被添加到了结果 DataTable
中。如果问题依旧存在,请提供更详细的数据样本和任何错误信息,以便进一步调试。