Variant 是一種特殊的數據類型,除了定長String數據及用戶定義類型外,能夠包含任何種類的數據。Variant 也能夠包含Empty、Error、Nothing及Null等特殊值。能夠用VarType函數或TypeName函數來決定如何處理 Variant 中的數據。程序員
數值數據能夠是任何整型或實型數,負數時範圍從 -1.797693134862315E308 到 -4.94066E-324,正數時則從 4.94066E-324 到 1.797693134862315E308。一般,數值Variant 數據保持爲其 Variant 中原來的數據類型。例如,若是把一個 Integer賦值給 Variant,則接下來的運算會把此 Variant 當成 Integer 來處理。然而,若是算術運算針對含 Byte、Integer、Long 或 Single 之一的Variant 執行,並當結果超過原來數據類型的正常範圍時,則在 Variant 中的結果會提高到較大的數據類型。如Byte則提高到 Integer,Integer 則提高到 Long,而 Long和Single 則提高爲 Double。當 Variant 變量中有 Currency、Decimal 及 Double 值超過它們各自的範圍時,會發生錯誤。數組
能夠用 Variant 數據類型來替換任何數據類型,這樣會更有適應性。若是 Variant 變量的內容是數字,它能夠用字符串來表示數字或是用它實際的值來表示,這將由上下文來決定,例如:數據結構
Dim MyVar As Variant函數
MyVar = 98052ui
在前面的例子中,MyVar 內有一實際值爲 98052 的數值。像指望的那樣,算術運算子能夠對 Variant 變量運算,其中包含數值或能被解釋爲數值的字符串數據。若是用 + 運算子來將 MyVar 與其餘含有數字的 Variant 或數值類型的變量相加,結果即是一算術和。spa
Empty 值用來標記還沒有初始化(給定初始值)的Variant 變量。內含 Empty 的 Variant 在數值的上下文中表示 0,若是是用在字符串的上下文中則表示零長度的字符串 ("")。指針
不該將 Empty 與 Null 弄混。Null 是表示 Variant 變量確實含有一個無效數據。code
在 Variant 中,Error 是用來指示在過程當中出現錯誤時的特殊值。然而,不像對其餘種類的錯誤那樣,程序並不產生普通的應用程序級的錯誤處理。這可讓程序員,或應用程序自己,根據此錯誤值採起另外的行動。能夠用 CVErr 函數將實數轉換爲錯誤值來產生 Error 值。htm
變體類型Variant,可以在運行期間動態的改變類型。變體類型能支持全部簡單的數據類型,如整型、浮點、字符串、布爾型、日期時間、貨幣及OLE自動化對象等,不可以表達Object Pascal對象。對象
1.VarArrayCreate function
建立一個變體類型的數組。
function VarArrayCreate(const Bounds: array of Integer; VarType: TVarType): Variant;
建立而且填充一個一維的變體類型的數組。
function VarArrayOf(const Values: array of Variant): Variant;
VarArrayCreate, VarArrayOf Example
var
A: Variant;
begin
A := VarArrayCreate([0, 4], varVariant);
A[0] := 1;
A[1] := 1234.5678;
A[2] := 'Hello world';
A[3] := True;
A[4] := VarArrayOf([1, 10, 100, 1000]);
WriteLn(A[2]); { Hello world }
WriteLn(A[4][2]); { 100 }
end;
2.VarArrayLock function
鎖住一個變體類型的數組而且返回一個指向這個數據的指針。
function VarArrayLock(const A: Variant): Pointer;
VarArrayLock, VarArrayUnlock Example
type
PArrayData = ^TArrayData;
TArrayData = array[0..9, 1..3] of Integer;
var
A: Variant;
P: PArrayData;
I, J: Integer;
begin
A := VarArrayCreate([1, 3, 0, 9], varInteger);
P := VarArrayLock(A);
try
for I := 0 to 9 do
for J := 1 to 3 do
P^[I, J] := J * 10 + I;
finally
VarArrayUnlock(A);
end;
WriteLn(A[1, 9]); { 19 }
WriteLn(A[3, 4]); { 34 }
end;
3.VarArrayUnlock procedure
Unlocks a variant array.
procedure VarArrayUnlock(var A: Variant);
VARIANT 數據類型在文件OAIDL.IDL中定義以下:
struct tagVARIANT {
union {
struct __tagVARIANT {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
ULONGLONG ullVal;
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
_VARIANT_BOOL bool;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
IUnknown * punkVal;
IDispatch * pdispVal;
SAFEARRAY * parray;
BYTE * pbVal;
SHORT * piVal;
LONG * plVal;
LONGLONG * pllVal;
FLOAT * pfltVal;
DOUBLE * pdblVal;
VARIANT_BOOL *pboolVal;
_VARIANT_BOOL *pbool;
SCODE * pscode;
CY * pcyVal;
DATE * pdate;
BSTR * pbstrVal;
IUnknown ** ppunkVal;
IDispatch ** ppdispVal;
SAFEARRAY ** pparray;
VARIANT * pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
INT intVal;
UINT uintVal;
DECIMAL * pdecVal;
CHAR * pcVal;
USHORT * puiVal;
ULONG * pulVal;
ULONGLONG * pullVal;
INT * pintVal;
UINT * puintVal;
struct __tagBRECORD {
PVOID pvRecord;
IRecordInfo * pRecInfo;
} __VARIANT_NAME_4;
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
};
VARIANT數據結構包含兩個域(若是不考慮保留的域)。vt域描述了第二個域的數據類型。爲了使多種類型可以在第二個域中出現,咱們定義了一個聯合結構。因此,第二個域的名稱隨着vt域中輸入值的不一樣而改變。用於指定vt域值狀況的常量在聯合的定義中以每一行的註釋形式給出。
使用VARIANT和VARIANTARG數據結構要分兩步徹底。舉一個例子,讓咱們考慮以下代碼:
long lValue = 999;
VARIANT vParam;
vParam.vt = VT_I4;
vParam.lVal = lValue;
在第一行中指定數據類型。常量VT_I4代表在第二個域中將出現一個long型的數據。根據類型VARIANT的定義,能夠得知,當一個long型數據存入VARIANT類型時,其第二個域使用的名稱是lVal。
使用VARIANT來傳遞參數意味着非強類型語言(例如VBScript)可以調用使用強類型語言(C++)實現的方法。Invoke()方法的實現能夠檢查參數VARIANT封裝的數值是否符合其正確的數據類型。若是符合,該類型將取出,並傳遞給調用方法。不然,Invoke()方法可以嘗試使用 VariantChangeType()API函數來將該數值轉換成正確的類型。
typedef unsigned short VARTYPE;
enum VARENUM
{ VT_EMPTY = 0,
VT_NULL = 1,
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_VARIANT = 12,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_VOID = 24,
VT_HRESULT = 25,
VT_PTR = 26,
VT_SAFEARRAY = 27,
VT_CARRAY = 28,
VT_USERDEFINED = 29,
VT_LPSTR = 30,
VT_LPWSTR = 31,
VT_RECORD = 36,
VT_INT_PTR = 37,
VT_UINT_PTR = 38,
VT_FILETIME = 64,
VT_BLOB = 65,
VT_STREAM = 66,
VT_STORAGE = 67,
VT_STREAMED_OBJECT = 68,
VT_STORED_OBJECT = 69,
VT_BLOB_OBJECT = 70,
VT_CF = 71,
VT_CLSID = 72,
VT_VERSIONED_STREAM = 73,
VT_BSTR_BLOB = 0xfff,
VT_VECTOR = 0x1000,
VT_ARRAY = 0x2000,
VT_BYREF = 0x4000,
VT_RESERVED = 0x8000,
VT_ILLEGAL = 0xffff,
VT_ILLEGALMASKED = 0xfff,
VT_TYPEMASK = 0xfff
} ;
VARIANT支持的類型,也就是vt成員的取值如表4-3所示。
表4-3 VARIANT支持的類型 |
|
類型名 |
含義 |
VT_EMPTY |
指示未指定值 |
VT_NULL |
指示空值(相似於 SQL 中的空值) |
VT_I2 |
指示 short 整數 |
VT_I4 |
指示 long 整數 |
VT_R4 |
指示 float 值 |
VT_R8 |
指示 double 值 |
VT_CY |
指示貨幣值 |
VT_DATE |
指示 DATE 值 |
VT_BSTR |
指示 BSTR 字符串 |
VT_DISPATCH |
指示 IDispatch 指針 |
VT_ERROR |
指示 SCODE |
VT_BOOL |
指示一個布爾值 |
VT_VARIANT |
指示 VARIANTfar 指針 |
VT_UNKNOWN |
指示 IUnknown 指針 |
VT_DECIMAL |
指示 decimal 值 |
VT_I1 |
指示 char 值 |
(續表)
類型名 |
含義 |
VT_UI1 |
指示 byte |
VT_UI2 |
指示 unsignedshort |
VT_UI4 |
指示 unsignedlong |
VT_I8 |
指示 64 位整數 |
VT_UI8 |
指示 64 位無符號整數 |
VT_INT |
指示整數值 |
VT_UINT |
指示 unsigned 整數值 |
VT_VOID |
指示 C 樣式 void |
VT_HRESULT |
指示 HRESULT |
VT_PTR |
指示指針類型 |
VT_SAFEARRAY |
指示 SAFEARRAY |
VT_CARRAY |
指示 C 樣式數組 |
VT_USERDEFINED |
指示用戶定義的類型 |
VT_LPSTR |
指示一個以 NULL 結尾的字符串 |
VT_LPWSTR |
指示由 nullNothingnullptrnull引用(在 Visual Basic 中爲 Nothing) 終止的寬字符串 |
VT_RECORD |
指示用戶定義的類型 |
VT_FILETIME |
指示 FILETIME 值 |
VT_BLOB |
指示以長度爲前綴的字節 |
VT_STREAM |
指示隨後是流的名稱 |
VT_STORAGE |
指示隨後是存儲的名稱 |
VT_STREAMED_OBJECT |
指示流包含對象 |
VT_STORED_OBJECT |
指示存儲包含對象 |
VT_BLOB_OBJECT |
指示 Blob 包含對象 |
VT_CF |
指示剪貼板格式 |
VT_CLSID |
指示類 ID |
VT_VECTOR |
指示簡單的已計數數組 |
VT_ARRAY |
指示 SAFEARRAY 指針 |
VT_BYREF |
指示值爲引 |