Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VBA函数:多次查找同一字符串,使用偏移量生成和,在动态范围结束时终止_Vba_Excel - Fatal编程技术网

VBA函数:多次查找同一字符串,使用偏移量生成和,在动态范围结束时终止

VBA函数:多次查找同一字符串,使用偏移量生成和,在动态范围结束时终止,vba,excel,Vba,Excel,我正在尝试编写一个函数,它根据调用函数的位置动态生成一个范围。然后,它应该从该范围的顶部进行迭代,在调用函数的行的开头查找与该字符串匹配的字符串。当一个字符串匹配时,它将在两列的总和上加一个值。一旦它在该范围内迭代,它应该终止 在这里,我有两个几乎有效的解决方案。这两种方法在求和的代码上都失败了,但在其他情况下效果绝对不错。我已经指出了每个失败的地方 Function Average_Power() Dim rngSearch As Range, rngLast As Range, rn

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

在这里,我有两个几乎有效的解决方案。这两种方法在求和的代码上都失败了,但在其他情况下效果绝对不错。我已经指出了每个失败的地方

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之和):


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

我认为
.FindNext
UDF
的上下文中不可用。这并不奇怪;因为
.FindNext
需要依靠记忆和更新工作表上的某些“状态”,并且不允许自定义项更改状态

然而,用另一个
.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

我觉得
.FindNext
UDF
的上下文中不可用。这并不奇怪;因为
.FindNext
需要依靠记忆和更新工作表上的某些“状态”,并且不允许自定义项更改状态

然而,用另一个
.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

如果你能模拟一些数据和预期的输出,并编辑你的帖子来插入这些信息,那么你就更容易理解你想做什么。如果你能指出哪些错误是由相应的代码行引起的,这也会很有帮助。也可以快速评论-我会避免使用
Sum
作为变量名,因为它接近VBA中的保留字。我个人使用的是,
iTotal
mySum
…你可以使用
=SUMIF($2:$A2,$A2,$C$2:$C2)
假设你的数据从A1开始,把它放在D2中,然后复制下来。这样会更容易理解你想做什么,如果你想模拟一些数据和预期的输出,并编辑你的帖子来插入这些信息。如果你能指出哪些错误是由相应的代码行引起的,这也会很有帮助。快速评论-我会避免使用
Sum
作为变量名,因为它接近VBA中的保留字。我个人使用像,
iTotal
mySum
…你可以使用
=SUMIF($2:$A2,$A2,$C2:$C2)
假设你的数据从A1开始,把它放在D2中并复制下来。是的,这样做了。完全没有考虑Find方法中的参数。谢谢是的,就是这样。完全没有考虑Find方法中的参数。谢谢