Variant Type

Purpose

The Variant data type is the data type for all variables that are not explicitly declared as some other type (using statements such as Dim, Local, Global, Public, or Static). The Variant data type has no type-declaration character.

Syntax

Dim v [As Variant]

v:variable name

Description

A Variant is a special data type that can contain one of a range of data types from Integers, Floating Point numbers, strings, objects and arrays (all the supported types are discussed in more detail later).

Variants are 16-byte variables: the first two bytes hold the code describing the variable type it is mimicing, the next six are reserved for system use and the last eight hold either the data value or a reference to it; described as a Type, it looks like this:

Type VariantType

wVarType As Word

wReserved1 As Word

wReserved2 As Word

wReserved3 As Word

pData As VariantData

EndType

Type VariantData Union

ByteData As Byte

ShortData As Word

LongData As Long

SingleData As Single

CurrencyData As Currency

DoubleData As Double

Date As Date

StringObject As Handle

EndType

Although Variants are more flexible than standard variable types, their complexity makes them slower in operation so they should be used mainly where their flexibility proves useful but less so where speed is of the essence. A speed comparison can be made by running the following code:

Local a, b, m%, n%, t1#, t2#

t1# = Timer

For a = 1 To 100000 : b = b + 50 : Next a       // Loop using Variants

t1# = Timer - t1#

t2# = Timer

For n% = 1 To 100000 : m% = m% + 50 : Next n%   // Loop using Int32 variables

t2# = Timer - t2#

Debug "Variant time: ";t1# : Debug "Integer time: ";t2#

Debug "Int32 variables were" & Round(((t1# / t2#) * 100), 2) & "% faster than Variants"

Initialisation and Conversion

To initialise a Variant use Dim var as Variant; you can omit the As Variant as any undefined variables are assumed to be Variants.

Once a Variant is initialised it is considered to be Empty until a value or object is assigned to it.

Generally, you do not have to concern yourself with the internal representation of data inside a Variant, nor with variable initialisation when a value is added, as GFABASIC and Windows handle this very competently. There are occasions, however, when you may wish to either specify or change the variable type for some purpose or other and, in most cases (except for Bytes and Shorts) this is possible using the conversion functions CInt, CSng, etc (see here). More information on how to do this is given below in the sections on Variable Types.

Similarly, comparisons and conversions between string and numeric data types are usually seamless, but errors will be thrown if you try to convert a string which is not numerical to a numerical data type, or compare such a string with a numeric literal or variable. The IsNumeric query function can be used to try and intercept any possible errors of this type.

When GFA-BASIC 32 converts a representation that is not numeric (such as a string containing a number) to a numeric value, it uses the Regional settings (specified in the Windows Control Panel) to interpret the thousands separator, decimal separator, and currency symbol.

Thus, if the country setting in the Windows Control Panel is set to United States, Canada, or Australia, these two statements would return true:

Print IsNumeric("$100")

Print IsNumeric("1,560.50")

While these two statements would return false:

Print IsNumeric("€100")

Print IsNumeric("1.560,50")

However, the reverse would be the case - the first two would return false and the second two true - if the country setting in the Windows Control Panel was set to Germany.

If you assign a Variant containing a number to a string variable or property, GFA-BASIC 32 converts the representation of the number to a string automatically. If you want to explicitly convert a number to a string, use the CStr function. You can also use the Format function to convert a number to a string that includes formatting such as currency, thousands separator, and decimal separator symbols. The Format function automatically uses the appropriate symbols according to the Regional Settings Properties dialog box in the Windows Control Panel.

It should also be noted that automatic conversion of data to a Variant does have its limits. What should be done when two Variants are added (or concatenated) when one contains a string and the other a numeric value? For the concatenation below, the possible courses of action are:

vntC = CVar("123") + CVar(456)

  1. Add them as if they were both numeric values, so convert the string to a numeric value.
  2. Concatenate them as strings, resulting in the string "123456".
  3. None of the above, but generate an error.

GFA-BASIC 32 copies VB and takes option 1; see Strings in Variants for more detail on this.

Accepted Variable Types for Variants

GFA-BASIC32 supports a large number of variable types that it is possible to enclose in a Variant, but by no means all. The supported types, which largely mirror those supported as standalone variable types (with the notable exception of Large Integers and Fixed Strings), are listed in detail below.

To discover which variable type a Variant contains, you can use TypeName to return a string or VarType to return a numerical representation of the type. There are also a range of type specific query functions, which are: IsArray, IsDate, IsEmpty, IsError, IsMissing, IsNothing, IsNull and IsObject; as well as the more general IsNumeric function.

Integers in Variants Show

Floating Point Numbers in Variants Show

Date and Time in Variants Show

Strings in Variants Show

Empty, Null, Missing and Error Show

Objects (and Variants) in Variants Show

Arrays in Variants Show

Variants passed to Procedures

Generally, Variants act in the same way as their GFABASIC counterparts when passed as parameters to Procedures, except in the following caase:

Known Issues

There is an odd bug when passing Boolean values to an optional variant parameter in a function IF the function is called form a procedure containing a Gosub...Return structure - an Access Violation Error is returned for no apparent reason pointing to the line containing Return. This is illustrated by the code examples below:

trial

 

Procedure trial

Local enb As Boolean = True

VarTrial(10, enb)

GoSub Here

Return

Here:

Print "Go to here"

EndProcedure

 

Function VarTrial(a%, Optional v As Variant)

Print a, v

EndFunction

This is an error within the compiler and, currently, unfixable. If you experience this, simple workarounds are: use a different variable type in the calling procedure (anything but Boolean seems to work); or change the optional parameter in the called Function to type Boolean.
[Reported by James Gaite, 11/03/2018]

{Created by James Gaite; Last updated: 15/01/2023 by James Gaite}