¿Cuál es la diferencia entre .text, .value y .value2?

180

No estoy pidiendo ayuda con ningún script, pero mi pregunta es para aclarar. Últimamente he estado haciendo muchas secuencias de comandos VB en Excel, por lo que realmente me estoy refiriendo a Excel en esta pregunta. ¿Cuál es la diferencia entre .text, .value y .value2? ¿Como cuando debo usar target.text, target.value y target.value2? Nunca utilicé la opción value2 pero todavía me gustaría saber para qué se utiliza.

A veces, si uso .text me da un error y necesito usar .value cuando solo estoy revisando o manipulando el texto dentro de una celda. Luego, a veces, cuando creo que debería usar .value, recibo un error y necesito usar .text. Por lo general, acepta cualquiera o sin un problema, pero a veces hace la diferencia. Sé que tiene que haber algo de lógica en esto, pero parece que no puedo entenderlo.

También descubrí que si lo dejas como objetivo sin especificar .text o .value, funcionará inicialmente, pero algo que alguien haga eventualmente causará un error en el script, por lo que siempre es mejor usar un .something en él . Supongo que lo que estoy preguntando es si alguien puede darme algún tipo de guía, regla general, sobre cómo usar cada una de manera adecuada y cuándo debe usarse.

Gracias por la explicación chicos. De alguna manera lo entiendo mejor. Ambas son buenas explicaciones. A continuación se muestra un pequeño ejemplo de algunos de mis códigos que sí funcionan. Pensé que debería ser target.text, pero sería un error, así que cuando usé target.value funcionó.

If LCase(Target.Value) = LCase("HLO") And Target.Column = 15 Then
    Target.Value = "Higher Level Outage"
End If

Todavía estoy un poco confundido porque cuando pienso en el valor o valor2, especialmente después de las respuestas que proporcionó, creo que solo deberían usarse para los números. Sin embargo, en mi ejemplo estoy hablando estrictamente de texto, que es mucho de lo que se refiere mi script (texto en las celdas, más que números).

Chris
fuente
LCase (Target.Value) fallará si Target.Value no es coercable a una cadena ya que LCase requiere una cadena para un argumento. Primero debe verificar el VarType según mi respuesta. También tenga en cuenta que podría usar UCase en su lugar y comparar directamente con "HLO": no tiene mucho sentido operar en un literal.
Betsabé
Gracias por la información sobre VarType. En cuanto a LCase o UCase para esto, realmente no importaría cuál usara. Algunas personas lo escriben como hlo y otras lo escriben como HLO. Por lo que vi, parecía que la minúscula se usaba con más frecuencia.
Chris

Respuestas:

238

.Textle proporciona una cadena que representa lo que se muestra en la pantalla para la celda. Usar .Text suele ser una mala idea porque podría obtener ####

.Value2 le da el valor subyacente de la celda (podría estar vacío, cadena, error, número (doble) o booleano)

.Value le da lo mismo que .Value2, excepto si la celda fue formateada como moneda o fecha, le da una moneda VBA (que puede truncar lugares decimales) o una fecha VBA.

Usar .Value o .Text suele ser una mala idea porque es posible que no obtenga el valor real de la celda, y son más lentos que .Value2

Para una discusión más extensa vea mi Texto vs Valor vs Valor2

Charles Williams
fuente
66
Probablemente usaría Format para controlar cómo se convierte el número en una cadena: var = Format (Range ("a1"). Value2, "#")
Charles Williams
2
Espero que esta no sea una pregunta separada, pero: ¿Cuál es el valor predeterminado? El OP afirma vagamente que omitir texto / valor / valor2 es problemático, pero ¿seguramente es uno de ellos?
Martin F
3
Lamento despertar esta publicación anterior, pero no puedo ver la ventaja de obligar Datea un a Double(usar .Value2) cuando lo que necesitas es un Date. ¿No .Valuedebería preferirse a .Value2cuando se busca un Datevalor? El artículo vinculado tampoco lo deja muy claro. Rendimiento porque no hay conversión? Claro, pero si su código VBA funciona con a Date, perderá esa ventaja al realizar la conversión usted mismo, implícita o explícitamente ... (contexto: siéntase libre de peso)
Mathieu Guindon
2
@ Mat's Mug: el problema es que Excel no tiene un tipo de datos de fecha verdadero: las fechas y horas de Excel son solo dobles que dependen del formato que el usuario haya aplicado o cambiado para aparecer como fechas, horas o moneda o simplemente un número. Entonces Value está coaccionando un Excel doble a una fecha VBA pero Value2 no está coaccionando ... Para las fechas coaccionando el doble a una fecha probablemente no esté haciendo ningún daño siempre que el código entienda que depende de un formato cambiable: pros y contras de cualquier manera: lo que realmente necesitamos son más tipos de datos nativos de Excel para evitar este problema.
Charles Williams
2
Cuando quiero para establecer un valor de celda igual a otro celular sin una conversión de tipo (por ejemplo, sin necesidad de convertir un número almacenado como texto a un número) utilizo este: Format$(Range.Value2, Range.NumberFormat).
ChrisB
55

