XLL+ Class Library (6.3)

Exceptions

Exception handling in add-in functions

The XLL+ Function Wizard creates three C++ functions for each add-in function. One is the wrapper function called by Excel 2003 and below, another is the wrapper function called by Excel 2007 and above, and the third is the common implementation function called by both wrapper functions.

The wrapper functions call the implementation function within a try-catch block, which catches exceptions of type CXlRuntimeException. While validating user input, the implementation function calls a number of XLL+ library functions which may throw exceptions of type CXlRuntimeException.

In the wrapper function the application-level method CXllApp::DisplayException() is called, which converts the caught exception into an error result to be returned to Excel.

The pseudo-code below illustrates this exception flow.

Raising exceptions

If your code raises an exception which is derived from CXlRuntimeException, then you do not need to handle it specially - the wrapper function will handle and translate it for you.

If your code raises exceptions of some other type, then you must catch them. Depending on your preference in programming style, you can deal with them in one of two ways.

  1. Set the value of xloResult to an error value and exit the function.
  2. Throw another exception, of a type derived from CXlRuntimeException. This will be caught by the wrapper function as usual.

Examples of the two techniques are shown below. The first block of code below was used in the HISTVOL add-in function, to trap a C++ exception and translate immediately to #NUM!.

CopyC++
CXlOper* HISTVOL_Impl(CXlOper& xloResult, const CXlOper* Prices_op, const 
    CXlOper* DaysPerYear_op)
{
    ...
//}}XLP_SRC 
    try
    {
        xloResult = CalcHistVol(Prices, DaysPerYear);
    }
    catch(const char*)
    {
        xloResult = xlerrNum;
    }
    return xloResult.Ret();
}

Another approach could have been used: to catch the error and rethrow it with a rich error message.

CopyC++
CXlOper* HISTVOL_Impl(CXlOper& xloResult, const CXlOper* Prices_op, const 
    CXlOper* DaysPerYear_op)
{
    ...
//}}XLP_SRC 
    try
    {
        xloResult = CalcHistVol(Prices, DaysPerYear);
    }
    catch(const char* ex)
    {
        throw CXlRuntimeException(ex);
    }
    return xloResult.Ret();
}

With this approach, the error string originally thrown by CalcHistVol() is caught by the wrapper function and passed to CXllApp::DisplayException(), so you get errors such as:

#ERROR: zero value
#ERROR: negative value
#ERROR: too few points

Next: Overriding exception-handling behavior >>