【问题标题】:Excel VBA Evaluate Function Wrong When Reference is Not Active Sheet for Named Range当命名范围的引用不是活动工作表时,Excel VBA评估函数错误
【发布时间】:2016-09-18 09:37:12
【问题描述】:

用更好的例子编辑

我正在尝试使用 Evaluate 函数来评估命名范围的公式引用。但是,在使用 Evaluate 函数时,如果您没有明确说明工作表引用和单元格引用,它将假定活动工作表作为单元格引用。这会导致错误的结果

在我的实际项目中,我试图只评估命名范围公式的一部分,因此它变得更加棘手。

使用我正在尝试做的一个基本示例,假设您在表格 1 单元格 A1 中有以下公式,其名称为 MyCell:

="Don't evaluate this part"&"My Result Is " & A2

如果活动工作表是工作表 2,并且您运行以下代码,它将给您错误的结果(这是一个快速而肮脏的示例来说明问题)

Dim s As String
s = Replace(Range("MyCell").Formula, """Don't evaluate this part""&", "")
Debug.Print Evaluate(s)

它没有给我工作表 1 的单元格 A2 中的值,而是给我工作表 2 的单元格 A2 中的值。

对此有什么想法吗?

这是我找到的最接近的,但这不是我的确切问题(尽管标题相似)并且它没有提供解决方案: Excel VBA evaluate formula from another sheet

【问题讨论】:

  • Sheet 2 中的单元格 A1 是否命名为 MyCell?您是否总是准确地评估单元格中的公式?如...是否有理由您不只是检查该单元格的值而不是公式?
  • Excel 是按设计运行并在必要时运行。如果你不能像我的第一条评论中提到的那样抓住价值,它会变得有点棘手,但有办法做到这一点
  • 为了更好地说明我的意思,请参阅我的新示例。
  • 回答您的问题。 1) 表 2 中的单元格 A1 未命名为 MyCell。相反,工作表 1 中的单元格 A1 被命名为 MyCell。 2) 我正在评估公式的部分内容(请参阅上面的编辑)。

标签: excel vba evaluate named-ranges


【解决方案1】:

您遇到的问题是,根据设计 Excel 会假定所有非特定单元格引用都引用现有工作表。这就是为什么建议尽可能在所有代码中明确说明工作表的原因。

最简洁的方法(通过一些 MSDN 定义搜索验证)是直接明确说明工作表而不激活它:

Sub test2()
    Debug.Print Range("MyCell").Worksheet.Evaluate(Range("MyCell").Formula)
End Sub

或者,此代码会将活动工作表更改为正确的工作表,然后在评估后将其改回。 不建议在没有情有可原的情况下执行如下代码所示的工作表激活。连这里都没有。

Sub test()
    Dim ws As Worksheet
    Set ws = ActiveSheet
    Dim s As String
    s = Replace(Range("MyCell").Formula, """Don't evaluate this part""&", "")
    Range("MyCell").Worksheet.Activate  ' Don't remember if .Worksheet or .Parent ??
    Debug.Print Evaluate(s)
    ws.Activate
End Sub

正如 ThunderFrame 在 cmets 中指出的那样,请务必记住,此代码假定 MyCell 是问题中所述的简单单元格引用。否则,您将需要使用其他方法来确定目标工作表名称(或对其进行硬编码)。

【讨论】:

  • 我了解这是设计使然,并且我了解在原始公式中明确说明工作表参考将避免此问题。通过这个发送给我无法控制他们如何输入公式的用户。无论如何,我只是想完全按照你的建议去做。这将是我的后备计划,因为我害怕表现。在我的真实项目中,它们可能是 100 到 1000 个具有类似公式的单元格。我很犹豫要为每个人激活工作表。但最终这可能会奏效。
  • @ptownbro 使用较短的代码。那不会实际激活工作表。
  • @ptownbro 实际上,应该在 99.999% 的情况下避免激活和选择,所以每次都使用较短的代码来避免这种情况。
  • 您可能需要检查定义的名称是否定义为文字(而不是单元格引用)。例如,名称 Foo 定义为 ="Bar" 将没有使用 Evaluate 或 Range 方法的公式或工作表属性。
  • @ThunderFrame 好点。 OP 确实声明了“名称为 MyCell 的表 1 单元格 A1”,因此在他的特定情况下,我的代码有效。但在一般问答网站的努力中,也许我应该注意到这一点。就实际实现该适应而言,您要么必须对所需的工作表进行硬编码,要么知道如何从文字中获取它。
【解决方案2】:

您的线路:

Debug.Print Evaluate(Range("MyCell").Formula)

相当于:

Debug.Print Evaluate("=""My Result Is "" & A2")

这就是你根据 ActiveSheet 中 A2 的值获得结果的原因。

如果要检查公式的内容,可以使用这一行:

Debug.Print [MyCell].Formula

如果您想要 MyCell 相对于 Sheet1 的值,那么您有 2 个选项:

1 - 使用Debug.Print Range("Sheet1!MyCell").Value

2 - 使用Debug.Print Sheet1.Range("MyCell").Value

【讨论】:

  • 不确定您是否看到与我相同的问题。他想在单元格中执行修改后的公式。您已经告诉他如何获取单元格值以及如何显示未计算的公式,但没有告诉他如何在非活动工作表上执行修改后的公式。
  • 是的,在之前的问题编辑中,我将问题解释为评估公式文本,而不是评估公式结果。
  • 很公平。我明白你的意思。这是我的第一印象。我知道发生了什么的唯一原因是因为我要求 OP 进行澄清。话又说回来......即使在得到很多“澄清”之后,我也已经完全脱离了基地。
  • 我在 VBA Rubberduck 上工作,所以我太习惯于解析公式了 :-\
  • 很好,很难频繁使用这些标签并且不知道该项目。似乎是一个不错的项目,我仍然需要下载。我尽量避免手动解析公式,因为这很痛苦,但我确实编写了一些非常干净的代码来通用解析 excel 公式(函数、命名范围、数组等)。出于某种原因,这很有趣...... ;)
【解决方案3】:

使用 Worksheet.Evaluate 而不是默认的 Application.Evaluate 几乎总是更好:正如 Mark Ba​​lhoff 指出的那样,它允许您控制不合格的引用。 但是 Worksheet.Evaluate 通常也比 Application.Evaluate 快两倍。 有关详细信息,请参阅我的博客文章 https://fastexcel.wordpress.com/2011/11/02/evaluate-functions-and-formulas-fun-how-to-make-excels-evaluate-method-twice-as-fast/

【讨论】:

  • 太棒了。我会检查一下,看看这对我的项目是否有帮助。谢谢。顺便说一句,我已经阅读并正在使用您的 Excel-DNA 说明 很棒的东西。 =)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-24
相关资源
最近更新 更多