The OPER
class is a variant datatype that corresponds to a cell or
range of cells in an Excel spreadsheet. It can be a number, string, boolean, reference,
error, range, missing, nil, simple reference, or integer. It is a struct with a
member called xltype that can be any of the following
values.
#define xltypeNum 0x0001 #define xltypeStr 0x0002 #define xltypeBool 0x0004 #define xltypeRef 0x0008 #define xltypeErr 0x0010 #define xltypeFlow 0x0020 #define xltypeMulti 0x0040 #define xltypeMissing 0x0080 #define xltypeNil 0x0100 #define xltypeSRef 0x0400 #define xltypeInt 0x0800 #define xlbitXLFree 0x1000 #define xlbitDLLFree 0x4000 #define xltypeBigData (xltypeStr | xltypeInt)
Here is the Microsoft XLOPER struct from XLCALL.H
:
typedef struct xloper { union { double num; /* xltypeNum */ LPSTR str; /* xltypeStr */ #ifdef __cplusplus WORD xbool; /* xltypeBool */ #else WORD bool; /* xltypeBool */ #endif WORD err; /* xltypeErr */ short int w; /* xltypeInt */ struct { WORD count; /* always = 1 */ XLREF ref; } sref; /* xltypeSRef */ struct { XLMREF *lpmref; DWORD idSheet; } mref; /* xltypeRef */ struct { struct xloper *lparray; WORD rows; WORD columns; } array; /* xltypeMulti */ // ...flow and bigdata removed... } val; WORD xltype; } XLOPER, *LPXLOPER;
C++ is a strongly typed language, but the OPER class is a wrapper around the XLOPER struct that was designed to behave just as you would expect a variant to behave.
OPER o; assert (o.xltype == xltypeNil); o = 1.23; // or o = Num(1.23); assert (o.xltype == xltypeNum); assert (o.val.num = 1.23); assert (o == 1.23 && 1.23 == o); o = OPER("string"); // or o = Str("string") assert (o.xltype == xltypeStr); assert (o == OPER("sTrInG")); // case insensitve o = true; // or o = Bool(true); assert (o.xltype == xltypeBool); assert (o); o = Err(xlerrValue); // #VALUE! assert (o.xltype == xltypeErr); assert (o.val.err == xlerrValue); o = Excel<XLOPER>(xlfEvaluate, OPER("{1,2,3;4,5,6}")); // or o = OPER(2, 3); o(0, 0) = 1; ...; o(1, 2) = 6; assert (o.xltype == xltypeMulti); assert (o.val.array.rows == 2); assert (o.val.array.columns == 3); assert (o.val.array.lparray[3].val.num == 4); assert (o[3] == 4); // same using 1-d index assert (o(1, 0) == 4); // same using 2-d index assert (Missing().xltype == xltypeMissing); assert (Nil().xltype == xltypeNil); o = 123; assert (o.xltype == xltypeNum); // not xltypeInt! assert (o == 123); o = Int(123); // if you really need an int assert (o.xltype == xltypeInt); assert (o.val.w == 123); // 16-bit short int assert (o == 123);
Don't do o = "a naked string" or the character pointer gets converted to a double and o will have xltype == xltypeNum and o.val.num equal to the value of the character pointer. You can only bend C++ so far.
The function
Excel
takes OPER
s as arguments and gives you access
to all of Excel's functionality.