【问题标题】:Sum unique values with multiple criteria对具有多个条件的唯一值求和
【发布时间】:2018-05-04 14:25:18
【问题描述】:

你好,
我需要一个等效的公式来根据某些标准对唯一值求和。 我想要的结果在E 列中。有 2 个条件(D 列的第一个条件和第二个条件,B 列必须是 ">10"

现在我使用这个公式: {=SUM(IF(FREQUENCY(IF($A$2:$A$10=D2,IF($B$2:$B$10>10,MATCH($B$2:$B$10,$B$2:$B$10,0))),ROW($B$2:$B$10)-ROW($B$2)+1),$B$2:$B$10))}

这个公式的问题在于,它不能用FormulaArray inVBA 设置。我知道我可以使用evaluate 来提取结果,但我想要的只是每个都有一个公式E 列中的单元格,可以计算正确。

谢谢!

【问题讨论】:

  • 为什么不使用循环?
  • 我不明白你的意思
  • 不要使用公式,而是使用带有嵌套 IF 条件的循环。
  • 也许先Remove Duplicates 然后使用SUMIFS 可以做到。
  • “这个公式的问题,是它不能用VBA中的FormulaArray设置。”:为什么不呢?只是:Range("E2").FormulaArray = "=SUM(IF(FREQUENCY(IF($A$2:$A$10=D2,IF($B$2:$B$10>10,MATCH($B$2:$B$10,$B$2:$B$10,0))),ROW($B$2:$B$10)-ROW($B$2)+1),$B$2:$B$10))" : Range("E2:E4").FillDown

标签: vba excel


【解决方案1】:

在找到一种可行的方法之前,我必须尝试几种方法,但我想通了。

将这些函数粘贴到一个模块中:

Public Function SumIfIf(rgeData As Range, matchCriteria As String, numCompCriteria As String) As Double

    Dim c As Range, arr_Distinct() As String, x As Long, totalOut As Double, str_ConcatRgeRow As String
    ReDim arr_Distinct(0)
    
    totalOut = 0
    If InStr("<>=", Left(numCompCriteria, 1)) = 0 Then numCompCriteria = "=" & numCompCriteria

    For Each c In rgeData.Columns(1).Cells
        str_ConcatRgeRow = c.Value & c.Offset(0, rgeData.Columns.Count - 1).Value
        If Not IsInArray(arr_Distinct, str_ConcatRgeRow) Then
            ReDim Preserve arr_Distinct(UBound(arr_Distinct) + 1)
            arr_Distinct(UBound(arr_Distinct)) = str_ConcatRgeRow
            If Evaluate(c.Value = matchCriteria) And Evaluate("=(" & c.Offset(0, rgeData.Columns.Count - 1).Value & numCompCriteria & ")") Then
                totalOut = totalOut + c.Offset(0, rgeData.Columns.Count - 1).Value
            End If
        End If
    Next c
    
    SumIfIf = totalOut

End Function

Function IsInArray(arrToCheck As Variant, valToFind As Variant) As Boolean
    Dim x As Long
    IsInArray = False
    For x = 1 To UBound(arrToCheck)
        If arrToCheck(x) = valToFind Then IsInArray = True
    Next x
End Function

在您的示例中,您可以这样使用它:

用法

SumIfIf(rgeData As Range, matchCriteria As String, numCompCriteria As String)

rgeData = 任意行数和至少 2 列的范围

函数匹配:

  • 与“matchCriteria”完全匹配的最左侧列,以及

  • 匹配“numCompCriteria”的最右侧列

...然后:

  • 返回numCompCriteria 匹配的总和

  • [matchCriteria] + [numCompCriteria] 是唯一的。

matchCriteria = 文本或数字标识符,要完全匹配

numCompCriteria = 一个数字标识符,具体为以 >= 开头的字符串,就像您为SumIf 工作表函数。

  • numCompCriteria 的示例:"=10""&lt;=10""10"

我的屏幕时间已达到一天的限制;如果您需要进一步的解释,请告诉我。同时希望这可以解决您的问题。 :)

+1 对挑战的问题,它的好处是正是我正在做的事情所需要的!


更新,进一步回答@BOB的问题:

进行比较的代码行是这一行:

If Evaluate(c.Value = matchCriteria) And Evaluate("=(" & c.Offset(0, rgeData.Columns.Count - 1).Value & numCompCriteria & ")") Then

因此,根据您的需要,您可以通过几种方式对其进行更改。

又快又脏,如果您的新标准是永久性的,请将上面的行替换为:

If Evaluate(c.Value = matchCriteria) _
    And Evaluate("=(" & c.Offset(0, rgeData.Columns.Count - 1).Value & ">10" & ")") _
    And Evaluate("=(" & c.Offset(0, rgeData.Columns.Count - 1).Value & "<=35" & ")") _
    Then

请注意,这将不再使用 numCompCriteria 的值,但您仍然需要指定一些内容,或者从函数声明中删除参数。或者,调整它为您的新标准添加更多参数。

按照该模式,您可以添加所有您喜欢的标准。这里使用它的方式,“Evaluate”返回 True 或 False。您可以通过以下方式进行演示:

debug.print Evaluate ("=(10>35)")

在上面的代码中

c.Offset(0, rgeData.Columns.Count - 1).Value

返回最右边列的值。

【讨论】:

  • 祝贺您的工作做得很好!我有一个问题,如果我想添加另一个标准,我该如何编写公式?例如(列B =SumIfIf($A$2:$B$10,D2,">10"&"<=35") 这个公式的结果是 0 。您的解决方案的另一个规范是要注意公式,因为它区分大小写。
  • 标准将始终为"&gt;10"&amp;"&lt;=35" 还是会有所不同?除此之外,您还需要其他标准吗?
  • 不客气。希望您能理解代码的工作原理,然后根据您的确切需求进行调整。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 2016-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多