You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by or...@apache.org on 2012/09/17 10:06:23 UTC
svn commit: r1386501 [5/10] - in /incubator/ooo/branches/writer001: ./
ext_libraries/ratscan/ ext_sources/ main/ main/autodoc/source/display/html/
main/basegfx/inc/basegfx/numeric/ main/basegfx/source/numeric/
main/basegfx/source/tools/ main/basic/sour...
Modified: incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr1.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr1.cxx?rev=1386501&r1=1386500&r2=1386501&view=diff
==============================================================================
--- incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr1.cxx (original)
+++ incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr1.cxx Mon Sep 17 08:06:09 2012
@@ -1332,6 +1332,106 @@ void ScInterpreter::ScOr()
}
}
+void ScInterpreter::ScXor()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScXor" );
+ nFuncFmtType = NUMBERFORMAT_LOGICAL;
+ short nParamCount = GetByte();
+ if ( MustHaveParamCountMin( nParamCount, 1 ) )
+ {
+ bool bHaveValue = false;
+ short nRes = 0;
+ size_t nRefInList = 0;
+ while( nParamCount-- > 0)
+ {
+ if ( !nGlobalError )
+ {
+ switch ( GetStackType() )
+ {
+ case svDouble :
+ bHaveValue = true;
+ nRes ^= ( PopDouble() != 0.0 );
+ break;
+ case svString :
+ Pop();
+ SetError( errNoValue );
+ break;
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ PopSingleRef( aAdr );
+ if ( !nGlobalError )
+ {
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData( pCell ) )
+ {
+ bHaveValue = true;
+ nRes ^= ( GetCellValue( aAdr, pCell ) != 0.0 );
+ }
+ /* TODO: set error? Excel doesn't have XOR, but
+ * doesn't set an error in this case for AND and
+ * OR. */
+ }
+ }
+ break;
+ case svDoubleRef:
+ case svRefList:
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange, nParamCount, nRefInList);
+ if ( !nGlobalError )
+ {
+ double fVal;
+ sal_uInt16 nErr = 0;
+ ScValueIterator aValIter( pDok, aRange );
+ if ( aValIter.GetFirst( fVal, nErr ) )
+ {
+ bHaveValue = true;
+ do
+ {
+ nRes ^= ( fVal != 0.0 );
+ } while ( (nErr == 0) &&
+ aValIter.GetNext( fVal, nErr ) );
+ }
+ SetError( nErr );
+ }
+ }
+ break;
+ case svMatrix:
+ {
+ bHaveValue = true;
+ ScMatrixRef pMat = GetMatrix();
+ if ( pMat )
+ {
+ bHaveValue = true;
+ double fVal = pMat->Xor();
+ sal_uInt16 nErr = GetDoubleErrorValue( fVal );
+ if ( nErr )
+ {
+ SetError( nErr );
+ nRes = 0;
+ }
+ else
+ nRes ^= (fVal != 0.0);
+ }
+ // else: GetMatrix did set errIllegalParameter
+ }
+ break;
+ default:
+ Pop();
+ SetError( errIllegalParameter);
+ }
+ }
+ else
+ Pop();
+ }
+ if ( bHaveValue )
+ PushInt( nRes );
+ else
+ PushNoValue();
+ }
+}
+
void ScInterpreter::ScNeg()
{
@@ -4409,89 +4509,134 @@ void ScInterpreter::ScCountEmptyCells()
}
-void ScInterpreter::ScCountIf()
+double ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc )
{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountIf" );
- if ( MustHaveParamCount( GetByte(), 2 ) )
+ sal_uInt8 nParamCount = GetByte();
+ if ( MustHaveParamCount( nParamCount, 2, 3 ) )
{
+ SCCOL nCol3 = 0;
+ SCROW nRow3 = 0;
+ SCTAB nTab3 = 0;
+
+ ScMatrixRef pSumExtraMatrix;
+ bool bSumExtraRange = (nParamCount == 3);
+ if (bSumExtraRange)
+ {
+ // Save only the upperleft cell in case of cell range. The geometry
+ // of the 3rd parameter is taken from the 1st parameter.
+
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ {
+ SCCOL nColJunk = 0;
+ SCROW nRowJunk = 0;
+ SCTAB nTabJunk = 0;
+ PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
+ if ( nTabJunk != nTab3 )
+ {
+ SetError( errIllegalParameter);
+ }
+ }
+ break;
+ case svSingleRef :
+ PopSingleRef( nCol3, nRow3, nTab3 );
+ break;
+ case svMatrix:
+ pSumExtraMatrix = PopMatrix();
+ //! nCol3, nRow3, nTab3 remain 0
+ break;
+ default:
+ SetError( errIllegalParameter);
+ }
+ }
String rString;
double fVal = 0.0;
- sal_Bool bIsString = sal_True;
+ bool bIsString = true;
switch ( GetStackType() )
{
case svDoubleRef :
case svSingleRef :
- {
- ScAddress aAdr;
- if ( !PopDoubleRefOrSingleRef( aAdr ) )
- {
- PushInt(0);
- return ;
- }
- ScBaseCell* pCell = GetCell( aAdr );
- switch ( GetCellType( pCell ) )
{
- case CELLTYPE_VALUE :
- fVal = GetCellValue( aAdr, pCell );
- bIsString = sal_False;
- break;
- case CELLTYPE_FORMULA :
- if( ((ScFormulaCell*)pCell)->IsValue() )
- {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ return 0;
+
+ ScBaseCell* pCell = GetCell( aAdr );
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
fVal = GetCellValue( aAdr, pCell );
- bIsString = sal_False;
- }
- else
+ bIsString = false;
+ break;
+ case CELLTYPE_FORMULA :
+ if( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = false;
+ }
+ else
+ GetCellString(rString, pCell);
+ break;
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
GetCellString(rString, pCell);
- break;
- case CELLTYPE_STRING :
- case CELLTYPE_EDIT :
- GetCellString(rString, pCell);
- break;
- default:
- fVal = 0.0;
- bIsString = sal_False;
+ break;
+ default:
+ fVal = 0.0;
+ bIsString = false;
+ }
}
- }
- break;
- case svMatrix :
- {
- ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
- rString);
- bIsString = ScMatrix::IsNonValueType( nType);
- }
- break;
+ break;
case svString:
rString = GetString();
- break;
+ break;
+ case svMatrix :
+ {
+ ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
+ bIsString = ScMatrix::IsNonValueType( nType);
+ }
+ break;
default:
- {
- fVal = GetDouble();
- bIsString = sal_False;
- }
+ {
+ fVal = GetDouble();
+ bIsString = false;
+ }
}
+
double fSum = 0.0;
+ double fMem = 0.0;
+ double fRes = 0.0;
+ double fCount = 0.0;
+ bool bNull = true;
short nParam = 1;
size_t nRefInList = 0;
while (nParam-- > 0)
{
- SCCOL nCol1;
- SCROW nRow1;
- SCTAB nTab1;
- SCCOL nCol2;
- SCROW nRow2;
- SCTAB nTab2;
+ SCCOL nCol1 = 0;
+ SCROW nRow1 = 0;
+ SCTAB nTab1 = 0;
+ SCCOL nCol2 = 0;
+ SCROW nRow2 = 0;
+ SCTAB nTab2 = 0;
ScMatrixRef pQueryMatrix;
switch ( GetStackType() )
{
- case svDoubleRef :
case svRefList :
+ if (bSumExtraRange)
+ {
+ SetError( errIllegalParameter);
+ }
+ else
{
ScRange aRange;
PopDoubleRef( aRange, nParam, nRefInList);
aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
}
break;
+ case svDoubleRef :
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ break;
case svSingleRef :
PopSingleRef( nCol1, nRow1, nTab1 );
nCol2 = nCol1;
@@ -4503,8 +4648,7 @@ void ScInterpreter::ScCountIf()
pQueryMatrix = PopMatrix();
if (!pQueryMatrix)
{
- PushIllegalParameter();
- return;
+ SetError( errIllegalParameter);
}
nCol1 = 0;
nRow1 = 0;
@@ -4517,19 +4661,58 @@ void ScInterpreter::ScCountIf()
}
break;
default:
- PushIllegalParameter();
- return ;
+ SetError( errIllegalParameter);
}
if ( nTab1 != nTab2 )
{
- PushIllegalParameter();
- return;
+ SetError( errIllegalParameter);
}
- if (nCol1 > nCol2)
+
+ if (bSumExtraRange)
{
- PushIllegalParameter();
- return;
+ // Take the range geometry of the 1st parameter and apply it to
+ // the 3rd. If parts of the resulting range would point outside
+ // the sheet, don't complain but silently ignore and simply cut
+ // them away, this is what Xcl does :-/
+
+ // For the cut-away part we also don't need to determine the
+ // criteria match, so shrink the source range accordingly,
+ // instead of the result range.
+ SCCOL nColDelta = nCol2 - nCol1;
+ SCROW nRowDelta = nRow2 - nRow1;
+ SCCOL nMaxCol;
+ SCROW nMaxRow;
+ if (pSumExtraMatrix)
+ {
+ SCSIZE nC, nR;
+ pSumExtraMatrix->GetDimensions( nC, nR);
+ nMaxCol = static_cast<SCCOL>(nC - 1);
+ nMaxRow = static_cast<SCROW>(nR - 1);
+ }
+ else
+ {
+ nMaxCol = MAXCOL;
+ nMaxRow = MAXROW;
+ }
+ if (nCol3 + nColDelta > nMaxCol)
+ {
+ SCCOL nNewDelta = nMaxCol - nCol3;
+ nCol2 = nCol1 + nNewDelta;
+ }
+
+ if (nRow3 + nRowDelta > nMaxRow)
+ {
+ SCROW nNewDelta = nMaxRow - nRow3;
+ nRow2 = nRow1 + nNewDelta;
+ }
+ }
+ else
+ {
+ nCol3 = nCol1;
+ nRow3 = nRow1;
+ nTab3 = nTab1;
}
+
if (nGlobalError == 0)
{
ScQueryParam rParam;
@@ -4537,10 +4720,10 @@ void ScInterpreter::ScCountIf()
rParam.nRow2 = nRow2;
ScQueryEntry& rEntry = rParam.GetEntry(0);
- rEntry.bDoQuery = sal_True;
+ rEntry.bDoQuery = true;
if (!bIsString)
{
- rEntry.bQueryByString = sal_False;
+ rEntry.bQueryByString = false;
rEntry.nVal = fVal;
rEntry.eOp = SC_EQUAL;
}
@@ -4554,9 +4737,13 @@ void ScInterpreter::ScCountIf()
if ( rEntry.bQueryByString )
rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
}
+ ScAddress aAdr;
+ aAdr.SetTab( nTab3 );
rParam.nCol1 = nCol1;
rParam.nCol2 = nCol2;
rEntry.nField = nCol1;
+ SCsCOL nColDiff = nCol3 - nCol1;
+ SCsROW nRowDiff = nRow3 - nRow1;
if (pQueryMatrix)
{
// Never case-sensitive.
@@ -4564,87 +4751,148 @@ void ScInterpreter::ScCountIf()
ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
if (nGlobalError || !pResultMatrix)
{
- PushIllegalParameter();
- return;
+ SetError( errIllegalParameter);
}
- SCSIZE nSize = pResultMatrix->GetElementCount();
- for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
- {
- if (pResultMatrix->IsValue( nIndex) &&
- pResultMatrix->GetDouble( nIndex))
- ++fSum;
- }
- }
- else
- {
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
- // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
- aCellIter.SetAdvanceQueryParamEntryField( sal_True );
- if ( aCellIter.GetFirst() )
+ if (pSumExtraMatrix)
{
- do
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
{
- fSum++;
- } while ( aCellIter.GetNext() );
- }
- }
- }
- else
- {
- PushIllegalParameter();
- return;
- }
- }
- PushDouble(fSum);
- }
-}
-
-
-void ScInterpreter::ScSumIf()
-{
- RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumIf" );
- sal_uInt8 nParamCount = GetByte();
- if ( MustHaveParamCount( nParamCount, 2, 3 ) )
- {
- SCCOL nCol3 = 0;
- SCROW nRow3 = 0;
- SCTAB nTab3 = 0;
-
- ScMatrixRef pSumExtraMatrix;
- bool bSumExtraRange = (nParamCount == 3);
- if (bSumExtraRange)
- {
- // Save only the upperleft cell in case of cell range. The geometry
- // of the 3rd parameter is taken from the 1st parameter.
-
- switch ( GetStackType() )
- {
- case svDoubleRef :
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ if (pResultMatrix->IsValue( nCol, nRow) &&
+ pResultMatrix->GetDouble( nCol, nRow))
+ {
+ SCSIZE nC = nCol + nColDiff;
+ SCSIZE nR = nRow + nRowDiff;
+ if (pSumExtraMatrix->IsValue( nC, nR))
+ {
+ fVal = pSumExtraMatrix->GetDouble( nC, nR);
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = false;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ {
+ if (pResultMatrix->GetDouble( nCol, nRow))
+ {
+ aAdr.SetCol( nCol + nColDiff);
+ aAdr.SetRow( nRow + nRowDiff);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = false;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
{
- SCCOL nColJunk = 0;
- SCROW nRowJunk = 0;
- SCTAB nTabJunk = 0;
- PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
- if ( nTabJunk != nTab3 )
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
+ // Increment Entry.nField in iterator when switching to next column.
+ aCellIter.SetAdvanceQueryParamEntryField( true );
+ if ( aCellIter.GetFirst() )
{
- PushIllegalParameter();
- return;
+ if (pSumExtraMatrix)
+ {
+ do
+ {
+ SCSIZE nC = aCellIter.GetCol() + nColDiff;
+ SCSIZE nR = aCellIter.GetRow() + nRowDiff;
+ if (pSumExtraMatrix->IsValue( nC, nR))
+ {
+ fVal = pSumExtraMatrix->GetDouble( nC, nR);
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = false;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
+ else
+ {
+ do
+ {
+ aAdr.SetCol( aCellIter.GetCol() + nColDiff);
+ aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
+ {
+ bNull = false;
+ fMem = fVal;
+ }
+ else
+ fSum += fVal;
+ }
+ } while ( aCellIter.GetNext() );
+ }
}
}
- break;
- case svSingleRef :
- PopSingleRef( nCol3, nRow3, nTab3 );
- break;
- case svMatrix:
- pSumExtraMatrix = PopMatrix();
- //! nCol3, nRow3, nTab3 remain 0
- break;
- default:
- PushIllegalParameter();
- return ;
+ }
+ else
+ {
+ SetError( errIllegalParameter);
}
}
+
+ switch( eFunc )
+ {
+ case ifSUMIF: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
+ case ifAVERAGEIF: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
+ }
+ return fRes;
+ }
+ return 0;
+}
+
+void ScInterpreter::ScSumIf()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumIf" );
+ PushDouble( IterateParametersIf( ifSUMIF));
+}
+
+void ScInterpreter::ScAverageIf()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScAverageIf" );
+ PushDouble( IterateParametersIf( ifAVERAGEIF));
+}
+
+void ScInterpreter::ScCountIf()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountIf" );
+ if ( MustHaveParamCount( GetByte(), 2 ) )
+ {
String rString;
double fVal = 0.0;
sal_Bool bIsString = sal_True;
@@ -4685,26 +4933,22 @@ void ScInterpreter::ScSumIf()
}
}
break;
- case svString:
- rString = GetString();
- break;
case svMatrix :
{
- ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
- rString);
+ ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
bIsString = ScMatrix::IsNonValueType( nType);
}
break;
+ case svString:
+ rString = GetString();
+ break;
default:
{
fVal = GetDouble();
bIsString = sal_False;
}
}
-
- double fSum = 0.0;
- double fMem = 0.0;
- sal_Bool bNull = sal_True;
+ double fCount = 0.0;
short nParam = 1;
size_t nRefInList = 0;
while (nParam-- > 0)
@@ -4718,22 +4962,14 @@ void ScInterpreter::ScSumIf()
ScMatrixRef pQueryMatrix;
switch ( GetStackType() )
{
+ case svDoubleRef :
case svRefList :
- if (bSumExtraRange)
- {
- PushIllegalParameter();
- return;
- }
- else
{
ScRange aRange;
PopDoubleRef( aRange, nParam, nRefInList);
aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
}
break;
- case svDoubleRef :
- PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
- break;
case svSingleRef :
PopSingleRef( nCol1, nRow1, nTab1 );
nCol2 = nCol1;
@@ -4764,66 +5000,256 @@ void ScInterpreter::ScSumIf()
}
if ( nTab1 != nTab2 )
{
- PushIllegalArgument();
+ PushIllegalParameter();
return;
}
-
- if (bSumExtraRange)
+ if (nCol1 > nCol2)
{
- // Take the range geometry of the 1st parameter and apply it to
- // the 3rd. If parts of the resulting range would point outside
- // the sheet, don't complain but silently ignore and simply cut
- // them away, this is what Xcl does :-/
+ PushIllegalParameter();
+ return;
+ }
+ if (nGlobalError == 0)
+ {
+ ScQueryParam rParam;
+ rParam.nRow1 = nRow1;
+ rParam.nRow2 = nRow2;
- // For the cut-away part we also don't need to determine the
- // criteria match, so shrink the source range accordingly,
- // instead of the result range.
- SCCOL nColDelta = nCol2 - nCol1;
- SCROW nRowDelta = nRow2 - nRow1;
- SCCOL nMaxCol;
- SCROW nMaxRow;
- if (pSumExtraMatrix)
+ ScQueryEntry& rEntry = rParam.GetEntry(0);
+ rEntry.bDoQuery = sal_True;
+ if (!bIsString)
{
- SCSIZE nC, nR;
- pSumExtraMatrix->GetDimensions( nC, nR);
- nMaxCol = static_cast<SCCOL>(nC - 1);
- nMaxRow = static_cast<SCROW>(nR - 1);
+ rEntry.bQueryByString = sal_False;
+ rEntry.nVal = fVal;
+ rEntry.eOp = SC_EQUAL;
}
else
{
- nMaxCol = MAXCOL;
- nMaxRow = MAXROW;
+ rParam.FillInExcelSyntax(rString, 0);
+ sal_uInt32 nIndex = 0;
+ rEntry.bQueryByString =
+ !(pFormatter->IsNumberFormat(
+ *rEntry.pStr, nIndex, rEntry.nVal));
+ if ( rEntry.bQueryByString )
+ rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
}
- if (nCol3 + nColDelta > nMaxCol)
+ rParam.nCol1 = nCol1;
+ rParam.nCol2 = nCol2;
+ rEntry.nField = nCol1;
+ if (pQueryMatrix)
{
- SCCOL nNewDelta = nMaxCol - nCol3;
- nCol2 = nCol1 + nNewDelta;
- }
+ // Never case-sensitive.
+ ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
+ ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
+ if (nGlobalError || !pResultMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
- if (nRow3 + nRowDelta > nMaxRow)
+ SCSIZE nSize = pResultMatrix->GetElementCount();
+ for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
+ {
+ if (pResultMatrix->IsValue( nIndex) &&
+ pResultMatrix->GetDouble( nIndex))
+ ++fCount;
+ }
+ }
+ else
{
- SCROW nNewDelta = nMaxRow - nRow3;
- nRow2 = nRow1 + nNewDelta;
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
+ // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
+ aCellIter.SetAdvanceQueryParamEntryField( sal_True );
+ if ( aCellIter.GetFirst() )
+ {
+ do
+ {
+ fCount++;
+ } while ( aCellIter.GetNext() );
+ }
}
}
else
{
- nCol3 = nCol1;
- nRow3 = nRow1;
- nTab3 = nTab1;
+ PushIllegalParameter();
+ return;
}
+ }
+ PushDouble(fCount);
+ }
+}
+
+double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
+{
+ sal_uInt8 nParamCount = GetByte();
+ sal_uInt8 nQueryCount = nParamCount / 2;
+ bool bCheck;
+ if ( eFunc == ifCOUNTIFS )
+ bCheck = (nParamCount >= 2) && (nParamCount % 2 == 0);
+ else
+ bCheck = (nParamCount >= 3) && (nParamCount % 2 == 1);
+
+ if ( !bCheck )
+ {
+ SetError( errParameterExpected);
+ }
+ else
+ {
+ ScMatrixRef pResMat;
+ double fVal = 0.0;
+ double fSum = 0.0;
+ double fMem = 0.0;
+ double fRes = 0.0;
+ double fCount = 0.0;
+ short nParam = 1;
+ size_t nRefInList = 0;
+ SCCOL nDimensionCols = 0;
+ SCROW nDimensionRows = 0;
+
+ while (nParamCount > 1 && !nGlobalError)
+ {
+ // take criteria
+ String rString;
+ fVal = 0.0;
+ bool bIsString = true;
+ switch ( GetStackType() )
+ {
+ case svDoubleRef :
+ case svSingleRef :
+ {
+ ScAddress aAdr;
+ if ( !PopDoubleRefOrSingleRef( aAdr ) )
+ return 0;
+
+ ScBaseCell* pCell = GetCell( aAdr );
+ switch ( GetCellType( pCell ) )
+ {
+ case CELLTYPE_VALUE :
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = false;
+ break;
+ case CELLTYPE_FORMULA :
+ if( ((ScFormulaCell*)pCell)->IsValue() )
+ {
+ fVal = GetCellValue( aAdr, pCell );
+ bIsString = false;
+ }
+ else
+ GetCellString(rString, pCell);
+ break;
+ case CELLTYPE_STRING :
+ case CELLTYPE_EDIT :
+ GetCellString(rString, pCell);
+ break;
+ default:
+ fVal = 0.0;
+ bIsString = false;
+ }
+ }
+ break;
+ case svString:
+ rString = GetString();
+ break;
+ case svMatrix :
+ {
+ ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
+ bIsString = ScMatrix::IsNonValueType( nType);
+ }
+ break;
+ default:
+ {
+ fVal = GetDouble();
+ bIsString = false;
+ }
+ }
+
+ if (nGlobalError)
+ continue; // and bail out, no need to evaluate other arguments
+
+ // take range
+ nParam = 1;
+ nRefInList = 0;
+ SCCOL nCol1 = 0;
+ SCROW nRow1 = 0;
+ SCTAB nTab1 = 0;
+ SCCOL nCol2 = 0;
+ SCROW nRow2 = 0;
+ SCTAB nTab2 = 0;
+ ScMatrixRef pQueryMatrix;
+ switch ( GetStackType() )
+ {
+ case svRefList :
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange, nParam, nRefInList);
+ aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
+ }
+ break;
+ case svDoubleRef :
+ PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nCol1, nRow1, nTab1 );
+ nCol2 = nCol1;
+ nRow2 = nRow1;
+ nTab2 = nTab1;
+ break;
+ case svMatrix:
+ {
+ pQueryMatrix = PopMatrix();
+ if (!pQueryMatrix)
+ {
+ SetError( errIllegalParameter);
+ }
+ nCol1 = 0;
+ nRow1 = 0;
+ nTab1 = 0;
+ SCSIZE nC, nR;
+ pQueryMatrix->GetDimensions( nC, nR);
+ nCol2 = static_cast<SCCOL>(nC - 1);
+ nRow2 = static_cast<SCROW>(nR - 1);
+ nTab2 = 0;
+ }
+ break;
+ default:
+ SetError( errIllegalParameter);
+ }
+ if ( nTab1 != nTab2 )
+ SetError( errIllegalArgument);
+
+ // All reference ranges must be of same dimension and size.
+ if (!nDimensionCols)
+ nDimensionCols = nCol2 - nCol1 + 1;
+ if (!nDimensionRows)
+ nDimensionRows = nRow2 - nRow1 + 1;
+ if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
+ SetError ( errIllegalArgument);
+
+ // recalculate matrix values
if (nGlobalError == 0)
{
+ // initialize temporary result matrix
+ if (!pResMat)
+ {
+ SCSIZE nResC, nResR;
+ nResC = nCol2 - nCol1 + 1;
+ nResR = nRow2 - nRow1 + 1;
+ pResMat = GetNewMat(nResC, nResR);
+ if (!pResMat)
+ SetError( errIllegalParameter);
+ else
+ pResMat->FillDouble( 0.0, 0, 0, nResC-1, nResR-1);
+ }
+
ScQueryParam rParam;
rParam.nRow1 = nRow1;
rParam.nRow2 = nRow2;
ScQueryEntry& rEntry = rParam.GetEntry(0);
- rEntry.bDoQuery = sal_True;
+ rEntry.bDoQuery = true;
if (!bIsString)
{
- rEntry.bQueryByString = sal_False;
+ rEntry.bQueryByString = false;
rEntry.nVal = fVal;
rEntry.eOp = SC_EQUAL;
}
@@ -4838,12 +5264,12 @@ void ScInterpreter::ScSumIf()
rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
}
ScAddress aAdr;
- aAdr.SetTab( nTab3 );
+ aAdr.SetTab( nTab1 );
rParam.nCol1 = nCol1;
rParam.nCol2 = nCol2;
rEntry.nField = nCol1;
- SCsCOL nColDiff = nCol3 - nCol1;
- SCsROW nRowDiff = nRow3 - nRow1;
+ SCsCOL nColDiff = -nCol1;
+ SCsROW nRowDiff = -nRow1;
if (pQueryMatrix)
{
// Never case-sensitive.
@@ -4851,122 +5277,206 @@ void ScInterpreter::ScSumIf()
ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
if (nGlobalError || !pResultMatrix)
{
- PushIllegalParameter();
- return;
+ SetError( errIllegalParameter);
}
- if (pSumExtraMatrix)
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
{
- for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
{
- for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
+ if (pResultMatrix->IsValue( nCol, nRow) &&
+ pResultMatrix->GetDouble( nCol, nRow))
{
- if (pResultMatrix->IsValue( nCol, nRow) &&
- pResultMatrix->GetDouble( nCol, nRow))
- {
- SCSIZE nC = nCol + nColDiff;
- SCSIZE nR = nRow + nRowDiff;
- if (pSumExtraMatrix->IsValue( nC, nR))
- {
- fVal = pSumExtraMatrix->GetDouble( nC, nR);
- if ( bNull && fVal != 0.0 )
- {
- bNull = sal_False;
- fMem = fVal;
- }
- else
- fSum += fVal;
- }
- }
- }
- }
- }
- else
- {
- for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
- {
- for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
- {
- if (pResultMatrix->GetDouble( nCol, nRow))
- {
- aAdr.SetCol( nCol + nColDiff);
- aAdr.SetRow( nRow + nRowDiff);
- ScBaseCell* pCell = GetCell( aAdr );
- if ( HasCellValueData(pCell) )
- {
- fVal = GetCellValue( aAdr, pCell );
- if ( bNull && fVal != 0.0 )
- {
- bNull = sal_False;
- fMem = fVal;
- }
- else
- fSum += fVal;
- }
- }
+ SCSIZE nC = nCol + nColDiff;
+ SCSIZE nR = nRow + nRowDiff;
+ pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
}
}
}
}
else
{
- ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
+ ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
// Increment Entry.nField in iterator when switching to next column.
- aCellIter.SetAdvanceQueryParamEntryField( sal_True );
+ aCellIter.SetAdvanceQueryParamEntryField( true );
if ( aCellIter.GetFirst() )
{
- if (pSumExtraMatrix)
+ do
{
- do
+ SCSIZE nC = aCellIter.GetCol() + nColDiff;
+ SCSIZE nR = aCellIter.GetRow() + nRowDiff;
+ pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
+ } while ( aCellIter.GetNext() );
+ }
+ }
+ }
+ nParamCount -= 2;
+ }
+
+ if (nGlobalError)
+ return 0; // bail out
+
+ // main range - only for AVERAGEIFS and SUMIFS
+ if (nParamCount == 1)
+ {
+ nParam = 1;
+ nRefInList = 0;
+ bool bNull = true;
+ SCCOL nMainCol1 = 0;
+ SCROW nMainRow1 = 0;
+ SCTAB nMainTab1 = 0;
+ SCCOL nMainCol2 = 0;
+ SCROW nMainRow2 = 0;
+ SCTAB nMainTab2 = 0;
+ ScMatrixRef pMainMatrix;
+ switch ( GetStackType() )
+ {
+ case svRefList :
+ {
+ ScRange aRange;
+ PopDoubleRef( aRange, nParam, nRefInList);
+ aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
+ }
+ break;
+ case svDoubleRef :
+ PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
+ break;
+ case svSingleRef :
+ PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
+ nMainCol2 = nMainCol1;
+ nMainRow2 = nMainRow1;
+ nMainTab2 = nMainTab1;
+ break;
+ case svMatrix:
+ {
+ pMainMatrix = PopMatrix();
+ if (!pMainMatrix)
+ {
+ SetError( errIllegalParameter);
+ }
+ nMainCol1 = 0;
+ nMainRow1 = 0;
+ nMainTab1 = 0;
+ SCSIZE nC, nR;
+ pMainMatrix->GetDimensions( nC, nR);
+ nMainCol2 = static_cast<SCCOL>(nC - 1);
+ nMainRow2 = static_cast<SCROW>(nR - 1);
+ nMainTab2 = 0;
+ }
+ break;
+ default:
+ SetError( errIllegalParameter);
+ }
+ if ( nMainTab1 != nMainTab2 )
+ SetError( errIllegalArgument);
+
+ // All reference ranges must be of same dimension and size.
+ if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
+ SetError ( errIllegalArgument);
+
+ if (nGlobalError)
+ return 0; // bail out
+
+ // end-result calculation
+ ScAddress aAdr;
+ aAdr.SetTab( nMainTab1 );
+ if (pMainMatrix)
+ {
+ SCSIZE nC, nR;
+ pResMat->GetDimensions(nC, nR);
+ for (SCSIZE nCol = 0; nCol < nC; ++nCol)
+ {
+ for (SCSIZE nRow = 0; nRow < nR; ++nRow)
+ {
+ if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
+ {
+ if (pMainMatrix->IsValue( nCol, nRow))
{
- SCSIZE nC = aCellIter.GetCol() + nColDiff;
- SCSIZE nR = aCellIter.GetRow() + nRowDiff;
- if (pSumExtraMatrix->IsValue( nC, nR))
+ fVal = pMainMatrix->GetDouble( nCol, nRow);
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
{
- fVal = pSumExtraMatrix->GetDouble( nC, nR);
- if ( bNull && fVal != 0.0 )
- {
- bNull = sal_False;
- fMem = fVal;
- }
- else
- fSum += fVal;
+ bNull = false;
+ fMem = fVal;
}
- } while ( aCellIter.GetNext() );
+ else
+ fSum += fVal;
+ }
}
- else
+ }
+ }
+ }
+ else
+ {
+ SCSIZE nC, nR;
+ pResMat->GetDimensions(nC, nR);
+ for (SCSIZE nCol = 0; nCol < nC; ++nCol)
+ {
+ for (SCSIZE nRow = 0; nRow < nR; ++nRow)
+ {
+ if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
{
- do
+ aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
+ aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
+ ScBaseCell* pCell = GetCell( aAdr );
+ if ( HasCellValueData(pCell) )
{
- aAdr.SetCol( aCellIter.GetCol() + nColDiff);
- aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
- ScBaseCell* pCell = GetCell( aAdr );
- if ( HasCellValueData(pCell) )
+ fVal = GetCellValue( aAdr, pCell );
+ ++fCount;
+ if ( bNull && fVal != 0.0 )
{
- fVal = GetCellValue( aAdr, pCell );
- if ( bNull && fVal != 0.0 )
- {
- bNull = sal_False;
- fMem = fVal;
- }
- else
- fSum += fVal;
+ bNull = false;
+ fMem = fVal;
}
- } while ( aCellIter.GetNext() );
+ else
+ fSum += fVal;
+ }
}
}
}
}
- else
+ }
+ else
+ {
+ SCSIZE nC, nR;
+ pResMat->GetDimensions(nC, nR);
+ for (SCSIZE nCol = 0; nCol < nC; ++nCol)
{
- PushIllegalParameter();
- return;
+ for (SCSIZE nRow = 0; nRow < nR; ++nRow)
+ if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
+ ++fCount;
}
}
- PushDouble( ::rtl::math::approxAdd( fSum, fMem ) );
+
+ switch( eFunc )
+ {
+ case ifSUMIFS: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
+ case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
+ case ifCOUNTIFS: fRes = fCount; break;
+ default: ; // nothing
+ }
+ return fRes;
}
+ return 0;
}
+void ScInterpreter::ScSumIfs()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScSumIfs" );
+ PushDouble( IterateParametersIfs( ifSUMIFS));
+}
+
+void ScInterpreter::ScAverageIfs()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScAverageIfs" );
+ PushDouble( IterateParametersIfs( ifAVERAGEIFS));
+}
+
+void ScInterpreter::ScCountIfs()
+{
+ RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScCountIfs" );
+ PushDouble( IterateParametersIfs( ifCOUNTIFS));
+}
void ScInterpreter::ScLookup()
{
Modified: incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr4.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr4.cxx?rev=1386501&r1=1386500&r2=1386501&view=diff
==============================================================================
--- incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr4.cxx (original)
+++ incubator/ooo/branches/writer001/main/sc/source/core/tool/interpr4.cxx Mon Sep 17 08:06:09 2012
@@ -3446,6 +3446,7 @@ StackVar ScInterpreter::Interpret()
case ocGreaterEqual : ScGreaterEqual(); break;
case ocAnd : ScAnd(); break;
case ocOr : ScOr(); break;
+ case ocXor : ScXor(); break;
case ocIntersect : ScIntersect(); break;
case ocRange : ScRangeFunc(); break;
case ocUnion : ScUnionFunc(); break;
@@ -3621,6 +3622,10 @@ StackVar ScInterpreter::Interpret()
case ocCountEmptyCells : ScCountEmptyCells(); break;
case ocCountIf : ScCountIf(); break;
case ocSumIf : ScSumIf(); break;
+ case ocAverageIf : ScAverageIf(); break;
+ case ocSumIfs : ScSumIfs(); break;
+ case ocAverageIfs : ScAverageIfs(); break;
+ case ocCountIfs : ScCountIfs(); break;
case ocLookup : ScLookup(); break;
case ocVLookup : ScVLookup(); break;
case ocHLookup : ScHLookup(); break;
Modified: incubator/ooo/branches/writer001/main/sc/source/core/tool/parclass.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/writer001/main/sc/source/core/tool/parclass.cxx?rev=1386501&r1=1386500&r2=1386501&view=diff
==============================================================================
--- incubator/ooo/branches/writer001/main/sc/source/core/tool/parclass.cxx (original)
+++ incubator/ooo/branches/writer001/main/sc/source/core/tool/parclass.cxx Mon Sep 17 08:06:09 2012
@@ -48,154 +48,162 @@
* - OpCodes not specified at all will have at least one and only parameters of
* type Value, no check is done on the count of parameters => no Bounds type
* is returned.
- * - For OpCodes with a variable number of parameters the type of the last
- * parameter specified determines the type of all following parameters.
+ * - For OpCodes with a variable number of parameters the type(s) of the last
+ * repeated parameter(s) specified determine(s) the type(s) of all following
+ * parameters.
*/
const ScParameterClassification::RawData ScParameterClassification::pRawData[] =
{
+ // { OpCode, {{ Type, ... }, nRepeatLast }},
+
// IF() and CHOOSE() are somewhat special, since the ScJumpMatrix is
// created inside those functions and ConvertMatrixParameters() is not
// called for them.
- { ocIf, {{ Array, Reference, Reference }, false }},
- { ocChose, {{ Array, Reference }, true }},
+ { ocIf, {{ Array, Reference, Reference }, 0 }},
+ { ocChose, {{ Array, Reference }, 1 }},
// Other specials.
- { ocOpen, {{ Bounds }, false }},
- { ocClose, {{ Bounds }, false }},
- { ocSep, {{ Bounds }, false }},
- { ocNoName, {{ Bounds }, false }},
- { ocErrCell, {{ Bounds }, false }},
- { ocStop, {{ Bounds }, false }},
- { ocUnion, {{ Reference, Reference }, false }},
- { ocRange, {{ Reference, Reference }, false }},
+ { ocOpen, {{ Bounds }, 0 }},
+ { ocClose, {{ Bounds }, 0 }},
+ { ocSep, {{ Bounds }, 0 }},
+ { ocNoName, {{ Bounds }, 0 }},
+ { ocErrCell, {{ Bounds }, 0 }},
+ { ocStop, {{ Bounds }, 0 }},
+ { ocUnion, {{ Reference, Reference }, 0 }},
+ { ocRange, {{ Reference, Reference }, 0 }},
// Functions with Value parameters only but not in resource.
- { ocBackSolver, {{ Value, Value, Value }, false }},
- { ocTableOp, {{ Value, Value, Value, Value, Value }, false }},
+ { ocBackSolver, {{ Value, Value, Value }, 0 }},
+ { ocTableOp, {{ Value, Value, Value, Value, Value }, 0 }},
// Operators and functions.
- { ocAdd, {{ Array, Array }, false }},
- { ocAmpersand, {{ Array, Array }, false }},
- { ocAnd, {{ Reference }, true }},
- { ocAreas, {{ Reference }, false }},
- { ocAveDev, {{ Reference }, true }},
- { ocAverage, {{ Reference }, true }},
- { ocAverageA, {{ Reference }, true }},
- { ocCell, {{ Value, Reference }, false }},
- { ocColumn, {{ Reference }, false }},
- { ocColumns, {{ Reference }, true }},
- { ocCorrel, {{ ForceArray, ForceArray }, false }},
- { ocCount, {{ Reference }, true }},
- { ocCount2, {{ Reference }, true }},
- { ocCountEmptyCells, {{ Reference }, false }},
- { ocCountIf, {{ Reference, Value }, false }},
- { ocCovar, {{ ForceArray, ForceArray }, false }},
- { ocDBAverage, {{ Reference, Reference, Reference }, false }},
- { ocDBCount, {{ Reference, Reference, Reference }, false }},
- { ocDBCount2, {{ Reference, Reference, Reference }, false }},
- { ocDBGet, {{ Reference, Reference, Reference }, false }},
- { ocDBMax, {{ Reference, Reference, Reference }, false }},
- { ocDBMin, {{ Reference, Reference, Reference }, false }},
- { ocDBProduct, {{ Reference, Reference, Reference }, false }},
- { ocDBStdDev, {{ Reference, Reference, Reference }, false }},
- { ocDBStdDevP, {{ Reference, Reference, Reference }, false }},
- { ocDBSum, {{ Reference, Reference, Reference }, false }},
- { ocDBVar, {{ Reference, Reference, Reference }, false }},
- { ocDBVarP, {{ Reference, Reference, Reference }, false }},
- { ocDevSq, {{ Reference }, true }},
- { ocDiv, {{ Array, Array }, false }},
- { ocEqual, {{ Array, Array }, false }},
- { ocForecast, {{ Value, ForceArray, ForceArray }, false }},
- { ocFrequency, {{ Reference, Reference }, false }},
- { ocFTest, {{ ForceArray, ForceArray }, false }},
- { ocGeoMean, {{ Reference }, true }},
- { ocGCD, {{ Reference }, true }},
- { ocGreater, {{ Array, Array }, false }},
- { ocGreaterEqual, {{ Array, Array }, false }},
- { ocGrowth, {{ Reference, Reference, Reference, Value }, false }},
- { ocHarMean, {{ Reference }, true }},
- { ocHLookup, {{ Value, Reference, Value, Value }, false }},
- { ocIRR, {{ Reference, Value }, false }},
- { ocIndex, {{ Reference, Value, Value, Value }, false }},
- { ocIntercept, {{ ForceArray, ForceArray }, false }},
- { ocIntersect, {{ Reference, Reference }, false }},
- { ocIsRef, {{ Reference }, false }},
- { ocLCM, {{ Reference }, true }},
- { ocKurt, {{ Reference }, true }},
- { ocLarge, {{ Reference, Value }, false }},
- { ocLess, {{ Array, Array }, false }},
- { ocLessEqual, {{ Array, Array }, false }},
- { ocLookup, {{ Value, ReferenceOrForceArray, ReferenceOrForceArray }, false }},
- { ocMatch, {{ Value, Reference, Reference }, false }},
- { ocMatDet, {{ ForceArray }, false }},
- { ocMatInv, {{ ForceArray }, false }},
- { ocMatMult, {{ ForceArray, ForceArray }, false }},
- { ocMatTrans, {{ Array }, false }}, // strange, but Xcl doesn't force MatTrans array
- { ocMatValue, {{ Reference, Value, Value }, false }},
- { ocMax, {{ Reference }, true }},
- { ocMaxA, {{ Reference }, true }},
- { ocMedian, {{ Reference }, true }},
- { ocMin, {{ Reference }, true }},
- { ocMinA, {{ Reference }, true }},
- { ocMIRR, {{ Reference, Value, Value }, false }},
- { ocModalValue, {{ ForceArray }, true }},
- { ocMul, {{ Array, Array }, false }},
- { ocMultiArea, {{ Reference }, true }},
- { ocN, {{ Reference }, false }},
- { ocNPV, {{ Value, Reference }, true }},
- { ocNeg, {{ Array }, false }},
- { ocNegSub, {{ Array }, false }},
- { ocNot, {{ Array }, false }},
- { ocNotEqual, {{ Array, Array }, false }},
- { ocOffset, {{ Reference, Value, Value, Value, Value }, false }},
- { ocOr, {{ Reference }, true }},
- { ocPearson, {{ ForceArray, ForceArray }, false }},
- { ocPercentile, {{ Reference, Value }, false }},
- { ocPercentrank, {{ Reference, Value }, false }},
- { ocPow, {{ Array, Array }, false }},
- { ocPower, {{ Array, Array }, false }},
- { ocProb, {{ ForceArray, ForceArray, Value, Value }, false }},
- { ocProduct, {{ Reference }, true }},
- { ocQuartile, {{ Reference, Value }, false }},
- { ocRank, {{ Value, Reference, Value }, false }},
- { ocRGP, {{ Reference, Reference, Value, Value }, false }},
- { ocRKP, {{ Reference, Reference, Value, Value }, false }},
- { ocRow, {{ Reference }, false }},
- { ocRows, {{ Reference }, true }},
- { ocRSQ, {{ ForceArray, ForceArray }, false }},
- { ocSchiefe, {{ Reference }, true }},
- { ocSlope, {{ ForceArray, ForceArray }, false }},
- { ocSmall, {{ Reference, Value }, false }},
- { ocStDev, {{ Reference }, true }},
- { ocStDevA, {{ Reference }, true }},
- { ocStDevP, {{ Reference }, true }},
- { ocStDevPA, {{ Reference }, true }},
- { ocSTEYX, {{ ForceArray, ForceArray }, false }},
- { ocSub, {{ Array, Array }, false }},
- { ocSubTotal, {{ Value, Reference }, true }},
- { ocSum, {{ Reference }, true }},
- { ocSumIf, {{ Reference, Value, Reference }, false }},
- { ocSumProduct, {{ ForceArray }, true }},
- { ocSumSQ, {{ Reference }, true }},
- { ocSumX2MY2, {{ ForceArray, ForceArray }, false }},
- { ocSumX2DY2, {{ ForceArray, ForceArray }, false }},
- { ocSumXMY2, {{ ForceArray, ForceArray }, false }},
- { ocTable, {{ Reference }, false }},
- { ocTables, {{ Reference }, true }},
- { ocTrend, {{ Reference, Reference, Reference, Value }, false }},
- { ocTrimMean, {{ Reference, Value }, false }},
- { ocTTest, {{ ForceArray, ForceArray, Value, Value }, false }},
- { ocVar, {{ Reference }, true }},
- { ocVarA, {{ Reference }, true }},
- { ocVarP, {{ Reference }, true }},
- { ocVarPA, {{ Reference }, true }},
- { ocVLookup, {{ Value, Reference, Value, Value }, false }},
- { ocZTest, {{ Reference, Value, Value }, false }},
+ { ocAdd, {{ Array, Array }, 0 }},
+ { ocAmpersand, {{ Array, Array }, 0 }},
+ { ocAnd, {{ Reference }, 1 }},
+ { ocAreas, {{ Reference }, 0 }},
+ { ocAveDev, {{ Reference }, 1 }},
+ { ocAverage, {{ Reference }, 1 }},
+ { ocAverageA, {{ Reference }, 1 }},
+ { ocAverageIf, {{ Reference, Value, Reference }, 0 }},
+ { ocAverageIfs, {{ Reference, Reference, Value }, 2 }},
+ { ocCell, {{ Value, Reference }, 0 }},
+ { ocColumn, {{ Reference }, 0 }},
+ { ocColumns, {{ Reference }, 1 }},
+ { ocCorrel, {{ ForceArray, ForceArray }, 0 }},
+ { ocCount, {{ Reference }, 1 }},
+ { ocCount2, {{ Reference }, 1 }},
+ { ocCountEmptyCells, {{ Reference }, 0 }},
+ { ocCountIf, {{ Reference, Value }, 0 }},
+ { ocCountIfs, {{ Reference, Value }, 2 }},
+ { ocCovar, {{ ForceArray, ForceArray }, 0 }},
+ { ocDBAverage, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBCount, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBCount2, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBGet, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBMax, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBMin, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBProduct, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBStdDev, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBStdDevP, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBSum, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBVar, {{ Reference, Reference, Reference }, 0 }},
+ { ocDBVarP, {{ Reference, Reference, Reference }, 0 }},
+ { ocDevSq, {{ Reference }, 1 }},
+ { ocDiv, {{ Array, Array }, 0 }},
+ { ocEqual, {{ Array, Array }, 0 }},
+ { ocForecast, {{ Value, ForceArray, ForceArray }, 0 }},
+ { ocFrequency, {{ Reference, Reference }, 0 }},
+ { ocFTest, {{ ForceArray, ForceArray }, 0 }},
+ { ocGeoMean, {{ Reference }, 1 }},
+ { ocGCD, {{ Reference }, 1 }},
+ { ocGreater, {{ Array, Array }, 0 }},
+ { ocGreaterEqual, {{ Array, Array }, 0 }},
+ { ocGrowth, {{ Reference, Reference, Reference, Value }, 0 }},
+ { ocHarMean, {{ Reference }, 1 }},
+ { ocHLookup, {{ Value, Reference, Value, Value }, 0 }},
+ { ocIRR, {{ Reference, Value }, 0 }},
+ { ocIndex, {{ Reference, Value, Value, Value }, 0 }},
+ { ocIntercept, {{ ForceArray, ForceArray }, 0 }},
+ { ocIntersect, {{ Reference, Reference }, 0 }},
+ { ocIsRef, {{ Reference }, 0 }},
+ { ocLCM, {{ Reference }, 1 }},
+ { ocKurt, {{ Reference }, 1 }},
+ { ocLarge, {{ Reference, Value }, 0 }},
+ { ocLess, {{ Array, Array }, 0 }},
+ { ocLessEqual, {{ Array, Array }, 0 }},
+ { ocLookup, {{ Value, ReferenceOrForceArray, ReferenceOrForceArray }, 0 }},
+ { ocMatch, {{ Value, Reference, Reference }, 0 }},
+ { ocMatDet, {{ ForceArray }, 0 }},
+ { ocMatInv, {{ ForceArray }, 0 }},
+ { ocMatMult, {{ ForceArray, ForceArray }, 0 }},
+ { ocMatTrans, {{ Array }, 0 }}, // strange, but Xcl doesn't force MatTrans array
+ { ocMatValue, {{ Reference, Value, Value }, 0 }},
+ { ocMax, {{ Reference }, 1 }},
+ { ocMaxA, {{ Reference }, 1 }},
+ { ocMedian, {{ Reference }, 1 }},
+ { ocMin, {{ Reference }, 1 }},
+ { ocMinA, {{ Reference }, 1 }},
+ { ocMIRR, {{ Reference, Value, Value }, 0 }},
+ { ocModalValue, {{ ForceArray }, 1 }},
+ { ocMul, {{ Array, Array }, 0 }},
+ { ocMultiArea, {{ Reference }, 1 }},
+ { ocN, {{ Reference }, 0 }},
+ { ocNPV, {{ Value, Reference }, 1 }},
+ { ocNeg, {{ Array }, 0 }},
+ { ocNegSub, {{ Array }, 0 }},
+ { ocNot, {{ Array }, 0 }},
+ { ocNotEqual, {{ Array, Array }, 0 }},
+ { ocOffset, {{ Reference, Value, Value, Value, Value }, 0 }},
+ { ocOr, {{ Reference }, 1 }},
+ { ocPearson, {{ ForceArray, ForceArray }, 0 }},
+ { ocPercentile, {{ Reference, Value }, 0 }},
+ { ocPercentrank, {{ Reference, Value }, 0 }},
+ { ocPow, {{ Array, Array }, 0 }},
+ { ocPower, {{ Array, Array }, 0 }},
+ { ocProb, {{ ForceArray, ForceArray, Value, Value }, 0 }},
+ { ocProduct, {{ Reference }, 1 }},
+ { ocQuartile, {{ Reference, Value }, 0 }},
+ { ocRank, {{ Value, Reference, Value }, 0 }},
+ { ocRGP, {{ Reference, Reference, Value, Value }, 0 }},
+ { ocRKP, {{ Reference, Reference, Value, Value }, 0 }},
+ { ocRow, {{ Reference }, 0 }},
+ { ocRows, {{ Reference }, 1 }},
+ { ocRSQ, {{ ForceArray, ForceArray }, 0 }},
+ { ocSchiefe, {{ Reference }, 1 }},
+ { ocSlope, {{ ForceArray, ForceArray }, 0 }},
+ { ocSmall, {{ Reference, Value }, 0 }},
+ { ocStDev, {{ Reference }, 1 }},
+ { ocStDevA, {{ Reference }, 1 }},
+ { ocStDevP, {{ Reference }, 1 }},
+ { ocStDevPA, {{ Reference }, 1 }},
+ { ocSTEYX, {{ ForceArray, ForceArray }, 0 }},
+ { ocSub, {{ Array, Array }, 0 }},
+ { ocSubTotal, {{ Value, Reference }, 1 }},
+ { ocSum, {{ Reference }, 1 }},
+ { ocSumIf, {{ Reference, Value, Reference }, 0 }},
+ { ocSumIfs, {{ Reference, Reference, Value }, 2 }},
+ { ocSumProduct, {{ ForceArray }, 1 }},
+ { ocSumSQ, {{ Reference }, 1 }},
+ { ocSumX2MY2, {{ ForceArray, ForceArray }, 0 }},
+ { ocSumX2DY2, {{ ForceArray, ForceArray }, 0 }},
+ { ocSumXMY2, {{ ForceArray, ForceArray }, 0 }},
+ { ocTable, {{ Reference }, 0 }},
+ { ocTables, {{ Reference }, 1 }},
+ { ocTrend, {{ Reference, Reference, Reference, Value }, 0 }},
+ { ocTrimMean, {{ Reference, Value }, 0 }},
+ { ocTTest, {{ ForceArray, ForceArray, Value, Value }, 0 }},
+ { ocVar, {{ Reference }, 1 }},
+ { ocVarA, {{ Reference }, 1 }},
+ { ocVarP, {{ Reference }, 1 }},
+ { ocVarPA, {{ Reference }, 1 }},
+ { ocVLookup, {{ Value, Reference, Value, Value }, 0 }},
+ { ocXor, {{ Reference }, 1 }},
+ { ocZTest, {{ Reference, Value, Value }, 0 }},
// Excel doubts:
// ocT: Excel says (and handles) Reference, error? This means no position
// dependent SingleRef if DoubleRef, and no array calculation, just the
// upper left corner. We never did that.
- { ocT, {{ Value }, false }},
+ { ocT, {{ Value }, 0 }},
// The stopper.
- { ocNone, {{ Bounds }, false } }
+ { ocNone, {{ Bounds }, 0 } }
};
ScParameterClassification::RunData * ScParameterClassification::pData = NULL;
@@ -227,18 +235,19 @@ void ScParameterClassification::Init()
#endif
memcpy( &(pRun->aData), &(pRaw->aData), sizeof(CommonData));
// fill 0-initialized fields with real values
- if ( pRun->aData.bRepeatLast )
+ if ( pRun->aData.nRepeatLast )
{
- Type eLast = Unknown;
for ( size_t j=0; j < CommonData::nMaxParams; ++j )
{
if ( pRun->aData.nParam[j] )
- {
- eLast = pRun->aData.nParam[j];
pRun->nMinParams = sal::static_int_cast<sal_uInt8>( j+1 );
- }
+ else if (j >= pRun->aData.nRepeatLast)
+ pRun->aData.nParam[j] = pRun->aData.nParam[j - pRun->aData.nRepeatLast];
else
- pRun->aData.nParam[j] = eLast;
+ {
+ DBG_ERROR2( "bad classification: eOp %d, repeated param %d negative offset", pRaw->eOp, j);
+ pRun->aData.nParam[j] = Unknown;
+ }
}
}
else
@@ -299,15 +308,23 @@ ScParameterClassification::Type ScParame
}
if ( 0 <= (short)eOp && eOp <= SC_OPCODE_LAST_OPCODE_ID )
{
+ sal_uInt8 nRepeat;
+ Type eType;
if ( nParameter < CommonData::nMaxParams )
+ eType = pData[eOp].aData.nParam[nParameter];
+ else if ( (nRepeat = pData[eOp].aData.nRepeatLast) > 0 )
{
- Type eT = pData[eOp].aData.nParam[nParameter];
- return eT == Unknown ? Value : eT;
+ // The usual case is 1 repeated parameter, we don't need to
+ // calculate that on each call.
+ sal_uInt16 nParam = (nRepeat > 1 ?
+ (pData[eOp].nMinParams -
+ ((nParameter - pData[eOp].nMinParams) % nRepeat)) :
+ pData[eOp].nMinParams);
+ return pData[eOp].aData.nParam[nParam];
}
- else if ( pData[eOp].aData.bRepeatLast )
- return pData[eOp].aData.nParam[CommonData::nMaxParams-1];
else
- return Bounds;
+ eType = Bounds;
+ return eType == Unknown ? Value : eType;
}
return Unknown;
}
@@ -402,25 +419,30 @@ void ScParameterClassification::MergeArg
RunData* pRun = &pData[ pDesc->nFIndex ];
sal_uInt16 nArgs = pDesc->GetSuppressedArgCount();
- if ( nArgs >= VAR_ARGS )
+ if ( nArgs >= PAIRED_VAR_ARGS )
+ {
+ nArgs -= PAIRED_VAR_ARGS - 2;
+ pRun->aData.nRepeatLast = 2;
+ }
+ else if ( nArgs >= VAR_ARGS )
{
nArgs -= VAR_ARGS - 1;
- pRun->aData.bRepeatLast = true;
+ pRun->aData.nRepeatLast = 1;
}
if ( nArgs > CommonData::nMaxParams )
{
DBG_ERROR2( "ScParameterClassification::Init: too many arguments in listed function: %s: %d",
ByteString( *(pDesc->pFuncName),
RTL_TEXTENCODING_UTF8).GetBuffer(), nArgs);
- nArgs = CommonData::nMaxParams;
- pRun->aData.bRepeatLast = true;
+ nArgs = CommonData::nMaxParams - 1;
+ pRun->aData.nRepeatLast = 1;
}
pRun->nMinParams = static_cast< sal_uInt8 >( nArgs );
for ( size_t j=0; j < nArgs; ++j )
{
pRun->aData.nParam[j] = Value;
}
- if ( pRun->aData.bRepeatLast )
+ if ( pRun->aData.nRepeatLast )
{
for ( size_t j = nArgs; j < CommonData::nMaxParams; ++j )
{