XLL+ Class Library

Using a matrix with continuous values

When you return to DevStudio, the following code will have been added to Tutorial.cpp.

// Function:    MAXCOORD
// Purpose:     Get the x or y coordinate of the maximum value in an array

//{{XLP_SRC(MAXCOORD)
    // NOTE - the FunctionWizard will add and remove mapping code here.
    //    DO NOT EDIT what you see in these blocks of generated code!
IMPLEMENT_XLLFN2(MAXCOORD, "RPA", "MAXCOORD", "Array,XCoord", 
    "Statistical", "Get the x or y coordinate of the maximum"
    " value in an array", "2-dimensional array of numbers\0True"
    " for the x coordinate (column number), false for y (row"
    " number)", "B()3()Array 2-dimensional array of numbers\0\0",
    1)

extern "C" __declspec( dllexport )
LPXLOPER MAXCOORD(const COper* Array, BOOL XCoord)
{
    CXlOper xloResult;
    BOOL bOk = TRUE;
    ple::mtx_flat<double> matArray;
    bOk = bOk && Array->ReadMatrix(matArray, "Array", xloResult, 0, 0, XLA_ARRAY_FLAGS_STD|XLA_FLAG_TRANSPOSE, 0, 0);
    if (!bOk)
        return xloResult.Ret();
//}}XLP_SRC

    // TODO - Set the value of xloResult
    return xloResult.Ret();
}

The matrix-reading code differs from that in INTERP2D in two ways:

  1. The matrix used is of type mtx_flat<T>.
  2. The flags argument to ReadMatrix includes the bit XLA_FLAG_TRANSPOSE.

After ReadMatrix() has run successfully, the data we need will be in matArray, as a continous array of doubles, arranged with rows together, which is what we wanted for our implementation function, FindMax().

Add the code below, to call FindMax():

extern "C" __declspec( dllexport )
LPXLOPER MAXCOORD(const COper* Array, BOOL XCoord)
{
    ...
//}}XLP_SRC

    int nMaxCol, nMaxRow;                                                               
    // Since we have transposed the matrix, by specifying that columns be held together,
    // matArray has columns as the outer axis (i.e. size(0)) and rows                   
    // as the inner axis (i.e. size(1)).                                                
    if (FindMax(matArray.size(0), matArray.size(1),                                     
                &matArray[0], // or, if you prefer, matArray.begin(),                   
                &nMaxCol, &nMaxRow))                                                    
    {                                                                                   
        int nCoord = XCoord ? nMaxCol : nMaxRow;                                        
        // Add 1 to the coordinate because Excel's coordinates are                      
        // 1-based while C's are zero-based                                             
        nCoord++;                                                                       
        // Return a numeric value                                                       
        xloResult = (double)nCoord;                                                     
    }                                                                                   
    else                                                                                
        xloResult = xlerrNum;                                                           

    return xloResult.Ret();
}

Notice that we add one to any coordinate's representation in Excel because Excel indices are by convention one-based, whereas C indices (being address offsets) are zero-based.

For full details on reading matrix arguments, see COper::ReadMatrix() in the class reference.

Next: Returning vectors to Excel >>