使用VBA DIctionary根据多个标准对具有相同ID的行进行求和

时间:2018-03-02 21:57:37

标签: excel excel-vba dictionary vba

我正在尝试(目前通过字典)来解决以下示例数据:

Sales Amount     Product       ID        Count
    100           apple      123ABC       1
    50            apple      456DEF       2
    50            apple      456DEF       2
    200           orange     456DEF       2
    200           orange     456DEF       2
    900           tomato     789GHI       1
    75            orange     999PPP       2
    25            apple      999PPP       2
    25            apple      999PPP       2

我需要做的是:对于count> 1的任何行,将所有共享ID但具有不同产品的行的销售额相加。然后,我想在Sales Amount列中的现有值上写入和值。最终结果如下:

  Sales Amount   Product       ID        Count
    100           apple      123ABC       1
    250           apple      456DEF       2
    250           apple      456DEF       2
    250           orange     456DEF       2
    250           orange     456DEF       2
    900           tomato     789GHI       1
    100           orange     999PPP       2
    100           apple      999PPP       2
    100           apple      999PPP       2

棘手的部分是我只想每Sales Amount使用一次product。所以例如ID 456DEF,我只想为苹果添加50,为橙添加200。我当前的代码(见下文)将每个ID的Sales Amount列中的所有值相加。因此,鉴于相同的示例ID 456DEF,我的代码在ID的每一行输出Sales Amount 500(200 + 200 + 50 + 50)。

当前代码:

Sub WontWorkYet

Dim x, x2, y, y2()
Dim i As Long
Dim dict As Object
Dim LastRowForDict As Long, LastRowResult As Long, shtSource As      Worksheet, shtResult As Worksheet
Dim p As Long


Set dict = CreateObject("Scripting.Dictionary")
Set ws = Worksheets("Sheet1")

With ws

    LastRowForDict = .Range("A" & Rows.Count).End(xlUp).Row

For p = 1 To LastRowForDict

    If ws.Cells(p, 4) > 1 Then               'checks if count column for unique products is >1

    x = .Range("C1:C" & LastRowForDict).Value
    x2 = .Range("A1:A" & LastRowForDict).Value


        'If key exists already ADD new value (SUM them)


If Not dict.exists(x(p, 1)) Then
    dict.Item(x(p, 1)) = x2(p, 1)
Else
   dict.Item(x(p, 1)) = CDbl(dict.Item(x(p, 1))) + CDbl(x2(p, 1))
End If

End If
Next p


End With


'map the values
  With ws
    LastRowResult = .Range("A" & Rows.Count).End(xlUp).Row
    y = .Range("C2:C" & LastRowResult).Value    'looks up to this range
  y2 = .Range("A2:A" & LastRowForDict).Value   'Sizes the output array without a Re-Dim which allows existing values to not be wiped out in column CL


    For i = 1 To UBound(y, 1)
        If dict.exists(y(i, 1)) Then
            y2(i, 1) = dict(y(i, 1))
       Else


        End If
    Next i
    .Range("A2:A" & LastRowResult).Value = y2  '<< place the output on the sheet
End With


End Sub

我的想法是将IDProduct联系起来然后删除此行,该行汇总已存在的密钥:dict.Item(x(p, 1)) = CDbl(dict.Item(x(p, 1))) + CDbl(x2(p, 1))。这会将值正确地存储(我相信)在字典中,但后来我试图找到一种方法来完成整个过程,方法是将每个ID的存储量相加并将它们正确地写入工作表。

我知道可以使用数组公式来解决这个问题,但我使用的数据集很大,数组公式太慢了。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

首先,试试这个公式。还是太慢了吗?

=SUMPRODUCT($A$2:$A$10/COUNTIFS($B$2:$B$10,$B$2:$B$10,$C$2:$C$10,$C$2:$C$10),--($C$2:$C$10=C2))

其次,在删除重复项的帮助下,这可以是一个简单的操作。试试这个:

  1. 将所有数据粘贴到sheet2中,选择整个范围,然后点击数据&gt;删除重复项&gt;确定
  2. 您在sheet2中的数据现在如下所示:

    Sales Amount    Product ID  Count
    100    apple    123ABC      1
    50     apple    456DEF      2
    200    orange   456DEF      2
    900    tomato   789GHI      1
    75     orange   999PPP      2
    25     apple    999PPP      2
    
    1. 现在回到您的第一张桌子并在A2中放置以下公式并向下拖动:

      = SUMIF(Sheet 2中C:!C,Sheet 1中C2,Sheet2的一个:!A)

    2. Et voila ,视需要而定。全部来自一个简单快捷的SUMIF公式。

      Sales Amount    Product ID  Count
      100     apple   123ABC      1
      250     apple   456DEF      2
      250     apple   456DEF      2
      250     orange  456DEF      2
      250     orange  456DEF      2
      900     tomato  789GHI      1
      100     orange  999PPP      2
      100     apple   999PPP      2
      100     apple   999PPP      2
      

      使用VBA也可以轻松实现这样一个简单的过程。