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

Я не прошу помощи с любым сценарием, но мой вопрос для уточнения. В последнее время я много занимался написанием сценариев на 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, особенно после ваших ответов, которые вы предоставили, я думаю, что они должны использоваться только для цифр. Тем не менее, в моем примере я говорю исключительно о тексте, что во многом относится к моему сценарию (текст в ячейках, в большей степени, чем числа).

7 ответов

Решение

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

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

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

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

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

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

.Значение
.Value2
.Текст

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

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

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

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

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

.Valueкомпилятор пытается преобразовать дату в DateTime object: {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

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

почти всегда лучший выбор для чтения или записи в ячейку Excel или диапазон... из VBA.

      Range.Value2 '<------Best way

Каждое из следующих действий может использоваться для чтения из диапазона:

      v = [a1]
v = [a1].Value
v = [a1].Value2
v = [a1].Text 
v = [a1].Formula
v = [a1].FormulaR1C1

Каждое из следующих действий может использоваться для записи в диапазон:

      [a1] = v
[a1].Value = v
[a1].Value2 = v
[a1].Formula = v
[a1].FormulaR1C1 = v

Чтобы прочитать много значений из большого диапазона или записать много значений, может быть на несколько порядков быстрее выполнение всей операции за один раз, а не ячейка за ячейкой:

      arr = [a1:z999].Value2

Если это переменная типа Variant, приведенная выше строка фактически создает структуру OLE SAFEARRAY из вариантов шириной 26 столбцов и высотой 999 строк и указывает на Variant. arrв структуре SAFEARRAY в памяти.

      [a1].Resize(UBound(arr), UBound(arr, 2).Value2 = arr

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

Свойством по умолчанию объекта диапазона является свойство. Таким образом, если для диапазона не указано свойство, по умолчанию на свойство ссылаются молча.

Однако это самое быстрое свойство для доступа к значениям диапазона, и при чтении оно возвращает истинное значение базовой ячейки. Он игнорирует числовые форматы, даты, время и валюту и всегда возвращает числа как тип данных VBA Double. Поскольку он пытается выполнить меньше работы, он выполняется немного быстрее, чем .

Свойство, с другой стороны, проверяет, имеет ли значение ячейки числовой формат даты или времени, и в этих случаях возвращает значение типа данных VBA Date. Если ваш код VBA будет работать с типом данных Date, может иметь смысл получить их с помощью свойства. И запись типа данных VBA Date в ячейку автоматически отформатирует ячейку с соответствующим форматом даты или времени. А запись типа данных VBA Currency в ячейку автоматически применит числовой формат валюты к соответствующим ячейкам.

Аналогичным образом проверяет форматирование валюты ячейки, а затем возвращает значения типа данных VBA Currency. Это может привести к потере точности, поскольку тип данных VBA Currency распознает только четыре десятичных знака (поскольку тип данных VBA Currency на самом деле представляет собой просто 64-битное целое число, масштабированное на 10000), и поэтому значения округляются максимум до четырех знаков. И как ни странно, эта точность сокращается до двух знаков после запятой при использовании для записи переменной VBA Currency в диапазон рабочего листа.

Свойство только для чтения всегда возвращает тип данных VBA String. Значение, возвращаемое Range.Textпредставляет собой текстовое представление того, что отображается в каждой ячейке, включая числовые форматы, даты, время, валюту и текст ошибки. Это неэффективный способ получения числовых значений в VBA, поскольку требуется неявное или явное принуждение. будет возвращать #######, когда столбцы слишком тонкие, и будет замедляться еще больше, когда высота некоторых строк регулируется. всегда ОЧЕНЬ медленно по сравнению с Valueа также . Однако, поскольку сохраняет отформатированный вид значений ячеек, Textможет быть полезно, особенно для заполнения элементов управления пользовательской формы правильно отформатированными текстовыми значениями.

Точно так же оба и всегда возвращают значения как тип данных VBA String. Если ячейка содержит формулу, она возвращает ее представление в стиле A1 и возвращает ее представление R1C1. Если ячейка имеет жесткое значение вместо формулы, то и то, и другое игнорирует все форматирование и возвращает истинное базовое значение ячейки точно так же, как Value2делает... а затем сделайте еще один шаг, чтобы преобразовать это значение в строку. Опять же, это неэффективный способ получения числовых значений в VBA, поскольку требуется неявное или явное принуждение. Однако, Formulaа также FormulaR1C1 необходимо использовать для чтения формул ячеек. И их следует использовать для записи формул в ячейки.

Если ячейка A1 содержит числовое значение 100,25 с форматированием номера валюты $#,##0,00_);($#,##0,00), рассмотрите следующее:

      MsgBox [a1].Value                   'Displays:  100.25
MsgBox TypeName([a1].Value)         'Displays: Currency
 
MsgBox [a1].Value2                  'Displays:  100.25
MsgBox TypeName([a1].Value2)        'Displays: Double
 
MsgBox [a1].Text                    'Displays: $ 100.25
MsgBox TypeName([a1].Text)          'Displays: String
 
MsgBox [a1].Formula                 'Displays: 100.25
MsgBox TypeName([a1].Formula)       'Displays: String
 
MsgBox [a1].FormulaR1C1             'Displays: 100.25
MsgBox TypeName([a1].FormulaR1C1)   'Displays: String
  

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

Другие вопросы по тегам