summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2013-10-15 20:42:00 -0400
committerKohei Yoshida <kohei.yoshida@collabora.com>2013-10-18 23:22:40 -0400
commita6f8102ba55d06ead9bf6e72be0985dcc1086ef5 (patch)
tree39c025c82c03c3c22f8bea37d7e46ae7f8244faf /sc
parent3629a512b5afb09f48f47f1994d4708c748c45e6 (diff)
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
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/formulacell.hxx1
-rw-r--r--sc/inc/formularesult.hxx21
-rw-r--r--sc/source/core/data/column2.cxx85
-rw-r--r--sc/source/core/data/formulacell.cxx11
-rw-r--r--sc/source/core/tool/formularesult.cxx47
5 files changed, 138 insertions, 27 deletions
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index ea80b1518300..9d27558208ad 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 8a7b36543284..3708c8a7efe2 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 a0ee0462bd53..8fbfd1b016bb 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 9d3210481bef..4d0284bb194b 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 5015a85a36ac..35d58188b721 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)