Действует ли .Value = .Value аналогично функции Evaluate() в VBA?

Рассмотрим следующий фрагмент. Он записывает одну и ту же формулу в две ячейки A1 и A2.

Sub Main()
    With Range("A1")
        .Formula = "=1+1"
    End With

    With Range("A2")
        .Formula = "=1+1"
        .Value = .Value
    End With
End Sub

Второй блок with использует .Value = .Value, который вычисляет/выполняет формулу, поэтому формула исчезает из строки формул. Обратитесь к скрытие формул из панели формул для дополнительной справки.

.Value = .Value скрывает формулу из строки

Теперь добавьте еще один блок

With Range("A3")
     .Formula = "=1+1"
End With
Range("A4") = Evaluate(Range("A3").Formula)

Вы добавляете формулу в ячейку A3, а затем формула этой новой ячейки Evaluated() переносится в другую ячейку A4. Результаты, как показано

Вычислить формулу ячеек

Я думаю, что приведенное выше показывает, что .Value = .Value и Evaluate() делают одно и то же.

Однако приведенный ниже код извлекает значение из закрытой книги, используя два упомянутых подхода. Я создал рабочую книгу book9.xlsm для этого примера с hello, помещенным в ячейку A1. book9.xlsm — это тот, из которого я буду получать значение A1. Рассмотрим код

Sub PullValue()
    With Range("A1")
        .Formula = "='C:\Users\admin\Desktop\[book9.xlsm]Sheet1'!A1"
    End With

    With Range("A2")
        .Formula = "='C:\Users\admin\Desktop\[book9.xlsm]Sheet1'!A1"
        .Value = .Value
    End With

    Range("A3").Formula = "='C:\Users\admin\Desktop\[book9.xlsm]Sheet1'!A1"
    Range("A4") = Evaluate(Range("A3").Formula)
End Sub

Первый блок with помещает формулу в значение A1 ячейки из блока book9.xlsm. Он выполняется, поэтому полученное значение равно hello, но в строке формул отображается фактическое .Formula, которое равно C:\....

Второй блок with использует .Value = .Value, как показано выше, для оценки формулы и скрытия формулы путем замены ее результатом.

Range("A3") совпадает с первым блоком with.

И теперь (A4) я следую тому же принципу, что и в первом примере (первый фрагмент в этом вопросе) к Evaluate() формуле, однако на этот раз она не работает.

Пожалуйста, просмотрите все значения активированных ячеек и строку формул для каждой из них.

результаты

Так что теперь я не могу сказать, что .Value = .Value равно Evaluate().

Примечания Evalutate() говорят, что его можно использовать с формулами. Но в примере, который я показал, это не работает.

Оценить() msdn

Ограничены ли формулы, используемые в качестве параметров в Evaluate()? Я всегда думал, что функция Evaluate очень мощная, но оказалось, что .Value = .Value на самом деле еще мощнее. Несмотря на то, что они очень похожи, они чем-то отличаются (но я считаю, что это может быть моя ошибка, поскольку формула, которую я выбрал для этого примера, может быть ограниченной или ограниченной). Думаю, я показал, что делает их двумя похожими и разными одновременно. Это все еще примерно 50%/50%, и я не могу точно сказать, одинаковы они или нет. Было бы здорово, если бы кто-нибудь смог объяснить, чего здесь не хватает.


person Community    schedule 19.07.2013    source источник
comment
@lori_m Я отменил ваше редактирование. Пожалуйста, не меняйте радикально смысл сообщений, особенно если вы просто догадываетесь, в чем вопрос. См. это метаобсуждение Больше подробностей.   -  person slhck    schedule 22.07.2013
comment
Боюсь, Evaluate() не работает, когда указанная ячейка находится в закрытой книге. Если вы откроете указанную книгу, она снова будет работать нормально. Так работает функция Evaluate, она не может читать из закрытой книги.   -  person Daniel Dušek    schedule 22.07.2013


Ответы (4)


.value и Evaluate не совпадают.
Excel поддерживает как значение, так и строку формулы для каждой используемой ячейки, и вы можете получить их независимо друг от друга, используя Range.Value и Range.Formula.
При использовании Application .Evaluate для оценки строки, строка оценивается как формула на активном листе (поэтому на самом деле лучше использовать Worksheet.Evaluate, а не Application.Evaluate, и это быстрее).
Использование Rng1.Value=Rng2.Value копирует значение из Rng2 в Rng1 и перезаписывает формулу Rng1.
Использование Rng1.Value=Evaluate(rng2.Formula) просит Excel извлечь строку формулы из Rng2, оценить ее и вернуть результат в Rng1.

Метод Evaluate работает не так, как формула в ячейке: у него есть много особенностей, о которых вам нужно знать (включая тот факт, что он не работает с формулами, относящимися к внешним закрытым книгам). : см. подробности в моем блоге
Также обычно лучше использовать .Value2, а не .Value: см. Value vs Value2 подробности

