使用 Excel VBA 宏基于 A 列求和 B 列

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10112604/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 12:55:05  来源:igfitidea点击:

Sum Column B based on Column A using Excel VBA Macro

excelvbaexcel-vbaexcel-2003

提问by Stephan Daudt

OK, I have a simple problem that I need help with in a VBA Macro. I have an excel sheet that looks like this...

好的,我有一个简单的问题需要在 VBA 宏中获得帮助。我有一个看起来像这样的excel表......

Product #     Count
101              1
102              1
101              2
102              2
107              7
101              4
101              4
189              9

I need a macro that adds up the "count" column based on the Product Number Column. I want it to over all look like this after I am done...

我需要一个根据产品编号列添加“计数”列的宏。我希望它在我完成后看起来像这样......

Product #    Count
101              7
102              7
107              7
189              9

I am an amiture to VBA so I would love any help I can get.

我是 VBA 的朋友,所以我希望能得到任何帮助。

回答by assylias

Assuming the data is in columns A and B, you can do it with a formula:

假设数据在 A 列和 B 列中,您可以使用公式:

=SUMIF(A:A,101,B:B)

Or if you put 101 in C1:

或者,如果您将 101 放入 C1:

=SUMIF(A:A,C1,B:B)

EDIT

编辑

However if you still require VBA, here is my (quick and dirty) proposal - I use a dictionary to keep track of the sum for each item.

但是,如果您仍然需要 VBA,这是我的(快速而肮脏的)建议 - 我使用字典来跟踪每个项目的总和。

Sub doIt()

  Dim data As Variant
  Dim i As Long
  Dim countDict As Variant
  Dim category As Variant
  Dim value As Variant

  Set countDict = CreateObject("Scripting.Dictionary")

  data = ActiveSheet.UsedRange 'Assumes data is in columns A/B

  'Populate the dictionary: key = category / Item = count
  For i = LBound(data, 1) To UBound(data, 1)
    category = data(i, 1)
    value = data(i, 2)
    If countDict.exists(category) Then
      countDict(category) = countDict(category) + value 'if we have already seen that category, add to the total
    Else
      countDict(category) = value 'first time we find that category, create it
    End If
  Next i

  'Copy dictionary into an array
  ReDim data(1 To countDict.Count, 1 To 2) As Variant

  Dim d As Variant
  i = 1
  For Each d In countDict
    data(i, 1) = d
    data(i, 2) = countDict(d)
    i = i + 1
  Next d

  'Puts the result back in the sheet in column D/E, including headers
  With ActiveSheet
    .Range("D1").Resize(UBound(data, 1), UBound(data, 2)) = data
  End With

End Sub

回答by Joseph

The easiest thing is to use a Pivot Table in this case as Tim suggested.

在这种情况下,最简单的方法是按照 Tim 的建议使用数据透视表。

enter image description here

在此处输入图片说明

回答by Joseph

Here is a VBA solution that uses multidimensional arrays. I noticed you said you are a bit new to VBA so I tried to put some meaningful comments in there. One thing that might look strange is when I redimension the arrays. That's because when you have multidimensional arrays you can only ReDim the last dimension in the array when you use the Preserve keyword.

这是一个使用多维数组的 VBA 解决方案。我注意到你说你对 VBA 有点陌生,所以我试着在那里发表一些有意义的评论。可能看起来很奇怪的一件事是当我重新调整数组的大小时。这是因为当您拥有多维数组时,您只能在使用 Preserve 关键字时重新调整数组中的最后一个维度。

Here is how my data looked:

这是我的数据的外观:

Product Count
101     1
102     1
101     2
102     2
107     7
101     4
101     4
189     9

And here is the code. It has the same output as my last answer. Test this in a new workbook and put the test data in Sheet1 with headers.

这是代码。它的输出与我上一个答案相同。在新的工作簿中对此进行测试,并将测试数据放在带有标题的 Sheet1 中。

Option Explicit

Sub testFunction()
    Dim rng As Excel.Range
    Dim arrProducts() As String
    Dim i As Long

    Set rng = Sheet1.Range("A2:A9")

    arrProducts = getSumOfCountArray(rng)

    Sheet2.Range("A1:B1").Value = Array("Product", "Sum of Count")

    ' go through array and output to Sheet2
    For i = 0 To UBound(arrProducts, 2)
        Sheet2.Cells(i + 2, "A").Value = arrProducts(0, i)
        Sheet2.Cells(i + 2, "B").Value = arrProducts(1, i)
    Next

End Sub

