В чем разница между.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
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