person Charles Williams    schedule 23.07.2013
comment
+1 - я понятия не имел, что .Value2 быстрее, чем .Value. Спасибо за хороший ответ, а также за сообщение в блоге. - person Jon Crowell; 23.07.2013

.Value = .Value и Evaluate() разные.

Я думаю, у вас есть некоторая путаница с объектами и их свойствами по умолчанию.

Всегда помните об этих двух понятиях:

  1. VBA позволяет использовать свойства и методы без указания объекта. VBA будет использовать свой объект по умолчанию. Например, когда вы используете Evaluate(), вы на самом деле используете Sheet1.Evaluate().

  2. VBA позволяет использовать объекты без указания свойства. VBA будет использовать их свойство по умолчанию. Например, когда вы используете Range("A1") = 1, вы на самом деле используете Range("A1").Formula = 1. (Вы на самом деле используете Sheet1.Range("A1").Formula = 1!)

Возвращаясь к вашему примеру, когда вы делаете .Value = .Value, вы на самом деле делаете Range("A2").Value = Range("A2").Value. Свойство Value ячейки может быть числом, строкой, ошибкой и т. д. А если это число, то это может быть неправильное число, которое не является правильным результатом формулы в этой ячейке (например, потому что у вас отключен автоматический расчет). Таким образом, .Value = .Value эквивалентно .Formula = "<xxx>", где <xxx> — это последнее значение, вычисленное в ячейке.

Когда вы делаете Range("A4") = Evaluate(Range("A3").Formula), вы просите Excel оценить формулу и присвоить результат свойству Formula диапазона A4 (поскольку свойство формулы является свойством по умолчанию для объекта диапазона).

person stenci    schedule 22.07.2013
comment
поэтому, согласно вашему последнему предложению, Range (A4) должен на самом деле говорить hello, а не выдавать ошибку. Возникает ли ошибка, потому что Evaluate не может извлечь значение из закрытой книги? - person ; 23.07.2013
comment
да. Excel довольно хорошо просматривает закрытые книги, когда формулы ссылаются на них, даже когда они закрыты. Метод Evaluate работает с данными в разных книгах, но только в том случае, если они уже открыты. Если вы знаете, что ваша следующая оценка попытается получить доступ к данным в другой книге, ваш макрос должен проверить, закрыта ли книга, и открыть ее. Но производительность будет намного медленнее (даже с ScreenUpdating = False), чем формула, потому что ваш макрос откроет всю книгу, в то время как формула может получить доступ только к необходимым данным внутри закрытого файла. - person stenci; 23.07.2013
comment
у вас есть ссылка, подтверждающая (You actually use Sheet1.Range("A1").Formula = 1!) из вашего ответа? Как вы выяснили, что Formula используется по умолчанию для Range? - person ; 28.01.2014
comment
@mehow У меня нет ссылки. Я думаю, это происходит потому, что Range("A2") = "=A1" работает, и из-за других подобных действий, но я могу ошибаться. - person stenci; 28.01.2014
comment
Благодарю. Пожалуйста, посмотри это в свободное время, может быть тебе будет интересно - person ; 28.01.2014

.Value = .Value (в блоке With ячейки) просто устанавливает значение ячейки в ее текущее значение, перезаписывая и удаляя ее формулу, если она есть. Свойство .Value просто представляет текущее значение ячейки. Если ячейка содержит формулу, которая еще не была рассчитана, например. если вычисление отключено, оно может не возвращать результат формулы, вместо этого возвращая предыдущее значение ячейки.

Excel.Application.Evaluate принимает строковое значение, оценивая содержимое строки, как если бы это была формула или имя ячейки, и возвращая значение этой ячейки или формулы. Если вы передадите ему строку, которая не может быть сопоставлена ​​с именем ячейки Excel или не является допустимой формулой, вы получите сообщение об ошибке. Назначение Evaluate состоит в том, чтобы обеспечить возможность оценки динамически созданных формул без необходимости записи формулы в ячейку. Если передана формула, она также должна возвращать результат, даже если вычисление рабочей книги отключено, хотя, если передано имя, я ожидаю, что оно вернет текущее значение ячейки, и если вычисление рабочей книги отключено, это значение может не отражать ожидаемое значение указанной ячейки.

Предположительно, поскольку .Value ячейки и Evaluate() могут возвращать разные результаты, механизм оценки формулы рабочего листа и механизм Application.Evaluate() различны или, по крайней мере, имеют несколько разных элементов.

person Monty Wild    schedule 22.07.2013

Evaluate — это функция, которая использует точку (.) после функции, которая называется свойством. Итак, ".Value", "Formula", ".Text" - это свойства Range, которые вы используете здесь.

Не путайте эти 2 вещи.

Функция принимает входные данные, выполняет действия, используя свои входные переменные, и возвращает результаты. И он работает с тем типом данных, для которого настроен.

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

так что есть вероятность, что вы получите ошибку от 1, а остальные работают абсолютно нормально.

person Kamal G    schedule 22.07.2013