summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-07-01 23:08:14 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-07-02 13:19:32 -0400
commitcfb2ce587b097b407eb15699cff7ce9fb6844123 (patch)
tree9ca222bdaf03e11ae3c3951ac84d0b3a2ce92aeb
parentdb377e02c309c20419aef1360409be09fe50fc42 (diff)
Re-implement the COUNT function for efficiency.
By taking advantage of the block structure of the new cell storage. Change-Id: Ib953c14d364ccdff7df5caf70d57cec86189e3be
-rw-r--r--sc/inc/column.hxx6
-rw-r--r--sc/inc/columnspanset.hxx29
-rw-r--r--sc/inc/document.hxx3
-rw-r--r--sc/inc/table.hxx4
-rw-r--r--sc/source/core/data/column.cxx54
-rw-r--r--sc/source/core/data/columnspanset.cxx84
-rw-r--r--sc/source/core/data/documen6.cxx4
-rw-r--r--sc/source/core/data/document.cxx17
-rw-r--r--sc/source/core/data/listenercontext.cxx4
-rw-r--r--sc/source/core/data/table3.cxx31
-rw-r--r--sc/source/core/tool/interpr1.cxx183
11 files changed, 396 insertions, 23 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 6cc3c4b11a93..7ce53ade706c 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -44,6 +44,7 @@ namespace sc {
class CopyToClipContext;
class CopyToDocContext;
class MixDocContext;
+ class ColumnSpanSet;
struct ColumnBlockPosition;
class SingleColumnSpanSet;
}
@@ -116,7 +117,6 @@ class ScColumn
friend class ScDocument; // for FillInfo
friend class ScTable;
-friend class ScDocumentIterator;
friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator;
@@ -127,6 +127,7 @@ friend class ScHorizontalAttrIterator;
friend class ScColumnTextWidthIterator;
friend class ScDocumentImport;
friend class sc::SingleColumnSpanSet;
+friend class sc::ColumnSpanSet;
ScColumn(const ScColumn&); // disabled
ScColumn& operator= (const ScColumn&); // disabled
@@ -242,6 +243,7 @@ public:
void SwapCol(ScColumn& rCol);
void MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol);
+ void MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nRow2, bool bVal ) const;
bool HasEditCells(SCROW nStartRow, SCROW nEndRow, SCROW& rFirst);
@@ -407,6 +409,8 @@ public:
void ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& rMark );
void ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark );
+ size_t CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const;
+
long GetNeededSize(
SCROW nRow, OutputDevice* pDev, double nPPTX, double nPPTY,
const Fraction& rZoomX, const Fraction& rZoomY,
diff --git a/sc/inc/columnspanset.hxx b/sc/inc/columnspanset.hxx
index 55c3f57507e9..98533e240f37 100644
--- a/sc/inc/columnspanset.hxx
+++ b/sc/inc/columnspanset.hxx
@@ -16,8 +16,10 @@
#include <mdds/flat_segment_tree.hpp>
#include <boost/noncopyable.hpp>
+class ScDocument;
class ScColumn;
class ScMarkData;
+class ScRange;
namespace sc {
@@ -30,12 +32,22 @@ struct ColumnBlockConstPosition;
class ColumnSpanSet : boost::noncopyable
{
typedef mdds::flat_segment_tree<SCROW, bool> ColumnSpansType;
- typedef std::vector<ColumnSpansType*> TableType;
+
+ struct ColumnType
+ {
+ ColumnSpansType maSpans;
+ ColumnSpansType::const_iterator miPos;
+
+ ColumnType(SCROW nStart, SCROW nEnd, bool bInit);
+ };
+
+ typedef std::vector<ColumnType*> TableType;
typedef std::vector<TableType*> DocType;
DocType maDoc;
+ bool mbInit;
- ColumnSpansType& getColumnSpans(SCTAB nTab, SCCOL nCol);
+ ColumnType& getColumn(SCTAB nTab, SCCOL nCol);
public:
class Action
@@ -46,12 +58,23 @@ public:
virtual void execute(const ScAddress& rPos, SCROW nLength, bool bVal) = 0;
};
+ class ColumnAction
+ {
+ public:
+ virtual ~ColumnAction() = 0;
+ virtual void startColumn(ScColumn* pCol) = 0;
+ virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal) = 0;
+ };
+
+ ColumnSpanSet(bool bInit);
~ColumnSpanSet();
void set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal);
void set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal);
+ void set(const ScRange& rRange, bool bVal);
- void executeFromTop(Action& ac) const;
+ void executeAction(Action& ac) const;
+ void executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const;
};
/**
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 806fb770e6a0..4d415659c24f 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -53,6 +53,7 @@ namespace sc {
class StartListeningContext;
class EndListeningContext;
class CopyFromClipContext;
+ class ColumnSpanSet;
struct ColumnBlockPosition;
}
class SvxFontItem;
@@ -228,6 +229,7 @@ friend class ScFormulaCell;
friend class ScTable;
friend struct ScRefCellValue;
friend class ScDocumentImport;
+friend class sc::ColumnSpanSet;
typedef ::std::vector<ScTable*> TableContainer;
private:
@@ -1960,6 +1962,7 @@ public:
void AddSubTotalCell(ScFormulaCell* pCell);
void RemoveSubTotalCell(ScFormulaCell* pCell);
void SetSubTotalCellsDirty(const ScRange& rDirtyRange);
+ void MarkSubTotalCells( sc::ColumnSpanSet& rSet, const ScRange& rRange, bool bVal ) const;
sal_uInt16 GetTextWidth( const ScAddress& rPos ) const;
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 03060bb4f2f2..a8d51288a04a 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -57,6 +57,7 @@ namespace sc {
class CopyToClipContext;
class CopyToDocContext;
class MixDocContext;
+ class ColumnSpanSet;
struct ColumnBlockPosition;
}
@@ -203,6 +204,7 @@ friend class ScDocAttrIterator;
friend class ScAttrRectIterator;
friend class ScColumnTextWidthIterator;
friend class ScDocumentImport;
+friend class sc::ColumnSpanSet;
public:
ScTable( ScDocument* pDoc, SCTAB nNewTab, const OUString& rNewName,
@@ -231,6 +233,8 @@ public:
void RemoveSubTotals( ScSubTotalParam& rParam );
bool DoSubTotals( ScSubTotalParam& rParam );
+ void MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal ) const;
+
const ScSheetEvents* GetSheetEvents() const { return pSheetEvents; }
void SetSheetEvents( const ScSheetEvents* pNew );
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index aa82f4d16613..2a59e7ee3c32 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -466,6 +466,33 @@ void ScColumn::ChangeSelectionIndent( bool bIncrement, const ScMarkData& rMark )
}
}
+namespace {
+
+class NumericCellCounter
+{
+ size_t mnCount;
+public:
+ NumericCellCounter() : mnCount(0) {}
+
+ void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
+ {
+ if (rNode.type != sc::element_type_numeric)
+ return;
+
+ mnCount += nDataSize;
+ }
+
+ size_t getCount() const { return mnCount; }
+};
+
+}
+
+size_t ScColumn::CountNumericCells( sc::ColumnBlockConstPosition& rPos, SCROW nRow1, SCROW nRow2 ) const
+{
+ NumericCellCounter aFunc;
+ rPos.miCellPos = sc::ParseBlock(rPos.miCellPos, maCells, aFunc, nRow1, nRow2);
+ return aFunc.getCount();
+}
void ScColumn::ClearSelectionItems( const sal_uInt16* pWhich,const ScMarkData& rMark )
{
@@ -2155,6 +2182,33 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
namespace {
+class SubTotalCellPicker
+{
+ sc::ColumnSpanSet& mrSet;
+ SCTAB mnTab;
+ SCCOL mnCol;
+ bool mbVal;
+public:
+ SubTotalCellPicker(sc::ColumnSpanSet& rSet, SCTAB nTab, SCCOL nCol, bool bVal) :
+ mrSet(rSet), mnTab(nTab), mnCol(nCol), mbVal(bVal) {}
+
+ void operator() (size_t nRow, const ScFormulaCell* pCell)
+ {
+ if (pCell->IsSubTotal())
+ mrSet.set(mnTab, mnCol, nRow, mbVal);
+ }
+};
+
+}
+
+void ScColumn::MarkSubTotalCells( sc::ColumnSpanSet& rSet, SCROW nRow1, SCROW nRow2, bool bVal ) const
+{
+ SubTotalCellPicker aFunc(rSet, nTab, nCol, bVal);
+ sc::ParseFormula(maCells.begin(), maCells, nRow1, nRow2, aFunc);
+}
+
+namespace {
+
class UpdateRefOnCopy
{
protected:
diff --git a/sc/source/core/data/columnspanset.cxx b/sc/source/core/data/columnspanset.cxx
index 8bfb7fc6fa79..f8c7813daf03 100644
--- a/sc/source/core/data/columnspanset.cxx
+++ b/sc/source/core/data/columnspanset.cxx
@@ -10,6 +10,8 @@
#include "columnspanset.hxx"
#include "stlalgorithm.hxx"
#include "column.hxx"
+#include "table.hxx"
+#include "document.hxx"
#include "mtvfunctions.hxx"
#include "markdata.hxx"
#include "rangelst.hxx"
@@ -18,9 +20,16 @@
namespace sc {
+ColumnSpanSet::ColumnType::ColumnType(SCROW nStart, SCROW nEnd, bool bInit) :
+ maSpans(nStart, nEnd+1, bInit), miPos(maSpans.begin()) {}
+
ColumnSpanSet::Action::~Action() {}
void ColumnSpanSet::Action::startColumn(SCTAB /*nTab*/, SCCOL /*nCol*/) {}
+ColumnSpanSet::ColumnAction::~ColumnAction() {}
+
+ColumnSpanSet::ColumnSpanSet(bool bInit) : mbInit(bInit) {}
+
ColumnSpanSet::~ColumnSpanSet()
{
DocType::iterator itTab = maDoc.begin(), itTabEnd = maDoc.end();
@@ -30,12 +39,12 @@ ColumnSpanSet::~ColumnSpanSet()
if (!pTab)
continue;
- std::for_each(pTab->begin(), pTab->end(), ScDeleteObjectByPtr<ColumnSpansType>());
+ std::for_each(pTab->begin(), pTab->end(), ScDeleteObjectByPtr<ColumnType>());
delete pTab;
}
}
-ColumnSpanSet::ColumnSpansType& ColumnSpanSet::getColumnSpans(SCTAB nTab, SCCOL nCol)
+ColumnSpanSet::ColumnType& ColumnSpanSet::getColumn(SCTAB nTab, SCCOL nCol)
{
if (static_cast<size_t>(nTab) >= maDoc.size())
maDoc.resize(nTab+1, NULL);
@@ -48,7 +57,7 @@ ColumnSpanSet::ColumnSpansType& ColumnSpanSet::getColumnSpans(SCTAB nTab, SCCOL
rTab.resize(nCol+1, NULL);
if (!rTab[nCol])
- rTab[nCol] = new ColumnSpansType(0, MAXROW+1, false);
+ rTab[nCol] = new ColumnType(0, MAXROW, mbInit);
return *rTab[nCol];
}
@@ -58,8 +67,8 @@ void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow, bool bVal)
if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow))
return;
- ColumnSpansType& rCol = getColumnSpans(nTab, nCol);
- rCol.insert_back(nRow, nRow+1, bVal);
+ ColumnType& rCol = getColumn(nTab, nCol);
+ rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow, nRow+1, bVal).first;
}
void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool bVal)
@@ -67,11 +76,23 @@ void ColumnSpanSet::set(SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2, bool b
if (!ValidTab(nTab) || !ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
return;
- ColumnSpansType& rCol = getColumnSpans(nTab, nCol);
- rCol.insert_back(nRow1, nRow2+1, bVal);
+ ColumnType& rCol = getColumn(nTab, nCol);
+ rCol.miPos = rCol.maSpans.insert(rCol.miPos, nRow1, nRow2+1, bVal).first;
}
-void ColumnSpanSet::executeFromTop(Action& ac) const
+void ColumnSpanSet::set(const ScRange& rRange, bool bVal)
+{
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ {
+ ColumnType& rCol = getColumn(nTab, nCol);
+ rCol.miPos = rCol.maSpans.insert(rCol.miPos, rRange.aStart.Row(), rRange.aEnd.Row()+1, bVal).first;
+ }
+ }
+}
+
+void ColumnSpanSet::executeAction(Action& ac) const
{
for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
{
@@ -85,8 +106,8 @@ void ColumnSpanSet::executeFromTop(Action& ac) const
continue;
ac.startColumn(nTab, nCol);
- ColumnSpansType& rCol = *rTab[nCol];
- ColumnSpansType::const_iterator it = rCol.begin(), itEnd = rCol.end();
+ ColumnType& rCol = *rTab[nCol];
+ ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
SCROW nRow1, nRow2;
nRow1 = it->first;
bool bVal = it->second;
@@ -102,6 +123,49 @@ void ColumnSpanSet::executeFromTop(Action& ac) const
}
}
+void ColumnSpanSet::executeColumnAction(ScDocument& rDoc, ColumnAction& ac) const
+{
+ for (size_t nTab = 0; nTab < maDoc.size(); ++nTab)
+ {
+ if (!maDoc[nTab])
+ continue;
+
+ const TableType& rTab = *maDoc[nTab];
+ for (size_t nCol = 0; nCol < rTab.size(); ++nCol)
+ {
+ if (!rTab[nCol])
+ continue;
+
+ ScTable* pTab = rDoc.FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ if (!ValidCol(nCol))
+ {
+ // End the loop.
+ nCol = rTab.size();
+ continue;
+ }
+
+ ScColumn& rColumn = pTab->aCol[nCol];
+ ac.startColumn(&rColumn);
+ ColumnType& rCol = *rTab[nCol];
+ ColumnSpansType::const_iterator it = rCol.maSpans.begin(), itEnd = rCol.maSpans.end();
+ SCROW nRow1, nRow2;
+ nRow1 = it->first;
+ bool bVal = it->second;
+ for (++it; it != itEnd; ++it)
+ {
+ nRow2 = it->first-1;
+ ac.execute(nRow1, nRow2, bVal);
+
+ nRow1 = nRow2+1; // for the next iteration.
+ bVal = it->second;
+ }
+ }
+ }
+}
+
namespace {
class Scanner
diff --git a/sc/source/core/data/documen6.cxx b/sc/source/core/data/documen6.cxx
index a165f97a31ef..b9b8d5f4dbe9 100644
--- a/sc/source/core/data/documen6.cxx
+++ b/sc/source/core/data/documen6.cxx
@@ -194,7 +194,7 @@ sal_uInt8 ScDocument::GetRangeScriptType(
sal_uInt8 ScDocument::GetRangeScriptType( const ScRangeList& rRanges )
{
- sc::ColumnSpanSet aSet;
+ sc::ColumnSpanSet aSet(false);
for (size_t i = 0, n = rRanges.size(); i < n; ++i)
{
const ScRange& rRange = *rRanges[i];
@@ -206,7 +206,7 @@ sal_uInt8 ScDocument::GetRangeScriptType( const ScRangeList& rRanges )
}
ScriptTypeAggregator aAction(*this);
- aSet.executeFromTop(aAction);
+ aSet.executeAction(aAction);
return aAction.getScriptType();
}
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 9d3c72f468b8..2920d990805e 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3538,8 +3538,7 @@ void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
void ScDocument::CalcAll()
{
ClearLookupCaches(); // Ensure we don't deliver zombie data.
- bool bOldAutoCalc = GetAutoCalc();
- SetAutoCalc( true );
+ sc::AutoCalcSwitch aSwitch(*this, true);
TableContainer::iterator it = maTabs.begin();
for (; it != maTabs.end(); ++it)
if (*it)
@@ -3548,7 +3547,6 @@ void ScDocument::CalcAll()
if (*it)
(*it)->CalcAll();
ClearFormulaTree();
- SetAutoCalc( bOldAutoCalc );
}
@@ -5925,6 +5923,19 @@ void ScDocument::SetSubTotalCellsDirty(const ScRange& rDirtyRange)
maSubTotalCells.swap(aNewSet); // update the list.
}
+void ScDocument::MarkSubTotalCells( sc::ColumnSpanSet& rSet, const ScRange& rRange, bool bVal ) const
+{
+ for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+ {
+ const ScTable* pTab = FetchTable(nTab);
+ if (!pTab)
+ continue;
+
+ pTab->MarkSubTotalCells(
+ rSet, rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), bVal);
+ }
+}
+
sal_uInt16 ScDocument::GetTextWidth( const ScAddress& rPos ) const
{
SCTAB nTab = rPos.Tab();
diff --git a/sc/source/core/data/listenercontext.cxx b/sc/source/core/data/listenercontext.cxx
index 6f67920d522b..dc9234681acb 100644
--- a/sc/source/core/data/listenercontext.cxx
+++ b/sc/source/core/data/listenercontext.cxx
@@ -53,7 +53,7 @@ ColumnBlockPosition* StartListeningContext::getBlockPosition(SCTAB nTab, SCCOL n
}
EndListeningContext::EndListeningContext(ScDocument& rDoc) :
- mrDoc(rDoc), mpPosSet(new ColumnBlockPositionSet(rDoc)) {}
+ mrDoc(rDoc), maSet(false), mpPosSet(new ColumnBlockPositionSet(rDoc)) {}
ScDocument& EndListeningContext::getDoc()
{
@@ -73,7 +73,7 @@ void EndListeningContext::addEmptyBroadcasterPosition(SCTAB nTab, SCCOL nCol, SC
void EndListeningContext::purgeEmptyBroadcasters()
{
PurgeAction aAction(mrDoc);
- maSet.executeFromTop(aAction);
+ maSet.executeAction(aAction);
}
}
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index eff2cd6f0a77..99718164027f 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -55,6 +55,7 @@
#include "cellvalue.hxx"
#include "tokenarray.hxx"
#include "mtvcellfunc.hxx"
+#include "columnspanset.hxx"
#include <vector>
#include <boost/unordered_set.hpp>
@@ -1159,6 +1160,36 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
return bSpaceLeft;
}
+void ScTable::MarkSubTotalCells(
+ sc::ColumnSpanSet& rSet, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, bool bVal ) const
+{
+ if (!ValidCol(nCol1) || !ValidCol(nCol2))
+ return;
+
+ // Pick up all subtotal formula cells.
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ aCol[nCol].MarkSubTotalCells(rSet, nRow1, nRow2, bVal);
+
+ // Pick up all filtered rows.
+ ScFlatBoolRowSegments::RangeData aFilteredSpan;
+ SCROW nRow = nRow1;
+ while (nRow <= nRow2)
+ {
+ if (!mpFilteredRows->getRangeData(nRow, aFilteredSpan))
+ // Failed for whatever reason.
+ return;
+
+ if (aFilteredSpan.mbValue)
+ {
+ // Filtered span found.
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ rSet.set(nTab, nCol, nRow, aFilteredSpan.mnRow2, bVal);
+ }
+
+ nRow = aFilteredSpan.mnRow2 + 1;
+ }
+}
+
namespace {
class QueryEvaluator
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index a88b542898f5..643a0aa3d321 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -58,6 +58,8 @@
#include "queryparam.hxx"
#include "queryentry.hxx"
#include "tokenarray.hxx"
+#include "columnspanset.hxx"
+#include "column.hxx"
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
@@ -4274,11 +4276,188 @@ 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()
{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount" );
- PushDouble( IterateParameters( ifCOUNT ) );
+ short nParamCount = GetByte();
+ double fVal = 0.0;
+ sal_uLong nCount = 0;
+ ScAddress aAdr;
+ ScRange aRange;
+ size_t nRefInList = 0;
+ if (nGlobalError)
+ nGlobalError = 0;
+
+ while (nParamCount-- > 0)
+ {
+ switch (GetStackType())
+ {
+ case svString:
+ {
+ String aStr( PopString() );
+ sal_uInt32 nFIndex = 0; // damit default Land/Spr.
+ if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
+ nCount++;
+ }
+ break;
+ case svDouble :
+ nCount++;
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+ break;
+ case svExternalSingleRef:
+ {
+ ScExternalRefCache::TokenRef pToken;
+ ScExternalRefCache::CellFormat aFmt;
+ PopExternalSingleRef(pToken, &aFmt);
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ break;
+ }
+
+ if (!pToken)
+ break;
+
+ StackVar eType = pToken->GetType();
+ if (eType == formula::svDouble)
+ {
+ nCount++;
+ if (aFmt.mbIsSet)
+ {
+ nFuncFmtType = aFmt.mnType;
+ nFuncFmtIndex = aFmt.mnIndex;
+ }
+
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ nCount--;
+ }
+ }
+ }
+ break;
+ case svSingleRef :
+ {
+ PopSingleRef( aAdr );
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ break;
+ }
+ if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
+ {
+ break;
+ }
+ ScRefCellValue aCell;
+ aCell.assign(*pDok, aAdr);
+ if (!aCell.isEmpty())
+ {
+ if (aCell.hasNumeric())
+ {
+ nCount++;
+ CurFmtToFuncFmt();
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ nCount--;
+ }
+ }
+ }
+ }
+ break;
+ case svDoubleRef :
+ case svRefList :
+ {
+ PopDoubleRef( aRange, nParamCount, nRefInList);
+ if (nGlobalError)
+ {
+ nGlobalError = 0;
+ break;
+ }
+
+ sc::ColumnSpanSet aSet(false);
+ aSet.set(aRange, true);
+ if (glSubTotal)
+ // Skip all filtered rows and subtotal formula cells.
+ pDok->MarkSubTotalCells(aSet, aRange, false);
+
+ FuncCount aAction;
+ aSet.executeColumnAction(*pDok, aAction);
+ nCount = aAction.getCount();
+
+ // 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;
+
+ double fMem = 0.0, fRes = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ }
+ break;
+ case svMatrix :
+ {
+ ScMatrixRef pMat = PopMatrix();
+ double fMem = 0.0, fRes = 0.0;
+ bool bNull = true;
+ IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
+ }
+ break;
+ case svError:
+ {
+ PopError();
+ nGlobalError = 0;
+ }
+ break;
+ default :
+ while (nParamCount-- > 0)
+ PopError();
+ SetError(errIllegalParameter);
+ }
+ }
+
+ nFuncFmtType = NUMBERFORMAT_NUMBER;
+
+ PushDouble(nCount);
}