Update of /cvsroot/objecthandler/ObjectHandler/ohxl
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv32397/ohxl
Modified Files:
callingrange.cpp callingrange.hpp objecthandlerxl.cpp
objecthandlerxl.hpp
Added Files:
rangereference.cpp rangereference.hpp
Log Message:
enable user to right-click anywhere in range to retrieve error message
Index: objecthandlerxl.cpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/objecthandlerxl.cpp,v
retrieving revision 1.16
retrieving revision 1.17
diff -C2 -d -r1.16 -r1.17
*** objecthandlerxl.cpp 18 Sep 2006 11:20:37 -0000 1.16
--- objecthandlerxl.cpp 20 Sep 2006 20:17:07 -0000 1.17
***************
*** 220,230 ****
}
! std::string ObjectHandlerXL::retrieveError(const std::string& address) {
! for (rangeMapIter i = callingRanges_.begin(); i != callingRanges_.end(); i++) {
! boost::shared_ptr<CallingRange> callingRange = i->second;
! if (callingRange->getAddressString() == address)
! return callingRange->errorMessage();
}
- return "";
}
--- 220,257 ----
}
! std::string ObjectHandlerXL::retrieveError() {
!
! // XLOPER which might need freeing in the event of an exception
!
! XLOPER xSelectionRef, xSelectionText;
!
! try {
!
! Excel(xlfSelection, &xSelectionRef, 0);
! Excel(xlfReftext, &xSelectionText, 1, &xSelectionRef);
! std::string selectionText;
! operToScalar(selectionText, xSelectionText);
! Excel(xlFree, 0, 2, &xSelectionRef, &xSelectionText);
! RangeReference selectionReference(selectionText);
!
! for (rangeMapIter i = callingRanges_.begin(); i != callingRanges_.end(); i++) {
! boost::shared_ptr<CallingRange> callingRange = i->second;
! if (callingRange->contains(selectionReference))
! return callingRange->errorMessage();
! }
! return "";
!
! } catch (const std::exception &e) {
!
! // free any memory that may have been allocated
!
! Excel(xlFree, 0, 2, &xSelectionRef, &xSelectionText);
!
! // propagate the exception
!
! std::ostringstream err;
! err << "ObjectHandlerXL::retrieveError(): " << e.what();
! throw Exception(err.str());
}
}
Index: objecthandlerxl.hpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/objecthandlerxl.hpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** objecthandlerxl.hpp 18 Sep 2006 11:20:37 -0000 1.13
--- objecthandlerxl.hpp 20 Sep 2006 20:17:07 -0000 1.14
***************
*** 70,74 ****
void logError(const std::string &message, const bool &append = false);
! std::string retrieveError(const std::string&);
void clearError();
private:
--- 70,74 ----
void logError(const std::string &message, const bool &append = false);
! std::string retrieveError();
void clearError();
private:
--- NEW FILE: rangereference.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.
*/
#include <ohxl/rangereference.hpp>
#include <oh/exception.hpp>
#include <oh/utilities.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
namespace ObjHandler {
RangeReference::RangeReference(const std::string &address)
: originalAddress_(address) {
std::string addressUpper = uppercase(address);
static boost::regex r(
"=?'?.*\\[([\\w\\s]+)(?:\\.XLS)?\\]([\\w\\s]+)'?!R(\\d*)C(\\d*)(?::R(\\d*)C(\\d*))?");
boost::smatch m;
if (!boost::regex_match(addressUpper, m, r)) {
std::ostringstream err;
err << "the string '" << address << "' is not a valid range reference";
throw Exception(err.str().c_str());
}
bookName_ = m[1];
sheetName_ = m[2];
rowStartNum_ = boost::lexical_cast<int>(m[3]);
colStartNum_ = boost::lexical_cast<int>(m[4]);
if (m[5].matched) {
multicell_ = true;
rowEndNum_ = boost::lexical_cast<int>(m[5]);
colEndNum_ = boost::lexical_cast<int>(m[6]);
} else {
multicell_ = false;
rowEndNum_ = -1;
colEndNum_ = -1;
}
}
bool RangeReference::contains(const RangeReference &r) const {
if (*this == r)
return true;
if (this->bookName_ != r.bookName_)
return false;
if (this->sheetName_ != r.sheetName_)
return false;
if (this->multicell_) {
if (r.multicell_) {
return r.rowStartNum_ >= this->rowStartNum_
&& r.rowEndNum_ <= this->rowEndNum_
&& r.colStartNum_ >= this->colStartNum_
&& r.colEndNum_ <= this->colEndNum_;
} else {
return r.rowStartNum_ >= this->rowStartNum_
&& r.rowStartNum_ <= this->rowEndNum_
&& r.colStartNum_ >= this->colStartNum_
&& r.colStartNum_ <= this->colEndNum_;
}
} else {
if (r.multicell_)
return false;
return r.rowStartNum_ == this->rowStartNum_
&& r.colStartNum_ == this->colStartNum_;
}
}
bool RangeReference::operator==(const RangeReference &r) const {
if (this->originalAddress_ == r.originalAddress_)
return true;
return this->bookName_ == r.bookName_
&& this->sheetName_ == r.sheetName_
&& this->multicell_ == r.multicell_
&& this->rowStartNum_ == r.rowStartNum_
&& this->colStartNum_ == r.colStartNum_
&& this->rowEndNum_ == r.rowEndNum_
&& this->colEndNum_ == r.colEndNum_;
}
std::ostream &operator<<(std::ostream &out, const RangeReference &r) {
out << "originalAddress = " << r.originalAddress_ << std::endl;
out << "bookName = " << r.bookName_ << std::endl;
out << "sheetName = " << r.sheetName_ << std::endl;
out << "multicell = " << r.multicell_ << std::endl;
out << "rowStartNum = " << r.rowStartNum_ << std::endl;
out << "colStartNum = " << r.colStartNum_ << std::endl;
out << "rowEndNum = " << r.rowEndNum_ << std::endl;
out << "colEndNum = " << r.colEndNum_ << std::endl;
return out;
}
}
--- NEW FILE: rangereference.hpp ---
/*
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.
*/
/*! \file
\brief Object class
*/
#include <string>
namespace ObjHandler {
//! A utility class for parsing range references in string format.
/*! The constructor to this class accepts strings returned from
Excel functions such as xlfGetName and xlfReftext. Strings are
parsed and their tokens stored in separate variables to facilitate
comparisons such as determing whether one range contains another.
Excel returns a variety of strings to represent references.
The following formats are supported:
normal:
"[Book1.xls]Sheet1!R1C1"
some excel functions prepend an '=' sign:
"=[Book1.xls]Sheet1!R1C1"
if book or sheet name contains spaces then Excel encloses the text
in single quotes:
"'[Bo ok1.xls]Sheet1'!R1C1"
for a new book that hasn't yet been saved, excel omits the .xls suffix:
"[Book1]Sheet1!R1C1"
sometimes the string includes the filesystem path:
"='C:\\path\\to\\[Book1.xls]Sheet1'!R1C1"
In all cases, the cell reference, represented above as R1C1, may also
be given as R1C1:R9C9 i.e. a range consisting of multiple cells, in
which case the RangeReference constructor sets multicell_ to true.
There is one further case which is not supported. If a workbook contains
a single sheet which has the same name as the book, Excel gives the string
reference in the following format, which the RangeReference constructor
doesn't recognize:
"xxx.xls!R1C1"
Unsupported formats cause an exception to be thrown.
*/
class RangeReference {
public:
RangeReference(const std::string &address);
bool operator==(const RangeReference&) const;
bool contains(const RangeReference&) const;
friend std::ostream &operator<<(std::ostream&, const RangeReference&);
private:
std::string originalAddress_;
std::string bookName_;
std::string sheetName_;
bool multicell_;
int rowStartNum_;
int colStartNum_;
int rowEndNum_;
int colEndNum_;
};
std::ostream &operator<<(std::ostream&, const RangeReference&);
}
Index: callingrange.hpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/callingrange.hpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** callingrange.hpp 18 Sep 2006 11:20:37 -0000 1.8
--- callingrange.hpp 20 Sep 2006 20:17:07 -0000 1.9
***************
*** 24,27 ****
--- 24,28 ----
#include <oh/object.hpp>
+ #include <ohxl/rangereference.hpp>
#include <map>
***************
*** 56,59 ****
--- 57,61 ----
}
std::string getAddressString() const;
+ bool contains(const RangeReference&);
private:
static int keyCount_;
***************
*** 66,69 ****
--- 68,72 ----
int invocationCount_;
std::map<std::string, boost::shared_ptr<Object> > residentObjects_;
+ boost::shared_ptr<RangeReference> rangeReference_;
};
Index: callingrange.cpp
===================================================================
RCS file: /cvsroot/objecthandler/ObjectHandler/ohxl/callingrange.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** callingrange.cpp 18 Sep 2006 11:20:37 -0000 1.9
--- callingrange.cpp 20 Sep 2006 20:17:07 -0000 1.10
***************
*** 135,138 ****
--- 135,139 ----
}
+ // FIXME cache this value
std::string CallingRange::getAddressString() const {
***************
*** 165,168 ****
--- 166,176 ----
}
+ bool CallingRange::contains(const RangeReference &testReference) {
+ if (!rangeReference_)
+ rangeReference_ = boost::shared_ptr<RangeReference>(
+ new RangeReference(getAddressString()));
+ return rangeReference_->contains(testReference);
+ }
+
void CallingRange::setErrorMessage(const std::string &errorMessage, const bool &append) {
if (append) {
|