Now that you know all about XLOPERs and specifying functions, you can take a closer look at the Excel4 function:
int _cdecl Excel4(int iFunction, LPXLOPER pxRes, int iCount, ...)
First, notice that this function is _cdecl. This means that it uses the C calling convention. For more information about calling conventions, see your compiler documentation.
The function takes at least three arguments. The following three arguments must always be present.
Following the iCount argument are the arguments to the Microsoft Excel function itself. These must all be LPXLOPERs, that is, pointers to XLOPERs that you have allocated. As a rule, all arguments to all Microsoft Excel functions and command equivalents are always specified as pointers to XLOPERs. In order to represent a missing (omitted) argument, create an XLOPER of type xltypeMissing, and pass a pointer to that, or use a NULL pointer.
With Microsoft Windows, it is a good idea to always cast these arguments to LPXLOPERs. For example, always write:
Excel4(xlfGetCell, &xResult, 1, (LPXLOPER) &xMyXloper);
Instead of:
Excel4(xlfGetCell, &xResult, 1, &xMyXloper); /* BAD!!! */
When you include XLCALL.H, the Excel4 function prototype automatically casts the second argument (the return value) to an LPXLOPER. All the other arguments, starting with the fourth, need to have casts. The cast forces the compiler to create a full 32-bit address for the XLOPER. This is important mainly in the 16-bit world, where the XLOPER could exist in the DS of the DLL. If you consistently cast all arguments past the second you will never run into this problem regardless of platform.
You should always check the return value from Excel4. If it is not xlretSuccess, something has prevented the call from succeeding. For example, one of the XLOPERs may not be valid; Microsoft Excel may be low on memory; or you may have used an invalid number of arguments. For a list of the possible return values, see "Excel4" on page 214. If Excel4 does not return xlretSuccess, the XLOPER returned (pxRes) will contain a #VALUE! error.
Note
The Excel function in the framework library automatically checks the return value to aid in debugging.
Be careful to distinguish between a Microsoft Excel function failing and the Excel4 function failing. When a Microsoft Excel function fails, Excel4 succeeds but pxRes contains one of the Microsoft Excel error codes. When Excel4 fails, it actually returns one of the xlret... failure codes. There is a fine distinction between a failure in Microsoft Excel and a failure in the callback mechanism.
You can call Excel4 only when control has been passed to your code by Microsoft Excel. You are not able to call back into Microsoft Excel anytime you want. In other words, you cannot set up a timer with a callback address, return control to Microsoft Excel, and then in your callback function call Excel4. Neither can you create a DLL that interacts with Microsoft Excel but is loaded and called by another application. To communicate with Microsoft Excel from another application you should use OLE Automation or DDE. For more information about OLE Automation, see Chapter 4, "Using OLE Automation." For more information about DDE, see Appendix A, "Dynamic Data Exchange and XlTable Format."
Important
Unless Microsoft Excel has called you, Microsoft Excel will not be ready to handle callbacks.
Note
Even though the Excel4 and Excel4v functions are named for Microsoft Excel version 4.0, they work with any version Microsoft Excel later than 4.0. The current Excel4 and Excel4v functions will continue to work even with future versions of Microsoft Excel. This ensures that any add-ins you develop now will still work with future versions of Microsoft Excel.
There is an additional function, Excel4v, which works like Excel4, but it takes an array of LPXLOPERs passed by reference instead of on the stack:
int _cdecl Excel4v(int iFunction, LPXLOPER pxRes,
int iCount, LPXLOPER rgx[]);
This function allows you to wrap up Excel4 in another function. For example:
int MyExcel4(int iFunction, LPXLOPER pxRes, int iCount, ...)
{
int result = Excel4v(iFunction, pxRes, iCount,
(LPXLOPER *) (&iCount+1));
assert(result == xlretSuccess);
return result;
}