HOW TO: How do I use a vector<int> as an argument or a result?

Reference: Q0022

Article last modified on 28-Mar-2006


The information in this article applies to:

  • XLL+ for Visual Studio 2005 - 5.0
  • XLL+ for Visual Studio .NET - 4.2, 4.3.1, 5.0
  • XLL+ for Visual Studio 6 - 3, 4.1, 4.2, 4.3.1, 5.0

How do I use a vector<int> as an argument or a result?

Question

The XLL+ Function Wizard lets me specify integer vector arguments, but only of the following types: long, short and unsigned short. How do I specify a vector of type vector<int>?

Answer

The XLL+ Function Wizard does not directly support the int integer type. (For the reasons, see "Background" below.)

vector<int> input arguments

If your code requires a vector <int> as an input, you need to write the code (3 lines of it) yourself, instead of letting the Function Wizard write it for you.

  1. In the Function Wizard, set the type to be COper.
  2. In your add-in function declare a local variable of type vector<int> to accept the input values.
  3. Call the COper::ReadVector(...) method to read and validate the input.
  4. If ReadVector fails (i.e. returns FALSE), return the error information which is placed into xloResult by ReadVector.

The example function below demonstrates this technique.

Returning a vector<int>

To return a vector<int> value, you cannot use the standard operator= overload, since this will cast all items in the vector to boolean values. Instead, use the CXlOper::FromNumericVector(...) method to copy the vector's values to the CXlOper containing the function's result.

Example

// Function:    IntArray
// Purpose:     Takes an array of integers as an argument

//{{XLP_SRC(IntArray)
    // NOTE - the FunctionWizard will add and remove mapping code here.
    //    DO NOT EDIT what you see in these blocks of generated code!
IMPLEMENT_XLLFN2(IntArray, "RP", "IntArray", "A", "User Defined",
    "Takes an array of integers as an argument", "Vector of integ"
    "ers\000", "\0appscope=1\0", 1)

extern "C" __declspec( dllexport )
LPXLOPER IntArray(const COper* A)
{
    XLL_FIX_STATE;
    CXlOper xloResult;
//}}XLP_SRC

    std::vector<int> vecA;
    if (!A->ReadVector(vecA, "A", xloResult))
        return xloResult.Ret();
    for (size_t i = 0; i < vecA.size(); i++)
        vecA[i] *= 2;
    xloResult.FromNumericVector(vecA);
    return xloResult.Ret();
}

Background

The reasons the XLL+ Function Wizard does not directly support type int are historical.

  1. First, the XLL+ toolkit was originally designed to work with both 16-bit and 32-bit Windows code. Integer type int was mapped to a 16-bit integer under 16-bit Windows and to a 32-bit integer under 32-bit environments. We decided to avoid the int type since it would lead to confusion and to difficulties porting code between environments. Instead, we used the types long, short and unsigned short, which were of consistent size under both 16-bit and 32-bit environments. (In addition, these types are supported internally by Excel.)
  2. Early versions of Microsoft C++ did not support the bool type, and instead used the type BOOL, which is typedef'ed as an int. We therefore supported this type directly in the Function Wizard (and continue to do so). Inputs of type BOOL are automatically transformed from numbers to boolean values. Since BOOL and int are the same, this means that variables of type int are treated as boolean values, rather than as integers.

In line with our overriding policy of not breaking code between XLL+ versions, we have therefore continued to support the BOOL type, at the expense of the int type.