Excel重复行
我有很多员工在一份名单上,上面写着他们上过哪些课程。A列是他们的客户ID,M列是他们完成的课程Excel重复行,excel,vba,Excel,Vba,我有很多员工在一份名单上,上面写着他们上过哪些课程。A列是他们的客户ID,M列是他们完成的课程 如果每个ID都有重复的课程记录,我如何删除一行,因为有些员工会使用相同的课程名称。使用Excel中的“删除重复项”功能,只需突出显示要消除重复值的两列即可。下面的快速示例: 然后在对话框中选择要检查重复值的两列(确保取消选中所有不相关的列) 我的示例输出: 使用Excel中的“删除重复项”功能,只需突出显示要消除重复值的两列。下面的快速示例: 然后在对话框中选择要检查重复值的两列(确保取消选中所有
如果每个ID都有重复的课程记录,我如何删除一行,因为有些员工会使用相同的课程名称。使用Excel中的“删除重复项”功能,只需突出显示要消除重复值的两列即可。下面的快速示例: 然后在对话框中选择要检查重复值的两列(确保取消选中所有不相关的列) 我的示例输出:
使用Excel中的“删除重复项”功能,只需突出显示要消除重复值的两列。下面的快速示例: 然后在对话框中选择要检查重复值的两列(确保取消选中所有不相关的列) 我的示例输出: 删除重复行,即隐藏或删除
- 第一个子项显示如何使用第二个子项,即主子项(
)removeDuplicateRows
- 其余的接头被称为主接头(也是必要的)
- 只有在完成测试后,才能从隐藏变为删除
Option Explicit
Sub testRemoveDuplicateRows()
Const wsName As String = "Sheet1"
Const LastRowColumnID As Variant = "A" ' e.g. 1 or "A"
Const FirstRow As Long = 2
Dim ColumnIDs As Variant: ColumnIDs = Array(1, "M")
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
' Hide duplicate rows.
removeDuplicateRows ws, ColumnIDs, LastRowColumnID, FirstRow, True
' Delete duplicate rows.
'removeDuplicateRows ws, ColumnIDs, LastRowColumnID, FirstRow
End Sub
Sub removeDuplicateRows(Sheet As Worksheet, _
ColumnIDs As Variant, _
Optional LastRowColumnID As Variant = 1, _
Optional FirstRow As Long = 1, _
Optional hideOnly As Boolean = False)
' Write values of columns to jagged array.
Dim Cols As Variant
getColumns Cols, Sheet, ColumnIDs, LastRowColumnID, FirstRow
' Join values of arrays in jagged array.
Dim Data As Variant: joinColumns Data, Cols
' Write duplicate row numbers to array.
Dim RowOffset As Long: RowOffset = FirstRow - 1 ' 1 = ubound(Data)
Dim DupeRows As Variant
collectDuplicateRows DupeRows, Data, RowOffset
' Hide or delete duplicate rows.
If hideOnly Then
hideRows Sheet, DupeRows
Else
deleteRows Sheet, DupeRows
End If
End Sub
Sub getColumns(ByRef Data As Variant, _
Sheet As Worksheet, _
ColumnIDs As Variant, _
Optional LastRowColumnID As Variant = 1, _
Optional FirstRow As Long = 1)
Dim ubc As Long: ubc = UBound(ColumnIDs)
If ubc = -1 Then Exit Sub
Dim rng As Range: getColumnRange rng, Sheet, LastRowColumnID, FirstRow
If rng Is Nothing Then Exit Sub
ReDim Data(ubc): getColumnFromColumnRange Data(0), rng
If ubc > 0 Then GoSub getRemainingColumns
Exit Sub
getRemainingColumns:
Dim j As Long
For j = 1 To ubc
getColumnFromColumnRange Data(j), _
rng.Offset(, Sheet.Columns(ColumnIDs(j)).Column - rng.Column)
Next j
Return
End Sub
Sub getColumnRange(ByRef ColumnRange As Range, _
Sheet As Worksheet, _
Optional ColumnID As Variant = 1, _
Optional FirstRow As Long = 1)
Set ColumnRange = Nothing
Dim rng As Range
Set rng = Sheet.Columns(ColumnID).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.Row < FirstRow Then Exit Sub
Set ColumnRange = Sheet.Range(Sheet.Cells(FirstRow, ColumnID), rng)
End Sub
Sub getColumnFromColumnRange(ByRef Data As Variant, _
ColumnRange As Range)
If ColumnRange Is Nothing Then Exit Sub
If ColumnRange.Cells.Count > 1 Then
Data = ColumnRange.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = ColumnRange.Value
End If
End Sub
Sub joinColumns(ByRef Data As Variant, _
ColumnsArray As Variant, _
Optional Delimiter As String = "|||")
Data = ColumnsArray(0)
If UBound(ColumnsArray) = 0 Then Exit Sub
Dim ubr As Long: ubr = UBound(Data)
Dim j As Long, i As Long
For j = 1 To UBound(ColumnsArray)
For i = 1 To ubr
Data(i, 1) = Data(i, 1) & Delimiter & ColumnsArray(j)(i, 1)
Next i
Next j
End Sub
Sub collectDuplicateRows(ByRef DupeRows As Variant, _
Data As Variant, _
Optional RowOffset As Long = 0, _
Optional DupeRowsFirstIndex As Long = 0)
Dim ub As Long: ub = UBound(Data)
If ub < 2 Then Exit Sub
Dim i As Long, k As Long, m As Long: m = DupeRowsFirstIndex - 1
ReDim DupeRows(DupeRowsFirstIndex To ub + DupeRowsFirstIndex - 2)
For i = 1 To ub - 1
For k = i + 1 To ub
If Data(k, 1) = Data(i, 1) Then
m = m + 1
DupeRows(m) = k + RowOffset
Exit For
End If
Next k
Next i
If m > DupeRowsFirstIndex - 1 Then
ReDim Preserve DupeRows(DupeRowsFirstIndex To m)
Else
DupeRows = Empty
End If
End Sub
Sub deleteRows(Sheet As Worksheet, _
RowNumbers As Variant)
Dim rng As Range: Set rng = Sheet.Rows(RowNumbers(LBound(RowNumbers)))
If UBound(RowNumbers) > LBound(RowNumbers) Then GoSub collectRemainingRows
If Not rng Is Nothing Then rng.EntireRow.Delete
Exit Sub
collectRemainingRows:
Dim j As Long
For j = LBound(RowNumbers) + 1 To UBound(RowNumbers)
Set rng = Union(rng, Sheet.Rows(RowNumbers(j)))
Next j
Return
End Sub
Sub hideRows(Sheet As Worksheet, _
RowNumbers As Variant)
Dim rng As Range: Set rng = Sheet.Rows(RowNumbers(LBound(RowNumbers)))
If UBound(RowNumbers) > LBound(RowNumbers) Then GoSub collectRemainingRows
If Not rng Is Nothing Then rng.EntireRow.Hidden = True
Exit Sub
collectRemainingRows:
Dim j As Long
For j = LBound(RowNumbers) + 1 To UBound(RowNumbers)
Set rng = Union(rng, Sheet.Rows(RowNumbers(j)))
Next j
Return
End Sub
选项显式
子TestRemovedUpplicateRows()
Const wsName As String=“Sheet1”
Const LastRowColumnID作为Variant=“A”例如1或“A”
常量第一行长度=2
Dim ColumnId作为变量:ColumnId=Array(1,“M”)
将wb设置为工作簿:设置wb=ThisWorkbook
将ws设置为工作表:设置ws=wb.Worksheets(wsName)
'隐藏重复行。
RemovedUpplicateRows ws,ColumnId,LastRowColumnID,FirstRow,True
'删除重复的行。
'RemovedUpplicateRows ws,ColumnId,LastRowColumnID,FirstRow
端接头
子移除的重复行(作为工作表的工作表_
柱状体作为变体_
可选LastRowColumnID作为变量=1_
可选的第一行,长度为1_
可选隐藏为布尔值=False)
'将列的值写入锯齿数组。
Dim Cols作为变体
getColumns Cols、Sheet、ColumnId、LastRowColumnID、FirstRow
'在交错数组中连接数组的值。
Dim数据作为变量:joinColumns数据,Cols
'将重复的行号写入数组。
按长度调整行偏移量:行偏移量=第一行-1'1=ubound(数据)
Dim Duperow作为变体
收集重复行DupeRows、数据、行偏移量
'隐藏或删除重复行。
如果很可怕的话
隐藏工作表
其他的
删除行表,DupeRows
如果结束
端接头
子getColumns(ByRef数据作为变量_
工作表作为工作表_
柱状体作为变体_
可选LastRowColumnID作为变量=1_
可选的第一行(长=1)
长度为的尺寸ubc:ubc=UBound(列ID)
如果ubc=-1,则退出Sub
Dim rng As Range:getColumnRange rng,Sheet,LastRowColumnID,FirstRow
如果rng为空,则退出Sub
ReDim数据(ubc):getColumnFromColumnRange数据(0),rng
如果ubc>0,则GoSub getRemainingColumns
出口接头
getRemainingColumns:
Dim j尽可能长
对于j=1至ubc
getColumnFromColumnRange数据(j)_
rng.Offset(,表列(列ID(j)).Column-rng.Column)
下一个j
返回
端接头
子getColumnRange(ByRef ColumnRange作为范围_
工作表作为工作表_
可选的ColumnID变量=1_
可选的第一行(长=1)
设置ColumnRange=Nothing
变暗rng As范围
Set rng=Sheet.Columns(ColumnID).Find(“*”,xlValues,,xlPrevious)
如果rng为空,则退出Sub
如果rng.Row<第一行,则退出Sub
Set ColumnRange=Sheet.Range(Sheet.Cells(第一行,ColumnID),rng)
端接头
Sub getColumnFromColumnRange(ByRef数据作为变量_
列范围作为范围)
如果ColumnRange为Nothing,则退出Sub
如果ColumnRange.Cells.Count>1,则
Data=ColumnRange.Value
其他的
ReDim数据(1到1,1到1):数据(1,1)=ColumnRange.Value
如果结束
端接头
子列(ByRef数据作为变量_
柱状体作为变体_
可选分隔符为String=“| | |”)
数据=列数组(0)
如果UBound(ColumnsArray)=0,则退出Sub
尺寸ubr长度:ubr=UBound(数据)
我和j一样长,我也一样长
对于j=1到UBound(ColumnsArray)
对于i=1至ubr
数据(i,1)=数据(i,1)&定界符和列数组(j)(i,1)
接下来我
下一个j
端接头
子集合重复行(ByRef DupeRows作为变量_
数据作为变量_
可选行偏移量,长度为0_
可选的DupeRowsFirstIndex(长度=0)
长度为的尺寸ub:ub=UBound(数据)
如果ub<2,则退出Sub
尺寸i等于长,k等于长,m等于长:m=DupeRowsFirstIndex-1
ReDim DupeRows(DupeRowsFirstIndex到ub+DupeRowsFirstIndex-2)
对于i=1到ub-1
对于k=i+1至ub
如果数据(k,1)=数据(i,1),则
m=m+1
DupeRows(m)=k+行偏移
退出
如果结束
下一个k
接下来我
如果m>DupeRowsFirstIndex-1,则
ReDim保留DupeRows(DupeRowsFirstIndex到m)
其他的
DupeRows=空
如果结束
端接头
子删除行(作为工作表的工作表_
行数(作为变量)
Dim rng As Range:设置rng=Sheet.Rows(行编号(LBound(行编号)))
如果UBound(行编号)>LBound(行编号),则GoSub collectRemainingRows
如果Not rng为Nothing,则rng.EntireRow.Delete
出口接头
收藏品