Excel Vba-需要从单行中删除重复项

Excel Vba-需要从单行中删除重复项

我遇到了从单行中删除重复项的问题。我想循环遍历某个范围内的所有行并从单行中删除重复项,而不影响工作表中的其余数据。以下是示例数据:

+---------------+------+------+------+---------------+---------------+
| name          | num1 | num2 | mun3 | emial1        | email2        |
+---------------+------+------+------+---------------+---------------+
| ali zubair    | 1    | 2    | 1    | [email protected]     | [email protected]     |
+---------------+------+------+------+---------------+---------------+
| tosif         | 1    | 2    | 2    | [email protected]      | [email protected]      |
+---------------+------+------+------+---------------+---------------+
| qadeer satter | 3    | 2    | 3    | [email protected]    | [email protected]  |
+---------------+------+------+------+---------------+---------------+
| asif          | 4    | 3    | 2    |               |               |
+---------------+------+------+------+---------------+---------------+
| hamid         | 1    | 5    | 2    | [email protected] | [email protected] |
+---------------+------+------+------+---------------+---------------+

下面的代码根据第 2 列删除重复的行,但不适用于我的情况。

ActiveSheet.Range("A1:f100").RemoveDuplicates Columns:=Array(2), Header:=xlYes

我不知道如何从选定的行范围中删除重复项。到目前为止,我拥有可以循环遍历数据中所有行的代码。

    Sub removeRowDubs()
      Dim nextRang As Range
      Dim sCellStr As String, eCellStr As String
      Dim dRow As Long
       
      dRow = Cells(Rows.Count, 1).End(xlUp).Row
        For dRow = 2 To dRow
               sCellStr = Range("A" & dRow).Offset(0, 1).Address
               eCellStr = Cells(dRow, Columns.Count).End(xlToLeft).Address
               
        Set nextRang = Range(sCellStr, eCellStr)
             Debug.Print nextRang.Address
             
        Next
           
End Sub

所以我需要的是一些代码来完成我需要在下面的代码后插入的操作。

Set nextRang = Range(sCellStr, eCellStr) 

我希望我的问题已经说清楚了,非常感谢您的帮助。我是 Excel VBA 编码的新手,需要您的耐心。

我也研究了我的代码,代码如下。它对我来说是可行的,但是回答我问题的人提供了更好的代码。

Sub removeRowDuplicates()
      Dim nextRang As Range                             ' Variables for
      Dim sCellStr As String, eCellStr As String        ' Going through all rows
      Dim dRow As Long                                  ' And selecting row range
        
        dRow = Cells(Rows.Count, 1).End(xlUp).Row    ' This code selects the                                         
        For dRow = 2 To dRow                         ' next row in the data                                                           
               sCellStr = Range("A" & dRow).Offset(0, 1).Address                            
               eCellStr = Cells(dRow, Columns.Count).End(xlToLeft).Address        
        Set nextRang = Range(sCellStr, eCellStr)                                                       
                                                             
         
        Dim aRange As Range, aCell As Range                ' Variables for                               
        Dim dubCheckCell As Range, dubCheckRange As Range  ' Loops to remove
        Dim dubCheckCell1 As Range                         ' Dublicates from                             
        Dim columnNum As Integer                           ' Current row                                
        
           
        Set aRange = nextRang
        columnNum = Range("b2:f2").Columns.Count + 1
        aRange.Select
        
              For Each aCell In aRange    'Loop for selecting 1 cell, if not blank from range to check its value against all other cell values
                      

                                 If aCell.Value <> "" Then
                                    Set dubCheckCell = aCell
                                 Else
                                             GoTo nextaCell   'If current cell is blank then go to next cell in range
                                 End If
                                 
                      If dubCheckCell.Offset(0, 2).Value <> "" Then                   'Selects range by offsetting 1 cell to right from current cell being checked for dublicate value
                   Set dubCheckRange = Range(dubCheckCell.Offset(, 1), dubCheckCell.Offset(, 1).End(xlToRight))
                   Else
                   Set dubCheckRange = Range(dubCheckCell.Offset(0, 1).Address)
                   End If
                                                
                                 
    For Each dubCheckCell1 In dubCheckRange   'Loop that goes through all cells in range selected by above if-statement
      Do While dubCheckCell1.Column <= columnNum
         If dubCheckCell = dubCheckCell1 Then
                 dubCheckCell1.ClearContents
                         Else
                          End If
             GoTo nextdubCheckCell1
             Loop         'For do while
