VBA函数:多次查找相同的字符串,使用offset生成sum,在动态范围结束时终止

时间:2017-05-22 19:35:54

标签: excel vba excel-vba

我正在尝试编写一个函数,该函数根据调用函数的位置动态生成一个范围。然后它应该从该范围的顶部进行迭代,寻找与调用函数的行开头的字符串匹配的字符串。当字符串匹配时,它会将两列的值添加到总和。一旦它迭代了范围,它就应该终止。

这里我有两个几乎可以工作的解决方案。两者都在执行求和的代码上失败,但是否则完全正常。我已经评论了每个失败的地方。

Function Average_Power()
    Dim rngSearch As Range, rngLast As Range, rngFound As Range, cell As Range
    Dim CallerAddr As String, strFirstAddress As String, strFamilyName As String, teststring As String
    Dim Sum As Double

    Sum = 0
    teststring = ""

    With Application.Caller
        CallerAddr = .Address
    End With

    strFamilyName = Application.Caller.Offset(0, -3).Value

    Set rngSearch = ActiveSheet.Range("B15", Range(CallerAddr))

    Set rngLast = rngSearch.Cells(rngSearch.Cells.Count)

    Set rngFound = rngSearch.Find(What:=strFamilyName, After:=rngLast, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)

    For Each cell In rngSearch.Cells
'        If InStr(cell.Value, strFamilyName) Then
'            Sum = Sum + cell.Offset(0, 2).Value
'        End If
    Next cell

    If Not rngFound Is Nothing Then
        strFirstAddress = rngFound.Address
        Sum = Sum + rngFound.Offset(0, 2).Value
        Do
'            Set rngFound = rngSearch.FindNext(rngFound)
'            Sum = Sum + rngFound.Offset(0, 2).Value
        Loop Until rngFound.Address = strFirstAddress
    End If

    Average_Power = Sum
End Function

这是我目前的输出,因为我仍在尝试对值进行求和,我将寻找最终的平均功率为6000(总和4000和2000):

https://i.stack.imgur.com/CMHEz.png

错误:“有一个或多个循环引用,其中公式直接或间接引用其自己的单元格。这可能导致它们计算错误。尝试删除或更改这些引用,或将公式移动到不同的单元格”我想解决方案可能是,如果有一种方法可以将范围向左移动一列,那么函数不会迭代过来? (这仍然包括进行计算的所有必要单元格)

1 个答案:

答案 0 :(得分:0)

我似乎.FindNextUDF的上下文中无法使用。这并不奇怪;因为.FindNext需要依赖记忆和更新某些状态"在工作表上,不允许UDF更改状态。

但是,用另一个.Find解决这个问题似乎可以解决这个问题。此外,我注意到你迭代匹配的方式并不准确。您的代码可以像这样重写:

Function Average_Power() As Double
    Dim rngSearch As Range, rngFound As Range
    Dim strFirstAddress As String, strFamilyName As String

    strFamilyName = Application.caller.Offset(0, -3).Value
    Set rngSearch = Application.caller.Parent.Range("B15", Application.caller)
    Set rngFound = rngSearch.Find(What:=strFamilyName, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)

    If rngFound Is Nothing Then Exit Function
    strFirstAddress = rngFound.Address
    Do
       Average_Power = Average_Power + rngFound.Offset(0, 2).Value

       ' FindNext re-written like this will work:
       Set rngFound = rngSearch.Find(What:=strFamilyName, After:=rngFound, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
       ''''''''''''                                      ^^^^^^^^^^^^^^^^

    Loop Until rngFound.Address = strFirstAddress
End Function