Excepto el primer formulario de respuesta de Bathsheba, excepto la información de MSDN para:

.Value
.Value2
.Text

podría analizar estas tablas para comprender mejor las diferencias entre las propiedades analizadas.

ingrese la descripción de la imagen aquí

Kazimierz Jawor
fuente
44
@ Chris, utilícelo .Valuecomo propiedad estándar todo el tiempo para texto y números. Úselo .Value2cuando piense en la fecha y algunos números. Y use .Textsiempre si necesita mantener el formato de cualquier cosa que tenga en la celda / rango. ¡Entonces, su ejemplo de pregunta si es correcto!
Kazimierz Jawor
1
¿Por qué la fecha cambió de 10:12 a 10:05? ¿error de tipografía?
Katrin
1
Creo que es solo el tiempo transcurrido entre la generación de resultados y el momento de hacer la captura de pantalla
Kazimierz Jawor
25

target.Valuete dará un Varianttipo

target.Value2le dará un Varianttipo también, pero a Datese coacciona a unDouble

target.Textintenta coaccionar a ay Stringfallará si el subyacente Variantno es coercable a un Stringtipo

Lo más seguro es hacer algo como

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

Y verifique el tipo de la variante usando VBA.VarType(v)antes de intentar una coerción explícita.

Betsabé
fuente
11

En cuanto a las convenciones en C #. Digamos que está leyendo una celda que contiene una fecha, por ejemplo, 2014-10-22.

Cuando usas:

.Text, obtendrá la representación formateada de la fecha, como se ve en el libro de trabajo en pantalla:
2014-10-22 . El tipo de esta propiedad es siempre stringpero no siempre puede devolver un resultado satisfactorio.

.Value, el compilador intenta convertir la fecha en un DateTimeobjeto: {2014-10-22 00:00:00} Lo más probable es que solo sea útil al leer fechas.

.Value2, le proporciona el valor real subyacente de la celda. En el caso de las fechas, es una serie de fechas: 41934 . Esta propiedad puede tener un tipo diferente según el contenido de la celda. Sin embargo, para las series de fechas, el tipo es double.

Para que pueda recuperar y almacenar el valor de una celda en cualquiera dynamic, varo objectpero tenga en cuenta que el valor siempre tendrá algún tipo de tipo natural que tendrá que actuar en consecuencia.

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
fuego de seda
fuente
2

.Text es el valor mostrado de la celda formateada; .Value es el valor de la celda posiblemente aumentada con indicadores de fecha o moneda; .Value2 es el valor subyacente bruto despojado de cualquier información extraña.

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

Si está procesando el valor de la celda, entonces leer el .Value2 sin procesar es marginalmente más rápido que .Value o .Text. Si está localizando errores, .Text devolverá algo así #N/Acomo texto y se puede comparar con una cadena, mientras que .Value y .Value2 se ahogarán al comparar su valor devuelto con una cadena. Si tiene algún formato de celda personalizado aplicado a sus datos, entonces .Texto puede ser la mejor opción al crear un informe.


fuente
0

Por curiosidad, quería ver cómo se Valuecomportaba en contra Value2. Después de aproximadamente 12 pruebas de procesos similares, no pude ver diferencias significativas en la velocidad, por lo que siempre recomendaría usar Value. Usé el siguiente código para ejecutar algunas pruebas con varios rangos.

Si alguien ve algo contrario al rendimiento, publíquelo.

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

ingrese la descripción de la imagen aquí

PGSystemTester
fuente