Properly invalidate cached sheet XML streams during reference update.
Failure to invalidate sheet streams during reference update caused formula cross referenceing between sheets to totallly get borked. The bug was originally reported in i#116833.
This commit is contained in:
parent
ecce776df1
commit
31dbdd1766
7 changed files with 58 additions and 12 deletions
|
@ -440,7 +440,7 @@ public:
|
|||
BOOL HasRelNameReference() const;
|
||||
BOOL HasColRowName() const;
|
||||
|
||||
void UpdateReference(UpdateRefMode eUpdateRefMode,
|
||||
bool UpdateReference(UpdateRefMode eUpdateRefMode,
|
||||
const ScRange& r,
|
||||
SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
|
||||
ScDocument* pUndoDoc = NULL,
|
||||
|
|
|
@ -285,7 +285,7 @@ public:
|
|||
|
||||
void ResetChanged( SCROW nStartRow, SCROW nEndRow );
|
||||
|
||||
void UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
|
||||
bool UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
|
||||
SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
|
||||
SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
|
||||
ScDocument* pUndoDoc = NULL );
|
||||
|
|
|
@ -946,14 +946,12 @@ void Test::testStreamValid()
|
|||
pCell = m_pDoc->GetCell(ScAddress(0, 2, 0));
|
||||
CPPUNIT_ASSERT_MESSAGE("Cell A3 should be empty.", pCell == NULL);
|
||||
|
||||
#if 0 // This currently fails.
|
||||
// After the move, Sheet1, Sheet2, and Sheet4 should have their stream
|
||||
// invalidated, whereas Sheet3's stream should still be valid.
|
||||
CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(0));
|
||||
CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(1));
|
||||
CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(3));
|
||||
CPPUNIT_ASSERT_MESSAGE("Stream should still be valid.", m_pDoc->IsStreamValid(2));
|
||||
#endif
|
||||
|
||||
m_pDoc->DeleteTab(3);
|
||||
m_pDoc->DeleteTab(2);
|
||||
|
|
|
@ -825,11 +825,13 @@ BOOL ScFormulaCell::HasColRowName() const
|
|||
return (pCode->GetNextColRowName() != NULL);
|
||||
}
|
||||
|
||||
void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
||||
bool ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
||||
const ScRange& r,
|
||||
SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
|
||||
ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
|
||||
{
|
||||
bool bCellStateChanged = false;
|
||||
|
||||
SCCOL nCol1 = r.aStart.Col();
|
||||
SCROW nRow1 = r.aStart.Row();
|
||||
SCTAB nTab1 = r.aStart.Tab();
|
||||
|
@ -858,6 +860,7 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
|||
nCol = 0;
|
||||
else if ( nCol > MAXCOL )
|
||||
nCol = MAXCOL;
|
||||
bCellStateChanged = aPos.Col() != nCol;
|
||||
aPos.SetCol( nCol );
|
||||
}
|
||||
}
|
||||
|
@ -871,6 +874,7 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
|||
nRow = 0;
|
||||
else if ( nRow > MAXROW )
|
||||
nRow = MAXROW;
|
||||
bCellStateChanged = aPos.Row() != nRow;
|
||||
aPos.SetRow( nRow );
|
||||
}
|
||||
}
|
||||
|
@ -885,6 +889,7 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
|||
nTab = 0;
|
||||
else if ( nTab > nMaxTab )
|
||||
nTab = nMaxTab;
|
||||
bCellStateChanged = aPos.Tab() != nTab;
|
||||
aPos.SetTab( nTab );
|
||||
}
|
||||
}
|
||||
|
@ -912,8 +917,8 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
|||
if( bHasRefs || bOnRefMove )
|
||||
{
|
||||
ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
|
||||
bool bValChanged = false;
|
||||
ScRangeData* pRangeData;
|
||||
bool bValChanged = false;
|
||||
bool bRangeModified = false; // any range, not only shared formula
|
||||
bool bRefSizeChanged = false;
|
||||
if ( bHasRefs )
|
||||
|
@ -932,6 +937,9 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
|||
bRangeModified = false;
|
||||
bRefSizeChanged = false;
|
||||
}
|
||||
|
||||
bCellStateChanged |= bValChanged;
|
||||
|
||||
if ( bOnRefMove )
|
||||
bOnRefMove = (bValChanged || (aPos != aOldPos));
|
||||
// Cell may reference itself, e.g. ocColumn, ocRow without parameter
|
||||
|
@ -1118,6 +1126,7 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
|
|||
|
||||
delete pOld;
|
||||
}
|
||||
return bCellStateChanged;
|
||||
}
|
||||
|
||||
void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
|
||||
|
|
|
@ -1617,10 +1617,11 @@ void ScColumn::MoveTo(SCROW nStartRow, SCROW nEndRow, ScColumn& rCol)
|
|||
}
|
||||
|
||||
|
||||
void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
|
||||
bool ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
|
||||
SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
|
||||
ScDocument* pUndoDoc )
|
||||
{
|
||||
bool bUpdated = false;
|
||||
if (pItems)
|
||||
{
|
||||
ScRange aRange( ScAddress( nCol1, nRow1, nTab1 ),
|
||||
|
@ -1632,7 +1633,8 @@ void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
{
|
||||
ScFormulaCell* pCell = (ScFormulaCell*) pItems[nIndex].pCell;
|
||||
if( pCell->GetCellType() == CELLTYPE_FORMULA)
|
||||
pCell->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
|
||||
bUpdated |= pCell->UpdateReference(
|
||||
eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1653,7 +1655,8 @@ void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
ScBaseCell* pCell = pItems[i].pCell;
|
||||
if( pCell->GetCellType() == CELLTYPE_FORMULA)
|
||||
{
|
||||
((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
|
||||
bUpdated |= ((ScFormulaCell*)pCell)->UpdateReference(
|
||||
eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc );
|
||||
if ( nRow != pItems[i].nRow )
|
||||
Search( nRow, i ); // Listener removed/inserted?
|
||||
}
|
||||
|
@ -1671,7 +1674,8 @@ void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
// When deleting rows on several sheets, the formula's position may be updated with the first call,
|
||||
// so the undo position must be passed from here.
|
||||
ScAddress aUndoPos( nCol, nRow, nTab );
|
||||
((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos );
|
||||
bUpdated |= ((ScFormulaCell*)pCell)->UpdateReference(
|
||||
eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos );
|
||||
if ( nRow != pItems[i].nRow )
|
||||
Search( nRow, i ); // Listener removed/inserted?
|
||||
}
|
||||
|
@ -1679,6 +1683,7 @@ void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
}
|
||||
}
|
||||
}
|
||||
return bUpdated;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1280,6 +1280,7 @@ void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
SCCOL nCol2, SCROW nRow2, SCTAB nTab2, SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
|
||||
ScDocument* pUndoDoc, BOOL bIncludeDraw, bool bUpdateNoteCaptionPos )
|
||||
{
|
||||
bool bUpdated = false;
|
||||
SCCOL i;
|
||||
SCCOL iMax;
|
||||
if ( eUpdateRefMode == URM_COPY )
|
||||
|
@ -1293,8 +1294,8 @@ void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
iMax = MAXCOL;
|
||||
}
|
||||
for ( ; i<=iMax; i++)
|
||||
aCol[i].UpdateReference( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2,
|
||||
nDx, nDy, nDz, pUndoDoc );
|
||||
bUpdated |= aCol[i].UpdateReference(
|
||||
eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz, pUndoDoc );
|
||||
|
||||
if ( bIncludeDraw )
|
||||
UpdateDrawRef( eUpdateRefMode, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, nDx, nDy, nDz, bUpdateNoteCaptionPos );
|
||||
|
@ -1379,6 +1380,9 @@ void ScTable::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW
|
|||
PAINT_GRID ) );
|
||||
}
|
||||
}
|
||||
|
||||
if (bUpdated && IsStreamValid())
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
void ScTable::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
|
||||
|
|
|
@ -177,6 +177,11 @@ void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
|
|||
DecRecalcLevel( false );
|
||||
|
||||
InvalidatePageBreaks();
|
||||
|
||||
if (IsStreamValid())
|
||||
// TODO: In the future we may want to check if the table has been
|
||||
// really modified before setting the stream invalid.
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -222,6 +227,11 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE
|
|||
DecRecalcLevel();
|
||||
|
||||
InvalidatePageBreaks();
|
||||
|
||||
if (IsStreamValid())
|
||||
// TODO: In the future we may want to check if the table has been
|
||||
// really modified before setting the stream invalid.
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,6 +319,11 @@ void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE
|
|||
DecRecalcLevel();
|
||||
|
||||
InvalidatePageBreaks();
|
||||
|
||||
if (IsStreamValid())
|
||||
// TODO: In the future we may want to check if the table has been
|
||||
// really modified before setting the stream invalid.
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -369,6 +384,11 @@ void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE
|
|||
DecRecalcLevel();
|
||||
|
||||
InvalidatePageBreaks();
|
||||
|
||||
if (IsStreamValid())
|
||||
// TODO: In the future we may want to check if the table has been
|
||||
// really modified before setting the stream invalid.
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -395,6 +415,11 @@ void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USH
|
|||
ApplyPatternArea( nCol1, nRow1, nCol2, nRow2, aPattern );
|
||||
}
|
||||
}
|
||||
|
||||
if (IsStreamValid())
|
||||
// TODO: In the future we may want to check if the table has been
|
||||
// really modified before setting the stream invalid.
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -418,6 +443,11 @@ void ScTable::DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark )
|
|||
SfxItemPoolCache aCache( pPool, &aSet );
|
||||
ApplySelectionCache( &aCache, rMark );
|
||||
}
|
||||
|
||||
if (IsStreamValid())
|
||||
// TODO: In the future we may want to check if the table has been
|
||||
// really modified before setting the stream invalid.
|
||||
SetStreamValid(false);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue