summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/table.hxx2
-rw-r--r--sc/inc/unonames.hxx1
-rw-r--r--sc/source/core/data/table6.cxx219
-rw-r--r--sc/source/ui/unoobj/srchuno.cxx2
4 files changed, 157 insertions, 67 deletions
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 0ddce1f139f4..32e63834ddc4 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -884,6 +884,8 @@ private:
void InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
BOOL bNumFormatChanged, BOOL bBroadcast );
+ void SkipFilteredRows(SCROW& rRow, SCROW& rLastNonFilteredRow, bool bForward);
+
/**
* In case the cell text goes beyond the column width, move the max column
* position to the right. This is called from ExtendPrintArea.
diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx
index 2d011f425398..a131c10f779e 100644
--- a/sc/inc/unonames.hxx
+++ b/sc/inc/unonames.hxx
@@ -354,6 +354,7 @@
#define SC_UNO_SRCHSTYLES "SearchStyles"
#define SC_UNO_SRCHTYPE "SearchType"
#define SC_UNO_SRCHWORDS "SearchWords"
+#define SC_UNO_SRCHFILTERED "SearchFiltered"
// old (5.2) property names for page styles - for compatibility only!
#define OLD_UNO_PAGE_BACKCOLOR "BackgroundColor"
diff --git a/sc/source/core/data/table6.cxx b/sc/source/core/data/table6.cxx
index e020390ebf80..277dd99af763 100644
--- a/sc/source/core/data/table6.cxx
+++ b/sc/source/core/data/table6.cxx
@@ -248,6 +248,42 @@ BOOL ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRo
return bFound;
}
+void ScTable::SkipFilteredRows(SCROW& rRow, SCROW& rLastNonFilteredRow, bool bForward)
+{
+ if (bForward)
+ {
+ // forward search
+
+ if (rRow <= rLastNonFilteredRow)
+ return;
+
+ SCROW nLastRow = rRow;
+ if (RowFiltered(rRow, NULL, &nLastRow))
+ // move to the first non-filtered row.
+ rRow = nLastRow + 1;
+ else
+ // record the last non-filtered row to avoid checking
+ // the filtered state for each and every row.
+ rLastNonFilteredRow = nLastRow;
+ }
+ else
+ {
+ // backward search
+
+ if (rRow >= rLastNonFilteredRow)
+ return;
+
+ SCROW nFirstRow = rRow;
+ if (RowFiltered(rRow, &nFirstRow, NULL))
+ // move to the first non-filtered row.
+ rRow = nFirstRow - 1;
+ else
+ // record the last non-filtered row to avoid checking
+ // the filtered state for each and every row.
+ rLastNonFilteredRow = nFirstRow;
+ }
+}
+
BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
const ScMarkData& rMark, String& rUndoStr, ScDocument* pUndoDoc)
{
@@ -259,8 +295,10 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
SCCOL nLastCol;
SCROW nLastRow;
GetLastDataPos(nLastCol, nLastRow);
+ bool bSkipFiltered = !rSearchItem.IsSearchFiltered();
if (!bAll && rSearchItem.GetBackward())
{
+ SCROW nLastNonFilteredRow = MAXROW + 1;
nCol = Min(nCol, (SCCOL)(nLastCol + 1));
nRow = Min(nRow, (SCROW)(nLastRow + 1));
if (rSearchItem.GetRowDirection())
@@ -268,6 +306,9 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
nCol--;
while (!bFound && ((SCsROW)nRow >= 0))
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, false);
+
while (!bFound && ((SCsCOL)nCol >= 0))
{
bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
@@ -299,6 +340,9 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
{
while (!bFound && ((SCsROW)nRow >= 0))
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, false);
+
bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
if (!bFound)
{
@@ -308,8 +352,10 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
}
if (!bFound)
{
+ // Not found in this column. Move to the next column.
BOOL bIsEmpty;
nRow = nLastRow;
+ nLastNonFilteredRow = MAXROW + 1;
do
{
nCol--;
@@ -325,11 +371,15 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
}
else
{
+ SCROW nLastNonFilteredRow = -1;
if (!bAll && rSearchItem.GetRowDirection())
{
nCol++;
while (!bFound && (nRow <= nLastRow))
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, true);
+
while (!bFound && (nCol <= nLastCol))
{
bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
@@ -353,6 +403,9 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
{
while (!bFound && (nRow <= nLastRow))
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, true);
+
bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc);
if (!bFound)
{
@@ -362,7 +415,9 @@ BOOL ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
}
if (!bFound)
{
+ // Not found in this column. Move to the next column.
nRow = 0;
+ nLastNonFilteredRow = -1;
nCol++;
while ((nCol <= nLastCol) && aCol[nCol].IsEmptyData()) nCol++;
}
@@ -767,20 +822,51 @@ bool ScTable::SearchAndReplaceEmptyCells(
return false;
}
+namespace {
+
+bool lcl_maybeReplaceCellString(
+ ScColumn& rColObj, SCCOL& rCol, SCROW& rRow, String& rUndoStr, SCCOL nCol, SCROW nRow, const SvxSearchItem& rSearchItem)
+{
+ ScBaseCell* pCell = rColObj.GetCell(nRow);
+ if (!pCell || pCell->GetCellType() == CELLTYPE_NOTE)
+ {
+ // empty cell found.
+ rCol = nCol;
+ rRow = nRow;
+ if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
+ rSearchItem.GetReplaceString().Len())
+ {
+ rColObj.Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
+ rUndoStr = String();
+ }
+ return true;
+ }
+ return false;
+}
+
+}
+
bool ScTable::SearchRangeForEmptyCell(
const ScRange& rRange, const SvxSearchItem& rSearchItem,
SCCOL& rCol, SCROW& rRow, String& rUndoStr, ScDocument* /*pUndoDoc*/)
{
sal_uInt16 nCmd = rSearchItem.GetCommand();
+ bool bSkipFiltered = rSearchItem.IsSearchFiltered();
if (rSearchItem.GetBackward())
{
// backward search
if (rSearchItem.GetRowDirection())
{
// row direction.
+ SCROW nLastNonFilteredRow = MAXROW + 1;
SCROW nBeginRow = rRange.aEnd.Row() > rRow ? rRow : rRange.aEnd.Row();
for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, false);
+ if (nRow < rRange.aStart.Row())
+ break;
+
SCCOL nBeginCol = rRange.aEnd.Col();
if (nRow == rRow && nBeginCol >= rCol)
// always start from one cell before the cursor.
@@ -788,20 +874,8 @@ bool ScTable::SearchRangeForEmptyCell(
for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
{
- ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
- if (!pCell)
- {
- // empty cell found.
- rCol = nCol;
- rRow = nRow;
- if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
- rSearchItem.GetReplaceString().Len())
- {
- aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
- rUndoStr = String();
- }
+ if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
return true;
- }
}
}
}
@@ -811,26 +885,20 @@ bool ScTable::SearchRangeForEmptyCell(
SCCOL nBeginCol = rRange.aEnd.Col() > rCol ? rCol : rRange.aEnd.Col();
for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
{
+ SCROW nLastNonFilteredRow = MAXROW + 1;
SCROW nBeginRow = rRange.aEnd.Row();
if (nCol == rCol && nBeginRow >= rRow)
// always start from one cell before the cursor.
nBeginRow = rRow - (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
{
- ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
- if (!pCell)
- {
- // empty cell found.
- rCol = nCol;
- rRow = nRow;
- if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
- rSearchItem.GetReplaceString().Len())
- {
- aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
- rUndoStr = String();
- }
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, false);
+ if (nRow < rRange.aStart.Row())
+ break;
+
+ if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
return true;
- }
}
}
}
@@ -841,29 +909,23 @@ bool ScTable::SearchRangeForEmptyCell(
if (rSearchItem.GetRowDirection())
{
// row direction.
+ SCROW nLastNonFilteredRow = -1;
SCROW nBeginRow = rRange.aStart.Row() < rRow ? rRow : rRange.aStart.Row();
for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, true);
+ if (nRow > rRange.aEnd.Row())
+ break;
+
SCCOL nBeginCol = rRange.aStart.Col();
if (nRow == rRow && nBeginCol <= rCol)
// always start from one cell past the cursor.
nBeginCol = rCol + (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
{
- ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
- if (!pCell)
- {
- // empty cell found.
- rCol = nCol;
- rRow = nRow;
- if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
- rSearchItem.GetReplaceString().Len())
- {
- aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
- rUndoStr = String();
- }
+ if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
return true;
- }
}
}
}
@@ -873,26 +935,20 @@ bool ScTable::SearchRangeForEmptyCell(
SCCOL nBeginCol = rRange.aStart.Col() < rCol ? rCol : rRange.aStart.Col();
for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
{
+ SCROW nLastNonFilteredRow = -1;
SCROW nBeginRow = rRange.aStart.Row();
if (nCol == rCol && nBeginRow <= rRow)
// always start from one cell past the cursor.
nBeginRow = rRow + (nCmd == SVX_SEARCHCMD_FIND ? 1 : 0);
for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
{
- ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
- if (!pCell)
- {
- // empty cell found.
- rCol = nCol;
- rRow = nRow;
- if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
- rSearchItem.GetReplaceString().Len())
- {
- aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
- rUndoStr = String();
- }
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, true);
+ if (nRow > rRange.aEnd.Row())
+ break;
+
+ if (lcl_maybeReplaceCellString(aCol[nCol], rCol, rRow, rUndoStr, nCol, nRow, rSearchItem))
return true;
- }
}
}
}
@@ -907,35 +963,49 @@ bool ScTable::SearchRangeForAllEmptyCells(
bool bFound = false;
bool bReplace = (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL) &&
(rSearchItem.GetReplaceString().Len() > 0);
+ bool bSkipFiltered = rSearchItem.IsSearchFiltered();
for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
{
+ SCROW nLastNonFilteredRow = -1;
if (aCol[nCol].IsEmptyData())
{
- // The entire column is empty. Add the whole column and move on.
- rMark.SetMultiMarkArea(
- ScRange(nCol, rRange.aStart.Row(), nTab, nCol, rRange.aEnd.Row(), nTab));
- bFound = true;
-
- if (bReplace)
+ // The entire column is empty.
+ for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
{
- const String& rNewStr = rSearchItem.GetReplaceString();
- for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
+ SCROW nLastRow;
+ if (!RowFiltered(nRow, NULL, &nLastRow))
{
- aCol[nCol].Insert(nRow, new ScStringCell(rNewStr));
- if (pUndoDoc)
- // TODO: I'm using a string cell with empty content to
- // trigger deletion of cell instance on undo. Maybe I
- // should create a new cell type for this?
- pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
+ rMark.SetMultiMarkArea(ScRange(nCol, nRow, nTab, nCol, nLastRow, nTab));
+ if (bReplace)
+ {
+ const String& rNewStr = rSearchItem.GetReplaceString();
+ for (SCROW i = nRow; i <= nLastRow; ++i)
+ {
+ aCol[nCol].Insert(i, new ScStringCell(rNewStr));
+ if (pUndoDoc)
+ // TODO: I'm using a string cell with empty content to
+ // trigger deletion of cell instance on undo. Maybe I
+ // should create a new cell type for this?
+ pUndoDoc->PutCell(nCol, i, nTab, new ScStringCell(String()));
+ }
+ rUndoStr = String();
+ }
}
- rUndoStr = String();
+
+ nRow = nLastRow; // move to the last filtered row.
}
+ bFound = true;
continue;
}
for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
{
+ if (bSkipFiltered)
+ SkipFilteredRows(nRow, nLastNonFilteredRow, true);
+ if (nRow > rRange.aEnd.Row())
+ break;
+
ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
if (!pCell)
{
@@ -953,6 +1023,21 @@ bool ScTable::SearchRangeForAllEmptyCells(
pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
}
}
+ else if (pCell->GetCellType() == CELLTYPE_NOTE)
+ {
+ rMark.SetMultiMarkArea(ScRange(nCol, nRow, nTab));
+ bFound = true;
+
+ if (bReplace)
+ {
+ if (pUndoDoc)
+ {
+ ScAddress aCellPos(nCol, nRow, nTab);
+ pUndoDoc->PutCell(nCol, nRow, nTab, pCell->CloneWithNote(aCellPos, *pUndoDoc, aCellPos));
+ }
+ aCol[nCol].SetString(nRow, nTab, rSearchItem.GetReplaceString());
+ }
+ }
}
}
return bFound;
diff --git a/sc/source/ui/unoobj/srchuno.cxx b/sc/source/ui/unoobj/srchuno.cxx
index b005d16ce482..f0bff44dc05c 100644
--- a/sc/source/ui/unoobj/srchuno.cxx
+++ b/sc/source/ui/unoobj/srchuno.cxx
@@ -172,6 +172,7 @@ void SAL_CALL ScCellSearchObj::setPropertyValue(
else if (aString.EqualsAscii( SC_UNO_SRCHSIMEX )) pSearchItem->SetLEVOther( ScUnoHelpFunctions::GetInt16FromAny( aValue ) );
else if (aString.EqualsAscii( SC_UNO_SRCHSIMREM )) pSearchItem->SetLEVShorter( ScUnoHelpFunctions::GetInt16FromAny( aValue ) );
else if (aString.EqualsAscii( SC_UNO_SRCHTYPE )) pSearchItem->SetCellType( ScUnoHelpFunctions::GetInt16FromAny( aValue ) );
+ else if (aString.EqualsAscii( SC_UNO_SRCHFILTERED )) pSearchItem->SetSearchFiltered( ScUnoHelpFunctions::GetBoolFromAny(aValue) );
}
uno::Any SAL_CALL ScCellSearchObj::getPropertyValue( const rtl::OUString& aPropertyName )
@@ -194,6 +195,7 @@ uno::Any SAL_CALL ScCellSearchObj::getPropertyValue( const rtl::OUString& aPrope
else if (aString.EqualsAscii( SC_UNO_SRCHSIMEX )) aRet <<= (sal_Int16) pSearchItem->GetLEVOther();
else if (aString.EqualsAscii( SC_UNO_SRCHSIMREM )) aRet <<= (sal_Int16) pSearchItem->GetLEVShorter();
else if (aString.EqualsAscii( SC_UNO_SRCHTYPE )) aRet <<= (sal_Int16) pSearchItem->GetCellType();
+ else if (aString.EqualsAscii( SC_UNO_SRCHFILTERED )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->IsSearchFiltered() );
return aRet;
}