The XLOPER Data Type

Microsoft Excel is polymorphic. Cells can hold many different types of values: strings, numbers, arrays, error values, or logical values. Internally, this is accomplished by using a special, 10-byte data type called an XLOPER. Every XLOPER has 2 bytes that indicate the type of data and 8 bytes that indicate the actual data. The 8 bytes are used differently, depending on the data type — sometimes they contain a pointer to data that is stored elsewhere.

Note

Although the actual size of an XLOPER is 10 bytes, the effective size may vary depending upon the operating system. C compilers and/or CPUs are frequently more efficient when structures are aligned on fixed byte boundaries. Under Win16 the preferred alignment is 2 bytes, and the effective size remains 10 bytes. Under Win32 the preferred alignment is 8 bytes. The best way to handle this is to set the Struct Member Alignment to 8 bytes. This is the default value in Microsoft Visual C++. This increases the effective size of an XLOPER to 16 bytes under Win32.

There are 12 different types of XLOPERs. You specify a type by entering a type constant in the xltype field of the XLOPER. The type constants are defined for you in XLCALL.H and are listed in the following table.

Type constant

xltype

Type of value

xltypeNum

0x0001

Numeric (IEEE floating-point)

xltypeStr

0x0002

String (byte-counted)

xltypeBool

0x0004

Logical (TRUE or FALSE)

xltypeRef

0x0008

General reference (external and/or disjoint)

xltypeErr

0x0010

Error

xltypeFlow

0x0020

Flow control in a macro

xltypeMulti

0x0040

Array

xltypeMissing

0x0080

Missing argument in a function call

xltypeNil

0x0100

None (for example, an empty cell)

xltypeSRef

0x0400

Single rectangular reference to current sheet

xltypeInt

0x0800

Integer (rarely used; use xltypeNum)

xltypeBigData

0x0802

Persistent data storage


The file XLCALL.H contains the definition of the XLOPER structure. In Windows, the definition appears as follows:

typedef struct xloper 
{
    union 
    {
        double num;                    /* xltypeNum */
        LPSTR str;                    /* xltypeStr */
        WORD bool;                    /* xltypeBool */
        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 */
        struct 
        {
            union
            {
                short int level;        /* xlflowRestart */
                short int tbctrl;    /* xlflowPause */
                DWORD idSheet;        /* xlflowGoto */
            } valflow;
            WORD rw;                    /* xlflowGoto */
            BYTE col;                /* xlflowGoto */
            BYTE xlflow;
        } flow;                        /* xltypeFlow */
        struct
        {
            union
            {
                 BYTE *lpbData;        /* data passed in */
                 HANDLE hdata;        /* data returned */
            } h;

            long cbData;
        } bigdata;                    /* xltypeBigData */
    } val;
    WORD xltype;
} XLOPER, *LPXLOPER;

typedef struct xlref 
{
    WORD rwFirst;
    WORD rwLast;
    BYTE colFirst;
    BYTE colLast;
} XLREF, *LPXLREF;

typedef struct xlmref 
{
    WORD count;
    XLREF reftbl[1];          /* actually reftbl[count] */
} XLMREF, *LPXLMREF;

Types of XLOPERs

Following are diagrams of the various types of XLOPERs.

Caution

When you get string XLOPERs from Microsoft Excel, they are not always null-terminated! Do not attempt to pass them directly to C string-handling functions, such as strcpy(), that expect null-terminated strings.

Note

Be sure to use an unsigned char or (BYTE) for the byte count. This is important, because otherwise it is possible to create negative string lengths. For example:

LPSTR s;
WORD w;

w = s[0];         /* Bad */
w = (BYTE) s[0]; /* Good */

For more information, see "Advanced Flow Control in Macro Sheets" on page 191.

Examples of XLOPERs in C

The following are some examples showing how to construct various types of XLOPERs in C. As a convention, XLOPER variable names start with a lowercase "x."

To construct an integer XLOPER with value 27

XLOPER xInt;

xInt.xltype = xltypeInt;
xInt.val.w = 27;

To construct a numeric (floating-point) XLOPER with the value 3.141592654

XLOPER xPi;

xPi.xltype = xltypeNum;
xPi.val.num = 3.141592654;

To construct an XLOPER containing the string "Excel String"

XLOPER xStr;

xStr.xltype = xltypeStr;
xStr.val.str = (LPSTR)"\014Excel String";
/* Notice the octal byte count in front of the string. */

To construct an XLOPER containing the logical value TRUE

XLOPER xBool;

xBool.xltype = xltypeBool;
xBool.val.bool = 1;

To construct an XLOPER containing a zero divide (#DIV/0!) error

XLOPER xZeroDivide;

xZeroDivide.xltype = xltypeErr;
xZeroDivide.val.err = xlerrDiv0;

To construct an XLOPER containing the array {1,2}

XLOPER rgx[2];
XLOPER xArray;

rgx[0].xltype = rgx[1].xltype = xltypeInt;
rgx[0].val.w = 1;
rgx[1].val.w = 2;
xArray.xltype = xltypeMulti;
xArray.val.array.lparray = (LPXLOPER) &(rgx[0]);
xArray.val.array.rows = 1;
xArray.val.array.columns = 2;

To construct a bigdata XLOPER

XLOPER xData;

xData.xltype = xltypeBigData; 
xData.val.bigdata.h.lpbData = lpbData;        // pointer to the data
xData.val.bigdata.cbData = cbData;            // data length in bytes

For more information about using bigdata XLOPERs, see "Persistent Storage" on page 175.