[Libreoffice-commits] core.git: Branch 'feature/calc-group-interpreter' - 3 commits - sc/inc sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Mon Jul 1 22:17:52 PDT 2013
sc/inc/column.hxx | 1
sc/inc/formulacell.hxx | 6
sc/inc/formularesult.hxx | 2
sc/inc/token.hxx | 13 --
sc/source/core/data/column.cxx | 56 +++++++-
sc/source/core/data/formulacell.cxx | 14 ++
sc/source/core/tool/formularesult.cxx | 12 +
sc/source/core/tool/interpr1.cxx | 219 ++++++++++++++++++++++++++++------
sc/source/core/tool/token.cxx | 12 +
9 files changed, 282 insertions(+), 53 deletions(-)
New commits:
commit 170c957cef174aac6a727ff15b67a49f96fa80f7
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 01:12:27 2013 -0400
COUNT should skip formula cells with error.
Change-Id: I829eaf309056403f77949526877888315a2ad720
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 7df7335..9ade34f 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -201,6 +201,7 @@ public:
// display as empty string if formula::svEmptyCell result
bool IsEmptyDisplayedAsString();
bool IsValue(); // also true if formula::svEmptyCell
+ bool IsValueNoError();
bool IsHybridValueCell(); // for cells after import to deal with inherited number formats
double GetValue();
double GetValueAlways(); // ignore errors
diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx
index e215daf..fdb5d31 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -130,6 +130,8 @@ public:
details instead. */
bool IsValue() const;
+ bool IsValueNoError() const;
+
/** Determines whether or not the result is a string containing more than
one paragraph */
bool IsMultiline() const;
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ca5c7ae..7843f7c 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -511,7 +511,7 @@ public:
for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
- if (rCell.IsValue())
+ if (rCell.IsValueNoError())
++mnCount;
}
}
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 96470e3..523995b 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1726,6 +1726,15 @@ bool ScFormulaCell::IsValue()
return aResult.IsValue();
}
+bool ScFormulaCell::IsValueNoError()
+{
+ MaybeInterpret();
+ if (pCode->GetCodeError())
+ return false;
+
+ return aResult.IsValueNoError();
+}
+
bool ScFormulaCell::IsHybridValueCell()
{
return aResult.GetType() == formula::svHybridValueCell;
diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx
index 6052e66..baeef1d 100644
--- a/sc/source/core/tool/formularesult.cxx
+++ b/sc/source/core/tool/formularesult.cxx
@@ -265,6 +265,18 @@ bool ScFormulaResult::IsValue() const
return isValue(GetCellResultType());
}
+bool ScFormulaResult::IsValueNoError() const
+{
+ switch (GetCellResultType())
+ {
+ case formula::svDouble:
+ case formula::svEmptyCell:
+ case formula::svHybridValueCell:
+ return true;
+ }
+ return false;
+}
+
bool ScFormulaResult::IsMultiline() const
{
if (meMultiline == MULTILINE_UNKNOWN)
commit b4ccd08f65e7236eca70651a6ee4169b4a980ccc
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 00:51:10 2013 -0400
Re-implement SUM function to make use of new cell storage.
And fix a bug in my new COUNT function, where I forgot to tally numeric
formula cells.
Change-Id: I52d26be3e48f646f656821066e23594d52f78c6d
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 2630f6e..bde6e3d 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -402,6 +402,7 @@ public:
void ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark );
void ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark );
+ double SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
size_t CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
long GetNeededSize(
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index b15d090..ca5c7ae 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -468,18 +468,57 @@ void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
namespace {
+class NumericCellAccumulator
+{
+ double mfSum;
+public:
+ NumericCellAccumulator() : mfSum(0.0) {}
+
+ void operator() (size_t, double fVal)
+ {
+ mfSum += fVal;
+ }
+
+ void operator() (size_t, const ScFormulaCell* pCell)
+ {
+ ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
+ if (rCell.IsValue())
+ mfSum += rCell.GetValue();
+ }
+
+ double getSum() const { return mfSum; }
+};
+
class NumericCellCounter
{
size_t mnCount;
public:
NumericCellCounter() : mnCount(0) {}
- void operator() (const sc::CellStoreType::value_type& rNode, size_t /*nOffset*/, size_t nDataSize)
+ void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
{
- if (rNode.type != sc::element_type_numeric)
- return;
-
- mnCount += nDataSize;
+ switch (rNode.type)
+ {
+ case sc::element_type_numeric:
+ mnCount += nDataSize;
+ break;
+ case sc::element_type_formula:
+ {
+ sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
+ std::advance(it, nOffset);
+ sc::formula_block::const_iterator itEnd = it;
+ std::advance(itEnd, nDataSize);
+ for (; it != itEnd; ++it)
+ {
+ ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
+ if (rCell.IsValue())
+ ++mnCount;
+ }
+ }
+ break;
+ default:
+ ;
+ }
}
size_t getCount() const { return mnCount; }
@@ -487,6 +526,13 @@ public:
}
+double ScColumn::SumNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
+{
+ NumericCellAccumulator aFunc;
+ rPos.miCellPos = sc::ParseFormulaNumeric(rPos.miCellPos, maCells, nRow1, nRow2, aFunc);
+ return aFunc.getSum();
+}
+
size_t ScColumn::CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
{
NumericCellCounter aFunc;
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 8fd0f5b..af83cfb 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -3853,6 +3853,64 @@ void ScInterpreter::ScMax( bool bTextAsZero )
namespace {
+class FuncCount : public sc::ColumnSpanSet::ColumnAction
+{
+ sc::ColumnBlockConstPosition maPos;
+ ScColumn* mpCol;
+ size_t mnCount;
+ sal_uInt32 mnNumFmt;
+
+public:
+ FuncCount() : mnCount(0), mnNumFmt(0) {}
+
+ virtual void startColumn(ScColumn* pCol)
+ {
+ mpCol = pCol;
+ mpCol->InitBlockPosition(maPos);
+ }
+
+ virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+ {
+ if (!bVal)
+ return;
+
+ mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
+ mnNumFmt = mpCol->GetNumberFormat(nRow2);
+ };
+
+ size_t getCount() const { return mnCount; }
+ sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
+class FuncSum : public sc::ColumnSpanSet::ColumnAction
+{
+ sc::ColumnBlockConstPosition maPos;
+ ScColumn* mpCol;
+ double mfSum;
+ sal_uInt32 mnNumFmt;
+
+public:
+ FuncSum() : mfSum(0.0), mnNumFmt(0) {}
+
+ virtual void startColumn(ScColumn* pCol)
+ {
+ mpCol = pCol;
+ mpCol->InitBlockPosition(maPos);
+ }
+
+ virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
+ {
+ if (!bVal)
+ return;
+
+ mfSum += mpCol->SumNumericCells(maPos, nRow1, nRow2);
+ mnNumFmt = mpCol->GetNumberFormat(nRow2);
+ };
+
+ double getSum() const { return mfSum; }
+ sal_uInt32 getNumberFormat() const { return mnNumFmt; }
+};
+
void IterateMatrix(
const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
@@ -4253,8 +4311,132 @@ void ScInterpreter::ScSumSQ()
void ScInterpreter::ScSum()
{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSum" );
- PushDouble( IterateParameters( ifSUM ) );
+ short nParamCount = GetByte();
+ double fRes = 0.0;
+ double fVal = 0.0;
+ ScAddress aAdr;
+ ScRange aRange;
+ size_t nRefInList = 0;
+ while (nParamCount-- > 0)
+ {
+ switch (GetStackType())
+ {
+ case svString:
+ {
+ while (nParamCount-- > 0)
+ Pop();
+ SetError( errNoValue );
+ }
+ break;
+ case svDouble :
+ fVal = GetDouble();
+ fRes += fVal;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ break;
+ case svExternalSingleRef:
+ {
+ ScExternalRefCache::TokenRef pToken;
+ ScExternalRefCache::CellFormat aFmt;
+ PopExternalSingleRef(pToken, &aFmt);
+
+ if (!pToken)
+ break;
+
+ StackVar eType = pToken->GetType();
+ if (eType == formula::svDouble)
+ {
+ fVal = pToken->GetDouble();
+ if (aFmt.mbIsSet)
+ {
+ nFuncFmtType = aFmt.mnType;
+ nFuncFmtIndex = aFmt.mnIndex;
+ }
+
+ fRes += fVal;
+ }
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+
+ if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+ {
+ break;
+ }
+ ScRefCellValue aCell;
+ aCell.assign(*pDok, aAdr);
+ if (!aCell.isEmpty())
+ {
+ if (aCell.hasNumeric())
+ {
+ fVal = GetCellValue(aAdr, aCell);
+ CurFmtToFuncFmt();
+ fRes += fVal;
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ case svRefList :
+ {
+ PopDoubleRef( aRange, nParamCount, nRefInList);
+
+ sc::ColumnSpanSet aSet(false);
+ aSet.set(aRange, true);
+ if (glSubTotal)
+ // Skip all filtered rows and subtotal formula cells.
+ pDok->MarkSubTotalCells(aSet, aRange, false);
+
+ FuncSum aAction;
+ aSet.executeColumnAction(*pDok, aAction);
+ fRes = aAction.getSum();
+
+ // Get the number format of the last iterated cell.
+ nFuncFmtIndex = aAction.getNumberFormat();
+ nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
+ }
+ break;
+ case svExternalDoubleRef:
+ {
+ ScMatrixRef pMat;
+ PopExternalDoubleRef(pMat);
+ if (nGlobalError)
+ break;
+
+ sal_uLong nCount = 0;
+ double fMem = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ fRes += fMem;
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrixRef pMat = PopMatrix();
+ sal_uLong nCount = 0;
+ double fMem = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ fRes += fMem;
+ }
+ break;
+ case svError:
+ {
+ PopError();
+ }
+ break;
+ default :
+ while (nParamCount-- > 0)
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+
+ if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+ PushDouble(fRes);
}
@@ -4271,39 +4453,6 @@ void ScInterpreter::ScAverage( bool bTextAsZero )
PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
}
-namespace {
-
-class FuncCount : public sc::ColumnSpanSet::ColumnAction
-{
- sc::ColumnBlockConstPosition maPos;
- ScColumn* mpCol;
- size_t mnCount;
- sal_uInt32 mnNumFmt;
-
-public:
- FuncCount() : mnCount(0), mnNumFmt(0) {}
-
- virtual void startColumn(ScColumn* pCol)
- {
- mpCol = pCol;
- mpCol->InitBlockPosition(maPos);
- }
-
- virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
- {
- if (!bVal)
- return;
-
- mnCount += mpCol->CountNumericCells(maPos, nRow1, nRow2);
- mnNumFmt = mpCol->GetNumberFormat(nRow2);
- };
-
- size_t getCount() const { return mnCount; }
- sal_uInt32 getNumberFormat() const { return mnNumFmt; }
-};
-
-}
-
void ScInterpreter::ScCount()
{
short nParamCount = GetByte();
commit aba6c7e275aa055bc613b6bec9692284c37500f1
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 00:06:22 2013 -0400
Put the matrix header back in for Windows build...
Conflicts:
sc/inc/formulacell.hxx
Change-Id: I676b3d9b702af51bf00dff9ef55d16e7fbdec65e
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 8b01ea8..7df7335 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -273,10 +273,7 @@ public:
void SetHybridValueString( double nVal, const OUString& r )
{ aResult.SetHybridValueString( nVal, r ); }
- void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
- {
- aResult.SetMatrix(nCols, nRows, pMat, pUL);
- }
+ void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL );
/** For import only: set a double result.
Use this instead of SetHybridDouble() if there is no (temporary)
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index bc8a4bd..0ed95bd 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -30,7 +30,7 @@
#include "scdllapi.h"
#include "formula/IFunctionDescription.hxx"
#include "formula/token.hxx"
-#include "types.hxx"
+#include "scmatrix.hxx"
class ScJumpMatrix;
@@ -318,7 +318,7 @@ public:
virtual const String & GetString() const;
virtual const ScMatrix* GetMatrix() const;
virtual bool operator==( const formula::FormulaToken& rToken ) const;
- virtual FormulaToken* Clone() const { return new ScMatrixCellResultToken(*this); }
+ virtual FormulaToken* Clone() const;
formula::StackVar GetUpperLeftType() const
{
return xUpperLeft ?
@@ -357,12 +357,9 @@ public:
SCCOL GetMatCols() const { return nCols; }
SCROW GetMatRows() const { return nRows; }
- /** Assign matrix result, keep matrix formula
- dimension. */
- void Assign( const ScMatrixCellResultToken & r )
- {
- ScMatrixCellResultToken::Assign( r);
- }
+ /** Assign matrix result, keep matrix formula
+ dimension. */
+ void Assign( const ScMatrixCellResultToken & r );
/** Assign any result, keep matrix formula
dimension. If token is of type
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 7e9cadc..96470e3 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1603,6 +1603,11 @@ void ScFormulaCell::SetResultToken( const formula::FormulaToken* pToken )
aResult.SetToken(pToken);
}
+void ScFormulaCell::SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
+{
+ aResult.SetMatrix(nCols, nRows, pMat, pUL);
+}
+
void ScFormulaCell::SetErrCode( sal_uInt16 n )
{
/* FIXME: check the numerous places where ScTokenArray::GetCodeError() is
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 8d64fb5..28a3ba5 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -37,7 +37,6 @@
#include "rangeseq.hxx"
#include "externalrefmgr.hxx"
#include "document.hxx"
-#include "scmatrix.hxx"
using ::std::vector;
@@ -1060,6 +1059,11 @@ bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
}
+FormulaToken* ScMatrixCellResultToken::Clone() const
+{
+ return new ScMatrixCellResultToken(*this);
+}
+
void ScMatrixCellResultToken::Assign( const ScMatrixCellResultToken & r )
{
xMatrix = r.xMatrix;
@@ -1088,6 +1092,12 @@ bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
return p && ScMatrixCellResultToken::operator==( r ) &&
nCols == p->nCols && nRows == p->nRows;
}
+
+void ScMatrixFormulaCellToken::Assign( const ScMatrixCellResultToken & r )
+{
+ ScMatrixCellResultToken::Assign( r);
+}
+
void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
{
if (this == &r)
More information about the Libreoffice-commits
mailing list