В чем разница между .text, .value и .value2?

180

Я не прошу помощи с любым сценарием, но мой вопрос для уточнения. В последнее время я много занимался написанием сценариев на VB в Excel, поэтому я действительно обращаюсь к Excel в этом вопросе. В чем разница между .text, .value и .value2? Например, когда я должен использовать target.text, target.value и target.value2? Я никогда не использовал параметр value2, но все же хотел бы знать, для чего он используется.

Иногда, если я использую .text, это дает мне ошибку, и мне нужно использовать .value, когда я проверяю или манипулирую только текстом внутри ячейки. Затем иногда, когда я думаю, что я должен использовать .value, я получаю ошибку, и мне нужно использовать .text. Обычно он принимает или без проблемы, но иногда это имеет значение. Я знаю, что в этом должна быть какая-то логика, но я не могу понять это.

Я также обнаружил, что если вы просто оставите его в качестве цели, не указав .text или .value, то он сначала будет работать, но затем что-то, что кто-то сделает, в итоге вызовет ошибку скрипта, поэтому всегда лучше использовать на нем , Я предполагаю, что я спрашиваю, может ли кто-нибудь дать мне какое-то руководство, эмпирическое правило о том, как правильно использовать каждый из них и когда его нужно использовать.

Спасибо за объяснение, ребята. Я вроде лучше понимаю. Они оба хорошие объяснения. Ниже приведен крошечный пример моего кода, который работает. Я думал, что это должен быть target.text, но это будет ошибка, поэтому, когда я использовал target.value, это сработало.

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

Я все еще немного сбит с толку, потому что когда я думаю о значении или значении2, особенно после ваших ответов, которые вы предоставили, я думаю, что они должны использоваться только для цифр. Тем не менее, в моем примере я говорю исключительно о тексте, что во многом относится к моему сценарию (текст в ячейках, в большей степени, чем числа).

Крис
источник
LCase (Target.Value) завершится ошибкой, если Target.Value не может быть принудительно приведен к строке, поскольку LCase требует строку для аргумента. Вы должны проверить VarType сначала согласно моему ответу. Также обратите внимание, что вы могли бы вместо этого использовать UCase и сравнивать непосредственно с «HLO»: не так уж много смысла работать с литералом.
Вирсавия
Спасибо за информацию о VarType. Что касается LCase или UCase для этого, на самом деле не имеет значения, какой я использовал. Некоторые люди вводят это как hlo, а другие вводят это как HLO. Из того, что я увидел, оказалось, что строчные буквы использовались чаще.
Крис

Ответы:

238

.Textдает вам строку, представляющую то, что отображается на экране для ячейки. Использование .Text обычно плохая идея, потому что вы можете получить ####

.Value2 дает базовое значение ячейки (может быть пустым, строка, ошибка, число (double) или логическое значение)

.Value выдает то же самое, что и .Value2, за исключением того, что ячейка была отформатирована как валюта или дата, она дает вам валюту VBA (которая может урезать десятичные знаки) или дату VBA.

Использование .Value или .Text обычно является плохой идеей, потому что вы не можете получить реальное значение из ячейки, и они медленнее, чем .Value2

Для более подробного обсуждения см. Мой текст против значения против значения2

Чарльз Уильямс
источник
6
Я бы, вероятно, использовал Формат для управления преобразованием числа в строку: var = Format (Range ("a1"). Value2, "#")
Чарльз Уильямс
2
Я надеюсь, что это не отдельный вопрос, а что такое по умолчанию? ФП смутно заявляет, что оставить текст / значение / значение2 проблематичным, но, несомненно, по умолчанию используется один из них?
Мартин Ф.
3
Извините, что разбудил этот oooooold пост, но я не вижу преимущества принуждения Dateв Double(использование .Value2), когда вам нужно это Date. Не .Valueследует ли отдавать предпочтение, .Value2когда вы смотрите на Dateзначение? Связанная статья не очень ясно дает понять это. Производительность, потому что нет конверсии? Конечно, но если ваш VBA-код работает с a Date, вы потеряете это преимущество, выполняя преобразование самостоятельно, неявно или явно ... (контекст - не стесняйтесь взвешивать)
Матье
2
@ Mat's Mug - проблема в том, что Excel не имеет истинного типа данных Date - даты и время в Excel просто удваиваются, что зависит от того, какой формат был применен или изменен пользователем, и будет отображаться в виде даты, времени или валюты или просто как число. Таким образом, Value принуждает двойник Excel к дате VBA, но Value2 не делает никакого принуждения ... Для принуждения дат к дате, вероятно, не будет никакого ущерба, пока код понимает, что это зависит от изменяемого формата: профи и минусы в любом случае - нам действительно нужны более родные типы данных Excel, чтобы избежать этой проблемы.
Чарльз Уильямс
2
Когда я хочу , чтобы установить значение ячейки равного в другую ячейку без преобразования типа (например, без преобразования номера , сохраненный в виде текста на ряд) Я использую это: Format$(Range.Value2, Range.NumberFormat).
ChrisB
55

За исключением формы первого ответа Вирсавии, кроме информации MSDN для:

.Value
.Value2
.Text

Вы можете проанализировать эти таблицы для лучшего понимания различий между анализируемыми свойствами.

введите описание изображения здесь

Казимеж Явор
источник
4
@Chris, .Valueвсе время используйте в качестве стандартного свойства для текста и чисел. Используйте, .Value2когда вы думаете о дате и некоторых цифрах. И используйте .Textвсегда, если вам нужно сохранить форматирование всего, что у вас есть в ячейке / диапазоне. Итак, ваш вопрос пример, если правильно!
Казимеж Явор
1
почему дата изменилась с 10:12 на 10:05? опечатка?
Катрин
1
Я думаю, что прошло только время между генерацией результатов и временем создания снимка экрана
Kazimierz Jawor
25

target.Valueдаст вам Variantтип

target.Value2даст вам Variantтип, но Dateвынужден кDouble

target.Textпытается привести к a 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)прежде чем пытаться явного принуждения.

Вирсавия
источник
11

Относительно соглашений в C #. Допустим, вы читаете ячейку с датой, например, 2014-10-22.

Когда используешь:

.Textвы получите отформатированное представление даты, как показано на экране рабочей книги:
2014-10-22 . Тип этого свойства всегда, stringно не всегда может дать удовлетворительный результат.

.Value, компилятор пытается преобразовать дату в DateTimeобъект: {2014-10-22 00:00:00} Скорее всего, полезно только при чтении дат.

.Value2, дает вам реальную, базовую ценность ячейки. В случае дат это серийный номер даты: 41934 . Это свойство может иметь различный тип в зависимости от содержимого ячейки. Для сериалов даты, хотя, тип double.

Таким образом , вы можете получить и сохранить значение ячейки либо dynamic, varили , objectно отмечает , что значение всегда будет иметь какое - то врожденный типа , что вы должны действовать в соответствии с .

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
источник
2

.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 может быть лучшим выбором при создании отчета.


источник
0

Из любопытства я хотел посмотреть, как Valueвыступают против Value2. После примерно 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

введите описание изображения здесь

PGSystemTester
источник