diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-07-01 23:08:14 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-07-02 13:19:32 -0400 |
commit | cfb2ce587b097b407eb15699cff7ce9fb6844123 (patch) | |
tree | 9ca222bdaf03e11ae3c3951ac84d0b3a2ce92aeb /sc | |
parent | db377e02c309c20419aef1360409be09fe50fc42 (diff) |
Re-implement the COUNT function for efficiency.
By taking advantage of the block structure of the new cell storage.
Change-Id: Ib953c14d364ccdff7df5caf70d57cec86189e3be
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 6 | ||||
-rw-r--r-- | sc/inc/columnspanset.hxx | 29 | ||||
-rw-r--r-- | sc/inc/document.hxx | 3 | ||||
-rw-r--r-- | sc/inc/table.hxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/column.cxx | 54 | ||||
-rw-r--r-- | sc/source/core/data/columnspanset.cxx | 84 | ||||
-rw-r--r-- | sc/source/core/data/documen6.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 17 | ||||
-rw-r--r-- | sc/source/core/data/listenercontext.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 31 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 183 |
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); } |