[Libreoffice-commits] core.git: 8 commits - sc/inc sc/source
Michael Meeks
michael.meeks at suse.com
Tue Jul 2 11:37:20 PDT 2013
sc/inc/column.hxx | 7
sc/inc/columnspanset.hxx | 29 ++
sc/inc/document.hxx | 3
sc/inc/formulacell.hxx | 1
sc/inc/formulagroup.hxx | 2
sc/inc/formularesult.hxx | 2
sc/inc/table.hxx | 4
sc/source/core/data/column.cxx | 100 +++++++++
sc/source/core/data/column2.cxx | 3
sc/source/core/data/columnspanset.cxx | 84 ++++++-
sc/source/core/data/documen6.cxx | 4
sc/source/core/data/document.cxx | 17 +
sc/source/core/data/formulacell.cxx | 9
sc/source/core/data/listenercontext.cxx | 4
sc/source/core/data/table3.cxx | 31 ++
sc/source/core/opencl/formulagroupcl.cxx | 7
sc/source/core/tool/formulagroup.cxx | 5
sc/source/core/tool/formularesult.cxx | 12 +
sc/source/core/tool/interpr1.cxx | 338 ++++++++++++++++++++++++++++++-
sc/source/core/tool/interpr5.cxx | 12 +
sc/source/core/tool/token.cxx | 2
21 files changed, 649 insertions(+), 27 deletions(-)
New commits:
commit 12a426b0261c44c4625f627ea21bd308266acae5
Author: Michael Meeks <michael.meeks at suse.com>
Date: Tue Jul 2 18:22:26 2013 +0100
fix naming snafu.
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 9530276..ca064fe 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -57,7 +57,7 @@ public:
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode);
};
-ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& rMat)
+ScMatrixRef FormulaGroupInterpreterOpenCL::inverseMatrix(const ScMatrix& rMat)
{
return ScMatrixRef();
}
commit 97b026d934cdad9121c980cae87ea50bae9e4aad
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 12:26:16 2013 -0400
Add a way to inverse matrix using openCL. It's an no-op for now.
Change-Id: I4659d57505c3dccf872e124b8b569e680b307b71
diff --git a/sc/inc/formulagroup.hxx b/sc/inc/formulagroup.hxx
index e5839e4..1c573c4 100644
--- a/sc/inc/formulagroup.hxx
+++ b/sc/inc/formulagroup.hxx
@@ -43,6 +43,7 @@ class SC_DLLPUBLIC FormulaGroupInterpreter
public:
static FormulaGroupInterpreter *getStatic();
+ virtual ScMatrixRef inverseMatrix(const ScMatrix& rMat) = 0;
virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode) = 0;
};
@@ -54,6 +55,7 @@ public:
FormulaGroupInterpreter() {}
virtual ~FormulaGroupInterpreterSoftware() {}
+ virtual ScMatrixRef inverseMatrix(const ScMatrix& rMat);
virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos, const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode);
};
diff --git a/sc/source/core/opencl/formulagroupcl.cxx b/sc/source/core/opencl/formulagroupcl.cxx
index 41e439c..9530276 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -51,10 +51,17 @@ public:
{
OclCalc::ReleaseOpenclRunEnv();
}
+
+ virtual ScMatrixRef inverseMatrix(const ScMatrix& rMat);
virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode);
};
+ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& rMat)
+{
+ return ScMatrixRef();
+}
+
bool FormulaGroupInterpreterOpenCL::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup, ScTokenArray& rCode)
{
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index 4a04f79..4754bd0 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -20,6 +20,11 @@
namespace sc {
+ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
+{
+ return ScMatrixRef();
+}
+
bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
const ScFormulaCellGroupRef& xGroup,
ScTokenArray& rCode)
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index 26c2378..d48cfe7 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -35,6 +35,7 @@
#include "scmatrix.hxx"
#include "globstr.hrc"
#include "cellkeytranslator.hxx"
+#include "formulagroup.hxx"
#include <vector>
@@ -850,6 +851,17 @@ void ScInterpreter::ScMatInv()
}
SCSIZE nC, nR;
pMat->GetDimensions(nC, nR);
+
+ if (ScInterpreter::GetGlobalConfig().mbOpenCLEnabled)
+ {
+ ScMatrixRef xResMat = sc::FormulaGroupInterpreter::getStatic()->inverseMatrix(*pMat);
+ if (xResMat)
+ {
+ PushMatrix(xResMat);
+ return;
+ }
+ }
+
if ( nC != nR || nC == 0 || (sal_uLong) nC * nC > ScMatrix::GetElementsMax() )
PushIllegalArgument();
else
commit 946e1cb115a2a46fa10f528f83ca7a214fc31544
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 12:00:02 2013 -0400
Enable group calculation on COUNT and COUNT2.
Change-Id: I7a1cb5aa485bd54e1f6e41262435129b6ac6b98b
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index e25ef60..3ce8fda 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1319,6 +1319,8 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
case ocSum:
case ocSumProduct:
case ocMatInv:
+ case ocCount:
+ case ocCount2:
// Don't change the state.
break;
default:
commit b8904b25d622bcf5c2b1435a993e507d1c7f7555
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jul 2 09:24:09 2013 -0400
Try not to iterate beyond the end of the formula block.
Or else a crash would ensue...
Change-Id: Ib08163ba91e4bac023ae778c704a0c052fa48ebb
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index abe2806..4becbb7 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2258,8 +2258,9 @@ const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW n
return &rArray[0];
}
+ // Requested length goes beyond a single block. Fill the array
+ // with the content of this formula block first.
itEnd = sc::formula_block::end(*aPos.first->data);
- std::advance(itEnd, nLenRequested);
for (; it != itEnd; ++it)
{
ScFormulaCell& rCell = **it;
commit cd2594c7504318a88719c710f7e627b9dd72fa16
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 a63025c..52a1474 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -202,6 +202,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 6736a10..f1f7b5d 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -128,6 +128,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 64aae03..61f57ab 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 1e86cfc..a129726 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1711,6 +1711,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 a20963b..72944a0 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 9d207f6fc479bf96db9fcde214f15f2ffb045001
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 7ce53ad..359b8ac 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 8d3f625..64aae03 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 643a0aa..93bcfef 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();
commit 3b10c65d9e9a3ffd1bbe176c39d45bbb76b1fc05
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Mon Jul 1 23:30:00 2013 -0400
Unused variable.
Change-Id: I1df58281896687e61d40675206d0fc3854d93866
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 2a59e7e..8d3f625 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -474,7 +474,7 @@ class NumericCellCounter
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;
commit cfb2ce587b097b407eb15699cff7ce9fb6844123
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Mon Jul 1 23:08:14 2013 -0400
Re-implement the COUNT function for efficiency.
By taking advantage of the block structure of the new cell storage.
Change-Id: Ib953c14d364ccdff7df5caf70d57cec86189e3be
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 6cc3c4b..7ce53ad 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 55c3f57..98533e2 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 806fb77..4d41565 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 03060bb..a8d5128 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 aa82f4d1..2a59e7e 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 8bfb7fc..f8c7813 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 a165f97..b9b8d5f 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 9d3c72f..2920d99 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 6f67920..dc92346 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 eff2cd6..9971816 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 a88b542..643a0aa 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);
}
More information about the Libreoffice-commits
mailing list