Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / interpr6.cxx
blobf4045616d9078f8a8130f528e3e5679c332e69a8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "interpre.hxx"
22 #include "columnspanset.hxx"
23 #include "column.hxx"
24 #include "document.hxx"
25 #include "cellvalue.hxx"
26 #include "dociter.hxx"
27 #include "mtvcellfunc.hxx"
29 #include "formula/token.hxx"
31 using namespace formula;
33 double const fHalfMachEps = 0.5 * ::std::numeric_limits<double>::epsilon();
35 // The idea how this group of gamma functions is calculated, is
36 // based on the Cephes library
37 // online http://www.moshier.net/#Cephes [called 2008-02]
39 /** You must ensure fA>0.0 && fX>0.0
40 valid results only if fX > fA+1.0
41 uses continued fraction with odd items */
42 double ScInterpreter::GetGammaContFraction( double fA, double fX )
45 double const fBigInv = ::std::numeric_limits<double>::epsilon();
46 double const fBig = 1.0/fBigInv;
47 double fCount = 0.0;
48 double fNum = 0.0; // dummy value
49 double fY = 1.0 - fA;
50 double fDenom = fX + 2.0-fA;
51 double fPk = 0.0; // dummy value
52 double fPkm1 = fX + 1.0;
53 double fPkm2 = 1.0;
54 double fQk = 1.0; // dummy value
55 double fQkm1 = fDenom * fX;
56 double fQkm2 = fX;
57 double fApprox = fPkm1/fQkm1;
58 bool bFinished = false;
59 double fR = 0.0; // dummy value
62 fCount = fCount +1.0;
63 fY = fY+ 1.0;
64 fNum = fY * fCount;
65 fDenom = fDenom +2.0;
66 fPk = fPkm1 * fDenom - fPkm2 * fNum;
67 fQk = fQkm1 * fDenom - fQkm2 * fNum;
68 if (fQk != 0.0)
70 fR = fPk/fQk;
71 bFinished = (fabs( (fApprox - fR)/fR ) <= fHalfMachEps);
72 fApprox = fR;
74 fPkm2 = fPkm1;
75 fPkm1 = fPk;
76 fQkm2 = fQkm1;
77 fQkm1 = fQk;
78 if (fabs(fPk) > fBig)
80 // reduce a fraction does not change the value
81 fPkm2 = fPkm2 * fBigInv;
82 fPkm1 = fPkm1 * fBigInv;
83 fQkm2 = fQkm2 * fBigInv;
84 fQkm1 = fQkm1 * fBigInv;
86 } while (!bFinished && fCount<10000);
87 // most iterations, if fX==fAlpha+1.0; approx sqrt(fAlpha) iterations then
88 if (!bFinished)
90 SetError(errNoConvergence);
92 return fApprox;
95 /** You must ensure fA>0.0 && fX>0.0
96 valid results only if fX <= fA+1.0
97 uses power series */
98 double ScInterpreter::GetGammaSeries( double fA, double fX )
100 double fDenomfactor = fA;
101 double fSummand = 1.0/fA;
102 double fSum = fSummand;
103 int nCount=1;
106 fDenomfactor = fDenomfactor + 1.0;
107 fSummand = fSummand * fX/fDenomfactor;
108 fSum = fSum + fSummand;
109 nCount = nCount+1;
110 } while ( fSummand/fSum > fHalfMachEps && nCount<=10000);
111 // large amount of iterations will be carried out for huge fAlpha, even
112 // if fX <= fAlpha+1.0
113 if (nCount>10000)
115 SetError(errNoConvergence);
117 return fSum;
120 /** You must ensure fA>0.0 && fX>0.0) */
121 double ScInterpreter::GetLowRegIGamma( double fA, double fX )
123 double fLnFactor = fA * log(fX) - fX - GetLogGamma(fA);
124 double fFactor = exp(fLnFactor); // Do we need more accuracy than exp(ln()) has?
125 if (fX>fA+1.0) // includes fX>1.0; 1-GetUpRegIGamma, continued fraction
126 return 1.0 - fFactor * GetGammaContFraction(fA,fX);
127 else // fX<=1.0 || fX<=fA+1.0, series
128 return fFactor * GetGammaSeries(fA,fX);
131 /** You must ensure fA>0.0 && fX>0.0) */
132 double ScInterpreter::GetUpRegIGamma( double fA, double fX )
135 double fLnFactor= fA*log(fX)-fX-GetLogGamma(fA);
136 double fFactor = exp(fLnFactor); //Do I need more accuracy than exp(ln()) has?;
137 if (fX>fA+1.0) // includes fX>1.0
138 return fFactor * GetGammaContFraction(fA,fX);
139 else //fX<=1 || fX<=fA+1, 1-GetLowRegIGamma, series
140 return 1.0 -fFactor * GetGammaSeries(fA,fX);
143 /** Gamma distribution, probability density function.
144 fLambda is "scale" parameter
145 You must ensure fAlpha>0.0 and fLambda>0.0 */
146 double ScInterpreter::GetGammaDistPDF( double fX, double fAlpha, double fLambda )
148 if (fX < 0.0)
149 return 0.0; // see ODFF
150 else if (fX == 0)
151 // in this case 0^0 isn't zero
153 if (fAlpha < 1.0)
155 SetError(errDivisionByZero); // should be #DIV/0
156 return HUGE_VAL;
158 else if (fAlpha == 1)
160 return (1.0 / fLambda);
162 else
164 return 0.0;
167 else
169 double fXr = fX / fLambda;
170 // use exp(ln()) only for large arguments because of less accuracy
171 if (fXr > 1.0)
173 const double fLogDblMax = log( ::std::numeric_limits<double>::max());
174 if (log(fXr) * (fAlpha-1.0) < fLogDblMax && fAlpha < fMaxGammaArgument)
176 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
178 else
180 return exp( (fAlpha-1.0) * log(fXr) - fXr - log(fLambda) - GetLogGamma(fAlpha));
183 else // fXr near to zero
185 if (fAlpha<fMaxGammaArgument)
187 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
189 else
191 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / exp( GetLogGamma(fAlpha));
197 /** Gamma distribution, cumulative distribution function.
198 fLambda is "scale" parameter
199 You must ensure fAlpha>0.0 and fLambda>0.0 */
200 double ScInterpreter::GetGammaDist( double fX, double fAlpha, double fLambda )
202 if (fX <= 0.0)
203 return 0.0;
204 else
205 return GetLowRegIGamma( fAlpha, fX / fLambda);
208 namespace {
210 class NumericCellAccumulator
212 double mfSum;
213 public:
214 NumericCellAccumulator() : mfSum(0.0) {}
216 void operator() (size_t, double fVal)
218 mfSum += fVal;
221 void operator() (size_t, const ScFormulaCell* pCell)
223 ScFormulaCell& rCell = const_cast<ScFormulaCell&>(*pCell);
224 if (rCell.IsValue())
225 mfSum += rCell.GetValue();
228 double getSum() const { return mfSum; }
231 class NumericCellCounter
233 size_t mnCount;
234 public:
235 NumericCellCounter() : mnCount(0) {}
237 void operator() (const sc::CellStoreType::value_type& rNode, size_t nOffset, size_t nDataSize)
239 switch (rNode.type)
241 case sc::element_type_numeric:
242 mnCount += nDataSize;
243 break;
244 case sc::element_type_formula:
246 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
247 std::advance(it, nOffset);
248 sc::formula_block::const_iterator itEnd = it;
249 std::advance(itEnd, nDataSize);
250 for (; it != itEnd; ++it)
252 ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it);
253 if (rCell.IsValueNoError())
254 ++mnCount;
257 break;
258 default:
263 size_t getCount() const { return mnCount; }
266 class FuncCount : public sc::ColumnSpanSet::ColumnAction
268 sc::ColumnBlockConstPosition maPos;
269 ScColumn* mpCol;
270 size_t mnCount;
271 sal_uInt32 mnNumFmt;
273 public:
274 FuncCount() : mpCol(0), mnCount(0), mnNumFmt(0) {}
276 virtual void startColumn(ScColumn* pCol)
278 mpCol = pCol;
279 mpCol->InitBlockPosition(maPos);
282 virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
284 if (!bVal)
285 return;
287 NumericCellCounter aFunc;
288 maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2);
289 mnCount += aFunc.getCount();
290 mnNumFmt = mpCol->GetNumberFormat(nRow2);
293 size_t getCount() const { return mnCount; }
294 sal_uInt32 getNumberFormat() const { return mnNumFmt; }
297 class FuncSum : public sc::ColumnSpanSet::ColumnAction
299 sc::ColumnBlockConstPosition maPos;
300 ScColumn* mpCol;
301 double mfSum;
302 sal_uInt32 mnNumFmt;
304 public:
305 FuncSum() : mpCol(0), mfSum(0.0), mnNumFmt(0) {}
307 virtual void startColumn(ScColumn* pCol)
309 mpCol = pCol;
310 mpCol->InitBlockPosition(maPos);
313 virtual void execute(SCROW nRow1, SCROW nRow2, bool bVal)
315 if (!bVal)
316 return;
318 NumericCellAccumulator aFunc;
319 maPos.miCellPos = sc::ParseFormulaNumeric(maPos.miCellPos, mpCol->GetCellStore(), nRow1, nRow2, aFunc);
320 mfSum += aFunc.getSum();
321 mnNumFmt = mpCol->GetNumberFormat(nRow2);
324 double getSum() const { return mfSum; }
325 sal_uInt32 getNumberFormat() const { return mnNumFmt; }
328 void IterateMatrix(
329 const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
330 sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
332 if (!pMat)
333 return;
335 rFuncFmtType = NUMBERFORMAT_NUMBER;
336 switch (eFunc)
338 case ifAVERAGE:
339 case ifSUM:
341 ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
342 if (bNull)
344 bNull = false;
345 fMem = aRes.mfFirst;
346 fRes += aRes.mfRest;
348 else
349 fRes += aRes.mfFirst + aRes.mfRest;
350 rCount += aRes.mnCount;
352 break;
353 case ifCOUNT:
354 rCount += pMat->Count(bTextAsZero);
355 break;
356 case ifCOUNT2:
357 rCount += pMat->Count(true);
358 break;
359 case ifPRODUCT:
361 ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
362 fRes *= aRes.mfRest;
363 rCount += aRes.mnCount;
365 break;
366 case ifSUMSQ:
368 ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
369 fRes += aRes.mfRest;
370 rCount += aRes.mnCount;
372 break;
373 default:
380 double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
382 short nParamCount = GetByte();
383 double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
384 double fVal = 0.0;
385 double fMem = 0.0; // first numeric value.
386 bool bNull = true;
387 sal_uLong nCount = 0;
388 ScAddress aAdr;
389 ScRange aRange;
390 size_t nRefInList = 0;
391 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
392 nGlobalError = 0;
393 while (nParamCount-- > 0)
395 switch (GetStackType())
397 case svString:
399 if( eFunc == ifCOUNT )
401 OUString aStr = PopString().getString();
402 sal_uInt32 nFIndex = 0; // damit default Land/Spr.
403 if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
404 nCount++;
406 else
408 switch ( eFunc )
410 case ifAVERAGE:
411 case ifSUM:
412 case ifSUMSQ:
413 case ifPRODUCT:
415 if ( bTextAsZero )
417 Pop();
418 nCount++;
419 if ( eFunc == ifPRODUCT )
420 fRes = 0.0;
422 else
424 while (nParamCount-- > 0)
425 Pop();
426 SetError( errNoValue );
429 break;
430 default:
431 Pop();
432 nCount++;
436 break;
437 case svDouble :
438 fVal = GetDouble();
439 nCount++;
440 switch( eFunc )
442 case ifAVERAGE:
443 case ifSUM:
444 if ( bNull && fVal != 0.0 )
446 bNull = false;
447 fMem = fVal;
449 else
450 fRes += fVal;
451 break;
452 case ifSUMSQ: fRes += fVal * fVal; break;
453 case ifPRODUCT: fRes *= fVal; break;
454 default: ; // nothing
456 nFuncFmtType = NUMBERFORMAT_NUMBER;
457 break;
458 case svExternalSingleRef:
460 ScExternalRefCache::TokenRef pToken;
461 ScExternalRefCache::CellFormat aFmt;
462 PopExternalSingleRef(pToken, &aFmt);
463 if (nGlobalError && (eFunc == ifCOUNT2 || eFunc == ifCOUNT))
465 nGlobalError = 0;
466 if ( eFunc == ifCOUNT2 )
467 ++nCount;
468 break;
471 if (!pToken)
472 break;
474 StackVar eType = pToken->GetType();
475 if (eFunc == ifCOUNT2)
477 if (eType != formula::svEmptyCell)
478 nCount++;
479 if (nGlobalError)
480 nGlobalError = 0;
482 else if (eType == formula::svDouble)
484 nCount++;
485 fVal = pToken->GetDouble();
486 if (aFmt.mbIsSet)
488 nFuncFmtType = aFmt.mnType;
489 nFuncFmtIndex = aFmt.mnIndex;
491 switch( eFunc )
493 case ifAVERAGE:
494 case ifSUM:
495 if ( bNull && fVal != 0.0 )
497 bNull = false;
498 fMem = fVal;
500 else
501 fRes += fVal;
502 break;
503 case ifSUMSQ: fRes += fVal * fVal; break;
504 case ifPRODUCT: fRes *= fVal; break;
505 case ifCOUNT:
506 if ( nGlobalError )
508 nGlobalError = 0;
509 nCount--;
511 break;
512 default: ; // nothing
515 else if (bTextAsZero && eType == formula::svString)
517 nCount++;
518 if ( eFunc == ifPRODUCT )
519 fRes = 0.0;
522 break;
523 case svSingleRef :
525 PopSingleRef( aAdr );
526 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
528 nGlobalError = 0;
529 if ( eFunc == ifCOUNT2 )
530 ++nCount;
531 break;
533 if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
535 break;
537 ScRefCellValue aCell;
538 aCell.assign(*pDok, aAdr);
539 if (!aCell.isEmpty())
541 if( eFunc == ifCOUNT2 )
543 CellType eCellType = aCell.meType;
544 if (eCellType != CELLTYPE_NONE)
545 nCount++;
546 if ( nGlobalError )
547 nGlobalError = 0;
549 else if (aCell.hasNumeric())
551 nCount++;
552 fVal = GetCellValue(aAdr, aCell);
553 CurFmtToFuncFmt();
554 switch( eFunc )
556 case ifAVERAGE:
557 case ifSUM:
558 if ( bNull && fVal != 0.0 )
560 bNull = false;
561 fMem = fVal;
563 else
564 fRes += fVal;
565 break;
566 case ifSUMSQ: fRes += fVal * fVal; break;
567 case ifPRODUCT: fRes *= fVal; break;
568 case ifCOUNT:
569 if ( nGlobalError )
571 nGlobalError = 0;
572 nCount--;
574 break;
575 default: ; // nothing
578 else if (bTextAsZero && aCell.hasString())
580 nCount++;
581 if ( eFunc == ifPRODUCT )
582 fRes = 0.0;
586 break;
587 case svDoubleRef :
588 case svRefList :
590 PopDoubleRef( aRange, nParamCount, nRefInList);
591 if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
593 nGlobalError = 0;
594 if ( eFunc == ifCOUNT2 )
595 ++nCount;
596 break;
598 if( eFunc == ifCOUNT2 )
600 ScCellIterator aIter( pDok, aRange, glSubTotal );
601 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
603 if (!aIter.hasEmptyData())
604 ++nCount;
607 if ( nGlobalError )
608 nGlobalError = 0;
610 else
612 ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
613 sal_uInt16 nErr = 0;
614 if (aValIter.GetFirst(fVal, nErr))
616 // placed the loop on the inside for performance reasons:
617 aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
618 switch( eFunc )
620 case ifAVERAGE:
621 case ifSUM:
624 SetError(nErr);
625 if ( bNull && fVal != 0.0 )
627 bNull = false;
628 fMem = fVal;
630 else
631 fRes += fVal;
632 nCount++;
634 while (aValIter.GetNext(fVal, nErr));
635 break;
636 case ifSUMSQ:
639 SetError(nErr);
640 fRes += fVal * fVal;
641 nCount++;
643 while (aValIter.GetNext(fVal, nErr));
644 break;
645 case ifPRODUCT:
648 SetError(nErr);
649 fRes *= fVal;
650 nCount++;
652 while (aValIter.GetNext(fVal, nErr));
653 break;
654 case ifCOUNT:
657 if ( !nErr )
658 nCount++;
660 while (aValIter.GetNext(fVal, nErr));
661 break;
662 default: ; // nothing
664 SetError( nErr );
668 break;
669 case svExternalDoubleRef:
671 ScMatrixRef pMat;
672 PopExternalDoubleRef(pMat);
673 if (nGlobalError)
674 break;
676 IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
678 break;
679 case svMatrix :
681 ScMatrixRef pMat = PopMatrix();
682 IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
684 break;
685 case svError:
687 PopError();
688 if ( eFunc == ifCOUNT )
690 nGlobalError = 0;
692 else if ( eFunc == ifCOUNT2 )
694 nCount++;
695 nGlobalError = 0;
698 break;
699 default :
700 while (nParamCount-- > 0)
701 PopError();
702 SetError(errIllegalParameter);
705 switch( eFunc )
707 case ifSUM: fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
708 case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
709 case ifCOUNT2:
710 case ifCOUNT: fRes = nCount; break;
711 case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
712 default: ; // nothing
714 // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
715 // und Anzahl ist immer Number (#38345#)
716 if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
717 nFuncFmtType = NUMBERFORMAT_NUMBER;
718 return fRes;
722 void ScInterpreter::ScSumSQ()
724 PushDouble( IterateParameters( ifSUMSQ ) );
728 void ScInterpreter::ScSum()
730 short nParamCount = GetByte();
731 double fRes = 0.0;
732 double fVal = 0.0;
733 ScAddress aAdr;
734 ScRange aRange;
735 size_t nRefInList = 0;
736 while (nParamCount-- > 0)
738 switch (GetStackType())
740 case svString:
742 while (nParamCount-- > 0)
743 Pop();
744 SetError( errNoValue );
746 break;
747 case svDouble :
748 fVal = GetDouble();
749 fRes += fVal;
750 nFuncFmtType = NUMBERFORMAT_NUMBER;
751 break;
752 case svExternalSingleRef:
754 ScExternalRefCache::TokenRef pToken;
755 ScExternalRefCache::CellFormat aFmt;
756 PopExternalSingleRef(pToken, &aFmt);
758 if (!pToken)
759 break;
761 StackVar eType = pToken->GetType();
762 if (eType == formula::svDouble)
764 fVal = pToken->GetDouble();
765 if (aFmt.mbIsSet)
767 nFuncFmtType = aFmt.mnType;
768 nFuncFmtIndex = aFmt.mnIndex;
771 fRes += fVal;
774 break;
775 case svSingleRef :
777 PopSingleRef( aAdr );
779 if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
781 break;
783 ScRefCellValue aCell;
784 aCell.assign(*pDok, aAdr);
785 if (!aCell.isEmpty())
787 if (aCell.hasNumeric())
789 fVal = GetCellValue(aAdr, aCell);
790 CurFmtToFuncFmt();
791 fRes += fVal;
795 break;
796 case svDoubleRef :
797 case svRefList :
799 PopDoubleRef( aRange, nParamCount, nRefInList);
801 sc::ColumnSpanSet aSet(false);
802 aSet.set(aRange, true);
803 if (glSubTotal)
804 // Skip all filtered rows and subtotal formula cells.
805 pDok->MarkSubTotalCells(aSet, aRange, false);
807 FuncSum aAction;
808 aSet.executeColumnAction(*pDok, aAction);
809 fRes += aAction.getSum();
811 // Get the number format of the last iterated cell.
812 nFuncFmtIndex = aAction.getNumberFormat();
813 nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
815 break;
816 case svExternalDoubleRef:
818 ScMatrixRef pMat;
819 PopExternalDoubleRef(pMat);
820 if (nGlobalError)
821 break;
823 sal_uLong nCount = 0;
824 double fMem = 0.0;
825 bool bNull = true;
826 IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
827 fRes += fMem;
829 break;
830 case svMatrix :
832 ScMatrixRef pMat = PopMatrix();
833 sal_uLong nCount = 0;
834 double fMem = 0.0;
835 bool bNull = true;
836 IterateMatrix(pMat, ifSUM, false, nCount, nFuncFmtType, fRes, fMem, bNull);
837 fRes += fMem;
839 break;
840 case svError:
842 PopError();
844 break;
845 default :
846 while (nParamCount-- > 0)
847 PopError();
848 SetError(errIllegalParameter);
852 if (nFuncFmtType == NUMBERFORMAT_LOGICAL)
853 nFuncFmtType = NUMBERFORMAT_NUMBER;
855 PushDouble(fRes);
859 void ScInterpreter::ScProduct()
861 PushDouble( IterateParameters( ifPRODUCT ) );
865 void ScInterpreter::ScAverage( bool bTextAsZero )
867 PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
870 void ScInterpreter::ScCount()
872 short nParamCount = GetByte();
873 double fVal = 0.0;
874 sal_uLong nCount = 0;
875 ScAddress aAdr;
876 ScRange aRange;
877 size_t nRefInList = 0;
878 if (nGlobalError)
879 nGlobalError = 0;
881 while (nParamCount-- > 0)
883 switch (GetRawStackType())
885 case svString:
887 OUString aStr = PopString().getString();
888 sal_uInt32 nFIndex = 0; // damit default Land/Spr.
889 if (pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
890 nCount++;
892 break;
893 case svDouble :
894 nCount++;
895 nFuncFmtType = NUMBERFORMAT_NUMBER;
896 break;
897 case svExternalSingleRef:
899 ScExternalRefCache::TokenRef pToken;
900 ScExternalRefCache::CellFormat aFmt;
901 PopExternalSingleRef(pToken, &aFmt);
902 if (nGlobalError)
904 nGlobalError = 0;
905 break;
908 if (!pToken)
909 break;
911 StackVar eType = pToken->GetType();
912 if (eType == formula::svDouble)
914 nCount++;
915 if (aFmt.mbIsSet)
917 nFuncFmtType = aFmt.mnType;
918 nFuncFmtIndex = aFmt.mnIndex;
921 if (nGlobalError)
923 nGlobalError = 0;
924 nCount--;
928 break;
929 case svSingleRef :
931 PopSingleRef( aAdr );
932 if (nGlobalError)
934 nGlobalError = 0;
935 break;
937 if (glSubTotal && pDok->RowFiltered( aAdr.Row(), aAdr.Tab()))
939 break;
941 ScRefCellValue aCell;
942 aCell.assign(*pDok, aAdr);
943 if (!aCell.isEmpty())
945 if (aCell.hasNumeric())
947 nCount++;
948 CurFmtToFuncFmt();
949 if (nGlobalError)
951 nGlobalError = 0;
952 nCount--;
957 break;
958 case svDoubleRef :
959 case svRefList :
961 PopDoubleRef( aRange, nParamCount, nRefInList);
962 if (nGlobalError)
964 nGlobalError = 0;
965 break;
968 sc::ColumnSpanSet aSet(false);
969 aSet.set(aRange, true);
970 if (glSubTotal)
971 // Skip all filtered rows and subtotal formula cells.
972 pDok->MarkSubTotalCells(aSet, aRange, false);
974 FuncCount aAction;
975 aSet.executeColumnAction(*pDok, aAction);
976 nCount += aAction.getCount();
978 // Get the number format of the last iterated cell.
979 nFuncFmtIndex = aAction.getNumberFormat();
980 nFuncFmtType = pDok->GetFormatTable()->GetType(nFuncFmtIndex);
982 break;
983 case svExternalDoubleRef:
985 ScMatrixRef pMat;
986 PopExternalDoubleRef(pMat);
987 if (nGlobalError)
988 break;
990 double fMem = 0.0, fRes = 0.0;
991 bool bNull = true;
992 IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
994 break;
995 case svMatrix :
997 ScMatrixRef pMat = PopMatrix();
998 double fMem = 0.0, fRes = 0.0;
999 bool bNull = true;
1000 IterateMatrix(pMat, ifCOUNT, false, nCount, nFuncFmtType, fRes, fMem, bNull);
1002 break;
1003 case svError:
1005 PopError();
1006 nGlobalError = 0;
1008 break;
1009 default :
1010 while (nParamCount-- > 0)
1011 PopError();
1012 SetError(errIllegalParameter);
1016 nFuncFmtType = NUMBERFORMAT_NUMBER;
1018 PushDouble(nCount);
1022 void ScInterpreter::ScCount2()
1024 PushDouble( IterateParameters( ifCOUNT2 ) );
1027 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */