diff options
author | Eike Rathke [er] <eike.rathke@oracle.com> | 2010-12-11 16:08:03 +0100 |
---|---|---|
committer | Eike Rathke [er] <eike.rathke@oracle.com> | 2010-12-11 16:08:03 +0100 |
commit | 558e0532aefac886e814bf1cb237261cf21a5e45 (patch) | |
tree | 029f6f6b7c54d573f6997932b0c5d3cb8c294bad /sc | |
parent | 60851227548d3576a92898b13b0e1c15cc719f44 (diff) |
ooo33gsl13: #i115906# obtain correct data range for external references
* Apparently ScTable::GetFirstDataPos() never worked as intended and selected
the first non-empty row of the first non-empty column instead of also taking
following columns into account where non-empty rows may be on top of that.
* Caller of ScDocument::ShrinkToDataArea() must check the return value, if
false there is no data in the area passed and the values obtained may be out
of bounds, not in order or unmodified.
* In ScExternalRefMgr a call of ScDocument::ShrinkToUsedDataArea() was
intended instead of ScDocument::ShrinkToDataArea(). For this changed the
return of ShrinkToUsedDataArea() to flag if there is any data and added an
out parameter to flag if the area was shrunk.
* Sanitized arguments and slightly optimized ScTable::ShrinkToUsedDataArea()
to not have to check for >0 and <MAX on each iteration.
(transplanted from 31b53a2ec7e32f9560464f8a3b9f6c3e07b29083)
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/document.hxx | 22 | ||||
-rw-r--r-- | sc/inc/table.hxx | 3 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 7 | ||||
-rw-r--r-- | sc/source/core/data/table1.cxx | 38 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 17 | ||||
-rw-r--r-- | sc/source/ui/docshell/externalrefmgr.cxx | 7 | ||||
-rw-r--r-- | sc/source/ui/view/dbfunc.cxx | 5 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwshe.cxx | 4 |
8 files changed, 72 insertions, 31 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 5c4685223281..7cfab10746ba 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -918,13 +918,29 @@ public: USHORT GetErrCode( const ScAddress& ) const; /** Shrink a range to only include data area. + This is not the actually used area within the selection, but the bounds of the sheet's data area - instead. */ + instead. + + @returns TRUE if the area passed intersected the data + area, FALSE if not, in which case the values + obtained may be out of bounds, not in order or + unmodified. TRUE does not mean that there + actually is any data within the selection. + */ bool ShrinkToDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow ) const; - /** Shrink a range to only include used data area. */ - bool ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; + /** Shrink a range to only include used data area. + + @param o_bShrunk + Out parameter, TRUE if area was shrunk, FALSE if not. + + @returns TRUE if there is any data, FALSE if not. + */ + bool ShrinkToUsedDataArea( bool& o_bShrunk, + SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, + SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; void GetDataArea( SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 63cefe22626a..19884a94e46a 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -417,7 +417,8 @@ public: void GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, BOOL bIncludeOld, bool bOnlyDown ) const; - bool ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; + bool ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, + SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const; SCSIZE GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScDirection eDir ); diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 1efe32446eef..3b78ab5b172f 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -698,12 +698,15 @@ bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow return true; // success! } -bool ScDocument::ShrinkToUsedDataArea( SCTAB nTab, SCCOL& rStartCol, +bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const { if (!ValidTab(nTab) || !pTab[nTab]) + { + o_bShrunk = false; return false; - return pTab[nTab]->ShrinkToUsedDataArea( rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly); + } + return pTab[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly); } // zusammenhaengender Bereich diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index baaabd3a8c8f..7abebea23686 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -740,18 +740,28 @@ void ScTable::GetDataArea( SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, S } -bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, +bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly ) const { - bool bRet = false; - bool bChanged; + o_bShrunk = false; + + PutInOrder( rStartCol, rEndCol); + PutInOrder( rStartRow, rEndRow); + if (rStartCol < 0) + rStartCol = 0, o_bShrunk = true; + if (rStartRow < 0) + rStartRow = 0, o_bShrunk = true; + if (rEndCol > MAXCOL) + rEndCol = MAXCOL, o_bShrunk = true; + if (rEndRow > MAXROW) + rEndRow = MAXROW, o_bShrunk = true; + bool bChanged; do { bChanged = false; - bool bCont = true; - while (rEndCol > 0 && bCont && rStartCol < rEndCol) + while (rStartCol < rEndCol) { if (aCol[rEndCol].IsEmptyBlock( rStartRow, rEndRow)) { @@ -759,11 +769,10 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, bChanged = true; } else - bCont = false; + break; // while } - bCont = true; - while (rStartCol < MAXCOL && bCont && rStartCol < rEndCol) + while (rStartCol < rEndCol) { if (aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow)) { @@ -771,12 +780,12 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, bChanged = true; } else - bCont = false; + break; // while } if (!bColumnsOnly) { - if (rStartRow < MAXROW && rStartRow < rEndRow) + if (rStartRow < rEndRow) { bool bFound = false; for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++) @@ -789,7 +798,7 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, } } - if (rEndRow > 0 && rStartRow < rEndRow) + if (rStartRow < rEndRow) { bool bFound = false; for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++) @@ -804,9 +813,12 @@ bool ScTable::ShrinkToUsedDataArea( SCCOL& rStartCol, SCROW& rStartRow, } if (bChanged) - bRet = true; + o_bShrunk = true; } while( bChanged ); - return bRet; + + return rStartCol != rEndCol || (bColumnsOnly ? + !aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow) : + (rStartRow != rEndRow || aCol[rStartCol].HasDataAt( rStartRow))); } diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 9bb22b68d2ad..e3f04f95e35c 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1135,10 +1135,16 @@ ScBaseCell* ScTable::GetCell( SCCOL nCol, SCROW nRow ) const void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const { rCol = 0; - rRow = 0; + rRow = MAXROW+1; while (aCol[rCol].IsEmptyData() && rCol < MAXCOL) ++rCol; - rRow = aCol[rCol].GetFirstDataPos(); + SCCOL nCol = rCol; + while (nCol <= MAXCOL && rRow > 0) + { + if (!aCol[nCol].IsEmptyData()) + rRow = ::std::min( rRow, aCol[nCol].GetFirstDataPos()); + ++nCol; + } } void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const @@ -1148,11 +1154,8 @@ void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const while (aCol[rCol].IsEmptyData() && (rCol > 0)) rCol--; SCCOL nCol = rCol; - while ((SCsCOL)nCol >= 0) - { - rRow = Max(rRow, aCol[nCol].GetLastDataPos()); - nCol--; - } + while (nCol >= 0 && rRow < MAXROW) + rRow = ::std::max( rRow, aCol[nCol--].GetLastDataPos()); } diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 7fa31246275a..ba39316768b7 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -1392,7 +1392,8 @@ static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, ScRange& rRang // Only loop within the data area. SCCOL nDataCol1 = nCol1, nDataCol2 = nCol2; SCROW nDataRow1 = nRow1, nDataRow2 = nRow2; - if (!pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2)) + bool bShrunk; + if (!pSrcDoc->ShrinkToUsedDataArea( bShrunk, nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2, false)) // no data within specified range. continue; @@ -1708,8 +1709,8 @@ ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken( SCCOL nDataCol1 = 0, nDataCol2 = MAXCOL; SCROW nDataRow1 = 0, nDataRow2 = MAXROW; - pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2); - if (rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row()) + bool bData = pSrcDoc->ShrinkToDataArea(nTab, nDataCol1, nDataRow1, nDataCol2, nDataRow2); + if (!bData || rCell.Col() < nDataCol1 || nDataCol2 < rCell.Col() || rCell.Row() < nDataRow1 || nDataRow2 < rCell.Row()) { // requested cell is outside the data area. Don't even bother caching // this data, but add it to the cached range to prevent accessing the diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx index 1e5a6b9da4ae..f2a277b987df 100644 --- a/sc/source/ui/view/dbfunc.cxx +++ b/sc/source/ui/view/dbfunc.cxx @@ -159,7 +159,10 @@ ScDBData* ScDBFunc::GetDBData( BOOL bMark, ScGetDBMode eMode, ScGetDBSelection e ScDocument* pDoc = pDocSh->GetDocument(); SCCOL nCol1 = aRange.aStart.Col(), nCol2 = aRange.aEnd.Col(); SCROW nRow1 = aRange.aStart.Row(), nRow2 = aRange.aEnd.Row(); - if (pDoc->ShrinkToUsedDataArea( aRange.aStart.Tab(), nCol1, nRow1, nCol2, nRow2, bShrinkColumnsOnly)) + bool bShrunk; + pDoc->ShrinkToUsedDataArea( bShrunk, aRange.aStart.Tab(), + nCol1, nRow1, nCol2, nRow2, bShrinkColumnsOnly); + if (bShrunk) { aRange.aStart.SetCol(nCol1); aRange.aEnd.SetCol(nCol2); diff --git a/sc/source/ui/view/tabvwshe.cxx b/sc/source/ui/view/tabvwshe.cxx index c0af39226c3f..6034ac81ecba 100644 --- a/sc/source/ui/view/tabvwshe.cxx +++ b/sc/source/ui/view/tabvwshe.cxx @@ -97,7 +97,9 @@ String __EXPORT ScTabViewShell::GetSelectionText( BOOL bWholeWord ) SCROW nRow1, nRow2; SCTAB nTab1, nTab2; aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); - if (pDoc->ShrinkToUsedDataArea( nTab1, nCol1, nRow1, nCol2, nRow2, false)) + bool bShrunk; + pDoc->ShrinkToUsedDataArea( bShrunk, nTab1, nCol1, nRow1, nCol2, nRow2, false); + if (bShrunk) { aRange.aStart.SetCol( nCol1 ); aRange.aStart.SetRow( nRow1 ); |