Kaydet (Commit) 4775df29 authored tarafından Eike Rathke's avatar Eike Rathke

dr78: #i92774# NPV evaluates arguments row-wise; ScHorizontalValueIterator

patch from <lvyue> with little modifications

# HG changeset patch
# User Eike Rathke [er] <eike.rathke@oracle.com>
# Date 1291410557 -3600
# Node ID 297b5255c27a9fa541bed948d675bba1c4d87ab0
# Parent  ce99b09497844a0d893ab78cb15a2749fcc932bf
üst fed1ed19
...@@ -115,6 +115,7 @@ private: ...@@ -115,6 +115,7 @@ private:
friend class ScDocument; // for FillInfo friend class ScDocument; // for FillInfo
friend class ScDocumentIterator; friend class ScDocumentIterator;
friend class ScValueIterator; friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator; friend class ScDBQueryDataIterator;
friend class ScColumnIterator; friend class ScColumnIterator;
friend class ScQueryCellIterator; friend class ScQueryCellIterator;
......
...@@ -425,6 +425,7 @@ private: ...@@ -425,6 +425,7 @@ private:
SCTAB nTab; SCTAB nTab;
SCCOL nStartCol; SCCOL nStartCol;
SCCOL nEndCol; SCCOL nEndCol;
SCROW nStartRow;
SCROW nEndRow; SCROW nEndRow;
SCROW* pNextRows; SCROW* pNextRows;
SCSIZE* pNextIndices; SCSIZE* pNextIndices;
...@@ -439,12 +440,47 @@ public: ...@@ -439,12 +440,47 @@ public:
ScBaseCell* GetNext( SCCOL& rCol, SCROW& rRow ); ScBaseCell* GetNext( SCCOL& rCol, SCROW& rRow );
sal_Bool ReturnNext( SCCOL& rCol, SCROW& rRow ); sal_Bool ReturnNext( SCCOL& rCol, SCROW& rRow );
/// Set a(nother) sheet and (re)init.
void SetTab( SCTAB nTab );
private: private:
void Advance(); void Advance();
}; };
/** Row-wise value iterator. */
class ScHorizontalValueIterator
{
private:
ScDocument *pDoc;
const ScAttrArray *pAttrArray;
ScHorizontalCellIterator *pCellIter;
sal_uLong nNumFormat; // for CalcAsShown
sal_uLong nNumFmtIndex;
SCTAB nEndTab;
SCCOL nCurCol;
SCROW nCurRow;
SCTAB nCurTab;
SCROW nAttrEndRow;
short nNumFmtType;
bool bNumValid;
bool bSubTotal;
bool bCalcAsShown;
bool bTextAsZero;
public:
ScHorizontalValueIterator( ScDocument* pDocument,
const ScRange& rRange,
bool bSTotal = false,
bool bTextAsZero = false );
~ScHorizontalValueIterator();
void GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
/// Does NOT reset rValue if no value found!
bool GetNext( double& rValue, sal_uInt16& rErr );
};
// //
// returns all areas with non-default formatting (horizontal) // returns all areas with non-default formatting (horizontal)
// //
......
...@@ -212,6 +212,7 @@ class ScDocument ...@@ -212,6 +212,7 @@ class ScDocument
{ {
friend class ScDocumentIterator; friend class ScDocumentIterator;
friend class ScValueIterator; friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator; friend class ScDBQueryDataIterator;
friend class ScCellIterator; friend class ScCellIterator;
friend class ScQueryCellIterator; friend class ScQueryCellIterator;
......
...@@ -185,6 +185,7 @@ private: ...@@ -185,6 +185,7 @@ private:
friend class ScDocument; // for FillInfo friend class ScDocument; // for FillInfo
friend class ScDocumentIterator; friend class ScDocumentIterator;
friend class ScValueIterator; friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator; friend class ScDBQueryDataIterator;
friend class ScCellIterator; friend class ScCellIterator;
friend class ScQueryCellIterator; friend class ScQueryCellIterator;
......
...@@ -1666,6 +1666,7 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB ...@@ -1666,6 +1666,7 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
nTab( nTable ), nTab( nTable ),
nStartCol( nCol1 ), nStartCol( nCol1 ),
nEndCol( nCol2 ), nEndCol( nCol2 ),
nStartRow( nRow1 ),
nEndRow( nRow2 ), nEndRow( nRow2 ),
nCol( nCol1 ), nCol( nCol1 ),
nRow( nRow1 ), nRow( nRow1 ),
...@@ -1673,17 +1674,32 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB ...@@ -1673,17 +1674,32 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
{ {
if (nTab >= pDoc->GetTableCount()) if (nTab >= pDoc->GetTableCount())
OSL_FAIL("try to access index out of bounds, FIX IT"); OSL_FAIL("try to access index out of bounds, FIX IT");
SCCOL i;
SCSIZE nIndex;
pNextRows = new SCROW[ nCol2-nCol1+1 ]; pNextRows = new SCROW[ nCol2-nCol1+1 ];
pNextIndices = new SCSIZE[ nCol2-nCol1+1 ]; pNextIndices = new SCSIZE[ nCol2-nCol1+1 ];
for (i=nStartCol; i<=nEndCol; i++) SetTab( nTab );
}
ScHorizontalCellIterator::~ScHorizontalCellIterator()
{
delete [] pNextRows;
delete [] pNextIndices;
}
void ScHorizontalCellIterator::SetTab( SCTAB nTabP )
{
nTab = nTabP;
nRow = nStartRow;
nCol = nStartCol;
bMore = true;
for (SCCOL i=nStartCol; i<=nEndCol; i++)
{ {
ScColumn* pCol = &pDoc->maTabs[nTab]->aCol[i]; ScColumn* pCol = &pDoc->maTabs[nTab]->aCol[i];
pCol->Search( nRow1, nIndex ); SCSIZE nIndex;
pCol->Search( nStartRow, nIndex );
if ( nIndex < pCol->nCount ) if ( nIndex < pCol->nCount )
{ {
pNextRows[i-nStartCol] = pCol->pItems[nIndex].nRow; pNextRows[i-nStartCol] = pCol->pItems[nIndex].nRow;
...@@ -1696,16 +1712,10 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB ...@@ -1696,16 +1712,10 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
} }
} }
if (pNextRows[0] != nRow1) if (pNextRows[0] != nStartRow)
Advance(); Advance();
} }
ScHorizontalCellIterator::~ScHorizontalCellIterator()
{
delete [] pNextRows;
delete [] pNextIndices;
}
ScBaseCell* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow ) ScBaseCell* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow )
{ {
if ( bMore ) if ( bMore )
...@@ -1775,6 +1785,156 @@ void ScHorizontalCellIterator::Advance() ...@@ -1775,6 +1785,156 @@ void ScHorizontalCellIterator::Advance()
bMore = false; bMore = false;
} }
//------------------------------------------------------------------------
ScHorizontalValueIterator::ScHorizontalValueIterator( ScDocument* pDocument,
const ScRange& rRange, bool bSTotal, bool bTextZero ) :
pDoc( pDocument ),
nNumFmtIndex(0),
nEndTab( rRange.aEnd.Tab() ),
nNumFmtType( NUMBERFORMAT_UNDEFINED ),
bNumValid( false ),
bSubTotal( bSTotal ),
bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
bTextAsZero( bTextZero )
{
SCCOL nStartCol = rRange.aStart.Col();
SCROW nStartRow = rRange.aStart.Row();
SCTAB nStartTab = rRange.aStart.Tab();
SCCOL nEndCol = rRange.aEnd.Col();
SCROW nEndRow = rRange.aEnd.Row();
PutInOrder( nStartCol, nEndCol);
PutInOrder( nStartRow, nEndRow);
PutInOrder( nStartTab, nEndTab );
if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
if (!ValidRow(nStartRow)) nStartRow = MAXROW;
if (!ValidRow(nEndRow)) nEndRow = MAXROW;
if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
nCurCol = nStartCol;
nCurRow = nStartRow;
nCurTab = nStartTab;
nNumFormat = 0; // will be initialized in GetNumberFormat()
pAttrArray = 0;
nAttrEndRow = 0;
pCellIter = new ScHorizontalCellIterator( pDoc, nStartTab, nStartCol,
nStartRow, nEndCol, nEndRow );
}
ScHorizontalValueIterator::~ScHorizontalValueIterator()
{
delete pCellIter;
}
bool ScHorizontalValueIterator::GetNext( double& rValue, sal_uInt16& rErr )
{
bool bFound = false;
while ( !bFound )
{
ScBaseCell* pCell = pCellIter->GetNext( nCurCol, nCurRow );
while ( !pCell )
{
if ( nCurTab < nEndTab )
{
pCellIter->SetTab( ++nCurTab);
pCell = pCellIter->GetNext( nCurCol, nCurRow );
}
else
return false;
}
if ( !bSubTotal || !pDoc->maTabs[nCurTab]->RowFiltered( nCurRow ) )
{
switch (pCell->GetCellType())
{
case CELLTYPE_VALUE:
{
bNumValid = false;
rValue = ((ScValueCell*)pCell)->GetValue();
rErr = 0;
if ( bCalcAsShown )
{
ScColumn* pCol = &pDoc->maTabs[nCurTab]->aCol[nCurCol];
lcl_IterGetNumberFormat( nNumFormat, pAttrArray,
nAttrEndRow, pCol->pAttrArray, nCurRow, pDoc );
rValue = pDoc->RoundValueAsShown( rValue, nNumFormat );
}
bFound = true;
}
break;
case CELLTYPE_FORMULA:
{
if (!bSubTotal || !((ScFormulaCell*)pCell)->IsSubTotal())
{
rErr = ((ScFormulaCell*)pCell)->GetErrCode();
if ( rErr || ((ScFormulaCell*)pCell)->IsValue() )
{
rValue = ((ScFormulaCell*)pCell)->GetValue();
bNumValid = false;
bFound = true;
}
else if ( bTextAsZero )
{
rValue = 0.0;
bNumValid = false;
bFound = true;
}
}
}
break;
case CELLTYPE_STRING :
case CELLTYPE_EDIT :
{
if ( bTextAsZero )
{
rErr = 0;
rValue = 0.0;
nNumFmtType = NUMBERFORMAT_NUMBER;
nNumFmtIndex = 0;
bNumValid = true;
bFound = true;
}
}
break;
default:
; // nothing
}
}
}
return bFound;
}
void ScHorizontalValueIterator::GetCurNumFmtInfo( short& nType, sal_uLong& nIndex )
{
if (!bNumValid)
{
const ScColumn* pCol = &(pDoc->maTabs[nCurTab])->aCol[nCurCol];
nNumFmtIndex = pCol->GetNumberFormat( nCurRow );
if ( (nNumFmtIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
{
const ScBaseCell* pCell;
SCSIZE nCurIndex;
if ( pCol->Search( nCurRow, nCurIndex ) )
pCell = pCol->pItems[nCurIndex].pCell;
else
pCell = NULL;
if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
((const ScFormulaCell*)pCell)->GetFormatInfo( nNumFmtType, nNumFmtIndex );
else
nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
}
else
nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
bNumValid = true;
}
nType = nNumFmtType;
nIndex = nNumFmtIndex;
}
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable, ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable,
......
...@@ -654,8 +654,15 @@ void ScInterpreter::ScNPV() ...@@ -654,8 +654,15 @@ void ScInterpreter::ScNPV()
break; break;
case svSingleRef : case svSingleRef :
{ {
nVal += (GetDouble() / pow(1.0 + nZins, (double)nCount)); ScAddress aAdr;
nCount++; PopSingleRef( aAdr );
ScBaseCell* pCell = GetCell( aAdr );
if (!HasCellEmptyData(pCell) && HasCellValueData(pCell))
{
double nCellVal = GetCellValue( aAdr, pCell );
nVal += (nCellVal / pow(1.0 + nZins, (double)nCount));
nCount++;
}
} }
break; break;
case svDoubleRef : case svDoubleRef :
...@@ -664,18 +671,14 @@ void ScInterpreter::ScNPV() ...@@ -664,18 +671,14 @@ void ScInterpreter::ScNPV()
sal_uInt16 nErr = 0; sal_uInt16 nErr = 0;
double nCellVal; double nCellVal;
PopDoubleRef( aRange, nParamCount, nRefInList); PopDoubleRef( aRange, nParamCount, nRefInList);
ScValueIterator aValIter(pDok, aRange, glSubTotal); ScHorizontalValueIterator aValIter( pDok, aRange, glSubTotal);
if (aValIter.GetFirst(nCellVal, nErr)) while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
{ {
nVal += (nCellVal / pow(1.0 + nZins, (double)nCount)); nVal += (nCellVal / pow(1.0 + nZins, (double)nCount));
nCount++; nCount++;
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
{
nVal += (nCellVal / pow(1.0 + nZins, (double)nCount));
nCount++;
}
SetError(nErr);
} }
if ( nErr != 0 )
SetError(nErr);
} }
break; break;
default : SetError(errIllegalParameter); break; default : SetError(errIllegalParameter); break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment