Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VBA: Unexpected Behaviour of Variant Data Type

Tags:

vba

As per MSDN, for Variant data types:

“Numeric data can be any integer or real number value ranging from -1.797693134862315E308 to -4.94066E-324 for negative values and from 4.94066E-324 to 1.797693134862315E308 for positive values.”

However, the following code gives an error even though all final values after computation fall well within the acceptable range:

Sub Test()

Dim v1, v2, v3, v4

v1 = 569847501 + 54678                  '  OKAY
v2 = 7784687414# + 98565821345#         '  OKAY
v3 = 7784687414# + 1132747441           '  OKAY
v4 = 1132747441 + 1788441323            '  FAILS

End Sub

MSDN also points out:

” However, if an arithmetic operation is performed on a Variant containing a Byte, an Integer, a Long, or a Single, and the result exceeds the normal range for the original data type, the result is promoted within the Variant to the next larger data type. A Byte is promoted to an Integer, an Integer is promoted to a Long, and a Long and a Single are promoted to a Double.”

The documentation states that the type should be promoted when an arithmetic operation exceeds the normal range for the original data type. Why isn’t v4 promoted to Double?

like image 478
Hiran Kaleka Avatar asked Sep 12 '16 19:09

Hiran Kaleka


People also ask

What are the disadvantages of Variant data type?

The disadvantages are that certain pieces of code using variant may process a little more slowly than others, or may not catch certain classes of programming errors. The default data type is variant. Variant is a self-describing data type that can hold simple numeric or string values.

What is the Variant data type in VBA?

The Variant data type is automatically specified if you don't specify a data type when you declare a constant, variable, or argument. Variables declared as the Variant data type can contain string, date, time, Boolean, or numeric values, and can convert the values that they contain automatically.

What three special values can be Variant data type hold?

A Variant is a special data type that can contain any kind of data except fixed-length String data. (Variant types now support user-defined types.) A Variant can also contain the special values Empty, Error, Nothing, and Null.

What is a Variant string in VBA?

Variant/String Also called a Variant-Character data type. This data type as its name suggests is a sub type of the variant data type. This data type uses 22 bytes plus the length of the string. This data type is much larger than a normal variable-length string.


2 Answers

You're working with numeric literals, which aren't Variants. They're interpreted by the compiler as the smallest necessary type to accommodate the literal value, although Byte values will default to type Integer.

Debug.Print TypeName(1132747441) 'Long
Debug.Print TypeName(1788441323) 'Long

As @ComIntern points out, you're assigning the result of 2 longs in an expression, the expression overflows before it is assigned to the Variant v4

As @dazedandconfused pointed out, you can coerce the literal values to a more suitable type, and the expression will evaluate, and the variant can be assigned.

In order to get the behavior that Microsoft documents for the Variant type, you need to coerce the literal values to variant, before using them in an expression. Both Variants will contain Longs, but you'll get the auto re-typing that the documentation asserts.

Sub Test()

  Dim v1, v2, v3, v4

  Debug.Print TypeName(1132747441) 'Long
  Debug.Print TypeName(1788441323) 'Long

  Dim v5, v6

  v5 = 1132747441
  v6 = 1788441323

  Debug.Print TypeName(v5) 'Long
  Debug.Print TypeName(v6) 'Long

  v4 = v5 + v6 'OKAY
  Debug.Print TypeName(v4) 'Double

  v4 = 0
  Debug.Print TypeName(v4) 'Integer

  v4 = CVar(1132747441) + CVar(1788441323) ' OKAY
  Debug.Print TypeName(v4) 'Double


  v1 = 569847501 + 54678                  '  OKAY
  v2 = 7784687414# + 98565821345#         '  OKAY
  v3 = 7784687414# + 1132747441           '  OKAY
  v4 = 1132747441 + 1788441323            '  FAILS

End Sub
like image 130
ThunderFrame Avatar answered Oct 14 '22 09:10

ThunderFrame


From https://support.microsoft.com/en-us/kb/199809 - See bolded statement

This statement generates an overflow error, since 24 * 24 * 60 = 34560, which exceeds the maximum size of a 2 byte integer (32767). Visual Basic does not evaluate the entire expression to check for the size of the result, but instead continues to use a 2 byte temporary space for the calculation. The same overflow error occurs if you declare the preceding values as constants and multiply the constants.

In order to work around this behavior, it is important to always explicitly type numbers when using them in numeric calculations or when defining constants. If the preceding expression is changed to the following:

So changing it to...

v4 = 1132747441# + 1788441323#

...does the trick, but it sure does smell.

like image 44
dazedandconfused Avatar answered Oct 14 '22 09:10

dazedandconfused