【问题标题】:Excel copy/sort data while counting/removing duplicatesExcel 在计算/删除重复项时复制/排序数据
【发布时间】:2013-08-03 20:42:48
【问题描述】:

好的,所以我搜索了又搜索,但找不到我要找的东西。

我有一本工作簿,我基本上想做的是从特定范围(Sheet1 - E4:E12、E14:E20、I4:I7、I9:I12、I14:I17 和 I19:I21 ) 并将它们放在 Sheet2 上的单独列表中。然后,我希望 Sheet2 上的新列表按照条目在 Sheet1 上出现的次数进行排序,并显示数量。

example http://demonik.doomdns.com/images/excel.png

显然,从我上面列出的范围可以看出,这个样本要小得多,哈哈,只是在试图弄清楚如何描述所有内容时遇到了麻烦,并认为图像会有所帮助。

基本上我正在尝试使用 VBA(通过点击按钮来初始化更新)从 Sheet1 复制数据并将所有范围放入 Sheet2 中的一个列表中,该列表按它在 Sheet1 上出现的次数排序,然后按字母顺序。

如果需要更好的描述,请发表评论并告诉我,我一直很讨厌试图描述这样的东西,哈哈。

提前致谢!

另一个细节:我不能让它搜索特定的东西,因为 Sheet1 范围内的数据可能会发生变化。一切都必须是动态的。

