【问题标题】:What is the difference between .text, .value, and .value2?.text、.value 和 .value2 之间有什么区别?
【发布时间】:2013-06-25 22:32:46
【问题描述】:

.text.value.value2 有什么区别?比如什么时候应该使用target.text、target.value、target.value2?

【问题讨论】:

  • 如果 Target.Value 不能强制转换为字符串,则 LCase(Target.Value) 将失败,因为 LCase 需要字符串作为参数。您应该按照我的回答首先检查 VarType。另请注意,您可以改用 UCase 并直接与“HLO”进行比较:对文字进行操作没有多大意义。
  • 感谢您提供有关 VarType 的信息。就 LCase 或 UCase 而言,我使用哪一个并不重要。有些人将其键入为 hlo,而其他人将其键入为 HLO。从我看到的情况来看,小写字母的使用频率更高。

标签: excel vba


【解决方案1】:

.Text 为您提供一个字符串,表示单元格在屏幕上显示的内容。使用.Text 通常是个坏主意,因为您可能会得到####

.Value2 为您提供单元格的基础值(可以是空、字符串、错误、数字(双精度)或布尔值)

.Value 为您提供与 .Value2 相同的信息,除非单元格被格式化为货币或日期,它为您提供 VBA 货币(可能会截断小数位)或 VBA 日期。

使用.Value.Text 通常是个坏主意,因为您可能无法从单元格中获取实际值,而且它们比.Value2

如需更广泛的讨论,请参阅我的Text vs Value vs Value2

【讨论】:

  • 我可能会使用 Format 来控制如何将数字转换为字符串: var = Format(Range("a1").Value2, "#")
  • 我希望这不是一个单独的问题,但是:默认值是什么? OP 含糊地声称省略 text/value/value2 是有问题的,但它肯定默认为 one 其中吗?
  • 很抱歉唤醒了这个 oooooold 帖子,但是当您需要的是 @987654335 时,我没有看到将 Date 强制转换为 Double(使用 .Value2)的优势@。当您查看Date 值时,.Value 不应该优先于.Value2 吗?链接的文章也没有说得很清楚。性能因为没有转换?当然可以,但是如果您的 VBA 代码正在使用 Date,那么您将失去自己执行转换的优势,隐式或显式...(context - feel free to weight in)
  • @Mat's Mug - 问题是 Excel 没有真正的 Date 数据类型 - Excel 日期和时间只是双倍,取决于用户应用或更改的任何格式显示为日期、时间或货币或只是一个数字。因此,Value 将 Excel 双精度强制转换为 VBA 日期,但 Value2 没有进行任何强制...对于将双精度强制转换为日期的日期可能不会造成任何损害,只要代码了解它依赖于可更改的格式:优点无论哪种方式都有缺点——我们真正需要的是更多的原生 Excel 数据类型来避免这个问题。
  • 当我想设置一个单元格值等于另一个单元格而不进行类型转换(例如,不将存储为文本的数字转换为数字)我使用这个:Format$(Range.Value2, Range.NumberFormat)
【解决方案2】:

除了第一个答案来自 Bathsheba,除了 MSDN 信息:

.Value
.Value2
.Text

您可以分析这些表格,以便更好地了解所分析属性之间的差异。

【讨论】:

  • @Chris,始终使用.Value 作为标准属性——文本和数字。当您想到日期和一些数字时,请使用.Value2。如果您需要保留单元格/范围内任何内容的格式,请始终使用.Text。所以,你的问题示例是否正确!
  • 为什么日期从 10:12 变成了 10:05?错别字?
  • 我认为生成结果和制作屏幕截图之间只是经过了一段时间
【解决方案3】:

target.Value 会给你一个Variant 类型

target.Value2 也会给你一个 Variant 类型,但 Date 被强制转换为 Double

target.Text 尝试强制转换为 String,如果底层 Variant 不能强制转换为 String 类型,则会失败

最安全的做法是

Dim v As Variant
v = target.Value 'but if you don't want to handle date types use Value2

并在尝试显式强制之前使用 VBA.VarType(v) 检查变体的类型。

