【问题标题】:vba circular reference error in function函数中的vba循环引用错误
【发布时间】:2013-06-15 16:27:43
【问题描述】:

我正在尝试使用 vba,但收效甚微。我想实现一个简单的函数,它根据年初到今天对一系列单元格的内容求和。不幸的是,当我调用该函数时,我得到了一个“循环引用”错误,我就是不明白为什么。任何帮助将不胜感激。

Public Function til2day(r As Integer) As Long ''supposed to receive cell("row") as parameter  
  Dim c As Integer  
  Dim c1 As Integer  
  Dim c_here As Integer  

  Application.Volatile True

  c_here = ActiveCell.Column
  c = 0
  c1 = 34 ''column contains 1/1/2013 date

  Range("AH4:OM4").Activate ''contains a timeline
  Do While ActiveCell.Offset(0, c).Value <> Date
    c = c + 1
  Loop
  If ActiveCell.Offset(0, c).Value = Date Then
      c = ActiveCell.Offset(0, c).Column
  End If

  til2day = Application.WorksheetFunction.Sum(Range(Cells(r, c1).Address, Cells(r, c).Address))
  Range(Cells(r, c_here).Address).Activate
End Function

【问题讨论】:

  • 您应该能够使用 VBA 调试器跟踪问题。 F8 键将逐步引导您完成程序。在每一步,将光标悬停在变量上以查看它们的值。但是有一个问题,为什么在 DO 循环之外的 Value = Date 上有 IF?看起来很奇怪。
  • if 真的是多余的,我只是在仔细检查我所在的列是否有今天的日期作为值。至于使用调试器,问题是即使有检查点,用 F8 运行它,它也不会显示错误并正确计算。问题是,当我从单元格调用函数时(我可能应该提到这一点,我的错)
  • 你是如何运行这个函数的?你有样品表吗?
  • 嗯,我不知道如何做样表。布局很简单,我在顶部有一个全年的时间线,还有几个项目排成一行,有点像甘特图风格。然后我在结果网格中输入小时数(数字格式)。我希望能够通过调用此函数来填充一列,让函数识别行并对相应的值求和,并将其返回到我放置函数的单元格中( =til2day() )。如果这个解释不清楚,请告诉我(这听起来确实让我感到困惑,但我不知道如何做得更好,抱歉)谢谢
  • 从工作表公式调用的函数无法以任何方式更改工作表(因此您的 .Activate 将静默失败,并且结果(如果有)将无法预测)。

标签: excel circular-reference vba


【解决方案1】:

在函数中使用“激活”是一个非常糟糕的主意;我无法确切地解释为什么会这样,除非您在计算期间更改了单元格的选择。在以下情况下,这将导致问题:

multiple cells are being calculated with this function, and 
you use `Application.Volatile`, and 
you refer to the active cell inside your function, and 
you allow multi-threaded calculation, 

事情不会按照您期望的顺序发生,并且在某些时候活动单元格会与您想象的不同。函数最终引用它所在的单元格,并且您有一个循环引用。当您运行调试器时不会发生这种情况,因为它根据定义作为单线程运行 - 这就是为什么您找不到问题的原因......

这里建议重写您的函数 - 它不会激活任何单元格,但会尝试保持相同的功能:

Public Function til2day(r As Integer) As Long ''supposed to receive cell("row") as parameter  
  Dim c As Integer  
  Dim c1 As Integer  
  Dim dateRange as Range
  Dime dateCell as Range

  Application.Volatile True

  c = 0
  c1 = 34 ''column contains 1/1/2013 date

  set dateRange = Range("AH4:OM4")

  For Each dateCell in dateRange
    If dateCell.Value = Date Then Exit For
  Next dateCell

  c = dateCell.Column

  til2day = Application.WorksheetFunction.Sum(Range(Cells(r, c1).Address, Cells(r, c).Address))

End Function

注意:我试图重现您的函数的功能 - 但没有您正在使用的工作表的良好示例以及您期望返回的值,很难测试。请尝试在您的工作表上运行它 - 如果事情没有按您的预期工作,请告诉我。

还要注意SUMIF函数可以使用效果很好:

=SUMIF(range, criteria, sum_range)

在你的情况下,使用

=SUMIF($AH$4:$OM$4, "<=" & NOW(), $AH18:$OM18)

其中“18”是您需要的任何行(当您将公式拖到不同的行时,由于$4 绝对引用,它将继续引用日期行,但计算总和由于 $AH18:$OM18 中的相对行引用,因此出现了不同的行。

这个函数的使用示例(简化范围...)

如您所见,自从我在 6 月 15 日执行此操作后,该函数才对列 C 到 F 求和。

【讨论】:

  • 您先生真棒。我要测试这个函数,但是 sumif 完全符合我的需要(老实说,这有点尴尬)。非常感谢
  • 很乐意提供帮助 - 并且很想知道 VBA 方法是否也有效。不过通常内置函数会更快。
猜你喜欢
  • 1970-01-01
  • 2020-08-15
  • 2018-02-20
  • 2018-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
相关资源
最近更新 更多