【问题标题】:VBA Sum cells values from specific column if value in another column = Specific如果另一列中的值=特定,则VBA对特定列中的单元格值求和
【发布时间】:2021-08-09 08:38:34
【问题描述】:

如果“E”列中的值相同且“G”列中的值为“Kede”,我正在尝试对“I”列中的值求和并删除重复行。

我有一段我不完全理解的代码,我正在尝试根据我的需要进行修改。最初,此代码在“E”列中查找重复值,并在“I”列中求和,以删除重复的行。


'Declare variables
Dim AcSh As Worksheet, LastRow As Long, dict As Object
Dim rngDel As Range, arrE, arrInt, arrI, i As Long, dKey
 
Set AcSh = ActiveSheet
LastRow = AcSh.Range("E" & AcSh.Rows.Count).End(xlUp).Row
 
arrE = AcSh.Range("E2:E" & LastRow).Value
Set dict = CreateObject("Scripting.Dictionary")
 
'Sum and delete duplicates
On Error Resume Next
For i = 1 To UBound(arrE)

    If Not dict.Exists(arrE(i, 1)) Then
    dict.Add arrE(i, 1), AcSh.Range("I" & i + 1).Address & "|" & CDbl(AcSh.Range("I" & i + 1).Value)
    Else
    arrInt = Split(dict(arrE(i, 1)), "|")
    dict(arrE(i, 1)) = arrInt(0) & "|" & CDbl(arrInt(1)) + CDbl(AcSh.Range("I" & i + 1).Value)
    
    If rngDel Is Nothing Then
    Set rngDel = AcSh.Range("E" & i + 1)
    Else
    Set rngDel = Union(rngDel, AcSh.Range("E" & i + 1))
    End If
    End If
    
Next i
 
On Error Resume Next
ReDim arrI(1 To LastRow, 1 To 1)

    For Each dKey In dict.keys()
    arrInt = Split(dict.Item(dKey), "|")
    arrI(Range(arrInt(0)).Row - 1, 1) = CDbl(arrInt(1))
    Next
    If Not rngDel Is Nothing Then
    AcSh.Range("I2").Resize(LastRow - 1, 1).Value = arrI
    rngDel.EntireRow.Delete
    End If

这就是我目前所拥有的


'Declare variables
     Dim AcSh As Worksheet, LastRow As Long, dict As Object
     Dim rngDel As Range, arrG, arrInt, arrI, i As Long, dKey
 
     Set AcSh = ActiveSheet
     LastRow = AcSh.Range("G" & AcSh.Rows.Count).End(xlUp).Row
 
     arrG = AcSh.Range("G2:G" & LastRow).Value
     Set dict = CreateObject("Scripting.Dictionary")

'Sum and delete duplicates
On Error Resume Next
For i = 1 To UBound(arrG)

If Not dict.Exists(arrG(i, 1)) And ThisWorkbook.Worksheets("BOM").Range(i, G).Value = "Kede" Then

dict.Add arrG(i, 1), AcSh.Range("I" & i + 1).Address & "|" & CDbl(AcSh.Range("I" & i + 1).Value)
Else:
arrInt = Split(dict(arrG(i, 1)), "|")
dict(arrG(i, 1)) = arrInt(0) & "|" & CDbl(arrInt(1)) + CDbl(AcSh.Range("I" & i + 1).Value)
    
    If rngDel Is Nothing Then
    Set rngDel = AcSh.Range("G" & i + 1)
    Else:
    Set rngDel = Union(rngDel, AcSh.Range("G" & i + 1))
    End If
End If

Next i

On Error Resume Next
ReDim arrI(1 To LastRow, 1 To 1)

For Each dKey In dict.keys()
    arrInt = Split(dict.Item(dKey), "|")
    arrI(Range(arrInt(0)).Row - 1, 1) = CDbl(arrInt(1))
Next

If Not rngDel Is Nothing Then
AcSh.Range("I2").Resize(LastRow - 1, 1).Value = arrI
rngDel.EntireRow.Delete
End If

