summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorEike Rathke [er] <eike.rathke@oracle.com>2010-12-11 16:08:03 +0100
committerEike Rathke [er] <eike.rathke@oracle.com>2010-12-11 16:08:03 +0100
commit558e0532aefac886e814bf1cb237261cf21a5e45 (patch)
tree029f6f6b7c54d573f6997932b0c5d3cb8c294bad /sc
parent60851227548d3576a92898b13b0e1c15cc719f44 (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.hxx22
-rw-r--r--sc/inc/table.hxx3
-rw-r--r--sc/source/core/data/document.cxx7
-rw-r--r--sc/source/core/data/table1.cxx38
-rw-r--r--sc/source/core/data/table2.cxx17
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx7
-rw-r--r--sc/source/ui/view/dbfunc.cxx5
-rw-r--r--sc/source/ui/view/tabvwshe.cxx4
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 );