Variant = Evil?
Many Visual Basic programmers have never used variant data
types, having been taught that variants are "evil". It's not really that
variants are evil, only that they are evil if you have the choice to use
something a bit more efficient, otherwise you simply use what you have. In all actuality, variants can help make your VBCE
application more optimized than you may think. We'll cover the hows and whys of that
later, but first let's talk about what a variant is.
Unlike regular Visual Basic, VBCE has only
one data type, the Variant. As the name implies, the Variant is a data type that can
contain different kinds of data, depending on how it's used.
Numeric or string information
A Variant behaves as a number when you're using
it in a numeric context and as a string when you use it in a string context. In other
words, if you're working with data that looks like numbers, VBCE assumes that the
data is a number and does the thing that is most appropriate for numbers. Strings work the
same way, if you're working with data that can only be string data, VBScript treats it as
string data. For example, if you perform a mathimatical function on two data types, VBCE
will treat the datatypes as if they are numbers. But, if the datatypes are assigned to
something that indicates string data, such as a form caption, the data types will be
treated as a string. See the following example:
Private Sub
Command1_Click()
Dim myFirstVariant
Dim mySecondVariant
'Assign Values
to the Variables
myFirstVariant = 19
mySecondVariant = 98
'Produces "117"
MsgBox "Variants Added
Together = " & _
myFirstVariant
+ mySecondVariant
'Produces
"1998"
MsgBox "Variants concatenated
Together = " & _
myFirstVariant
& mySecondVariant
End Sub
Other Information
A Variant can also contain numeric information that represents a
date or a time. When used with other date or time data, the result is always expressed as
a date or a time. You can also have numeric information ranging in size from Boolean
values to huge floating-point numbers. These different categories of information that can
be contained in a Variant are called subtypes. Most of the time,
you can just put the kind of data you want in a Variant and it behaves in a way that is
most appropriate for the data it contains.
The following table shows the various subtypes of data that a
Variant can contain:
| Subtype |
Description |
| Empty |
Variant is uninitialized. Value is
either 0 for numeric variables or a zero-length string ("") for string
variables. |
| Null |
Variant intentionally contains no valid
data. |
| Boolean |
Contains either True or False. |
| Byte |
Contains integer in the range 0 to 255. |
| Integer |
Contains integer in the range -32,768 to
32,767. |
| Currency |
-922,337,203,685,477.5808 to
922,337,203,685,477.5807. |
| Long |
Contains integer in the range -2,147,483,648 to
2,147,483,647. |
| Single |
Contains a single-precision, floating-point
number in the range -3.402823E38 to -1.401298E-45 for negative values; 1.401298E-45 to
3.402823E38 for positive values. |
| Double |
Contains a double-precision, floating-point
number in the range -1.79769313486232E308 to -4.94065645841247E-324 for negative values;
4.94065645841247E-324 to 1.79769313486232E308 for positive values. |
| Date (Time) |
Contains a number that represents a date
between January 1, 100 to December 31, 9999. |
| String |
Contains a variable-length string that can be
up to approximately 2 billion characters in length. |
| Object |
Contains an object. |
| Error |
Contains an error number. |
Converting from one subtype to another
VBCE contains a rich set of conversion functions you can use to convert from one
variant subtype to another:
| Function |
Use |
| ASC |
Returns the ANSI character code corresponding to the first
letter in a string. |
| CBool |
Returns an expression that has been converted to a Variant
of subtype Boolean |
| CByte |
Returns an expression that has been converted to a Variant
of subtype Byte. |
| CCur |
Returns an expression that has been converted to a Variant
of subtype Currency. |
| CDate |
Returns an expression that has been converted to a Variant
of subtype Date. |
| CDbl |
Returns an expression that has been converted to a Variant
of subtype Double. |
| Chr |
Returns the character associated with the specified ANSI
character code. |
| CInt |
Returns an expression that has been converted to a Variant
of subtype Integer. |
| CLng |
Returns an expression that has been converted to a Variant
of subtype Long. |
| CSng |
Returns an expression that has been converted to a Variant
of subtype Single. |
| CStr |
Returns an expression that has been converted to a Variant
of subtype String. |
| Hex |
Returns a string representing the hexadecimal value of a
number. |
| Oct |
Returns a string representing the octal value of a number. |
Also, the VarType function
returns information about how the data is stored within a Variant:
Description
Returns a value indicating the subtype of a variable.
Syntax
VarType(varname)
The varname argument can be any variable.
Return Values
The VarType function returns the following values:
| Constant |
Value |
Description |
| vbEmpty |
0 |
Empty (uninitialized) |
| vbNull |
1 |
Null (no valid data) |
| vbInteger |
2 |
Integer |
| vbLong |
3 |
Long integer |
| vbSingle |
4 |
Single-precision floating-point number |
| vbDouble |
5 |
Double-precision floating-point number |
| vbCurrency |
6 |
Currency |
| vbDate |
7 |
Date |
| vbString |
8 |
String |
| vbObject |
9 |
Automation object |
| vbError |
10 |
Error |
| vbBoolean |
11 |
Boolean |
| vbVariant |
12 |
Variant (used only with arrays of Variants) |
| vbDataObject |
13 |
A data-access object |
| vbByte |
17 |
Byte |
| vbArray |
8192 |
Array |
Note These constants are specified
by VBCE. As a result, the names can be used anywhere in your code in place of the actual
values.
Variants are More Reusable
I said earlier "In all
actuality variants can help make your VBCE application more optimized than you may
think." What I mean by this is simply the fact that you can reuse a variant for
several purposes. This may not lend itself very well to more readable code, but it can
help reduce the memory foot print of your application. The way this can be used is when
you application may require a bunch of global variables or variables that you want to
reuse, instead of dimming a bunch of them, you might be able to get away with dimming a
"varTemp" variable and reusing it.
Most of the time you'll want to use more structured code, but there
may be times where this seems somewhat appropriate.
Variants have their benifits and drawbacks. One such benfit is not
having to type the datatype and being able to change the way you use the varialble in code
(be sure to comment your code when you do this). The drawback is that when you dimmension
a variant to hold, for example, a control - VB has no indication of what type of data it
is going to be so you do not get data tips and such while coding. One way to help with
this is to use a good method of coding conventions. Be sure to read the VBCE Coding Conventions article.
mike@vbce.com |
"In all actuality, variants
can help make your VBCE application more optimized than you may think." |