' Pass in the range of the products
Function getSumOfCountArray(ByRef rngProduct As Excel.Range) As String()
    Dim arrProducts() As String
    Dim i As Long, j As Long
    Dim index As Long

    ReDim arrProducts(1, 0)

    For j = 1 To rngProduct.Rows.Count
        index = getProductIndex(arrProducts, rngProduct.Cells(j, 1).Value)
        If (index = -1) Then
            ' create value in array
            ReDim Preserve arrProducts(1, i)
            arrProducts(0, i) = rngProduct.Cells(j, 1).Value ' product name
            arrProducts(1, i) = rngProduct.Cells(j, 2).Value ' count value
            i = i + 1
        Else
            ' value found, add to id
            arrProducts(1, index) = arrProducts(1, index) + rngProduct.Cells(j, 2).Value
        End If
    Next

    getSumOfCountArray = arrProducts
End Function

Function getProductIndex(ByRef arrProducts() As String, ByRef strSearch As String) As Long
    ' returns the index of the array if found
    Dim i As Long
    For i = 0 To UBound(arrProducts, 2)
        If (arrProducts(0, i) = strSearch) Then
            getProductIndex = i
            Exit Function
        End If
    Next

    ' not found
    getProductIndex = -1
End Function

回答by Freelancer

Sub BestWaytoDoIt()

Dim i As Long                    ' Loop Counter
Dim int_DestRwCntr As Integer    ' Dest. sheet Counter
Dim dic_UniquePrd As Scripting.Dictionary
Set dic_UniquePrd = New Scripting.Dictionary

For i = 2 To Sheet1.Range("A" & Sheet1.Cells.Rows.Count - 1).End(xlUp).Row
    If dic_UniquePrd.exist(Sheet1.Range("A" & i).Value) <> True Then
        dic_UniquePrd.Add Sheet1.Range("A" & i).Value, DestRwCntr
        sheet2.Range("A" & int_DestRwCntr).Value = Sheet1.Range("A" & i).Value
        sheet2.Range("B" & int_DestRwCntr).Value = Sheet1.Range("B" & i).Value
    Else
        sheet2.Range("A" & dic_UniquePrd.Item(Sheet1.Range("A" & i).Value)).Value = sheet2.Range("B" & dic_UniquePrd.Item(Sheet1.Range("A" & i).Value)).Value + Sheet1.Range("B" & i).Value
    End If
Next
End Sub

This will serve the purpose.. Only thing to remember is to activate "Microsoft Scripting Runtimes" in references.

这将达到目的.. 唯一要记住的是在参考中激活“Microsoft Scripting Runtimes”。

回答by user1579247

Based the code in Sub doIt(), is possible in the for Each ycle to retrive also the number of occurence?

基于 Sub doIt() 中的代码,是否可以在 for Each ycle 中检索出现次数?

Example:

例子:

Product # 101 have 4 occurence

产品 # 101 有 4 次出现

Product # 102 have 2 occurence ecc...

产品 # 102 有 2 次出现 ecc...

回答by user3598756

I know it' late... but I've been brought here by Sum up column B based on colum C valuesand so I post a solution with the same "formula" approach I used there but adapted to this actual need

我知道已经晚了......但是我已经根据列 C 值总结 B 列将我带到这里,所以我发布了一个解决方案,该解决方案与我在那里使用的相同“公式”方法但适应了这种实际需要

Option Explicit

Sub main()

    With ActiveSheet
        With .Range("A:B").Resize(.cells(.Rows.Count, 1).End(xlUp).row) '<== here adjust "A:B" to whatever colums range you need
            With .Offset(1).Resize(.Rows.Count - 1)
                .Offset(, .Columns.Count).Resize(, 1).FormulaR1C1 = "=SUMIF(C1,RC1,C2)" ' "helper" column: it's the 1st column right of data columns (since ".Offset(, .Columns.Count)")
                .Columns(2).Value = .Offset(, .Columns.Count).Resize(, 1).Value 'update "count" with sum-up from "helper" column

                With .Offset(, .Columns.Count).Resize(, 1) ' reference to "helper" column
                    .FormulaR1C1 = "=IF(countIF(R1C1:RC1,RC1)=1,1,"""")" ' locate Product# repetition with blank cells
                    .Value = .Value 'fix values
                    .SpecialCells(xlCellTypeBlanks).EntireRow.Delete 'delete rows corresponding to blank cells
                    .ClearContents ' clear "helper" column
                End With
            End With
        End With
    End With

    End Sub

it makes use of a "helper" columns, which I assumed could be the one adjacent to the last data columns (i.e.: if data columns are "A:B" then helper column is "C")

它使用了一个“辅助”列,我认为它可能是与最后一个数据列相邻的列(即:如果数据列是“A:B”,那么辅助列是“C”)

should different "helper" column be needed then see comments about how it's located and change code accordingly

如果需要不同的“助手”列,然后查看有关它如何定位的注释并相应地更改代码