summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/column.hxx1
-rw-r--r--sc/source/core/data/column.cxx56
-rw-r--r--sc/source/core/tool/interpr1.cxx219
3 files changed, 236 insertions, 40 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 7ce53ade706c..359b8ac6f322 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -409,6 +409,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 8d3f62508bc3..64aae039a853 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 643a0aa3d321..93bcfef1440a 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -3854,6 +3854,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)
@@ -4258,8 +4316,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);
}
@@ -4276,39 +4458,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();