sc/inc/formulacell.hxx | 1 sc/inc/formularesult.hxx | 21 ++++++++ sc/source/core/data/column2.cxx | 85 +++++++++++++++++++++++----------- sc/source/core/data/formulacell.cxx | 11 ++++ sc/source/core/tool/formularesult.cxx | 47 ++++++++++++++++++ 5 files changed, 138 insertions(+), 27 deletions(-)
New commits: commit 87fe06a25dd22a3244f9741a079ce0e734acb6c8 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Tue Oct 15 20:42:00 2013 -0400 Re-do fetching of vector ref array to support number / string mixture. For now it only works when the range starts with string cell. With this, the test now passes. Change-Id: I6f79415ce11233648cdb20c8075f500b8c3d2f76 diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index ea80b15..9d27558 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -253,6 +253,7 @@ public: sal_uInt16 GetRawError(); // don't interpret, just return code or result error bool GetErrorOrValue( sal_uInt16& rErr, double& rVal ); bool GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rStr ); + sc::FormulaResultValue GetResult(); sal_uInt8 GetMatrixFlag() const; ScTokenArray* GetCode(); const ScTokenArray* GetCode() const; diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index 8a7b365..3708c8a 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -23,6 +23,26 @@ #include "token.hxx" #include "scdllapi.h" +namespace sc { + +struct FormulaResultValue +{ + enum Type { Invalid, Value, String, Error }; + + Type meType; + + double mfValue; + svl::SharedString maString; + sal_uInt16 mnError; + + FormulaResultValue(); + FormulaResultValue( double fValue ); + FormulaResultValue(const svl::SharedString& rStr ); + FormulaResultValue( sal_uInt16 nErr ); +}; + +} + /** Store a variable formula cell result, balancing between runtime performance and memory consumption. */ class ScFormulaResult @@ -136,6 +156,7 @@ public: bool GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const; bool GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rStr ) const; + sc::FormulaResultValue GetResult() const; /** Get error code if set or GetCellResultType() is formula::svError or svUnknown, else 0. */ diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index a0ee046..8fbfd1b 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2178,12 +2178,16 @@ bool appendDouble( return false; } -bool appendStrings( - ScDocument* pDoc, sc::FormulaGroupContext::StrArrayType& rArray, - size_t nLen, sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd) +formula::VectorRefArray appendBlocks( + ScDocument* pDoc, sc::FormulaGroupContext& rCxt, size_t nPos, + size_t nLenRequested, sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd ) { - size_t nLenRemain = nLen; + sc::FormulaGroupContext::StrArrayType& rStrArray = rCxt.maStrArrays.back(); + sc::FormulaGroupContext::NumArrayType* pNumArray = NULL; svl::SharedStringPool& rPool = pDoc->GetSharedStringPool(); + size_t nLenRemain = nLenRequested - nPos; + double fNan; + rtl::math::setNan(&fNan); for (; it != itEnd; ++it) { @@ -2194,8 +2198,8 @@ bool appendStrings( sc::string_block::iterator itData, itDataEnd; getBlockIterators<sc::string_block>(it, nLenRemain, itData, itDataEnd); - for (; itData != itDataEnd; ++itData) - rArray.push_back(itData->getDataIgnoreCase()); + for (; itData != itDataEnd; ++itData, ++nPos) + rStrArray[nPos] = itData->getDataIgnoreCase(); } break; case sc::element_type_edittext: @@ -2203,10 +2207,10 @@ bool appendStrings( sc::edittext_block::iterator itData, itDataEnd; getBlockIterators<sc::edittext_block>(it, nLenRemain, itData, itDataEnd); - for (; itData != itDataEnd; ++itData) + for (; itData != itDataEnd; ++itData, ++nPos) { OUString aStr = ScEditUtil::GetString(**itData, pDoc); - rArray.push_back(rPool.intern(aStr).getDataIgnoreCase()); + rStrArray[nPos] = rPool.intern(aStr).getDataIgnoreCase(); } } break; @@ -2215,51 +2219,81 @@ bool appendStrings( sc::formula_block::iterator itData, itDataEnd; getBlockIterators<sc::formula_block>(it, nLenRemain, itData, itDataEnd); - sal_uInt16 nErr; - svl::SharedString aStr; - for (; itData != itDataEnd; ++itData) + for (; itData != itDataEnd; ++itData, ++nPos) { ScFormulaCell& rFC = **itData; - if (!rFC.GetErrorOrString(nErr, aStr) || nErr) + sc::FormulaResultValue aRes = rFC.GetResult(); + if (aRes.meType == sc::FormulaResultValue::Invalid || aRes.mnError) { - if (nErr == ScErrorCodes::errCircularReference) + if (aRes.mnError == ScErrorCodes::errCircularReference) { // This cell needs to be recalculated on next visit. rFC.SetErrCode(0); rFC.SetDirtyVar(); } - return false; + return formula::VectorRefArray(); } - rArray.push_back(aStr.getDataIgnoreCase()); + if (aRes.meType == sc::FormulaResultValue::String) + rStrArray[nPos] = aRes.maString.getDataIgnoreCase(); + else + { + if (!pNumArray) + { + rCxt.maNumArrays.push_back( + new sc::FormulaGroupContext::NumArrayType(nLenRequested, fNan)); + pNumArray = &rCxt.maNumArrays.back(); + } + + (*pNumArray)[nPos] = aRes.mfValue; + } } } break; case sc::element_type_empty: { - // Fill it with NULL pointers. - if (nLenRemain >= it->size) + if (nLenRemain > it->size) { - rArray.resize(rArray.size() + it->size, NULL); + nPos += it->size; nLenRemain -= it->size; } else { - rArray.resize(rArray.size() + nLenRemain, NULL); + nPos = nLenRequested; nLenRemain = 0; } } break; case sc::element_type_numeric: + { + sc::numeric_block::iterator itData, itDataEnd; + getBlockIterators<sc::numeric_block>(it, nLenRemain, itData, itDataEnd); + + if (!pNumArray) + { + rCxt.maNumArrays.push_back( + new sc::FormulaGroupContext::NumArrayType(nLenRequested, fNan)); + pNumArray = &rCxt.maNumArrays.back(); + } + + for (; itData != itDataEnd; ++itData, ++nPos) + (*pNumArray)[nPos] = *itData; + } + break; default: - return false; + return formula::VectorRefArray(); } if (!nLenRemain) - return true; + { + if (pNumArray) + return formula::VectorRefArray(&(*pNumArray)[0], &rStrArray[0]); + else + return formula::VectorRefArray(&rStrArray[0]); + } } - return false; + return formula::VectorRefArray(); } void copyFirstStringBlock( @@ -2412,14 +2446,11 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext& } copyFirstStringBlock(*pDocument, rCxt, nLen, aPos); - sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back(); + rCxt.maStrArrays.back().resize(nLenRequested, NULL); // allocate array to requested length. // Fill the remaining array with values from the following blocks. ++aPos.first; - if (!appendStrings(pDocument, rArray, nLenRequested - nLen, aPos.first, maCells.end())) - return formula::VectorRefArray(); - - return formula::VectorRefArray(&rArray[0]); + return appendBlocks(pDocument, rCxt, nLen, nLenRequested, aPos.first, maCells.end()); } break; case sc::element_type_empty: diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 9d32104..4d0284b 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2094,6 +2094,17 @@ bool ScFormulaCell::GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rStr return aResult.GetErrorOrString(rErr, rStr); } +sc::FormulaResultValue ScFormulaCell::GetResult() +{ + MaybeInterpret(); + + sal_uInt16 nErr = pCode->GetCodeError(); + if (nErr) + return sc::FormulaResultValue(nErr); + + return aResult.GetResult(); +} + bool ScFormulaCell::HasOneReference( ScRange& r ) const { pCode->Reset(); diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index 5015a85..35d5818 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -10,6 +10,15 @@ #include "formularesult.hxx" #include "scmatrix.hxx" +namespace sc { + +FormulaResultValue::FormulaResultValue() : meType(Invalid), mfValue(0.0), mnError(0) {} +FormulaResultValue::FormulaResultValue( double fValue ) : meType(Value), mfValue(fValue), mnError(0) {} +FormulaResultValue::FormulaResultValue( const svl::SharedString& rStr ) : meType(String), mfValue(0.0), maString(rStr), mnError(0) {} +FormulaResultValue::FormulaResultValue( sal_uInt16 nErr ) : meType(Error), mfValue(0.0), mnError(nErr) {} + +} + ScFormulaResult::ScFormulaResult() : mpToken(NULL), mnError(0), mbToken(true), mbEmpty(false), mbEmptyDisplayedAsString(false), @@ -372,6 +381,44 @@ bool ScFormulaResult::GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rSt return true; } +sc::FormulaResultValue ScFormulaResult::GetResult() const +{ + if (mnError) + return sc::FormulaResultValue(mnError); + + formula::StackVar sv = GetCellResultType(); + sal_uInt16 nErr = 0; + if (sv == formula::svError) + { + if (GetType() == formula::svMatrixCell) + { + // don't need to test for mpToken here, GetType() already did it + nErr = static_cast<const ScMatrixCellResultToken*>(mpToken)-> + GetUpperLeftToken()->GetError(); + } + else if (mpToken) + { + nErr = mpToken->GetError(); + } + } + + if (nErr) + return sc::FormulaResultValue(nErr); + + if (isValue(sv)) + return sc::FormulaResultValue(GetDouble()); + + if (!mbToken) + // String result type needs token. + return sc::FormulaResultValue(); + + if (isString(sv)) + return sc::FormulaResultValue(GetString()); + + // Invalid + return sc::FormulaResultValue(); +} + sal_uInt16 ScFormulaResult::GetResultError() const { if (mnError) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits