.Value = .Value在VBA中是否类似于Evaluate()函数?

5
考虑下面的代码片段。它将同一个公式写入了两个单元格A1A2
Sub Main()
    With Range("A1")
        .Formula = "=1+1"
    End With

    With Range("A2")
        .Formula = "=1+1"
        .Value = .Value
    End With
End Sub

第二个with块使用.Value = .Value,计算/执行公式,因此公式从公式栏中消失。请参考隐藏公式栏中的公式以获取支持性参考。

.Value = .Value hides the formula from bar

现在,添加另一个with块
With Range("A3")
     .Formula = "=1+1"
End With
Range("A4") = Evaluate(Range("A3").Formula)

您在单元格A3中添加了一个公式,然后将该新单元格的公式Evaluate()到另一个单元格A4中。结果如下所示:

Evaluate cells formula

我认为上面的内容表明.Value = .ValueEvaluate()是相同的。
但是,以下代码使用上述两种方法从关闭的工作簿中提取值。 我已经为此示例创建了一个名为book9.xlsm的工作簿,并将hello放入单元格A1中。 book9.xlsm是我将从中提取A1的值的那个文件。请考虑以下代码:
Sub PullValue()
    With Range("A1")
        .Formula = "='C:\Users\admin\Desktop\[book9.xlsm]Sheet1'!A1"
    End With

    With Range("A2")
        .Formula = "='C:\Users\admin\Desktop\[book9.xlsm]Sheet1'!A1"
        .Value = .Value
    End With

    Range("A3").Formula = "='C:\Users\admin\Desktop\[book9.xlsm]Sheet1'!A1"
    Range("A4") = Evaluate(Range("A3").Formula)
End Sub

第一个with块将来自book9.xlsm的公式放入单元格A1的值中。它被执行,因此拉出的值是hello,但公式栏显示实际的.Formula,即C:\...
第二个with块使用.Value = .Value,如上所示,用于评估公式并通过替换结果来隐藏公式。
Range("A3")与第一个with块相同。
现在(A4),我遵循第一个示例(此问题中的第一个片段)的相同原则来Evaluate()公式,但这次不起作用。
请查看每个激活单元格的值和公式栏。
所以现在,我不能说.Value = .Value等于Evaluate()Evalutate()的备注说它可以与公式一起使用。但在我展示的示例中,它不起作用。
公式在Evaluate()中用作参数是否有限制?我一直认为Evaluate非常强大,但事实证明,.Value = .Value实际上更加强大。尽管它们非常相似,但它们在某种程度上是不同的(但我认为这可能是我的错,因为我选择的公式可能受到限制或限制)。我认为我已经展示了它们两个同时相似和不同之处。它仍然像50%/50%一样,我无法确定它们是否相同。如果有人能够解释这里缺少什么,那将是很好的。

6
@lori_m,我已经恢复了您的编辑。请不要大幅更改帖子的含义,尤其是如果您只是“猜测”问题是什么。有关详细信息,请参见此元讨论 - slhck
2
当引用的单元格位于关闭的工作簿中时,Evaluate()函数会失败。如果您打开引用的工作簿,则它将再次正常工作。这是Evaluate函数的工作方式,它无法从关闭的工作簿中读取。 - Daniel Dušek
4个回答

8

.value和Evaluate不同。
Excel为每个使用的单元格都维护了一个值和一个公式字符串,您可以使用Range.Value和Range.Formula分别获取这两个值。
当您使用Application.Evaluate来评估字符串时,该字符串将在活动工作表上作为公式进行评估(因此实际上最好使用Worksheet.Evaluate而不是Application.Evaluate,而且速度更快)。
使用Rng1.Value = Rng2.Value将Rng2中的值复制到Rng1并覆盖Rng1的公式。
使用Rng1.Value = Evaluate(rng2.Formula)要求Excel从rng2检索公式字符串,对其进行评估并将结果返回给Rng1。

Evaluate方法与单元格中的公式不完全相同:它具有许多需要注意的“怪癖”(包括它无法处理引用外部关闭的工作簿的公式):请参见我的博客文章以获取详细信息
此外,通常最好使用.Value2而不是.Value:请参见Value vs Value2以获取详细信息


