Update of /cvsroot/objecthandler/ObjectHandler/ohxl/Functions
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv31124/ohxl/Functions
Modified Files:
.cvsignore
Added Files:
manual.cpp
Log Message:
cleaner implementation for ohPack/ohParseFields
Index: .cvsignore
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/Functions/.cvsignore,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** .cvsignore 2 Oct 2006 12:31:17 -0000 1.1
--- .cvsignore 3 Oct 2006 09:32:37 -0000 1.2
***************
*** 1 ****
! *.*
--- 1 ----
! functions.cpp
--- NEW FILE: manual.cpp ---
/*
Copyright (C) 2006 Eric Ehlers
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it under the
terms of the QuantLib license. You should have received a copy of the
license along with this program; if not, please email qua...@li...
The license is also available online at http://quantlib.org/html/license.html
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
// Excel functions coded by hand, to be registered with Excel
// alongside the autogenerated functions.
#include <oh/utilities.hpp>
#include <oh/exception.hpp>
#include <ohxl/objecthandlerxl.hpp>
#include <ohxl/conversions.hpp>
#include <ohxl/functioncall.hpp>
#include <ohxl/functioncount.hpp>
#include <sstream>
#include <map>
#include <boost/lexical_cast.hpp>
#define XLL_DEC extern "C"
#define SET_SESSION_ID
XLL_DEC long *ohDependsOn(
OPER *dummy0,
OPER *dummy1,
OPER *dummy2,
OPER *dummy3,
OPER *dummy4,
OPER *dummy5,
OPER *dummy6,
OPER *dummy7,
OPER *dummy8,
OPER *dummy9,
OPER *trigger) {
boost::shared_ptr<ObjHandler::FunctionCall> functionCall;
try {
// initialize Function Call object
functionCall = boost::shared_ptr<ObjHandler::FunctionCall>
( new ObjHandler::FunctionCall("ohDependsOn") );
if (functionCall->IsCalledByFuncWiz())
return 0;
ObjHandler::validateTrigger(trigger);
// initialize the QuantLib session ID (if enabled)
SET_SESSION_ID
// reset the calling cell
ObjHandler::ObjectHandlerXL::instance().resetCaller();
// invoke the utility function
static std::map < std::string, long > iterators;
static long returnValue;
returnValue = iterators[ObjHandler::FunctionCall::instance().getAddressString()]++;
// convert and return the return value
return &returnValue;
} catch (const std::exception &e) {
std::ostringstream err;
err << "ohDependsOn - ";
if (functionCall) err << functionCall->getAddressString() << " - ";
err << e.what();
ObjHandler::ObjectHandlerXL::instance().logError(err.str());
return 0;
}
}
XLL_DEC long *ohFunctionCount() {
// FUNCTION_COUNT gives the number of autogenerated functions,
// add 4 for the hand-written functions in this file
static long returnValue = FUNCTION_COUNT + 4;
return &returnValue;
}
int countValidRows(const XLOPER &xMulti) {
for (int numValidRows=xMulti.val.array.rows; numValidRows; numValidRows--) {
for (int i=0; i<xMulti.val.array.columns; i++) {
int index = (numValidRows - 1) * xMulti.val.array.columns + i;
if (!(xMulti.val.array.lparray[index].xltype & (xltypeErr | xltypeNil)))
return numValidRows;
}
}
return 1;
}
int countValidCols(const XLOPER &xMulti) {
for (int numValidCols=xMulti.val.array.columns; numValidCols; numValidCols--) {
for (int i=0; i<xMulti.val.array.rows; i++) {
int index = (numValidCols - 1) + i * xMulti.val.array.columns;
if (!(xMulti.val.array.lparray[index].xltype & (xltypeErr | xltypeNil)))
return numValidCols;
}
}
return 1;
}
XLL_DEC XLOPER *ohPack(OPER *xInputRange) {
boost::shared_ptr < ObjHandler::FunctionCall > functionCall;
XLOPER xMulti;
static XLOPER xRet;
xRet.val.array.lparray = 0;
try {
functionCall = boost::shared_ptr < ObjHandler::FunctionCall >
( new ObjHandler::FunctionCall("ohPack") );
Excel(xlCoerce, &xMulti, 2, xInputRange, TempInt(xltypeMulti));
int numValidRows = countValidRows(xMulti);
int numValidCols = countValidCols(xMulti);
xRet.val.array.rows = numValidRows;
xRet.val.array.columns = numValidCols;
xRet.val.array.lparray = new XLOPER[numValidRows * numValidCols];
if (!xRet.val.array.lparray)
throw ObjHandler::Exception("ohPack: error on call to new");
xRet.xltype = xltypeMulti | xlbitDLLFree;
for (int i=0; i<numValidRows; i++) {
for (int j=0; j<numValidCols; j++) {
int indexSource = i * xMulti.val.array.columns + j;
int indexTarget = i * numValidCols + j;
ObjHandler::operToOper(&xRet.val.array.lparray[indexTarget],
&xMulti.val.array.lparray[indexSource]);
}
}
Excel(xlFree, 0, 1, &xMulti);
return &xRet;
} catch (const std::exception &e) {
// free any memory that may have been allocated
Excel(xlFree, 0, 1, &xMulti);
if (xRet.xltype & xltypeMulti && xRet.val.array.lparray) {
for (int i=0; i<xRet.val.array.columns * xRet.val.array.rows; i++) {
if (xRet.val.array.lparray[i].xltype & xltypeStr && xRet.val.array.lparray[i].val.str)
delete [] xRet.val.array.lparray[i].val.str;
}
delete [] xRet.val.array.lparray;
}
// log the exception and return a null pointer (#NUM!) to Excel
std::ostringstream err;
err << "ohPack - ";
if (functionCall) err << functionCall->getAddressString() << " - ";
err << e.what();
ObjHandler::logMessage(err.str(), 2);
return 0;
}
}
XLL_DEC XLOPER *ohParseField(
char *line,
long *index,
char *type,
OPER *delim) {
boost::shared_ptr < ObjHandler::FunctionCall > functionCall;
try {
functionCall = boost::shared_ptr < ObjHandler::FunctionCall >
( new ObjHandler::FunctionCall("ohParseField") );
SET_SESSION_ID
// reset the calling cell
ObjHandler::ObjectHandlerXL::instance().resetCaller();
// invoke the utility function
std::string delimStr;
ObjHandler::operToScalar(delimStr, *delim, "[:space:]");
if (*index<1) {
std::stringstream msg;
msg << "the index of the requested field - " << *index
<< " - is invalid - minimum value is 1.";
throw ObjHandler::Exception(msg.str());
}
unsigned int i = static_cast<unsigned int>(*index);
std::vector<std::string> fields = ObjHandler::split(line, i, delimStr);
if (i>fields.size()) {
std::stringstream msg;
msg << "Error parsing string -" << std::endl
<< line << std::endl << "- requested field index " << i
<< " exceeds #fields (" << fields.size() << ") found in string";
throw ObjHandler::Exception(msg.str());
}
static XLOPER xRet;
std::string typeStr(type);
if (typeStr.empty() || ObjHandler::uppercase(typeStr) == "NUMBER") {
double ret;
try {
ret = boost::lexical_cast<double>(fields[i-1]);
} catch (boost::bad_lexical_cast &) {
std::stringstream msg;
msg << "Error parsing string -" << std::endl
<< line << std::endl << "- the requested field #" << i
<< " comprising text '" << fields[i-1]
<< "' could not be converted to a number";
throw ObjHandler::Exception(msg.str());
}
ObjHandler::scalarToXloper(xRet, ret);
} else if (ObjHandler::uppercase(typeStr) == "STRING") {
ObjHandler::scalarToXloper(xRet, fields[i-1]);
} else {
std::stringstream msg;
msg << "invalid type specified -"
<< " expected 'NUMBER' or 'STRING' -"
<< " detected '" << type << "'";
throw ObjHandler::Exception(msg.str());
}
return &xRet;
} catch (const std::exception &e) {
std::ostringstream err;
err << "ohParseField - ";
if (functionCall) err << functionCall->getAddressString() << " - ";
err << e.what();
ObjHandler::logMessage(err.str(), 2);
return 0;
}
}
|