XLL+ Class Library (7.0)

CXlOper::GetCaller() Example

The following example demonstrates GetCaller. It looks at the size of the range of cells that called the function, and fills them with evenly interpolated values between the start and end values supplied. If it was not called from a cell or cells, but from a command or an event handler, then it gracefully returns #NA.

CopyC++
// Function:    MyFillRange 
// Returns:     LPXLOPER 
// Description: Return a series interpolated between start and end values 
 
//{{XLP_SRC(MyFillRange) 
    // NOTE - the FunctionWizard will add and remove mapping code here. 
    //    DO NOT EDIT what you see in these blocks of generated code! 
 
#pragma region MyFillRange support code
IMPLEMENT_XLLFN4(MyFillRange, MyFillRange_4, MyFillRange_12, "RBB", "UBB", 
    L"MyFillRange", 0, L"Start,End", 0, L"14", 0, L"Return a series interpolat"
    L"ed between start and end values", 0, L"Start value for series\0End value"
    L" for series\0", 0, 0, L"{MyFillRange,,,Return a series interpolated betw"
    L"een start and end values,14,1,128,U,{{0,{Start,Double,0,,Start value for"
    L" series,,,,}},{0,{End,Double,0,,End value for series,,,,}}},{},3,,0,0,,,"
    L",0,0}", 1, 0, 0)
CXlOper* MyFillRange_Impl(CXlOper&, double, double);
extern "C" __declspec(dllexport)
LPXLOPER12 MyFillRange_12(double Start, double End)
{
    XLL_FIX_STATE;
    CXlOper xloResult;
    try {
        CXlStructuredExceptionHandler _seh_;
        xloResult.HandleResult(MyFillRange_Impl(xloResult, Start, End));
    }
    catch(const CXlRuntimeException& ex) {
        CXllApp::Instance()->DisplayException(xloResult, ex);
    }
    XLP_CATCH_CLR_EXCEPTIONS_TO(xloResult)
    return xloResult.Ret12();
}
extern "C" __declspec(dllexport)
LPXLOPER4 MyFillRange_4(double Start, double End)
{
    XLL_FIX_STATE;
    CXlOper xloResult;
    try {
        CXlStructuredExceptionHandler _seh_;
        xloResult.HandleResult(MyFillRange_Impl(xloResult, Start, End));
    }
    catch(const CXlRuntimeException& ex) {
        CXllApp::Instance()->DisplayException(xloResult, ex);
    }
    XLP_CATCH_CLR_EXCEPTIONS_TO(xloResult)
    return xloResult.Ret4();
}

#pragma endregion

CXlOper* MyFillRange_Impl(CXlOper& xloResult, double Start, double End)
{
    // End of generated code 
//}}XLP_SRC

    CXlOper xloCaller;
    double dValue, dInc;
    int nCells;

    // Get caller. Fail if it is not a range of cells 
    if ( ( xloCaller.GetCaller() != 0 ) || !xloCaller.IsRef() )
    {
        xloResult = xlerrNA;
        return xloResult.Ret();
    }

    // Get the first (and only) reference from 
    // the caller CXlOper
    CXlRef xlrefCaller = xloCaller.GetRefItem(0);

    // Create the result array
    xloResult.AllocArray(xlrefCaller.Height(), 
                         xlrefCaller.Width());

    // Fill it with evenly spaced values between  
    // Start and End
    nCells = xlrefCaller.Height() * xlrefCaller.Width();
    dInc = (nCells > 1) ? ( (End - Start) / (nCells - 1) ) 
                        : 0.0;
    dValue = Start;
    for ( int i = 0; i < xlrefCaller.Height(); i++ )
    {
        for ( int j = 0; j < xlrefCaller.Width(); j++ )
        {
            xloResult.Cell(i, j) = dValue;
            dValue += dInc;
        }
    }

    // Return the array, which will be exactly the  
    // right size and shape to fill the array formula 
    // that called it 
    return xloResult.Ret();
}

Uses

CXlOper::GetCaller | CXlOper::IsRef | CXlOper::GetRefItem | CXlOper::AllocArray | CXlRef | CXlRef::Height | CXlRef::Width | CXlOper::Cell