LET statement (with Variants)  

Purpose

Assign a value or an object reference to a variant variable.

Syntax

[LET] VariantVar = variant expression

[LET] VariantVar = TypeVar AS STRING

Remarks

Although notoriously lacking in efficiency, Variant variables are commonly used as COM Object parameters due to their flexibility. They also prove valuable in a situation where a procedure must run properly with parameters of multiple data types (a Collection would be a good example).  You can think of a Variant as a kind of container, which can hold a variable of most any data type, numeric, string, object, or even a UDT or an entire array.  This simplifies the process of calling procedures in a COM Object Server, as there is little need to worry about the myriad of possible data types for each parameter.

This flexibility comes at a great price in performance, so PowerBASIC limits their use to data storage and parameters only.  You may assign a numeric value, a string value, a UDT, an object, or even an entire array to a Variant with the LET statement, or its implied equivalent.  In the same way, you may assign one Variant value to another Variant variable, or even assign an array contained in a Variant to a compatible PowerBASIC array, or the reverse.

You may extract a scalar value from a Variant with VARIANT# (for numeric values), VARIANT$ (for ANSI byte strings or user-defined types), or VARIANT$$ (for wide Unicode strings).  When you assign string data to a variant variable, ANSI strings are automatically converted to wide Unicode characters, as this is the accepted standard for variants. However, when you assign UDT data to a variant variable, it is stored as a dynamic string of bytes.  When you retrieve that UDT data (with Variant$), PowerBASIC understands the content and handles it accurately.  However, other programming languages may not, so the use of this technique should be limited to PowerBASIC applications.

LET VrntVar= vrntvar

This form duplicates the contents of one variant variable, assigning it to a second variant variable.

LET VrntVar= expression [AS vartype]

The numeric or string expression is evaluated, and the result is stored in the variant variable.  PowerBASIC will choose an appropriate numeric or string data type to use.  However, you can specify a preferred format by adding an optional AS vartype clause. This can be BYTE, WORD, DWORD, INTEGER, LONG, QUAD, SINGLE, DOUBLE, CURRENCY, or WSTRING.  Strings in a variant are always stored in wide Unicode, regardless of whether you add AS WSTRING or not.  PowerBASIC handles the conversion automatically, if it is needed.

In prior versions of PowerBASIC, the term AS STRING was interpreted to mean AS WSTRING for wide Unicode.  However, with the new support for Unicode data types, this can no longer be allowed.  All references to AS STRING with variants must be changed to AS WSTRING.

LET VrntVar = TypeVar AS STRING

The data contained in the User-Defined Type variable (UDT) is stored in the variant variable.  It is stored internally as a dynamic string of bytes (vt_bstr).  When you retrieve that UDT data (with Variant$), PowerBASIC understands the content and handles it accurately.  However, other programming languages may not understand this technique, so it should generally be limited to PowerBASIC applications.

In prior versions of PowerBASIC, the AS STRING clause was not a requirement, as it is currently.  Although it represents a change, it was a necessary restriction to confirm that the conversion to string is your intention.

LET VrntVar = EMPTY

The variant variable is set to %VT_EMPTY, which means it contains no value of any kind.

LET VrntVar = ERROR numr

This form assigns a specific COM error number, which is usually a COM specific error, such as %E_NOINTERFACE, etc.

LET VrntVar = array()

An entire PowerBASIC array is assigned to a variant variable.  In the case of a string array, PowerBASIC automatically handles Unicode conversions needed for the COM specification.  Array assignment is limited to the following data types: BYTE, WORD, DWORD, INTEGER, LONG, QUAD, SINGLE, DOUBLE, CURRENCY, or STRING, as Windows does not support all PowerBASIC data forms.

LET array() = vrntvar

An entire array is assigned from a variant variable to a PowerBASIC array.  In the case of a string array, PowerBASIC automatically handles Unicode conversions.  You can not assign an array with more than eight dimensions to a PowerBASIC array.

LET VrntVar = BYREF variable

This form is used to allow a variant to contain a typed pointer to a specific variable.  Any changes to the variant will cause the variable to be changed, as it is the target of the pointer.  The variable may be of any data type which is supported by variants and COM objects:   Byte, Word, Dword, Integer, Long, Quad, Single, Double, Currency, Variant, String, and WString.  If you attempt to use an unsupported variable type (like Extended, Bit, STRINGZ, etc.),  PowerBASIC will  generate an error 482 (Data Type Mismatch).  Further, you may not use a register variable (automatic or explicit), or an error 491 (Invalid Register Variable) will be generated.  Note that strings used with COM objects are expected to be in Unicode format, rather than ANSI.  The ACODE$ and UCODE$ functions may be used to convert the strings as necessary.  You should exercise caution with a BYREF ANSI string, as it may not be recognized accurately by other code which expects only Unicode strings.

LET objvar = vrnt

Attempts to open an interface of the specified class for objvar on the object of vrnt, and assigns a reference to objvar.  It assumes that vrnt contains a reference to an object of type %VT_UNKNOWN or %VT_DISPATCH.  If the desired interface can not be opened, the object variable objvar is set to NOTHING.  You can test for success/failure with the ISOBJECT(objvar) function.

LET vrnt = objvar

This may be used to assign an object reference from an object variable to a variant variable.  It attempts to open an IDispatch interface, else an IUnknown interface on the object of objvar, and assigns that reference to vrnt.  Variant variables can not contain references to custom interfaces, only IDispatch or IUnknown.  If the assignment is successful, VARIANTVT(vrnt) will return either %VT_UNKNOWN or %VT_DISPATCH.  If it is unsuccessful, vrnt is set to %VT_EMPTY.

See also

Just what is COM?, LET, LET (with Objects), LET (with Types), VARIANT#, VARIANT$, VARIANTVT