Qual é a diferença entre .text, .value e .value2?

180

Não estou pedindo ajuda com nenhum script, mas minha pergunta é para esclarecimento. Ultimamente, tenho feito muitos scripts VB no Excel, então estou realmente me referindo ao Excel nesta questão. Qual é a diferença entre .text, .value e .value2? Como quando devo usar target.text, target.value e target.value2? Eu nunca usei a opção value2, mas ainda gostaria de saber para que ela é usada.

Às vezes, se eu uso .text, ocorre um erro e preciso usar .value quando estou apenas verificando ou manipulando o texto em uma célula. Às vezes, quando penso que devo usar .value, recebo um erro e preciso usar .text. Geralmente, ele aceita ou não um problema, mas às vezes faz diferença. Eu sei que tem que haver alguma lógica nisso, mas não consigo entender.

Também descobri que, se você o deixar como destino sem especificar .text ou .value, ele funcionará inicialmente, mas algo que alguém fará eventualmente causará um erro no script, por isso é sempre melhor usar algo. . Acho que o que estou perguntando é se alguém pode me dar algum tipo de orientação, regra geral, sobre como usar adequadamente cada um e quando ele precisa ser usado.

Obrigado pela explicação pessoal. Eu meio que entendo melhor. Ambas são boas explicações. Abaixo está um pequeno exemplo de alguns dos meus códigos que funcionam. Eu pensei que deveria ser target.text, mas seria um erro quando eu usei target.value funcionou.

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

Ainda estou um pouco confuso porque, quando penso em valor ou valor2, especialmente depois das respostas que você forneceu, acho que elas devem ser usadas apenas para números. No entanto, no meu exemplo, estou falando estritamente de texto, que é muito do que meu script se refere (texto nas células, mais do que números).

Chris
fonte
LCase (Target.Value) falhará se Target.Value não for coercível a uma sequência, pois a LCase exige uma sequência para um argumento. Você deve verificar o VarType primeiro, de acordo com minha resposta. Observe também que você pode usar o UCase e comparar diretamente com "HLO": não há muito sentido em operar em um literal.
Bate-Seba
Obrigado pela informação sobre VarType. Quanto ao LCase ou UCase para isso, realmente não importa qual deles eu usei. Algumas pessoas o digitam como hlo e outras o digitam como HLO. Pelo que vi, a letra minúscula foi usada com mais frequência.
28413 Chris

Respostas:

238

.Textfornece uma sequência que representa o que é exibido na tela da célula. Usar .Text geralmente é uma má ideia, pois você pode obter ####

.Value2 fornece o valor subjacente da célula (pode estar vazio, sequência, erro, número (duplo) ou booleano)

.Value fornece o mesmo que .Value2, exceto se a célula foi formatada como moeda ou data, fornece uma moeda VBA (que pode truncar casas decimais) ou uma data VBA.

Usar .Value ou .Text geralmente é uma má ideia, porque você pode não obter o valor real da célula e é mais lento que .Value2

Para uma discussão mais extensa, veja meu Texto x Valor x Valor2