【问题讨论】:

    标签: sorting excel duplicates vba


    【解决方案1】:

    我从这些数据开始

    并使用以下代码将其读入数组,对数组进行排序,计算重复值,然后将结果输出到sheet2

    Sub Example()
        Dim vCell As Range
        Dim vRng() As Variant
        Dim i As Integer
    
        ReDim vRng(0 To 0) As Variant
    
        Sheets("Sheet2").Cells.Delete
        Sheets("Sheet1").Select
    
        For Each vCell In ActiveSheet.UsedRange
            If vCell.Value <> "" Then
                ReDim Preserve vRng(0 To i) As Variant
                vRng(i) = vCell.Value
                i = i + 1
            End If
        Next
    
        vRng = CountDuplicates(vRng)
    
        Sheets("Sheet2").Select
        Range(Cells(1, 1), Cells(UBound(vRng), UBound(vRng, 2))) = vRng
        Rows(1).Insert
        Range("A1:B1") = Array("Entry", "Times Entered")
        ActiveSheet.UsedRange.Sort Range("B1"), xlDescending
    End Sub
    
    Function CountDuplicates(List() As Variant) As Variant()
        Dim CurVal As String
        Dim NxtVal As String
        Dim DupCnt As Integer
        Dim Result() As Variant
        Dim i As Integer
        Dim x As Integer
        ReDim Result(1 To 2, 0 To 0) As Variant
    
        List = SortAZ(List)
    
        For i = 0 To UBound(List)
            CurVal = List(i)
    
            If i = UBound(List) Then
                NxtVal = ""
            Else
                NxtVal = List(i + 1)
            End If
    
            If CurVal = NxtVal Then
                DupCnt = DupCnt + 1
            Else
                DupCnt = DupCnt + 1
                ReDim Preserve Result(1 To 2, 0 To x) As Variant
    
                Result(1, x) = CurVal
                Result(2, x) = DupCnt
    
                x = x + 1
                DupCnt = 0
            End If
        Next
        Result = WorksheetFunction.Transpose(Result)
        CountDuplicates = Result
    End Function
    
    Function SortAZ(MyArray() As Variant) As Variant()
        Dim First As Integer
        Dim Last As Integer
        Dim i As Integer
        Dim x As Integer
        Dim Temp As String
    
        First = LBound(MyArray)
        Last = UBound(MyArray)
    
        For i = First To Last - 1
            For x = i + 1 To Last
                If MyArray(i) > MyArray(x) Then
                    Temp = MyArray(x)
                    MyArray(x) = MyArray(i)
                    MyArray(i) = Temp
                End If
            Next
        Next
    
        SortAZ = MyArray
    End Function
    

    最终结果:

    【讨论】:

    • 太棒了,谢谢。我会做一些小的调整,让它把信息准确地放在我想要的地方,但是你的代码可以满足我的需要!谢谢
    • 是的,我没有对最终结果进行排序或添加列标题。它应该很容易添加。如果您对任何代码在做什么有疑问,我很乐意解释它或返回并添加 cmets。我没有对此进行任何测试,但是如果您有大量数据要输出到某个范围并让 excel 对其进行排序,然后将其读回,它可能会更快。SortAZ 代码只是在进行冒泡排序,它不是那么快。
    • 它没有做的一件事是首先按数量对数据进行排序。 (使用您的样本,它将首先对 B 列进行排序,然后在数量范围内对 A 进行排序,即在您的最终结果图像中,A 列的顺序将是 c、d、a、b、e)如果这是可能的
    • (这不是问题,我可以处理,只需将评论放在那里,所以如果其他人以这个答案为例,他们会意识到这一点)
    • 再次感谢,现在一切都完成了,您的代码完成了工作,然后我添加了代码来移动已排序的数据并将其分成两列,填充颜色和边框等。
    【解决方案2】:

    这是我为您准备的一个可能的解决方案。你要求做的事情变得相当复杂。这是我到目前为止所拥有的: 显式选项

    Sub test()
        Dim items() As String
        Dim itemCount() As String
        Dim currCell As Range
        Dim currString As String
        Dim inArr As Boolean
        Dim arrLength As Integer
        Dim iterator As Integer
        Dim x As Integer
        Dim fullRange As Range
        Set fullRange = Range("E1:E15")
        iterator = 0
    
        For Each cell In fullRange 'cycle through the range that has the values
            inArr = False
            For Each currString In items 'cycle through all values in array, if
            'values is found in array, then inArr is set to true
                If currCell.Value = currString Then 'if the value in the cell we
                'are currently checking is in the array, then set inArr to true
                    inArr = True
                End If
            Next
            If inArr = False Then 'if we did not find the value in the array
                arrLength = arrLength + 1
                ReDim Preserve items(arrLength) 'resize the array to fit the new values
                items(iterator) = currCell.Value 'add the value to the array
                iterator = iterator + 1
            End If
        Next
        'This where it gets tricky. Now that you have all unique values in the array,
        'you will need to count how many times each value is in the range.
        'You can either make another array to hold those values or you can
        'put those counts on the sheet somewhere to store them and access them later.
        'This is tough stuff! It is not easy what you need to be done.
        For x = 1 To UBound(items)
    
        Next
    
    End Sub
    

    到目前为止,它所做的只是将唯一值放入数组中,以便您可以计算每个值在该范围内的次数。

    【讨论】:

    • 好的,午饭后我看看那个,看看我能不能从那里得到它。感谢您的快速回复
    • 午餐前有一个小时,哈哈,brainfart,你 Dim itemcount(),但永远不要使用它...这是为空循环中的需要做准备吗?
    • 是的,我正在考虑对每个元素进行计数并将计数保留在数组中,但要保持两个数组同步并在另一个数组中的值的键获取时表现得好像一个黏。这就是为什么我认为您可以使用字典或将计数粘贴在某处的地方保持清洁。
    • excels VBA可以使用多维数组吗?如果可以的话,似乎会更容易。 (即在主循环中,如果不在数组中,则向数组添加条目,如果在其中存储增量 num,则类似于 item(x,y) 其中 x 是条目,y 是计数。
    • 是的,这就是字典。我对它们不太熟悉,它们可能很难处理,但这里有一个 link 到 MSDN 谈论它们,这里是一个使用示例:link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    • 2011-02-09
    • 2016-10-01
    • 2012-03-10
    • 1970-01-01
    • 2021-11-08
    相关资源
    最近更新 更多