nextdubCheckCell1:
        Next dubCheckCell1            'Next for dubCheckRange
nextaCell:
        Next aCell                    'Next for aRange
              
              Next    'For drow
    
    End Sub

答案1

我修改了宏以使用我自己的变量。宏首先获取行数和列数。然后循环遍历行、列和单元格并比较值。如果发现重复值,则将其替换为空值。

Sub removeRowDubs()
  
    Dim dRow As Long
    Dim dCol As Double
    Dim i, j, k As Integer
    Dim rng As Range
   
    i = 1
    dCol = 0
    Set rng = Range(i & ":" & i)
      
    'Get the rows
    dRow = Cells(Rows.Count, 1).End(xlUp).Row
    'Get the columns
    dCol = WorksheetFunction.CountIfs(rng, "<>" & "")
   
    'Contains the value to search
    Dim cvalue As String
  
    'Loop through the rows
    For i = 2 To dRow
        'Loop through the columns
        For j = 2 To dRow
                
            cvalue = Cells(i, j).Value
            'Loop through the cells
            For k = (j + 1) To dCol
        
                If Cells(i, k).Value = cvalue Then
        
                    Cells(i, k).Value = ""
        
                End If
        
            Next
        Next
      Next
           
End Sub

单击放大 gif 图像来查看宏的运行情况。

在此处输入图片描述

答案2

您可以使用这样的循环:

Sub remdupes()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

Dim MyArr As Variant
Dim x As Long, j As Long, n As Long
MyArr = Sheet8.Range("A1").CurrentRegion
 For x = LBound(MyArr, 1) To UBound(MyArr, 1)
        For j = LBound(MyArr, 2) To UBound(MyArr, 2) - 1
           For n = j + 1 To UBound(MyArr, 2)
        
                If UCase(MyArr(x, j)) = UCase(MyArr(x, n)) Then MyArr(x, n) = vbNullString
            
            Next n
        Next j
    Next x

Sheet8.Range("A1").CurrentRegion = MyArr
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic

End Sub

如果您有与要删除重复项的区域相邻的数据,只需将 .currentregion 引用更改为您要编辑的范围。

答案3

我喜欢使用 Dictionary 对象来删除重复项。它快速、简单且易于理解。

我也更喜欢使用 VBA 数组,而不是重复读取/写入工作表。这通常会使例程速度提高 5-10 倍。(尽管数据量较少,实际差异可能微不足道。不过,这是一种习惯)。

下面对二者进行了演示。

Option Explicit
Sub remDupRows()
    Dim WS As Worksheet, R As Range
    Dim LR As Long, LC As Long
    Dim vData As Variant
    Dim I As Long, J As Long
    Dim D As Object
    
'Set worksheet and data range
Set WS = ThisWorkbook.Worksheets("sheet10")

With WS
    LR = .Cells(.Rows.Count, 1).End(xlUp).Row
    LC = .Cells(1, .Columns.Count).End(xlToLeft).Column
    Set R = .Range(.Cells(1, 1), .Cells(LR, LC))
End With

'read data into variant array for faster processing
vData = R

'use dictionary for removing duplicates from each row
For I = 2 To UBound(vData, 1)
    Set D = CreateObject("scripting.dictionary")
        D.CompareMode = vbTextCompare 'case insensitive
    For J = 1 To UBound(vData, 2)
        If D.Exists(vData(I, J)) Then
            vData(I, J) = ""
        Else
            D.Add vData(I, J), vData(I, J)
        End If
    Next J
Next I

'write the results back to the worksheet
'could overwrite the original data, but won't do that here
Set R = WS.Cells(LR + 2, LC + 2)
Set R = R.Resize(UBound(vData, 1), UBound(vData, 2))

With R
    .Value = vData
    .Style = "Output" 'not internationally aware
    .EntireColumn.AutoFit
End With

End Sub

在此处输入图片描述

相关内容