Books
in black and white
Main menu
Share a book About us Home
Books
Biology Business Chemistry Computers Culture Economics Fiction Games Guide History Management Mathematical Medicine Mental Fitnes Physics Psychology Scince Sport Technics
Ads

Excel add in development in C++ Aplications in finance - Dalton S.

Dalton S. Excel add in development in C++ Aplications in finance - Wiley publishing , 2005. - 425 p.
ISBN 0-470-02469-0
Download (direct link): exceladdindevelopmentincand2005.pdf
Previous << 1 .. 117 118 119 120 121 122 < 123 > 124 125 126 127 128 129 .. 168 >> Next

HRESULT OLE_ExcelCalculate(void)
{
if(ipExcelDisp)
return S_FALSE;
static DISPID dispid = 0;
DISPPARAMS Params; char cErr[64];
HRESULT hr;
// DISPPARAMS has four members which should all be initialised Params.rgdispidNamedArgs = NULL; // Dispatch IDs of named args Params.rgvarg = NULL; // Array of arguments Params.cArgs = 0; // Number of arguments Params.cNamedArgs = 0; // Number of named arguments
// Get the Calculate method's dispid
if(dispid ==0) // first call to this function {
// GetIDsOfNames will only be called once. Dispid is cached since it // is a static variable. Subsequent calls will be faster.
wchar_t *ucName = L"Calculate";
hr = pExcelDisp->GetIDsOfNames(IID_NULL, &ucName, 1, LOCALE_SYSTEM_DEFAULT, kdispid);
if(FAILED(hr))
{
// Perhaps VBA command or function does not exist
sprintf(cErr, "Error, hr = 0x%08lx", hr);
MessageBox(NULL, cErr, "GetIDsOfNames",
300
Excel Add-in Development in C/C++
MB_OK | MB_SETFOREGROUND); return hr;
}
}
// Call the Calculate method
hr = pExcelDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, iParams, NULL, NULL, NULL);
if(FAILED(hr))
{
// Most likely reason to get an error is because of an error in a // UDF that makes a COM call to Excel or some other automation // interface
sprintf(cErr, "Error, hr = 0x%08lx", hr);
MessageBox(NULL, cErr, "Calculate", MB_OK | MB_SETFOREGROUND);
}
return hr; // = S_OK if successful
}
Note that calls to Invoke do not have to be method calls such as this. Invoke is also called for accessor functions that get and/or set Excel properties. For a full explanation of Invokeā€™s syntax, see the Win32 SDK help.
9.5.3 Calling user-defined commands using COM
This is achieved using the Run method exposed by Excel via the COM interface. Once the above initialisation of the pExcelDisp IDispatch object has taken place, the following code will run any command that takes no arguments and that has been registered with Excel in this session. (The function could, of course, be generalised to accommodate commands that take arguments.) Where the command is within the XLL, the required parameter cmd_name should be the same as the 4th argument passed to the xlfRegister function, i.e., the name Excel recognises the command rather than the source code name. Note that the call to the GetIDsOfNames() method to get the DISPID is done only once for the Run command, greatly speeding up subsequent calls.
#define MAX_COM_CMD_LEN 512
HRESULT OLE_RunXllCommand(char *cmd_name)
{
static DISPID dispid = 0;
VARIANTARG Command;
DISPPARAMS Params;
HRESULT hr;
wchar_t w[MAX_COM_CMD_LEN +1]; char cErr[64];
int cmd_len = strlen(cmd_name); if(!pExcelDisp || !cmd_name || !*cmd_name
Miscellaneous Topics 301
|| (cmd_len = strlen(cmd_name)) > MAX_COM_CMD_LEN) return S_FALSE;
try
{
// Convert the byte string into a wide char string. A simple C-style // type cast would not work!
mbstowcs(w, cmd_name, cmd_len + 1);
Command.vt = VT_BSTR;
Command.bstrVal = SysAllocString(w);
Params.rgdispidNamedArgs = NULL;
Params.rgvarg = &Command;
Params.cArgs = 1;
Params.cNamedArgs = 0;
if(dispid == 0)
{
wchar_t *ucName = L"Run";
hr = pExcelDisp->GetIDsOfNames(IID_NULL, &ucName, 1, LOCALE_SYSTEM_DEFAULT, kdispid);
if(FAILED(hr))
{
sprintf(cErr, "Error, hr = 0x%08lx", hr); MessageBox(NULL, cErr, "GetIDsOfNames", MB_OK|MB_SETFOREGROUND);
}
}
SysFreeString(Command.bstrVal); return hr;
hr = pExcelDisp->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, iParams, NULL, NULL, NULL);
if(FAILED(hr))
{
sprintf(cErr, "Error, hr = 0x%08lx", hr);
MessageBox(NULL, cErr, "Invoke",
MB_OK | MB_SETFOREGROUND);
SysFreeString(Command.bstrVal); return hr;
}
// Success.
}
catch(_com_error ice)
{
// If COM throws an exception, we end up here. Most probably we will // get a useful description of the error.
MessageBoxW(NULL, ce.Description(), L"Run",
MB_OK | MB_SETFOREGROUND);
// Get and display the error code in case the message wasn't helpful hr = ce.Error();
302
Excel Add-in Development in C/C++
sprintf(cErr, "Error, hr = 0x%08lx", hr); MessageBox(NULL, cErr, "The Error code", MB_OK|MB_SETFOREGROUND);
}
SysFreeString(Command.bstrVal); return hr;
}
9.5.4 Calling user-defined functions using COM
This is achieved using the Run method exposed by Excel via the COM interface.
There are some limitations on the exported XLL functions that can be called using COM: the OLE Automation interface for Excel only accepts and returns Variants of types that this interface supports. It is not possible to pass or retrieve Variant equivalents of xloper types xltypeSRef, xltypeSRef, xltypeMissing, xltypeNil or xltypeFlow. Only types xltypeNum, xltypeInt, xltypeBool, xltypeErr and xltypeMulti arrays of these types have Variant equivalents that are supported. Therefore only functions that accept and return these things can be accessed in this way. (The cpp_xloper class contains xloper-VARIANT conversion routines.)
Once the above initialisation of the pExcelDisp IDispatch object has taken place, the following code will run any command that has been registered with Excel in this session. Where the command is within the XLL, the parameter CmdName should be same as the 4th argument passed to the xlfRegister function, i.e. the name Excel recognises the command by rather than the source code name. Note that the call to the GetIDsOfNames() method to get the DISPID is executed only once for the Run command, greatly speeding up subsequent calls.
Previous << 1 .. 117 118 119 120 121 122 < 123 > 124 125 126 127 128 129 .. 168 >> Next