Charles Williams
fonte
6
Eu provavelmente usaria Format para controlar como o número é convertido para uma string: var = Format (Range ( "A1") Value2, "#".)
Charles Williams
2
Espero que não seja uma pergunta separada, mas: Qual é o padrão? O OP afirma vagamente que deixar de fora o texto / valor / valor2 é problemático, mas certamente o padrão é um deles?
Martin F
3
Desculpe acordar este post, oooooold, mas não vejo a vantagem de forçar um Datea Double(usando .Value2) quando o que você precisa é um Date. Não deve .Valueser preferido .Value2quando você procura um Datevalor? O artigo vinculado também não deixa isso muito claro. Desempenho porque não há conversão? Claro, mas se o seu código VBA estiver trabalhando com a Date, você perderá essa vantagem realizando a conversão, de forma implícita ou explícita ... (contexto - sinta-se à vontade para
ponderar
2
@ Caneca do Mat - o problema é que o Excel não possui um tipo de dados Data verdadeiro - as datas e horários do Excel são apenas o dobro que depende de qualquer formato que tenha sido aplicado ou alterado pelo usuário para aparecer como datas, horas ou moeda ou apenas um número. Portanto, o Value está coagindo um dobro do Excel a uma data do VBA, mas o Value2 não está fazendo nenhuma coação ... Para datas coagindo o dobro a uma data provavelmente não está causando nenhum dano, desde que o código entenda que depende de um formato mutável: pros e contras de qualquer maneira - o que realmente precisamos é de mais tipos de dados nativos do Excel para evitar esse problema.
Charles Williams
2
Quando eu quiser definir um valor de célula igual a outro celular sem uma conversão de tipo (por exemplo, sem converter um número armazenado como texto para um número) Eu uso este: Format$(Range.Value2, Range.NumberFormat).
21818 ChrisB
55

Exceto o formulário de primeira resposta Bathsheba, exceto as informações do MSDN para:

.Value
.Value2
.Text

você pode analisar essas tabelas para entender melhor as diferenças entre as propriedades analisadas.

insira a descrição da imagem aqui

Kazimierz Jawor
fonte
4
@ Chris, use .Valuecomo propriedade padrão o tempo todo - para texto e números. Use .Value2quando pensar em data e alguns números. E use .Textsempre se precisar manter a formatação de qualquer coisa que tenha na célula / intervalo. Portanto, seu exemplo de pergunta, se correto!
Kazimierz Jawor
1
por que a data mudou de 10:12 para 10:05? erro de digitação?
Katrin
1
Eu acho que é apenas o tempo decorrido entre os resultados de geração e tempo de tela tornando tiro
Kazimierz Jawor
25

target.Valuevai te dar um Varianttipo

target.Value2também lhe dará um Varianttipo, mas um Dateé coagido a umDouble

target.Texttenta coagir a um Stringe falhará se o subjacente Variantnão for coercível a um Stringtipo

A coisa mais segura a fazer é algo como

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

E verifique o tipo da variante usando VBA.VarType(v)antes de tentar uma coerção explícita.

Bathsheba
fonte
11

Em relação às convenções em C #. Digamos que você esteja lendo uma célula que contenha uma data, por exemplo, 22/10/2014.

Ao usar:

.Text, você obterá a representação formatada da data, conforme visto na pasta de trabalho na tela:
22/10/2014 . O tipo desta propriedade é sempre, stringmas nem sempre pode retornar um resultado satisfatório.

.Value, o compilador tenta converter a data em um DateTimeobjeto: {2014-10-22 00:00:00} Provavelmente só é útil ao ler datas.

.Value2, fornece o valor real subjacente da célula. No caso de datas, é uma série de datas: 41934 . Esta propriedade pode ter um tipo diferente, dependendo do conteúdo da célula. Para os folhetins de data, o tipo é double.

Portanto, você pode recuperar e armazenar o valor de uma célula em qualquer um deles dynamic, varou objectobserve que o valor sempre terá algum tipo de tipo inato no qual você terá que agir.

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
silkfire
fonte
2

.Text é o valor exibido da célula formatada; .Value é o valor da célula possivelmente aumentado com indicadores de data ou moeda; .Value2 é o valor subjacente bruto retirado de qualquer informação estranha.

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

Se você estiver processando o valor da célula, a leitura do .Value2 bruto é marginalmente mais rápida que .Value ou .Text. Se você estiver localizando erros, o .Text retornará algo como #N/Atexto e poderá ser comparado a uma string, enquanto .Value e .Value2 serão bloqueados comparando o valor retornado a uma string. Se você tiver alguma formatação de célula personalizada aplicada aos seus dados, o .Text pode ser a melhor opção ao criar um relatório.


fonte
0

Por curiosidade, eu queria ver como é o Valuedesempenho Value2. Após cerca de 12 tentativas de processos semelhantes, não pude ver nenhuma diferença significativa na velocidade, portanto sempre recomendo o uso Value. Usei o código abaixo para executar alguns testes com vários intervalos.

Se alguém vir algo contrário em relação ao desempenho, poste.

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

insira a descrição da imagem aqui

PGSystemTester
fonte