所以基本上我试图在原始代码中添加一个更多标准,如果“G”列中的值是“Kede”,它也会查找。 有人可以帮我修改这段代码并向我解释得更清楚吗?

【问题讨论】:

    标签: excel vba sum


    【解决方案1】:

    如果我理解正确,您想忽略并删除 G 列中没有“Kede”的行。如果是这样,这段代码应该通过在开头删除它们来解决问题。

        'Declare variables
        Dim AcSh As Worksheet, LastRow As Long, dict As Object
        Dim rngDel As Range, arrE, arrInt, arrI, i As Long, dKey
         
     
        Set AcSh = ActiveSheet
        LastRow = AcSh.Range("E" & AcSh.Rows.Count).End(xlUp).Row
        
        'Remove non-Kede rows and reset LastRow
        For i = LastRow + 1 To 2 Step -1
            If AcSh.Range("G" & i).Value <> "Kede" Then AcSh.Range("G" & i).EntireRow.Delete
        Next i
        LastRow = AcSh.Range("E" & AcSh.Rows.Count).End(xlUp).Row
        
        arrE = AcSh.Range("E2:E" & LastRow).Value
        Set dict = CreateObject("Scripting.Dictionary")
         
         
        'Sum and delete duplicates
        On Error Resume Next
        For i = 1 To UBound(arrE)
        
            If Not dict.Exists(arrE(i, 1)) Then
            dict.Add arrE(i, 1), AcSh.Range("I" & i + 1).Address & "|" & CDbl(AcSh.Range("I" & i + 1).Value)
            Else
            arrInt = Split(dict(arrE(i, 1)), "|")
            dict(arrE(i, 1)) = arrInt(0) & "|" & CDbl(arrInt(1)) + CDbl(AcSh.Range("I" & i + 1).Value)
            
            If rngDel Is Nothing Then
            Set rngDel = AcSh.Range("E" & i + 1)
            Else
            Set rngDel = Union(rngDel, AcSh.Range("E" & i + 1))
            End If
            End If
            
        Next i
         
        On Error Resume Next
        ReDim arrI(1 To LastRow, 1 To 1)
    
        For Each dKey In dict.keys()
        arrInt = Split(dict.Item(dKey), "|")
        arrI(Range(arrInt(0)).Row - 1, 1) = CDbl(arrInt(1))
        Next
        If Not rngDel Is Nothing Then
        AcSh.Range("I2").Resize(LastRow - 1, 1).Value = arrI
        rngDel.EntireRow.Delete
        End If
    
    

    编辑:感谢下面的 cmets,我相信我现在明白了您的期望。我很确定这不是解决问题的最有说服力的方法,但我认为它有效。请尝试。

        'Declare variables
        Dim AcSh As Worksheet, LastRow As Long, dict As Object
        Dim rngDel As Range, arrE, arrInt, arrI, i As Long, dKey
         
        
    
        
        Set AcSh = ActiveSheet
        LastRow = AcSh.Range("E" & AcSh.Rows.Count).End(xlUp).Row
        
        'Remove non-Kede rows and reset LastRow
       ' For i = LastRow + 1 To 2 Step -1
       '     If AcSh.Range("G" & i).Value <> "Kede" Then AcSh.Range("G" & i).EntireRow.Delete
       ' Next i
        LastRow = AcSh.Range("E" & AcSh.Rows.Count).End(xlUp).Row
        
        arrE = AcSh.Range("E2:E" & LastRow).Value
        arrG = AcSh.Range("G2:G" & LastRow).Value
        Set dict = CreateObject("Scripting.Dictionary")
         
         
    
        'Sum and delete duplicates
        On Error Resume Next
        For i = 1 To UBound(arrE)
        
            If Not dict.Exists(arrE(i, 1) & arrG(i, 1)) Then
                dict.Add arrE(i, 1) & arrG(i, 1), AcSh.Range("I" & i + 1).Address & "|" & CDbl(AcSh.Range("I" & i + 1).Value)
            ElseIf arrG(i, 1) = "Kede" Then
                arrInt = Split(dict(arrE(i, 1) & arrG(i, 1)), "|")
                dict(arrE(i, 1) & arrG(i, 1)) = arrInt(0) & "|" & CDbl(arrInt(1)) + CDbl(AcSh.Range("I" & i + 1).Value)
                
                If rngDel Is Nothing Then
                    Set rngDel = AcSh.Range("E" & i + 1)
                Else
                    Set rngDel = Union(rngDel, AcSh.Range("E" & i + 1))
                End If
            Else
                dict.Add AcSh.Range("E" & i + 1).Address, AcSh.Range("I" & i + 1).Address & "|" & CDbl(AcSh.Range("I" & i + 1).Value)
            End If
            
        Next i
         
        On Error Resume Next
        ReDim arrI(1 To LastRow, 1 To 1)
    
        For Each dKey In dict.keys()
            arrInt = Split(dict.Item(dKey), "|")
            arrI(Range(arrInt(0)).Row - 1, 1) = CDbl(arrInt(1))
        Next
        If Not rngDel Is Nothing Then
            AcSh.Range("I2").Resize(LastRow - 1, 1).Value = arrI
            rngDel.EntireRow.Delete
        End If
    

    【讨论】:

    • 感谢您的回答,朋友!不,我只想对具有“Kede”的行的值求和。换句话说,我在“I”中有数量/长度,在“E”中有一个零件名称。 “科德”意为“链条”。所以我只想总结列表中具有相同零件名称的链的数量。因为我可能有多个所述链的相同零件名称的实例,所以我希望删除所有重复的行,留下具有总和数量的行。除了列表中的“链”项之外,我可能还有数千种其他类型的部件,它们必须保持不变
    • 我基本上有一个巨大的列表,除了其他项目之外还有链节的各个部分。以及它们的数量(以 pcs 为单位)。我有一个可以翻译 pcs 的宏。仅对链节部分进行长度调整。除此之外,我的宏还重命名了那些单独的链节名称,以便我知道同名链节属于同一个链段。现在我需要根据“E”中的值来总结链的长度。但是我如何区分所有项目以仅确定链的方式是“G”中的值必须是“Kede”,这就是我如何知道实例是链
    • 如果我在运行之前只过滤“Kede”项目,我的原始代码似乎仍然可以满足我的需求
    • 我想我得到了你想要的。查看上面的更新代码
    【解决方案2】:

    这段代码肯定有点混乱。本质上,他们正在使用来自 E:E 的键和来自 I:I 的值制作一个字典。可能可以重做,但我可以建议一个更简单的替代方案:数据透视表。它们更灵活,更不容易折断。我整理了一张模拟表,以表明您希望它看起来像:

    自己做这个:

    1. 选择包含数据的列 (E:I)
    2. 单击插入 -> 数据透视表
    3. 将列 E:E、G:G 和 I:I 的标题名称拖动到图片中 Column1、Column2 和 Column3 所在的位置。
    4. 更换过滤器科德

    我希望这会有所帮助!如果您有任何问题,我会尽力提供帮助。

    【讨论】:

    • 感谢您的回答!不幸的是,我不允许将任何临时或附加数据写入工作表。我需要它发生在宏中。这就是它的全部意义
    • 该死。我希望这会奏效。如果有帮助,您可以将数据透视表放在不同的工作表甚至不同的工作簿中。我看了一下宏,它确实假设每一行都涉及。在我重写代码之前,我需要知道您希望其他单元格会发生什么。
    • 顺便说一句,原始代码完美地完成了它的工作。它在“E”列中查找相同的值,并将它们在“I”列中的值相加。并删除重复的行,只留下一个与“I”中的总和值相同的行。我要添加的附加规则是,它还必须查看列“G”是否具有值“Kede”,然后才认为它是一个有效的求和行,你知道吗?
    • 好的。我更新了代码并将其发布到单独的答案中,以使两种解决方案分开。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 2015-07-20
    • 2018-10-06
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    相关资源
    最近更新 更多