【讨论】:

    【解决方案4】:

    关于 C# 中的约定。假设您正在阅读一个包含日期的单元格,例如2014-10-22.

    使用时:

    .Text,您将获得日期的格式化表示,如屏幕上的工作簿所示:
    2014-10-22。此属性的类型始终为 string,但可能并不总是返回令人满意的结果。

    .Value,编译器尝试将日期转换为 DateTime 对象:{2014-10-22 00:00:00} 很可能仅在读取日期时有用。 p>

    .Value2,为您提供单元格的真实基础价值。对于日期,它是一个日期序列:41934。此属性可以具有不同的类型,具体取决于单元格的内容。但是对于日期序列,类型是 double

    因此,您可以在 dynamicvarobject 中检索和存储单元格的值,但请注意,该值始终具有某种您必须采取行动的先天类型。

    dynamic x = ws.get_Range("A1").Value2;
    object  y = ws.get_Range("A1").Value2;
    var     z = ws.get_Range("A1").Value2;
    double  d = ws.get_Range("A1").Value2;      // Value of a serial is always a double
    

    【讨论】:

      【解决方案5】:

      .Text 是格式化单元格的显示值; .Value 是可能增加了日期或货币指示符的单元格的值; .Value2 是去除任何无关信息的原始基础值。

      range("A1") = Date
      range("A1").numberformat = "yyyy-mm-dd"
      debug.print range("A1").text
      debug.print range("A1").value
      debug.print range("A1").value2
      
      'results from Immediate window
      2018-06-14
      6/14/2018 
      43265 
      
      range("A1") = "abc"
      range("A1").numberformat = "_(_(_(@"
      debug.print range("A1").text
      debug.print range("A1").value
      debug.print range("A1").value2
      
      'results from Immediate window
         abc
      abc
      abc
      
      range("A1") = 12
      range("A1").numberformat = "0 \m\m"
      debug.print range("A1").text
      debug.print range("A1").value
      debug.print range("A1").value2
      
      'results from Immediate window
      12 mm
      12
      12
      

      如果您正在处理单元格的值,则读取原始 .Value2 比 .Value 或 .Text 略快。如果您正在定位错误,那么 .Text 将返回类似 #N/A 的文本,并且可以与字符串进行比较,而 .Value 和 .Value2 会将它们的返回值与字符串进行比较。如果您对数据应用了一些自定义单元格格式,那么在构建报告时,.Text 可能是更好的选择。

      【讨论】:

        【解决方案6】:

        出于好奇,我想看看ValueValue2 的表现如何。在对类似过程进行了大约 12 次试验后,我看不出速度上有任何显着差异,因此我始终建议使用 Value。我使用下面的代码运行了一些不同范围的测试。

        如果有人对性能有任何相反的看法,请发帖。

        Sub Trial_RUN()
            For t = 0 To 5
                TestValueMethod (True)
                TestValueMethod (False)
            Next t
        
        End Sub
        
        
        
        
        Sub TestValueMethod(useValue2 As Boolean)
        Dim beginTime As Date, aCell As Range, rngAddress As String, ResultsColumn As Long
        ResultsColumn = 5
        
        'have some values in your RngAddress. in my case i put =Rand() in the cells, and then set to values
        rngAddress = "A2:A399999" 'I changed this around on my sets.
        
        
        
        With ThisWorkbook.Sheets(1)
        .Range(rngAddress).Offset(0, 1).ClearContents
        
        
        beginTime = Now
        
        For Each aCell In .Range(rngAddress).Cells
            If useValue2 Then
                aCell.Offset(0, 1).Value2 = aCell.Value2 + aCell.Offset(-1, 1).Value2
            Else
                aCell.Offset(0, 1).Value = aCell.Value + aCell.Offset(-1, 1).Value
            End If
        
        Next aCell
        
        Dim Answer As String
         If useValue2 Then Answer = " using Value2"
        
        .Cells(Rows.Count, ResultsColumn).End(xlUp).Offset(1, 0) = DateDiff("S", beginTime, Now) & _
                    " seconds. For " & .Range(rngAddress).Cells.Count & " cells, at " & Now & Answer
        
        
        End With
        
        
        End Sub
        

        【讨论】:

        • 您的时间完全被引用单元格的开销所淹没(逐个单元格的遍历对性能来说是一场灾难)。尝试使用分配给变体的大量单元格并创建二维变体数组。
        • @CharlesWilliams 是的,你是对的。我称它为 CRINGE CODE 意味着它是我在了解其他东西(即数组的重要性)之前编写的代码,回首往事我......你猜对了......畏缩。无论如何,谢谢你的提示。稍后我可能会重新发布一些内容。
        猜你喜欢
        • 2013-09-22
        • 1970-01-01
        • 2011-09-01
        • 2015-04-27
        • 2017-02-16
        • 1970-01-01
        • 2016-11-22
        • 2022-01-21
        相关资源
        最近更新 更多