除非重新输入,否则Excel将使用VBA函数计算公式作为错误

Ala*_*ain 15 excel vba user-defined-functions

我在工作表中设置了一个简单的if语句,其中if条件是VBA用户定义的函数:

Function CellIsFormula(ByRef rng)
    CellIsFormula = rng(1).HasFormula
End Function
Run Code Online (Sandbox Code Playgroud)

这个功能似乎工作正常:

评估1 评估2

但由于某些原因,我无法弄清楚,该单元正在评估错误.更糟糕的是,在评估公式时,excel将错误归因于不会产生错误的计算步骤:

评估4 评估5 评估6

最重要的是,真正让我感到震惊的是,如果我只是重新输入公式,或强制完全重新计算(Ctrl+ Alt+ F9) - 公式评估没问题!

重新输入公式 计算有效

我已经尝试通过添加Application.Volatile到函数代码使公式变为volatile ,但它没有改变任何东西.刷新计算的其他方法,例如将计算设置为手动然后返回自动,隐藏"重新计算工作表",或仅使用F9Ctrl+ F9不工作,只重新输入公式或Ctrl+ Alt+ F9将导致函数正确重新计算.

更改if语句中引用的其中一个单元格不会解决问题,但是,更改"CellIsFormula"函数引用的单元格确实可以解决问题.每次重新打开工作表时,错误都会恢复.

Ala*_*ain 15

我发现了确切的问题,但我想向大家投票,试图帮助我解决这个问题,并给予GSerg一定的荣誉,因为虽然我并没有完全失去运气,但他仍然坚持他的建议

Excel确实希望在计算的某些阶段使某个范围的某些属性不可用.

很好找到GSerg.

The problem was with Event Handlers. The workbook contains a series of event handlers like Workbook_Open, Worksheet_Change, etc. Every now and then, one of the actions taken by these event handlers will cause some cells in the workbook to recalculate. If excel triggers a recalculation while a macro is running, any cells containing this UDF will result in an error. This is because for some reason, during the VBA triggered recalculation, the .HasFormula property was unavailable, just like @GSerg said: Property Unavailable

Presumably - the next bit is an oversight on Excel's part, but once the macro is done running, if a recalculation has been done, resulting in errors because UDFs didn't run properly, excel will not try to run the UDFs again. The resulting error value will be assumed to be the return value of the call, and will not change unless it thinks the parameter to that UDF has changed. Excel will cache the result of the User Defined Function call until the cell its parameter references is changed.

That is why stepping through 'Evaluate Formula' will show everything working until the very last step, where it doesn't actually evaluate the last step, it just shows the value from the spreadsheet as was last calculated.

实际上有两种可能的解决方案.我发现的第一个解决方案是在事件处理程序开始时禁用自动计算,然后重新启用它.出于某种原因,即使宏在运行时计算被设置回xlCalculationAutomatic,它也会导致UDF成功重新评估,并且该属性可用.

第二个解决方案,我更喜欢,因为它可以防止意外再次发生,是使用不同的方法来检查公式:

Function CellIsFormula(ByRef rng As Range) As Boolean
    CellIsFormula = Left(rng(1).Formula, 1) = "="
End Function
Run Code Online (Sandbox Code Playgroud)

.Formula属性永远不可用.所以这个问题永远不会发生

  • 终于得到了错误.它似乎只适用于工作簿级别的事件.另一个额外的修复是设置'Application.EnableEvents = False',然后执行您的事件代码,然后在完成后重新打开事件. (2认同)

GSe*_*erg 6

我无法重现此错误,但是:

  1. 签名应该是:

    Public Function CellIsFormula2(ByVal rng As Range) As Boolean
      CellIsFormula2 = rng.Cells(1).HasFormula
    End Function
    
    Run Code Online (Sandbox Code Playgroud)
  2. Excel确实希望在计算的某些阶段使某个范围的某些属性不可用.我多次看到该.Text物业突然无法使用.因此,如果更改签名不起作用,那么您可能运气不好.