如何摆脱VBA动态范围内的循环参考?

时间:2018-06-24 22:18:27

标签: vba excel-vba circular-reference

我正在尝试创建一个用户定义的Excel函数,该函数部分地对公式所在的单元格上方的所有非空白单元格进行计数(技术上是从定义该范围内第一个单元格的特定单元格开始)。我遇到的麻烦是将公式向下复制会导致循环引用。我不希望其他用户遇到此问题。如何避免循环引用?

我一直在尝试解决以下问题:

Set CellOne = Range(“A10”)
Set CellTwo = Range(Selection.Address).Offset(-1, 0)
Set MyRange = Application.Range(Cell1:=CellOne.Address, Cell2:=CellTwo.Address)
CountNonBlanks = Application.WorksheetFunction.CountA(MyRange)

此代码在向下复制时也会引起循环引用:

Set CellTwo = Range(ActiveCell.Address).Offset(-1, 0)

该问题似乎是由于引用相对于所选或活动的单元格引起的。我只希望MyRange可以在公式所在位置的上方结束一个单元格,而不管哪个单元格处于活动状态或选定状态。

FWIW,用户定义的公式的最终目的是返回字母中的下一个字母,无论该公式位于前一个字母下方多少行。此本机函数有效,但我希望有一个更优雅的出现解决方案:

=MID("abcdefghijklmnopqrstuvwxyz",COUNTA(A$10:A10)+1,1)

谢谢。

1 个答案:

答案 0 :(得分:0)

您不应在工作表的udf中使用Selection或Activecell,因为它们会不断变化。将范围引用传递到udf或使用application.caller将包含udf的单元格引用为范围对象。

如果您发布了整个udf或至少是声明,我可以编辑此回复以提供更具体的帮助。这是一个例子。

Public Function nextLetter()

    'since no reference is passed in, you might want to make this volatile
    Application.Volatile

    With Application.Caller.Parent
        nextLetter = Chr(97 + Application.CountA(.Range(.Cells(10, "A"), _
                                         .Cells(Application.Caller.Row - 1, "A"))))
    End With

End Function

传入起始单元格的替代方法。

Public Function nextLetter2(startRng As Range)

    'since only a single cell reference is passed in, you might want to make this volatile
    Application.Volatile

    With Application.Caller.Parent
        nextLetter2 = Chr(97 + Application.CountA(.Range(startRng, _
                                         .Cells(Application.Caller.Row-1, startRng.Column))))
    End With

End Function

=nextLetter2(A$10)一样使用