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:
friend class ScDocument; // for FillInfo
friend class ScDocumentIterator;
friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator;
friend class ScColumnIterator;
friend class ScQueryCellIterator;
......
......@@ -425,6 +425,7 @@ private:
SCTAB nTab;
SCCOL nStartCol;
SCCOL nEndCol;
SCROW nStartRow;
SCROW nEndRow;
SCROW* pNextRows;
SCSIZE* pNextIndices;
......@@ -439,12 +440,47 @@ public:
ScBaseCell* GetNext( SCCOL& rCol, SCROW& rRow );
sal_Bool ReturnNext( SCCOL& rCol, SCROW& rRow );
/// Set a(nother) sheet and (re)init.
void SetTab( SCTAB nTab );
private:
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)
//
......
......@@ -212,6 +212,7 @@ class ScDocument
{
friend class ScDocumentIterator;
friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator;
friend class ScCellIterator;
friend class ScQueryCellIterator;
......
......@@ -185,6 +185,7 @@ private:
friend class ScDocument; // for FillInfo
friend class ScDocumentIterator;
friend class ScValueIterator;
friend class ScHorizontalValueIterator;
friend class ScDBQueryDataIterator;
friend class ScCellIterator;
friend class ScQueryCellIterator;
......
......@@ -1666,6 +1666,7 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
nTab( nTable ),
nStartCol( nCol1 ),
nEndCol( nCol2 ),
nStartRow( nRow1 ),
nEndRow( nRow2 ),
nCol( nCol1 ),
nRow( nRow1 ),
......@@ -1673,17 +1674,32 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
{
if (nTab >= pDoc->GetTableCount())
OSL_FAIL("try to access index out of bounds, FIX IT");
SCCOL i;
SCSIZE nIndex;
pNextRows = new SCROW[ 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];
pCol->Search( nRow1, nIndex );
SCSIZE nIndex;
pCol->Search( nStartRow, nIndex );
if ( nIndex < pCol->nCount )
{
pNextRows[i-nStartCol] = pCol->pItems[nIndex].nRow;
......@@ -1696,16 +1712,10 @@ ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument* pDocument, SCTAB
}
}
if (pNextRows[0] != nRow1)
if (pNextRows[0] != nStartRow)
Advance();
}
ScHorizontalCellIterator::~ScHorizontalCellIterator()
{
delete [] pNextRows;
delete [] pNextIndices;
}
ScBaseCell* ScHorizontalCellIterator::GetNext( SCCOL& rCol, SCROW& rRow )
{
if ( bMore )
......@@ -1775,6 +1785,156 @@ void ScHorizontalCellIterator::Advance()
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,
......
......@@ -654,8 +654,15 @@ void ScInterpreter::ScNPV()
break;
case svSingleRef :
{
nVal += (GetDouble() / pow(1.0 + nZins, (double)nCount));
nCount++;
ScAddress aAdr;
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;
case svDoubleRef :
......@@ -664,18 +671,14 @@ void ScInterpreter::ScNPV()
sal_uInt16 nErr = 0;
double nCellVal;
PopDoubleRef( aRange, nParamCount, nRefInList);
ScValueIterator aValIter(pDok, aRange, glSubTotal);
if (aValIter.GetFirst(nCellVal, nErr))
ScHorizontalValueIterator aValIter( pDok, aRange, glSubTotal);
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
{
nVal += (nCellVal / pow(1.0 + nZins, (double)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;
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