1
+1 - 我不知道.Value2比.Value更快。感谢您的好答案以及博客文章。 - Jon Crowell

2

.Value = .Value(在单元格的With块中)只是将单元格的值设置为其当前值,覆盖并删除其公式(如果有)。 .Value属性仅表示单元格的当前值。如果单元格包含尚未计算的公式,例如如果关闭了计算,则它可能不会返回公式结果,而是返回单元格的先前值。

Excel.Application.Evaluate接受字符串值,将字符串的内容作为公式或单元格名称进行评估,并返回该单元格或公式的值。如果传递给它一个无法映射到Excel单元格名称或无效的公式的字符串,您将收到一个错误。 Evaluate的目的是允许动态创建的公式在不必写出公式到单元格的情况下进行评估。如果传递了一个公式,即使工作簿计算被关闭,它也应该返回结果,但是如果传递了一个名称,我希望它返回单元格的当前值,如果工作簿计算关闭,则该值可能不反映所引用单元格的预期值。

假设因为单元格的.ValueEvaluate()可以返回不同的结果,因此工作表公式评估引擎和Application.Evaluate()引擎是不同的,或者至少具有一些不同的元素。


1

.Value = .ValueEvaluate()是不同的。

我认为你在对象及其默认属性方面有些混淆。

始终牢记这两个概念:

  1. VBA允许您在不指定对象的情况下使用属性和方法。VBA将使用它们的默认对象。例如,当您使用Evaluate()时,实际上使用的是Sheet1.Evaluate()

  2. VBA允许您在不指定属性的情况下使用对象。VBA将使用它们的默认属性。例如,当您使用Range("A1") = 1时,实际上使用的是Range("A1").Formula = 1。(您实际上使用的是Sheet1.Range("A1").Formula = 1!)

回到你的例子,当你执行.Value = .Value时,实际上执行的是Range("A2").Value = Range("A2").Value。单元格的Value属性可以是数字、字符串、错误等。而且当它是一个数字时,它可能是一个错误的数字,即不是该单元格中公式的正确结果(例如,因为您禁用了自动计算)。因此,.Value = .Value等同于.Formula = "<xxx>",其中<xxx>是在该单元格上计算的最后一个值。
当您执行Range("A4") = Evaluate(Range("A3").Formula)时,您要求Excel评估该公式并将结果分配给范围A4的Formula属性(因为公式属性是范围对象的默认属性)。

所以根据你最后一句话,Range("A4") 实际上应该显示 hello 而不是抛出错误。那么错误是因为 Evaluate 无法从已关闭的工作簿中获取值吗? - user2140173
是的。Excel在公式引用到已关闭的工作簿时,能够做到相当好的查看。Evaluate方法能够处理跨工作簿的数据,但前提是这些工作簿已经打开了。如果你知道下一个Evaluate会尝试访问另一个工作簿上的数据,那么你的宏就应该检查工作簿是否关闭并打开它。但性能会比公式慢得多(即使使用ScreenUpdating = False),因为你的宏需要打开整个工作簿,而公式能够访问已关闭文件中所需的数据。 - stenci
你有任何支持你回答中的(You actually use Sheet1.Range("A1").Formula = 1!)的参考资料吗?你是如何发现Formula是Range的默认值的? - user2140173
@mehow 我没有任何参考资料。我认为这是因为 Range("A2") = "=A1" 可以工作,以及其他类似的行为,但我可能是错的。 - stenci
请在您的空余时间查看此内容,它可能对您有所帮助:点击这里谢谢。 - user2140173

0

Evaluate是一个函数,而在函数后面跟着一个点(.)的东西被称为属性。因此,“.Value”、“.Formula”、“.Text”是您在此处使用的Range的属性。

不要混淆这两个概念。

函数接受输入,使用其输入变量执行操作并返回结果。它适用于其配置的数据类型。

.value是一个通用属性,不依赖于数据类型。它可以是字符串、数字、浮点数或其他任何类型。

因此,有可能会从一个地方得到错误,而从另一个地方完全正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接