excel - (VBA) 如何删除重复行并将相应值求和到右列?

标签 excel vba sum duplicates

我有一个“测试”Excel,其中有从 A-D 的 4 列。如果 A 和 B 值与另一行相同,宏将删除“较旧”行,并将另一行的相应值求和到 C 和 D 列中。

      A | B | C | D                         A | B | C | D 

 1    1 | 2 | 1 | 5                         2 | 3 | 2 | 5
 2    2 | 3 | 2 | 5                         2 | 6 | 2 | 5
 3    2 | 6 | 2 | 5      After Macro        1 | 2 | 4 | 9
 4    1 | 2 | 3 | 4      --------->         5 | 4 | 1 | 2
 5    5 | 4 | 1 | 2

已编辑!因此,这里第 1 行和第 4 行在 A 列和 B 列上具有相同的值,因此宏删除第 1 行并将第 1 行列 C D 值添加到第 4 行列 C D !!

我尝试过使用这段代码,但现在它只向 D 列添加值,而不是向 C 列添加值。我真的不知道该怎么做。这是我的代码:

    Private Sub CommandButton1_Click()

    Dim i As Long, lrk As Long, tmp As Variant, vals As Variant

        With Worksheets(1)
            tmp = .Range(.Cells(2, "A"), .Cells(Rows.Count, "D").End(xlUp)).Value2
            ReDim vals(LBound(tmp, 1) To UBound(tmp, 1), 1 To 1)
            For i = LBound(vals, 1) To UBound(vals, 1)
                vals(i, 1) = Application.SumIfs(.Columns(3), .Columns(1), tmp(i, 1), Columns(2), tmp(i, 2), Columns(3), tmp(i, 3), Columns(4), tmp(i, 4))

            Next i
            .Cells(2, "D").Resize(UBound(vals, 1), UBound(vals, 2)) = vals
            With .Cells(1, "A").CurrentRegion
                .RemoveDuplicates Columns:=Array(1, 2, 3, 4), Header:=xlYes
            End With
        End With
    End Sub

实际的 Excel 有近 2000 行..所以我也希望这个宏足够快。感谢您的帮助,我对我的英语感到抱歉。我希望你能理解:)

最佳答案

好吧,答案很大程度上基于 this我最近给出的答案。 @DisplayName 在同一个线程中还有另一个聪明的答案,您可能想利用它,但这是我对使用类模块和字典的可理解方法的看法。


假设以下输入数据从A1开始:

| 1 | 2 | 1 | 5 |
| 2 | 3 | 2 | 5 |
| 2 | 6 | 2 | 5 |
| 1 | 2 | 3 | 4 |
| 5 | 4 | 1 | 2 |

首先创建一个class模块并为其命名,例如:clssList,其中包含以下代码:

Public Col1 As Variant
Public Col2 As Variant
Public Col3 As Variant
Public Col4 As Variant

第二创建一个模块,并在其中放入以下代码:

Sub BuildList()

Dim x As Long, arr As Variant, lst As clssList
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")

'Fill array variable from sheet
With Sheet1
    x = .Cells(.Rows.Count, 1).End(xlUp).Row
    arr = .Range("A1:D" & x).Value
End With

'Load array into dictionary with use of class
For x = LBound(arr) To UBound(arr)
    If Not dict.Exists(arr(x, 1) & "|" & arr(x, 2)) Then
        Set lst = New clssList
        lst.Col1 = arr(x, 1)
        lst.Col2 = arr(x, 2)
        lst.Col3 = arr(x, 3)
        lst.Col4 = arr(x, 4)
        dict.Add arr(x, 1) & "|" & arr(x, 2), lst
    Else 'In case column 2 is the same then add the values to the lst object
        dict(arr(x, 1) & "|" & arr(x, 2)).Col3 = dict(arr(x, 1) & "|" & arr(x, 2)).Col3 + arr(x, 3)
        dict(arr(x, 1) & "|" & arr(x, 2)).Col4 = dict(arr(x, 1) & "|" & arr(x, 2)).Col4 + arr(x, 4)
    End If
Next x

'Transpose dictionary into sheet3
With Sheet1
    x = 1
    For Each Key In dict.Keys
        .Cells(x, 6).Value = dict(Key).Col1
        .Cells(x, 7).Value = dict(Key).Col2
        .Cells(x, 8).Value = dict(Key).Col3
        .Cells(x, 9).Value = dict(Key).Col4
        x = x + 1
    Next Key
End With

End Sub

这有点广泛,但我以这样的方式编写,这样很容易理解发生了什么。对于 20000 条记录来说应该相当快。


上面的结果是一个从范围 F1 开始的矩阵,如下所示:

enter image description here


Running a speed test on 100.000 rows returned a total elapsed time of around 3,4 seconds. 20.000 Records came down to around 1,8 seconds.


另一种更短(编写代码,而不是速度)的方法是不使用类模块并连接数组项(您将使用的分隔符存在于值中的风险很小)。顶部的链接中显示了一个示例。我刚刚看到 @RonRosenFeld 举了一个关于如何使用它的示例。

关于excel - (VBA) 如何删除重复行并将相应值求和到右列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58391896/

相关文章:

dependencies - OpenMP : communicating values between threads 中的并行累积(前缀)总和

mysql varchar 列的聚合函数

python - 将数组写入 csv python(一列)

excel - VBA 属性 Let - 两个参数

excel - (10*1.11=11.1) 评估为 FALSE。如何纠正

Word 中的 VBA : Programmatically add content control with a style

python - 如何使用 win32com.client 通过 python 将 XLA 添加到 Excel 中?

vba - 调试 VBA 中的空格

vba - 获取括号之间的值

prolog - 在 Prolog 中计算总和