Uses handles to represent vectors of numbers
This project demonstrates the use of handles to represent large data sets. Each handle represents a vector of numbers.
Each vector is held in a NumericVector
object;
the NumericVector
class is a thin wrapper around std::vector
.
class NumericVector : public std::vector<double> { public: NumericVector() { } NumericVector(const std::vector<double>& source) { assign(source.begin(), source.end()); } NumericVector(size_t size) { resize(size); } };
The add-in function CreateVector
takes a vector of numbers as an argument,
creates a NumericVector
object, adds it to the object cache
and returns a handle to the object.
CXlOper* CreateVector_Impl(CXlOper& xloResult, const CXlOper* numbers_op) { // Input buffers std::vector<double> numbers; // Validate and translate inputs XlReadVector(*numbers_op, numbers, L"numbers", XLA_TRUNC_ONEMPTY| XLA_TRUNC_ONBLANK); // End of generated code //}}XLP_SRC NumericVector* vec = new NumericVector(numbers); xloResult = psl::CreateHandleInCache(vec); return xloResult.Ret(); }
The add-in function UseVector1
takes a handle to a NumericVector
as an argument, and returns the sum of the numbers in the vector.
The XLL+ Function Wizard was used to declare the argument vec
as of type
Handle to NumericVector
.
In the code below, note that the auto-generated code deals with all the work of converting the handle into
a pointer to the cached NumericVector
object. If the conversion fails, then an exception is thrown
and the developer-defined code that uses vec
is never reached.
CXlOper* UseVector1_Impl(CXlOper& xloResult, const CXlStringArg& vec_op) { // Input buffers const NumericVector* vec; // Validate and translate inputs XlReadScalarEx(vec_op, vec, psl::HandleConverter<NumericVector >(), CScalarConvertParams<const NumericVector*>(L"vec", 0, 0, -1). SetStringParam(0, L"NumericVector")); // End of generated code //}}XLP_SRC xloResult = std::accumulate(vec->begin(), vec->end(), 0.0); return xloResult.Ret(); }
The add-in function UseVector2
uses a variable type argument, which can be either:
NumericVector
object; or
This behavior is achieved by defining the argument as a Choice type, which can be either a Double[]
or a Handle
to NumericVector
, as shown below:
CXlOper* UseVector2_Impl(CXlOper& xloResult, const CXlOper* HandleOrArray) { // Input buffers std::vector<double> numbers; const NumericVector* vec; // Validate and translate inputs int HandleOrArray__index = -1; if (HandleOrArray__index < 0) { try { XlReadVector(*HandleOrArray, numbers, L"numbers", XLA_TRUNC_ONEMPTY| XLA_TRUNC_ONBLANK); HandleOrArray__index = 0; } catch(...) {} } if (HandleOrArray__index < 0) { try { XlReadScalarEx(*HandleOrArray, vec, psl::HandleConverter< NumericVector >(), CScalarConvertParams<const NumericVector*>( L"vec", 0, 0, -1).SetStringParam(0, L"NumericVector")); HandleOrArray__index = 1; } catch(...) {} } if (HandleOrArray__index < 0) throw CXlChoiceFailedException("HandleOrArray"); // End of generated code //}}XLP_SRC const std::vector<double>* input = (HandleOrArray__index == 0) ? &numbers : (const std::vector<double>*)vec; xloResult = std::accumulate(input->begin(), input->end(), 0.0); return xloResult.Ret(); }
The auto-generated code shown above takes care of reading the argument into one of the variables
numbers
or vec
.
Note that the code sets the indicator variable
HandleOrArray__index
to either 0
or 1
to indicate which input variable was set.
So the developer-provided code simply inspects HandleOrArray__index
and uses the
appropriate input variable:
const std::vector<double>* input = (HandleOrArray__index == 0) ? &numbers : (const std::vector<double>*)vec;
Each sample project is located in a sub-directory of the Samples directory of the XLL+ installation. To use the sample project, open the solution file ArrayHandles.sln or the project file ArrayHandles.vcproj.
You can enable debugging under Excel by using the Setup Debugging command in the XLL+ ToolWindow.
When delivered, the help files are excluded from the build.
You can enable the help build by selecting the files
ArrayHandles.help.xml
and
ArrayHandles.chm
in the Solution Explorer,
and using the right-click menu to view Properties.
Select the page "Configuration Properties/General" and
set the "Excluded from build" property to "No".
See Generating help
in the User Guide for more information.