Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 删除重复的可见行_Vba_Excel_Filter - Fatal编程技术网

Vba 删除重复的可见行

Vba 删除重复的可见行,vba,excel,filter,Vba,Excel,Filter,我尝试使用下面的VBA代码来做两件事 计算筛选工作表中唯一可见行的数量 删除重复的行 到目前为止: Function UniqueVisible(MyRange As Range) As Integer Dim ws As Worksheet Set ws = Worksheets(1) Dim R As Range Dim V() As String ReDim V(0 To MyRange.Count) As String For E

我尝试使用下面的VBA代码来做两件事

  • 计算筛选工作表中唯一可见行的数量
  • 删除重复的行
  • 到目前为止:

    Function UniqueVisible(MyRange As Range) As Integer
    
    
        Dim ws As Worksheet
        Set ws = Worksheets(1)
    
        Dim R As Range
        Dim V() As String
        ReDim V(0 To MyRange.Count) As String
    
    
        For Each R In MyRange
            If (R.EntireRow.Hidden = False) Then
                For Index = 0 To UniqueVisible
                    If (V(Index) = R.Value) Then
                        R.Delete
                        Exit For
                    End If
    
                    If (Index = UniqueVisible) Then
                        V(UniqueVisible) = R.Value
                        UniqueVisible = UniqueVisible + 1
                    End If
                Next
            End If
        Next R
    
    End Function
    
    这算好了,如果我用
    MsgBox(R.Row)
    替换
    R.Delete
    ,我会得到副本的正确行号

    • R.Delete
      什么都不做
    • R.EntireRow.Delete
      不执行任何操作
    • ws.Rows(R.Row)。删除
      不执行任何操作
    更新

    这似乎不起作用

    Function UniqueVisible(MyRange As Range) As Integer
    
        Dim ws As Worksheet
        Set ws = Worksheets(1)
    
        Dim R As Range
    
        Dim Dup As Integer
        Dup = 0
    
        Dim Dups() As Integer
        ReDim Dups(0 To MyRange.Count) As Integer
    
        Dim V() As String
        ReDim V(0 To MyRange.Count) As String
    
    
        For Each R In MyRange
            If (R.EntireRow.Hidden = False) Then
                For Index = 0 To UniqueVisible
                    If (V(Index) = R.Value) Then
                        Dups(Dup) = R.Row
                        Dup = Dup + 1
                        Exit For
                    End If
    
                    If (Index = UniqueVisible) Then
                        V(UniqueVisible) = R.Value
                        UniqueVisible = UniqueVisible + 1
                    End If
                Next
            End If
        Next R
    
        For Each D In Dups
            ws.Rows(D).Delete
        Next D
    
    End Function
    

    在行之间循环时,不能删除行。您需要将需要删除的行存储在一个数组中,然后在该数组中循环,并在循环完成后删除这些行。

    您似乎违反了一些规则

  • 不能使用函数删除VBA中的行。无论是将该函数用作工作表上的用户定义函数(也称为UDF),还是从VBA项目中的子项调用它,都无关紧要。函数的作用是返回一个值,而不是执行修改工作表上的结构(甚至是除自身单元格以外的值)的操作。在您的情况下,它可以返回一个行号数组,由子行删除

  • 在删除行时,从底部(或列的右侧)开始并向上移动被认为是一种规范做法。删除一行并循环到下一行时,从上到下的工作可能会跳过行

  • 下面是一个示例,其中sub调用函数来收集唯一可见条目的计数和要删除的行数组

    Sub remove_rows()
        Dim v As Long, vDelete_These As Variant, iUnique As Long
        Dim ws As Worksheet
    
        Set ws = Worksheets(1)
    
        vDelete_These = UniqueVisible(ws.Range("A1:A20"))
    
        iUnique = vDelete_These(LBound(vDelete_These))
    
        For v = UBound(vDelete_These) To (LBound(vDelete_These) + 1) Step -1 'not that we are working from the bottom up
            ws.Rows(vDelete_These(v)).EntireRow.Delete
        Next v
    
        Debug.Print "There were " & iUnique & " unique, visible values."
    
    End Sub
    
    Function UniqueVisible(MyRange As Range)
        Dim R As Range
        Dim uniq As Long
        Dim Dups As Variant
        Dim v As String
    
        ReDim Dups(1 To 1) 'make room for the unique count
        v = ChrW(8203) 'seed out string hash check with the delimiter
    
        For Each R In MyRange
            If Not R.EntireRow.Hidden Then
                If CBool(InStr(1, v, ChrW(8203) & R.Value & ChrW(8203), vbTextCompare)) Then
                    ReDim Preserve Dups(1 To UBound(Dups) + 1)
                    Dups(UBound(Dups)) = R.Row
                Else
                    uniq = uniq + 1
                    v = v & R.Value & ChrW(8203)
                End If
            End If
        Next R
    
        Dups(LBound(Dups)) = uniq  'stuff the unique count into the primary of the array
    
        UniqueVisible = Dups
    
    End Function
    
    现在,我可能不会这样做。把整件事情写进一个子部分似乎更容易。但是,理解过程和限制很重要,所以我希望你能处理这个问题


    请注意,这没有任何错误控制。在处理数组和删除循环中的行时,应该会出现这种情况。

    我不知道。我试过了,如上所示。我还在做错事吗?请记住数组中的对象是行对象,所以您可能只需要执行“D.delete”而不是ws.Rows(D.delete)。您现在已经有了大致的想法,但我对VBA还不够了解,无法100%确定为什么它在没有积极调试的情况下无法工作。确保它确实正在将对象放入数组中。它是。我认为问题在于数组中要填充的元素多于行。当它通过所有重复项,并且下一个元素是“0”时,它抛出一个错误。我可能需要创建一个大小为(range.count-UniqueVisible)的新数组,并复制所有值以避免出现问题。理想情况下,每次需要向数组中添加行时,都会对该数组进行重新排序,这样它就永远不会比需要的大。如果您使用的是VB.NET,则可以使用更易于使用的ArrayList对象。显然(ws.Rows())返回一个只读对象。我不明白其他人是如何使用它的…VB.Net还是VBA?它们不是同一件事,同时拥有两个标签只会产生混乱。混乱首先是我的。看起来不错。我现在不在办公室。我会尽快测试的。我甚至不知道sub是一个东西。我没有得到
    v=ChrW(8203)
    InStr
    函数调用。。。其余的让老师觉得我明白了。您正在将
    v
    设置为空白字符,检查当前行值是否在
    v
    中,如果不是,则将当前行值添加到
    v
    并重复。您使用的不是字符串数组,而是单个字符串。
    uniq
    为什么需要填充在
    dup
    中,而不是直接插入
    UniqueVisible
    ChrW(8203)
    是零长度空间的unicode。我使用它作为分隔符,这样检查ace不会在脸上返回假阳性
    InStr
    检查一个字符串是否在另一个字符串中。通过收集一个字符串并连接一个分隔符,如果要检查的原始值在范围内,则该分隔符不太可能是一部分。如果找到,则该值是重复的。如果未找到,则将1添加到uniq,并将该值放入字符串中,以便在再次出现时将其作为副本找到。