diff options
-rw-r--r-- | sc/inc/table.hxx | 2 | ||||
-rw-r--r-- | sc/inc/unonames.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/data/table6.cxx | 219 | ||||
-rw-r--r-- | sc/source/ui/unoobj/srchuno.cxx | 2 |
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; } |