sc/inc/cellform.hxx | 4 ++-- sc/inc/cellvalue.hxx | 4 ++-- sc/inc/column.hxx | 16 ++++++++++++++-- sc/inc/table.hxx | 2 +- sc/source/core/data/cellvalue.cxx | 4 ++-- sc/source/core/data/column2.cxx | 5 +++++ sc/source/core/data/column3.cxx | 7 ++----- sc/source/core/data/table6.cxx | 31 ++++++++++++++++++++----------- sc/source/core/tool/cellform.cxx | 4 ++-- 9 files changed, 50 insertions(+), 27 deletions(-)
New commits: commit fce7c123203c91f62b45447f45e1d1f1b45d5b48 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Tue May 14 15:59:29 2019 +0200 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Tue May 14 22:06:44 2019 +0200 cache cell positions when searching in calc (tdf#108347) The document has a large number of rows, and mdds normally always searches from the first item when looking up the container position, which leads to a quadratic cost when searching the entire sheet. GetCellValue() already has a variant that caches the last position, so just use it (and make sure to invalidate if it's search&replace and something changes). Change-Id: I26da60cebf641e10ed92e548fe5f9016900d3cf0 Reviewed-on: https://gerrit.libreoffice.org/72290 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/sc/inc/cellform.hxx b/sc/inc/cellform.hxx index 618ad7146220..6a21b525defa 100644 --- a/sc/inc/cellform.hxx +++ b/sc/inc/cellform.hxx @@ -34,7 +34,7 @@ class SC_DLLPUBLIC ScCellFormat public: static void GetString( - ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, + const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, Color** ppColor, SvNumberFormatter& rFormatter, const ScDocument* pDoc, bool bNullVals = true, bool bFormula = false, bool bUseStarFormat = false ); @@ -44,7 +44,7 @@ public: bool bFormula = false ); static void GetInputString( - ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter, + const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter, const ScDocument* pDoc ); static OUString GetOutputString( diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx index 153411c2b63e..7b6e3aad5794 100644 --- a/sc/inc/cellvalue.hxx +++ b/sc/inc/cellvalue.hxx @@ -78,7 +78,7 @@ struct SC_DLLPUBLIC ScCellValue void release( ScColumn& rColumn, SCROW nRow, sc::StartListeningType eListenType = sc::SingleCellListening ); - OUString getString( const ScDocument* pDoc ); + OUString getString( const ScDocument* pDoc ) const; bool isEmpty() const; @@ -156,7 +156,7 @@ struct SC_DLLPUBLIC ScRefCellValue * specific fields can not be resolved. See * ScEditUtil::GetString(). */ - OUString getString( const ScDocument* pDoc ); + OUString getString( const ScDocument* pDoc ) const; /** * Retrieve a string value without modifying the states of any objects in diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index bb218ea37c72..023e77427e01 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -22,6 +22,7 @@ #include "global.hxx" #include "address.hxx" +#include "cellvalue.hxx" #include "rangelst.hxx" #include "types.hxx" #include "mtvelements.hxx" @@ -355,9 +356,16 @@ public: void SetValue( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, double fVal, bool bBroadcast = true ); void SetError( SCROW nRow, const FormulaError nError); - void GetString( SCROW nRow, OUString& rString, const ScInterpreterContext* pContext = nullptr ) const; + void GetString( SCROW nRow, OUString& rString, const ScInterpreterContext* pContext = nullptr ) const + { return GetString( GetCellValue( nRow ), nRow, rString, pContext ); } + void GetString( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, + OUString& rString, const ScInterpreterContext* pContext = nullptr ) const + { return GetString( GetCellValue( rBlockPos, nRow ), nRow, rString, pContext ); } double* GetValueCell( SCROW nRow ); - void GetInputString( SCROW nRow, OUString& rString ) const; + void GetInputString( SCROW nRow, OUString& rString ) const + { return GetInputString( GetCellValue( nRow ), nRow, rString ); } + void GetInputString( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, OUString& rString ) const + { return GetInputString( GetCellValue( rBlockPos, nRow ), nRow, rString ); } double GetValue( SCROW nRow ) const; const EditTextObject* GetEditText( SCROW nRow ) const; void RemoveEditTextCharAttribs( SCROW nRow, const ScPatternAttr& rAttr ); @@ -599,6 +607,7 @@ public: // cell notes ScPostIt* GetCellNote( SCROW nRow ); const ScPostIt* GetCellNote( SCROW nRow ) const; + ScPostIt* GetCellNote( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ); const ScPostIt* GetCellNote( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) const; void DeleteCellNotes( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2, bool bForgetCaptionOwnership ); bool HasCellNotes() const; @@ -729,6 +738,9 @@ private: sc::CellStoreType::const_iterator& itPos, SCROW nRow, bool bForward) const; SCROW FindNextVisibleRow(SCROW nRow, bool bForward) const; + void GetString( const ScRefCellValue& cell, SCROW nRow, OUString& rString, const ScInterpreterContext* pContext = nullptr ) const; + void GetInputString( const ScRefCellValue& cell, SCROW nRow, OUString& rString ) const; + /** * Called whenever the state of cell array gets modified i.e. new cell * insertion, cell removal or relocation, cell value update and so on. diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index dbbf7b57d831..547d9936e44b 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -1106,7 +1106,7 @@ private: const ScPatternAttr& rAttr, sal_uInt16 nFormatNo); void GetAutoFormatAttr(SCCOL nCol, SCROW nRow, sal_uInt16 nIndex, ScAutoFormatData& rData); void GetAutoFormatFrame(SCCOL nCol, SCROW nRow, sal_uInt16 nFlags, sal_uInt16 nIndex, ScAutoFormatData& rData); - bool SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRow, + bool SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, const ScMarkData& rMark, OUString& rUndoStr, ScDocument* pUndoDoc); bool Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark, OUString& rUndoStr, ScDocument* pUndoDoc); diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx index b131debdb7a2..7fffc669ee6c 100644 --- a/sc/source/core/data/cellvalue.cxx +++ b/sc/source/core/data/cellvalue.cxx @@ -491,7 +491,7 @@ void ScCellValue::release( ScColumn& rColumn, SCROW nRow, sc::StartListeningType mfValue = 0.0; } -OUString ScCellValue::getString( const ScDocument* pDoc ) +OUString ScCellValue::getString( const ScDocument* pDoc ) const { return getStringImpl(*this, pDoc); } @@ -647,7 +647,7 @@ double ScRefCellValue::getRawValue() const return 0.0; } -OUString ScRefCellValue::getString( const ScDocument* pDoc ) +OUString ScRefCellValue::getString( const ScDocument* pDoc ) const { return getStringImpl(*this, pDoc); } diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index d1654ac7e49e..bea0497e4c84 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1904,6 +1904,11 @@ const ScPostIt* ScColumn::GetCellNote( sc::ColumnBlockConstPosition& rBlockPos, return sc::cellnote_block::at(*aPos.first->data, aPos.second); } +ScPostIt* ScColumn::GetCellNote( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow ) +{ + return const_cast<ScPostIt*>(const_cast<const ScColumn*>(this)->GetCellNote( rBlockPos, nRow )); +} + void ScColumn::SetCellNote(SCROW nRow, std::unique_ptr<ScPostIt> pNote) { //pNote->UpdateCaptionPos(ScAddress(nCol, nRow, nTab)); // TODO notes useful ? slow import with many notes diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index a760f1428336..26847a3a6126 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -2822,10 +2822,8 @@ void ScColumn::SetValue( BroadcastNewCell(nRow); } -void ScColumn::GetString( SCROW nRow, OUString& rString, const ScInterpreterContext* pContext ) const +void ScColumn::GetString( const ScRefCellValue& aCell, SCROW nRow, OUString& rString, const ScInterpreterContext* pContext ) const { - ScRefCellValue aCell = GetCellValue(nRow); - // ugly hack for ordering problem with GetNumberFormat and missing inherited formats if (aCell.meType == CELLTYPE_FORMULA) aCell.mpFormula->MaybeInterpret(); @@ -2849,9 +2847,8 @@ double* ScColumn::GetValueCell( SCROW nRow ) return &sc::numeric_block::at(*it->data, aPos.second); } -void ScColumn::GetInputString( SCROW nRow, OUString& rString ) const +void ScColumn::GetInputString( const ScRefCellValue& aCell, SCROW nRow, OUString& rString ) const { - ScRefCellValue aCell = GetCellValue(nRow); sal_uLong nFormat = GetNumberFormat(GetDoc()->GetNonThreadedContext(), nRow); ScCellFormat::GetInputString(aCell, nFormat, rString, *(GetDoc()->GetFormatTable()), GetDoc()); } diff --git a/sc/source/core/data/table6.cxx b/sc/source/core/data/table6.cxx index 728a86ee744b..4daeb308bfd7 100644 --- a/sc/source/core/data/table6.cxx +++ b/sc/source/core/data/table6.cxx @@ -47,7 +47,7 @@ bool lcl_GetTextWithBreaks( const EditTextObject& rData, ScDocument* pDoc, OUStr } -bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRow, +bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, const ScMarkData& rMark, OUString& rUndoStr, ScDocument* pUndoDoc) { if ( !IsColRowValid( nCol, nRow ) ) @@ -69,13 +69,13 @@ bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRo ScPostIt* pNote; if (rSearchItem.GetCellType() == SvxSearchCellType::NOTE) { - pNote = aCol[nCol].GetCellNote(nRow); + pNote = aCol[nCol].GetCellNote(rBlockPos, nRow); if (!pNote) return false; } else { - aCell = aCol[nCol].GetCellValue(nRow); + aCell = aCol[nCol].GetCellValue(rBlockPos, nRow); if (aCell.isEmpty()) return false; pNote = nullptr; @@ -94,9 +94,9 @@ bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRo else { if( !bSearchFormatted ) - aCol[nCol].GetInputString( nRow, aString ); + aCol[nCol].GetInputString( rBlockPos, nRow, aString ); else - aCol[nCol].GetString( nRow, aString ); + aCol[nCol].GetString( rBlockPos, nRow, aString ); } break; } @@ -106,9 +106,9 @@ bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRo else { if( !bSearchFormatted ) - aCol[nCol].GetInputString( nRow, aString ); + aCol[nCol].GetInputString( rBlockPos, nRow, aString ); else - aCol[nCol].GetString( nRow, aString ); + aCol[nCol].GetString( rBlockPos, nRow, aString ); } break; case SvxSearchCellType::NOTE: @@ -262,6 +262,7 @@ bool ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRo else aCol[nCol].SetString(nRow, nTab, aString, pDocument->GetAddressConvention()); // pCell is invalid now (deleted) + aCol[nCol].InitBlockPosition( rBlockPos ); // invalidate also the cached position } return bFound; } @@ -326,6 +327,10 @@ bool ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, bool bSkipFiltered = !rSearchItem.IsSearchFiltered(); bool bSearchNotes = (rSearchItem.GetCellType() == SvxSearchCellType::NOTE); + // We need to cache sc::ColumnBlockConstPosition per each column. + std::vector< sc::ColumnBlockConstPosition > blockPos( nLastCol + 1 ); + for( SCCOL i = 0; i <= nLastCol; ++i ) + aCol[ i ].InitBlockPosition( blockPos[ i ] ); if (!bAll && rSearchItem.GetBackward()) { SCROW nLastNonFilteredRow = MAXROW + 1; @@ -341,7 +346,8 @@ bool ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, while (!bFound && (nCol >= 0)) { - bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc); + bFound = SearchCell(rSearchItem, nCol, blockPos[ nCol ], nRow, + rMark, rUndoStr, pUndoDoc); if (!bFound) { bool bIsEmpty; @@ -378,7 +384,8 @@ bool ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, if (bSkipFiltered) SkipFilteredRows(nRow, nLastNonFilteredRow, false); - bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc); + bFound = SearchCell(rSearchItem, nCol, blockPos[ nCol ], + nRow, rMark, rUndoStr, pUndoDoc); if (!bFound) { if (bSearchNotes) @@ -430,7 +437,8 @@ bool ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, while (!bFound && (nCol <= nLastCol)) { - bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc); + bFound = SearchCell(rSearchItem, nCol, blockPos[ nCol ], + nRow, rMark, rUndoStr, pUndoDoc); if (!bFound) { nCol++; @@ -456,7 +464,8 @@ bool ScTable::Search(const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, if (bSkipFiltered) SkipFilteredRows(nRow, nLastNonFilteredRow, true); - bFound = SearchCell(rSearchItem, nCol, nRow, rMark, rUndoStr, pUndoDoc); + bFound = SearchCell(rSearchItem, nCol, blockPos[ nCol ], + nRow, rMark, rUndoStr, pUndoDoc); if (!bFound) { if (bSearchNotes) diff --git a/sc/source/core/tool/cellform.cxx b/sc/source/core/tool/cellform.cxx index 858097ed8357..e7e004471c0c 100644 --- a/sc/source/core/tool/cellform.cxx +++ b/sc/source/core/tool/cellform.cxx @@ -30,7 +30,7 @@ #include <sc.hrc> #include <editutil.hxx> -void ScCellFormat::GetString( ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, +void ScCellFormat::GetString( const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, Color** ppColor, SvNumberFormatter& rFormatter, const ScDocument* pDoc, bool bNullVals, bool bFormula, bool bUseStarFormat ) { @@ -118,7 +118,7 @@ OUString ScCellFormat::GetString( } void ScCellFormat::GetInputString( - ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter, const ScDocument* pDoc ) + const ScRefCellValue& rCell, sal_uInt32 nFormat, OUString& rString, SvNumberFormatter& rFormatter, const ScDocument* pDoc ) { switch (rCell.meType) { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits