TL; DR: Преобразования типов.
Range.Value
- это Variant
, который представляет собой специальный тип данных, который хранит указатель на значение вместе сописание типа данных: вот как ячейка может содержать значение Double
, String
, Boolean
или Error
.
Все, что глубже, не имеет отношения к вопросупод рукой.
Integer
- это 16-разрядный целочисленный тип со знаком, который легко помещается в Double
, который намного больше 16-разрядных.Если вы выполнили присваивание .Value
с этим:
Debug.Print TypeName(Range("A1").Value)
В результате отладки вы получите Double
.
Где-то в реализации свойства Range.Value
, проверкауказанного значения выполняется, и если значение является приемлемым, оно сохраняется внутри соответствующего типа данных.Если значение не является допустимым типом данных, выдается ошибка 1004.Integer
- точное числовое значение, все в порядке.
То же самое происходит во втором фрагменте: Double
- точное числовое значение, все в порядке.И поскольку любое числовое значение, взятое из ячейки, равно Variant/Double
, мы можем разумно сделать вывод, что где-то во внутренних кишках Range
числовые значения сохраняются как Double
- хотя это вполне может быть просто деталью реализациио том, как реализовано getter свойства Range.Value
.
VBA был разработан для работы с определенным набором типов данных и библиотеками типов хост-приложений VBA (например, Excel)были разработаны для принятия этих типов данных.Следовательно, вам придется потрудиться, чтобы присвоить Range.Value
значение, с которым он не может справиться, используя код VBA.
Но прежде, чем значение попадет в свойство Range.Value
, неявное преобразование типаво втором фрагменте произошла ошибка.
Dim x As Integer
x = 6
Здесь 6
- это целочисленный литерал .Когда VBA выполняет инструкцию x = 6
, этот 6
уже имеет тип данных - и этот тип данных Integer
.
Dim x As Double
x = 6
Здесь 6
также является целочисленным литералом, но ему назначаетсяв Double
, что не совпадает с типом: происходит неявное преобразование типа, и x
счастливо принимает значение Integer
- потому что преобразование расширяется .
Теперь рассмотрим:
Dim x As Double
x = 6#
Здесь 6#
использует подсказку типа .Debug.Print TypeName(6#)
печатает Double
: 6#
является литералом Double
- здесь преобразование типов не происходит.Но это ужасно.
Dim x As Double
x = CDbl(6)
Теперь преобразование расширяющего типа является явным.
Когда неявное преобразование вместо этого сужается , и значение не может вписаться внеобходимый тип данных ...
Dim x As Integer
x = 32768 '<~ that's a Long integer literal: doesn't fit the 16 bits of an Integer
... затем выдается ошибка времени выполнения 6 («переполнение»).Поскольку каждый числовой тип данных VBA можно безопасно преобразовать в Double
, каждому числовому значению, которое может быть предоставлено кодом VBA, можно присвоить Range.Value
.