diff options
-rw-r--r-- | sc/inc/column.hxx | 17 | ||||
-rw-r--r-- | sc/inc/document.hxx | 23 | ||||
-rw-r--r-- | sc/inc/sortparam.hxx | 69 | ||||
-rw-r--r-- | sc/inc/table.hxx | 24 | ||||
-rw-r--r-- | sc/qa/unit/ucalc_sort.cxx | 8 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 81 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/sortparam.cxx | 41 | ||||
-rw-r--r-- | sc/source/core/data/table1.cxx | 56 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 338 | ||||
-rw-r--r-- | sc/source/filter/xml/XMLExportDatabaseRanges.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/app/transobj.cxx | 22 | ||||
-rw-r--r-- | sc/source/ui/dbgui/tpsort.cxx | 12 | ||||
-rw-r--r-- | sc/source/ui/docshell/dbdocfun.cxx | 64 | ||||
-rw-r--r-- | sc/source/ui/undo/undosort.cxx | 15 | ||||
-rw-r--r-- | sc/source/ui/unoobj/datauno.cxx | 4 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh2.cxx | 12 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin.cxx | 6 |
18 files changed, 518 insertions, 281 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 20ae065c1613..72527a76cd9e 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -218,19 +218,16 @@ public: // data only: bool IsEmptyBlock(SCROW nStartRow, SCROW nEndRow) const; SCSIZE GetEmptyLinesInBlock( SCROW nStartRow, SCROW nEndRow, ScDirection eDir ) const; - bool HasDataAt(SCROW nRow, bool bConsiderCellNotes = false, - bool bConsiderCellDrawObjects = false, bool bConsiderCellFormats = false) const; - bool HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, - bool bConsiderCellNotes = false, bool bConsiderCellDrawObjects = false, - bool bConsiderCellFormats = false) const; - bool HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow, bool bConsiderCellNotes = false, - bool bConsiderCellDrawObjects = false, bool bConsiderCellFormats = false); + bool HasDataAt( SCROW nRow, ScDataAreaExtras* pDataAreaExtras = nullptr ) const; + bool HasDataAt( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, + ScDataAreaExtras* pDataAreaExtras = nullptr ) const; + bool HasDataAt( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, + ScDataAreaExtras* pDataAreaExtras = nullptr ); + void GetDataExtrasAt( SCROW nRow, ScDataAreaExtras& rDataAreaExtras ) const; bool HasVisibleDataAt(SCROW nRow) const; SCROW GetFirstDataPos() const; SCROW GetLastDataPos() const; - SCROW GetLastDataPos(SCROW nLastRow, bool bConsiderCellNotes = false, - bool bConsiderCellDrawObjects = false, - bool bConsiderCellFormats = false) const; + SCROW GetLastDataPos( SCROW nLastRow, ScDataAreaExtras* pDataAreaExtras = nullptr ) const; bool GetPrevDataPos(SCROW& rRow) const; bool GetNextDataPos(SCROW& rRow) const; bool TrimEmptyBlocks(SCROW& rRowStart, SCROW& rRowEnd) const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 7d1aac444847..7c798cf08674 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -201,6 +201,7 @@ class ScColumnsRange; struct ScFilterEntries; typedef o3tl::sorted_vector<sal_uInt32> ScCondFormatIndexes; struct ScSheetLimits; +struct ScDataAreaExtras; namespace sc { @@ -1398,18 +1399,20 @@ public: /** Shrink a range to only include used data area. - @param o_bShrunk - Out parameter, true if area was shrunk, false if not. + @param o_bShrunk + Out parameter, true if area was shrunk, false if not. + @param bColumnsOnly + If TRUE, shrink only by columns, not rows. @param bStickyTopRow If TRUE, do not adjust the top row. @param bStickyLeftCol If TRUE, do not adjust the left column. - @param bConsiderCellNotes - If TRUE, consider the presence of cell notes besides data. - @param bConsiderCellDrawObjects - If TRUE, consider the presence of draw objects anchored to the cell. - @param bConsiderCellFormats - If TRUE, consider the presence of cell formats. + @param pDataAreaExtras + Consider additional area attributes like cell + formatting, cell notes and draw objects. The + possibly larger area than the actual cell + content data area is returned within the + struct. @returns true if there is any data, false if not. */ @@ -1417,9 +1420,7 @@ public: SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly, bool bStickyTopRow = false, bool bStickyLeftCol = false, - bool bConsiderCellNotes = false, - bool bConsiderCellDrawObjects = false, - bool bConsiderCellFormats = false ) const; + ScDataAreaExtras* pDataAreaExtras = nullptr ) const; /** * Return the last non-empty row position in given columns that's no diff --git a/sc/inc/sortparam.hxx b/sc/inc/sortparam.hxx index 365151cf2bec..d9047f873b1e 100644 --- a/sc/inc/sortparam.hxx +++ b/sc/inc/sortparam.hxx @@ -37,21 +37,82 @@ struct ScSortKeyState bool bAscending; }; +/** Struct to hold non-data extended area, used with + ScDocument::ShrinkToUsedDataArea(). +*/ +struct ScDataAreaExtras +{ + /// If TRUE, consider the presence of cell notes besides data. + bool mbCellNotes = false; + /// If TRUE, consider the presence of draw objects anchored to the cell. + bool mbCellDrawObjects = false; + /// If TRUE, consider the presence of cell formats. + bool mbCellFormats = false; + SCCOL mnStartCol = SCCOL_MAX; + SCROW mnStartRow = SCROW_MAX; + SCCOL mnEndCol = -1; + SCROW mnEndRow = -1; + + bool anyExtrasWanted() const { return mbCellNotes || mbCellDrawObjects || mbCellFormats; } + void resetArea() { mnStartCol = SCCOL_MAX; mnStartRow = SCROW_MAX; mnEndCol = -1; mnEndRow = -1; } + + bool operator==( const ScDataAreaExtras& rOther ) const + { + // Ignore area range, this is used in ScSortParam::operator==(). + return mbCellNotes == rOther.mbCellNotes + && mbCellDrawObjects == rOther.mbCellDrawObjects + && mbCellFormats == rOther.mbCellFormats; + } + + enum class Clip + { + None, + Col, + Row + }; + + /// Obtain the overall range if area extras are larger. + void GetOverallRange( SCCOL& nCol1, SCROW& nRow1, SCCOL& nCol2, SCROW& nRow2, Clip eClip = Clip::None ) const + { + if (eClip != Clip::Col) + { + if (nCol1 > mnStartCol) + nCol1 = mnStartCol; + if (nCol2 < mnEndCol) + nCol2 = mnEndCol; + } + if (eClip != Clip::Row) + { + if (nRow1 > mnStartRow) + nRow1 = mnStartRow; + if (nRow2 < mnEndRow) + nRow2 = mnEndRow; + } + } + + /// Set the overall range. + void SetOverallRange( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) + { + mnStartCol = nCol1; + mnStartRow = nRow1; + mnEndCol = nCol2; + mnEndRow = nRow2; + } +}; + struct SC_DLLPUBLIC ScSortParam { SCCOL nCol1; SCROW nRow1; SCCOL nCol2; SCROW nRow2; + ScDataAreaExtras aDataAreaExtras; sal_uInt16 nUserIndex; bool bHasHeader; bool bByRow; bool bCaseSens; bool bNaturalSort; - bool bIncludeComments; - bool bIncludeGraphicObjects; bool bUserDef; - bool bIncludePattern; bool bInplace; SCTAB nDestTab; SCCOL nDestCol; @@ -88,13 +149,13 @@ struct ReorderParam * excludes that row / column. */ ScRange maSortRange; + ScDataAreaExtras maDataAreaExtras; /** * List of original column / row positions after reordering. */ std::vector<SCCOLROW> maOrderIndices; bool mbByRow; - bool mbPattern; bool mbHiddenFiltered; bool mbUpdateRefs; bool mbHasHeaders; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 1f68937f87d2..c3ba8d112e9d 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -596,12 +596,11 @@ public: bool ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly, - bool bStickyTopRow, bool bStickyLeftCol, bool bConsiderCellNotes, - bool bConsiderCellDrawObjects, bool bConsiderCellPatterns ) const; + bool bStickyTopRow, bool bStickyLeftCol, + ScDataAreaExtras* pDataAreaExtras ) const; - SCROW GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow, bool bConsiderCellNotes = false, - bool bConsiderCellDrawObjects = false, - bool bConsiderCellPatterns = false ) const; + SCROW GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow, + ScDataAreaExtras* pDataAreaExtras = nullptr ) const; SCSIZE GetEmptyLinesInBlock( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, ScDirection eDir ) const; @@ -1194,10 +1193,17 @@ private: const ScSortParam& rSortParam, SCCOLROW nInd1, SCCOLROW nInd2, bool bKeepQuery, bool bUpdateRefs ); void QuickSort( ScSortInfoArray*, SCCOLROW nLo, SCCOLROW nHi); - void SortReorderByColumn( const ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2, bool bPattern, ScProgress* pProgress ); - - void SortReorderByRow( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress ); - void SortReorderByRowRefUpdate( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress ); + void SortReorderByColumn( const ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2, + bool bPattern, ScProgress* pProgress ); + void SortReorderAreaExtrasByColumn( const ScSortInfoArray* pArray, SCROW nDataRow1, SCROW nDataRow2, + const ScDataAreaExtras& rDataAreaExtras, ScProgress* pProgress ); + + void SortReorderByRow( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, + ScProgress* pProgress, bool bOnlyDataAreaExtras ); + void SortReorderByRowRefUpdate( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, + ScProgress* pProgress ); + void SortReorderAreaExtrasByRow( ScSortInfoArray* pArray, SCCOL nDataCol1, SCCOL nDataCol2, + const ScDataAreaExtras& rDataAreaExtras, ScProgress* pProgress ); bool CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam); bool CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScQueryParam& rQueryParam); diff --git a/sc/qa/unit/ucalc_sort.cxx b/sc/qa/unit/ucalc_sort.cxx index f885fe2be76f..6e54e08952bd 100644 --- a/sc/qa/unit/ucalc_sort.cxx +++ b/sc/qa/unit/ucalc_sort.cxx @@ -253,7 +253,7 @@ void TestSort::testSortHorizontal() aSortData.nRow2 = 3; aSortData.bHasHeader = true; aSortData.bByRow = false; // Sort by column (in horizontal direction). - aSortData.bIncludePattern = true; + aSortData.aDataAreaExtras.mbCellFormats = true; aSortData.maKeyState[0].bDoSort = true; aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; @@ -320,7 +320,7 @@ void TestSort::testSortHorizontalWholeColumn() aSortData.nRow2 = nRow2; aSortData.bHasHeader = false; aSortData.bByRow = false; // Sort by column (in horizontal direction). - aSortData.bIncludePattern = true; + aSortData.aDataAreaExtras.mbCellFormats = true; aSortData.maKeyState[0].bDoSort = true; aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; @@ -381,7 +381,7 @@ void TestSort::testSortSingleRow() aSortData.nRow2 = 0; aSortData.bHasHeader = true; aSortData.bByRow = true; - aSortData.bIncludePattern = true; + aSortData.aDataAreaExtras.mbCellFormats = true; aSortData.maKeyState[0].bDoSort = true; aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; @@ -749,7 +749,7 @@ void TestSort::testSortWithCellFormats() aSortData.nRow1 = 0; aSortData.nRow2 = 3; aSortData.bHasHeader = true; - aSortData.bIncludePattern = true; + aSortData.aDataAreaExtras.mbCellFormats = true; aSortData.maKeyState[0].bDoSort = true; aSortData.maKeyState[0].nField = 0; aSortData.maKeyState[0].bAscending = true; diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 21217e9cbbe1..e6fa9f4f728e 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -41,6 +41,7 @@ #include <scmatrix.hxx> #include <rowheightcontext.hxx> #include <tokenstringcontext.hxx> +#include <sortparam.hxx> #include <editeng/eeitem.hxx> #include <o3tl/safeint.hxx> @@ -1350,19 +1351,20 @@ SCROW ScColumn::GetLastDataPos() const return GetDoc().MaxRow() - static_cast<SCROW>(it->size); } -SCROW ScColumn::GetLastDataPos( SCROW nLastRow, bool bConsiderCellNotes, - bool bConsiderCellDrawObjects, bool bConsiderCellFormats ) const +SCROW ScColumn::GetLastDataPos( SCROW nLastRow, ScDataAreaExtras* pDataAreaExtras ) const { - sc::CellStoreType::const_position_type aPos = maCells.position(std::min(nLastRow,GetDoc().MaxRow())); + nLastRow = std::min( nLastRow, GetDoc().MaxRow()); - if (bConsiderCellNotes && !IsNotesEmptyBlock(nLastRow, nLastRow)) - return nLastRow; - - if (bConsiderCellDrawObjects && !IsDrawObjectsEmptyBlock(nLastRow, nLastRow)) - return nLastRow; + if (pDataAreaExtras && pDataAreaExtras->mnEndRow < nLastRow) + { + // Check in order of likeliness. + if ( (pDataAreaExtras->mbCellFormats && HasVisibleAttrIn(nLastRow, nLastRow)) || + (pDataAreaExtras->mbCellNotes && !IsNotesEmptyBlock(nLastRow, nLastRow)) || + (pDataAreaExtras->mbCellDrawObjects && !IsDrawObjectsEmptyBlock(nLastRow, nLastRow))) + pDataAreaExtras->mnEndRow = nLastRow; + } - if (bConsiderCellFormats && HasVisibleAttrIn(nLastRow, nLastRow)) - return nLastRow; + sc::CellStoreType::const_position_type aPos = maCells.position(nLastRow); if (aPos.first->type != sc::element_type_empty) return nLastRow; @@ -3119,33 +3121,19 @@ void ScColumn::FindDataAreaPos(SCROW& rRow, bool bDown) const rRow = nLastRow; } -bool ScColumn::HasDataAt(SCROW nRow, bool bConsiderCellNotes, bool bConsiderCellDrawObjects, - bool bConsiderCellFormats) const +bool ScColumn::HasDataAt(SCROW nRow, ScDataAreaExtras* pDataAreaExtras ) const { - if (bConsiderCellNotes && !IsNotesEmptyBlock(nRow, nRow)) - return true; - - if (bConsiderCellDrawObjects && !IsDrawObjectsEmptyBlock(nRow, nRow)) - return true; - - if (bConsiderCellFormats && HasVisibleAttrIn(nRow, nRow)) - return true; + if (pDataAreaExtras) + GetDataExtrasAt( nRow, *pDataAreaExtras); return maCells.get_type(nRow) != sc::element_type_empty; } -bool ScColumn::HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, - bool bConsiderCellNotes, bool bConsiderCellDrawObjects, - bool bConsiderCellFormats) const +bool ScColumn::HasDataAt( sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, + ScDataAreaExtras* pDataAreaExtras ) const { - if (bConsiderCellNotes && !IsNotesEmptyBlock(nRow, nRow)) - return true; - - if (bConsiderCellDrawObjects && !IsDrawObjectsEmptyBlock(nRow, nRow)) - return true; - - if (bConsiderCellFormats && HasVisibleAttrIn(nRow, nRow)) - return true; + if (pDataAreaExtras) + GetDataExtrasAt( nRow, *pDataAreaExtras); std::pair<sc::CellStoreType::const_iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow); if (aPos.first == maCells.end()) @@ -3154,17 +3142,11 @@ bool ScColumn::HasDataAt(sc::ColumnBlockConstPosition& rBlockPos, SCROW nRow, return aPos.first->type != sc::element_type_empty; } -bool ScColumn::HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow, - bool bConsiderCellNotes, bool bConsiderCellDrawObjects, bool bConsiderCellFormats) +bool ScColumn::HasDataAt( sc::ColumnBlockPosition& rBlockPos, SCROW nRow, + ScDataAreaExtras* pDataAreaExtras ) { - if (bConsiderCellNotes && !IsNotesEmptyBlock(nRow, nRow)) - return true; - - if (bConsiderCellDrawObjects && !IsDrawObjectsEmptyBlock(nRow, nRow)) - return true; - - if (bConsiderCellFormats && HasVisibleAttrIn(nRow, nRow)) - return true; + if (pDataAreaExtras) + GetDataExtrasAt( nRow, *pDataAreaExtras); std::pair<sc::CellStoreType::iterator,size_t> aPos = maCells.position(rBlockPos.miCellPos, nRow); if (aPos.first == maCells.end()) @@ -3173,6 +3155,23 @@ bool ScColumn::HasDataAt(sc::ColumnBlockPosition& rBlockPos, SCROW nRow, return aPos.first->type != sc::element_type_empty; } +void ScColumn::GetDataExtrasAt( SCROW nRow, ScDataAreaExtras& rDataAreaExtras ) const +{ + if (rDataAreaExtras.mnStartRow <= nRow && nRow <= rDataAreaExtras.mnEndRow) + return; + + // Check in order of likeliness. + if ( (rDataAreaExtras.mbCellFormats && HasVisibleAttrIn(nRow, nRow)) || + (rDataAreaExtras.mbCellNotes && !IsNotesEmptyBlock(nRow, nRow)) || + (rDataAreaExtras.mbCellDrawObjects && !IsDrawObjectsEmptyBlock(nRow, nRow))) + { + if (rDataAreaExtras.mnStartRow > nRow) + rDataAreaExtras.mnStartRow = nRow; + if (rDataAreaExtras.mnEndRow < nRow) + rDataAreaExtras.mnEndRow = nRow; + } +} + bool ScColumn::IsAllAttrEqual( const ScColumn& rCol, SCROW nStartRow, SCROW nEndRow ) const { if (pAttrArray && rCol.pAttrArray) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index c9a30aedc012..86e13f815c91 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -1061,8 +1061,7 @@ bool ScDocument::ShrinkToDataArea(SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly, - bool bStickyTopRow, bool bStickyLeftCol, bool bConsiderCellNotes, - bool bConsiderCellDrawObjects, bool bConsiderCellFormats ) const + bool bStickyTopRow, bool bStickyLeftCol, ScDataAreaExtras* pDataAreaExtras ) const { if (!ValidTab(nTab) || nTab >= static_cast<SCTAB> (maTabs.size()) || !maTabs[nTab]) { @@ -1071,7 +1070,7 @@ bool ScDocument::ShrinkToUsedDataArea( bool& o_bShrunk, SCTAB nTab, SCCOL& rStar } return maTabs[nTab]->ShrinkToUsedDataArea( o_bShrunk, rStartCol, rStartRow, rEndCol, rEndRow, bColumnsOnly, bStickyTopRow, - bStickyLeftCol, bConsiderCellNotes, bConsiderCellDrawObjects, bConsiderCellFormats); + bStickyLeftCol, pDataAreaExtras); } SCROW ScDocument::GetLastDataRow( SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nLastRow ) const diff --git a/sc/source/core/data/sortparam.cxx b/sc/source/core/data/sortparam.cxx index cd98dd07a982..cb369baae99c 100644 --- a/sc/source/core/data/sortparam.cxx +++ b/sc/source/core/data/sortparam.cxx @@ -33,11 +33,13 @@ ScSortParam::ScSortParam() } ScSortParam::ScSortParam( const ScSortParam& r ) : - nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2),nUserIndex(r.nUserIndex), + nCol1(r.nCol1),nRow1(r.nRow1),nCol2(r.nCol2),nRow2(r.nRow2), + aDataAreaExtras(r.aDataAreaExtras), + nUserIndex(r.nUserIndex), bHasHeader(r.bHasHeader),bByRow(r.bByRow),bCaseSens(r.bCaseSens), - bNaturalSort(r.bNaturalSort),bIncludeComments(r.bIncludeComments), - bIncludeGraphicObjects(r.bIncludeGraphicObjects),bUserDef(r.bUserDef), - bIncludePattern(r.bIncludePattern),bInplace(r.bInplace), + bNaturalSort(r.bNaturalSort), + bUserDef(r.bUserDef), + bInplace(r.bInplace), nDestTab(r.nDestTab),nDestCol(r.nDestCol),nDestRow(r.nDestRow), maKeyState( r.maKeyState ), aCollatorLocale( r.aCollatorLocale ), aCollatorAlgorithm( r.aCollatorAlgorithm ), @@ -53,13 +55,14 @@ void ScSortParam::Clear() nCol1=nCol2=nDestCol = 0; nRow1=nRow2=nDestRow = 0; + aDataAreaExtras = ScDataAreaExtras(); + aDataAreaExtras.mbCellDrawObjects = true; + aDataAreaExtras.mbCellFormats = true; nCompatHeader = 2; nDestTab = 0; nUserIndex = 0; bHasHeader=bCaseSens=bUserDef=bNaturalSort = false; - bIncludeComments = false; - bIncludeGraphicObjects = true; - bByRow=bIncludePattern=bInplace = true; + bByRow = bInplace = true; aCollatorLocale = css::lang::Locale(); aCollatorAlgorithm.clear(); @@ -77,15 +80,13 @@ ScSortParam& ScSortParam::operator=( const ScSortParam& r ) nRow1 = r.nRow1; nCol2 = r.nCol2; nRow2 = r.nRow2; + aDataAreaExtras = r.aDataAreaExtras; nUserIndex = r.nUserIndex; bHasHeader = r.bHasHeader; bByRow = r.bByRow; bCaseSens = r.bCaseSens; bNaturalSort = r.bNaturalSort; - bIncludeComments= r.bIncludeComments; - bIncludeGraphicObjects = r.bIncludeGraphicObjects; bUserDef = r.bUserDef; - bIncludePattern = r.bIncludePattern; bInplace = r.bInplace; nDestTab = r.nDestTab; nDestCol = r.nDestCol; @@ -123,15 +124,13 @@ bool ScSortParam::operator==( const ScSortParam& rOther ) const && (nRow1 == rOther.nRow1) && (nCol2 == rOther.nCol2) && (nRow2 == rOther.nRow2) + && (aDataAreaExtras == rOther.aDataAreaExtras) && (bHasHeader == rOther.bHasHeader) && (bByRow == rOther.bByRow) && (bCaseSens == rOther.bCaseSens) && (bNaturalSort == rOther.bNaturalSort) - && (bIncludeComments== rOther.bIncludeComments) - && (bIncludeGraphicObjects == rOther.bIncludeGraphicObjects) && (bUserDef == rOther.bUserDef) && (nUserIndex == rOther.nUserIndex) - && (bIncludePattern == rOther.bIncludePattern) && (bInplace == rOther.bInplace) && (nDestTab == rOther.nDestTab) && (nDestCol == rOther.nDestCol) @@ -155,15 +154,19 @@ bool ScSortParam::operator==( const ScSortParam& rOther ) const } ScSortParam::ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld ) : - nCol1(rSub.nCol1),nRow1(rSub.nRow1),nCol2(rSub.nCol2),nRow2(rSub.nRow2),nUserIndex(rSub.nUserIndex), + nCol1(rSub.nCol1),nRow1(rSub.nRow1),nCol2(rSub.nCol2),nRow2(rSub.nRow2), + aDataAreaExtras(rOld.aDataAreaExtras), + nUserIndex(rSub.nUserIndex), bHasHeader(true),bByRow(true),bCaseSens(rSub.bCaseSens),bNaturalSort(rOld.bNaturalSort), - bIncludeComments(rOld.bIncludeComments),bIncludeGraphicObjects(rOld.bIncludeGraphicObjects), - bUserDef(rSub.bUserDef),bIncludePattern(rSub.bIncludePattern), + bUserDef(rSub.bUserDef), bInplace(true), nDestTab(0),nDestCol(0),nDestRow(0), aCollatorLocale( rOld.aCollatorLocale ), aCollatorAlgorithm( rOld.aCollatorAlgorithm ), nCompatHeader( rOld.nCompatHeader ) { + aDataAreaExtras.mbCellFormats = rSub.bIncludePattern; + aDataAreaExtras.resetArea(); + sal_uInt16 i; // first the groups from the partial results @@ -201,12 +204,14 @@ ScSortParam::ScSortParam( const ScSubTotalParam& rSub, const ScSortParam& rOld ) ScSortParam::ScSortParam( const ScQueryParam& rParam, SCCOL nCol ) : nCol1(nCol),nRow1(rParam.nRow1),nCol2(nCol),nRow2(rParam.nRow2),nUserIndex(0), bHasHeader(rParam.bHasHeader),bByRow(true),bCaseSens(rParam.bCaseSens), - bNaturalSort(false),bIncludeComments(false),bIncludeGraphicObjects(true), + bNaturalSort(false), //TODO: what about Locale and Algorithm? - bUserDef(false),bIncludePattern(false), + bUserDef(false), bInplace(true), nDestTab(0),nDestCol(0),nDestRow(0), nCompatHeader(2) { + aDataAreaExtras.mbCellDrawObjects = true; + ScSortKeyState aKeyState; aKeyState.bDoSort = true; aKeyState.nField = nCol; diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 40aeab42cfa2..67903850927b 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -976,7 +976,7 @@ bool ScTable::GetDataAreaSubrange( ScRange& rRange ) const bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rStartRow, SCCOL& rEndCol, SCROW& rEndRow, bool bColumnsOnly, bool bStickyTopRow, bool bStickyLeftCol, - bool bConsiderCellNotes, bool bConsiderCellDrawObjects, bool bConsiderCellFormats ) const + ScDataAreaExtras* pDataAreaExtras ) const { rStartCol = std::min<SCCOL>( rStartCol, aCol.size()-1 ); // check for rEndCol is done below. @@ -1010,14 +1010,18 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS { if (aCol[rEndCol].IsEmptyBlock( rStartRow, rEndRow)) { - if (bConsiderCellNotes && !aCol[rEndCol].IsNotesEmptyBlock( rStartRow, rEndRow )) - break; - - if (bConsiderCellDrawObjects && !aCol[rEndCol].IsDrawObjectsEmptyBlock( rStartRow, rEndRow )) - break; - - if (bConsiderCellFormats && aCol[rEndCol].HasVisibleAttrIn(rStartRow, rEndRow)) - break; + if (pDataAreaExtras && pDataAreaExtras->mnEndCol < rEndCol) + { + // Check in order of likeliness. + if ( (pDataAreaExtras->mbCellFormats + && aCol[rEndCol].GetPatternCount( rStartRow, rEndRow) > 1 + && aCol[rEndCol].HasVisibleAttrIn( rStartRow, rEndRow)) || + (pDataAreaExtras->mbCellNotes + && !aCol[rEndCol].IsNotesEmptyBlock( rStartRow, rEndRow)) || + (pDataAreaExtras->mbCellDrawObjects + && !aCol[rEndCol].IsDrawObjectsEmptyBlock( rStartRow, rEndRow))) + pDataAreaExtras->mnEndCol = rEndCol; + } --rEndCol; o_bShrunk = true; @@ -1032,14 +1036,18 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS { if (aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow)) { - if (bConsiderCellNotes && !aCol[rStartCol].IsNotesEmptyBlock( rStartRow, rEndRow )) - break; - - if (bConsiderCellDrawObjects && !aCol[rStartCol].IsDrawObjectsEmptyBlock( rStartRow, rEndRow )) - break; - - if (bConsiderCellFormats && aCol[rEndCol].HasVisibleAttrIn(rStartRow, rEndRow)) - break; + if (pDataAreaExtras && pDataAreaExtras->mnStartCol > rStartCol) + { + // Check in order of likeliness. + if ( (pDataAreaExtras->mbCellFormats + && aCol[rStartCol].GetPatternCount( rStartRow, rEndRow) > 1 + && aCol[rStartCol].HasVisibleAttrIn( rStartRow, rEndRow)) || + (pDataAreaExtras->mbCellNotes + && !aCol[rStartCol].IsNotesEmptyBlock( rStartRow, rEndRow)) || + (pDataAreaExtras->mbCellDrawObjects + && !aCol[rStartCol].IsDrawObjectsEmptyBlock( rStartRow, rEndRow))) + pDataAreaExtras->mnStartCol = rStartCol; + } ++rStartCol; o_bShrunk = true; @@ -1058,8 +1066,7 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS bool bFound = false; for (SCCOL i=rStartCol; i<=rEndCol && !bFound; i++) { - if (aCol[i].HasDataAt(rStartRow, bConsiderCellNotes, bConsiderCellDrawObjects, - bConsiderCellFormats)) + if (aCol[i].HasDataAt(rStartRow, pDataAreaExtras)) bFound = true; } if (!bFound) @@ -1074,8 +1081,7 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS while (rStartRow < rEndRow) { - SCROW nLastDataRow = GetLastDataRow(rStartCol, rEndCol, rEndRow, bConsiderCellNotes, - bConsiderCellDrawObjects, bConsiderCellFormats); + SCROW nLastDataRow = GetLastDataRow(rStartCol, rEndCol, rEndRow, pDataAreaExtras); if (0 <= nLastDataRow && nLastDataRow < rEndRow) { rEndRow = std::max( rStartRow, nLastDataRow); @@ -1089,11 +1095,10 @@ bool ScTable::ShrinkToUsedDataArea( bool& o_bShrunk, SCCOL& rStartCol, SCROW& rS return rStartCol != rEndCol || (bColumnsOnly ? !aCol[rStartCol].IsEmptyBlock( rStartRow, rEndRow) : (rStartRow != rEndRow || - aCol[rStartCol].HasDataAt( rStartRow, bConsiderCellNotes, bConsiderCellDrawObjects, bConsiderCellFormats ))); + aCol[rStartCol].HasDataAt( rStartRow, pDataAreaExtras))); } -SCROW ScTable::GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow, bool bConsiderCellNotes, - bool bConsiderCellDrawObjects, bool bConsiderCellFormats ) const +SCROW ScTable::GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow, ScDataAreaExtras* pDataAreaExtras ) const { if ( !IsColValid( nCol1 ) || !ValidCol( nCol2 ) ) return -1; @@ -1103,8 +1108,7 @@ SCROW ScTable::GetLastDataRow( SCCOL nCol1, SCCOL nCol2, SCROW nLastRow, bool bC SCROW nNewLastRow = 0; for (SCCOL i = nCol1; i <= nCol2; ++i) { - SCROW nThis = aCol[i].GetLastDataPos(nLastRow, bConsiderCellNotes, bConsiderCellDrawObjects, - bConsiderCellFormats); + SCROW nThis = aCol[i].GetLastDataPos(nLastRow, pDataAreaExtras); if (nNewLastRow < nThis) nNewLastRow = nThis; } diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 20e16b455c29..1958a7044d05 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -396,16 +396,26 @@ public: } }; +// Assume that we can handle 512MB, which with a ~100 bytes +// ScSortInfoArray::Cell element for 500MB are about 5 million cells plus +// overhead in one chunk. +constexpr sal_Int32 kSortCellsChunk = 500 * 1024 * 1024 / sizeof(ScSortInfoArray::Cell); + namespace { void initDataRows( ScSortInfoArray& rArray, ScTable& rTab, ScColContainer& rCols, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - bool bPattern, bool bHiddenFiltered ) + bool bHiddenFiltered, bool bPattern, bool bCellNotes, bool bCellDrawObjects, bool bOnlyDataAreaExtras ) { // Fill row-wise data table. ScSortInfoArray::RowsType& rRows = rArray.InitDataRows(nRow2-nRow1+1, nCol2-nCol1+1); + const std::vector<SCCOLROW>& rOrderIndices = rArray.GetOrderIndices(); + assert(!bOnlyDataAreaExtras || (rOrderIndices.size() == static_cast<size_t>(nRow2 - nRow1 + 1) + && nRow1 == rArray.GetStart())); + + ScDrawLayer* pDrawLayer = (bCellDrawObjects ? rTab.GetDoc().GetDrawLayer() : nullptr); for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) { ScColumn& rCol = rCols[nCol]; @@ -416,17 +426,21 @@ void initDataRows( sc::ColumnBlockConstPosition aBlockPos; rCol.InitBlockPosition(aBlockPos); std::map<SCROW, std::vector<SdrObject*>> aRowDrawObjects; - ScDrawLayer* pDrawLayer = rTab.GetDoc().GetDrawLayer(); if (pDrawLayer) aRowDrawObjects = pDrawLayer->GetObjectsAnchoredToRange(rTab.GetTab(), nCol, nRow1, nRow2); - for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + for (SCROW nR = nRow1; nR <= nRow2; ++nR) { - ScSortInfoArray::Row& rRow = rRows[nRow-nRow1]; + const SCROW nRow = (bOnlyDataAreaExtras ? rOrderIndices[nR - rArray.GetStart()] : nR); + ScSortInfoArray::Row& rRow = rRows[nR-nRow1]; ScSortInfoArray::Cell& rCell = rRow.maCells[nCol-nCol1]; - rCell.maCell = rCol.GetCellValue(aBlockPos, nRow); - rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow); - rCell.mpNote = rCol.GetCellNote(aBlockPos, nRow); + if (!bOnlyDataAreaExtras) + { + rCell.maCell = rCol.GetCellValue(aBlockPos, nRow); + rCell.mpAttr = rCol.GetCellTextAttr(aBlockPos, nRow); + } + if (bCellNotes) + rCell.mpNote = rCol.GetCellNote(aBlockPos, nRow); if (pDrawLayer) rCell.maDrawObjects = aRowDrawObjects[nRow]; @@ -435,7 +449,7 @@ void initDataRows( } } - if (bHiddenFiltered) + if (!bOnlyDataAreaExtras && bHiddenFiltered) { for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) { @@ -464,9 +478,8 @@ std::unique_ptr<ScSortInfoArray> ScTable::CreateSortInfoArray( const sc::Reorder pArray->SetKeepQuery(rParam.mbHiddenFiltered); pArray->SetUpdateRefs(rParam.mbUpdateRefs); - initDataRows( - *pArray, *this, aCol, nCol1, nRow1, nCol2, nRow2, - rParam.mbPattern, rParam.mbHiddenFiltered); + initDataRows( *pArray, *this, aCol, nCol1, nRow1, nCol2, nRow2, rParam.mbHiddenFiltered, + rParam.maDataAreaExtras.mbCellFormats, true, true, false); } else { @@ -508,9 +521,8 @@ std::unique_ptr<ScSortInfoArray> ScTable::CreateSortInfoArray( } } - initDataRows( - *pArray, *this, aCol, rSortParam.nCol1, nInd1, rSortParam.nCol2, nInd2, - rSortParam.bIncludePattern, bKeepQuery); + initDataRows( *pArray, *this, aCol, rSortParam.nCol1, nInd1, rSortParam.nCol2, nInd2, bKeepQuery, + rSortParam.aDataAreaExtras.mbCellFormats, true, true, false); } else { @@ -676,8 +688,11 @@ void fillSortedColumnArray( std::vector<std::unique_ptr<SortedColumn>>& rSortedCols, SortedRowFlags& rRowFlags, std::vector<SvtListener*>& rCellListeners, - ScSortInfoArray* pArray, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress, const ScTable* pTable ) + ScSortInfoArray* pArray, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress, const ScTable* pTable, + bool bOnlyDataAreaExtras ) { + assert(!bOnlyDataAreaExtras || !pArray->IsUpdateRefs()); + SCROW nRow1 = pArray->GetStart(); ScSortInfoArray::RowsType* pRows = pArray->GetDataRows(); std::vector<SCCOLROW> aOrderIndices = pArray->GetOrderIndices(); @@ -696,72 +711,83 @@ void fillSortedColumnArray( for (size_t i = 0; i < pRows->size(); ++i) { + const SCROW nRow = nRow1 + i; + ScSortInfoArray::Row& rRow = (*pRows)[i]; for (size_t j = 0; j < rRow.maCells.size(); ++j) { - ScAddress aCellPos(nCol1 + j, nRow1 + i, nTab); - ScSortInfoArray::Cell& rCell = rRow.maCells[j]; - sc::CellStoreType& rCellStore = aSortedCols.at(j)->maCells; - switch (rCell.maCell.meType) + // If bOnlyDataAreaExtras, + // sc::CellStoreType aSortedCols.at(j)->maCells + // and + // sc::CellTextAttrStoreType aSortedCols.at(j)->maCellTextAttrs + // are by definition all empty mdds::multi_type_vector, so nothing + // needs to be done to push *all* empty. + + if (!bOnlyDataAreaExtras) { - case CELLTYPE_STRING: - assert(rCell.mpAttr); - rCellStore.push_back(*rCell.maCell.mpString); - break; - case CELLTYPE_VALUE: - assert(rCell.mpAttr); - rCellStore.push_back(rCell.maCell.mfValue); - break; - case CELLTYPE_EDIT: - assert(rCell.mpAttr); - rCellStore.push_back(rCell.maCell.mpEditText->Clone().release()); - break; - case CELLTYPE_FORMULA: + sc::CellStoreType& rCellStore = aSortedCols.at(j)->maCells; + switch (rCell.maCell.meType) { - assert(rCell.mpAttr); - ScAddress aOldPos = rCell.maCell.mpFormula->aPos; - - ScFormulaCell* pNew = rCell.maCell.mpFormula->Clone( aCellPos ); - if (pArray->IsUpdateRefs()) - { - pNew->CopyAllBroadcasters(*rCell.maCell.mpFormula); - pNew->GetCode()->AdjustReferenceOnMovedOrigin(aOldPos, aCellPos); - } - else - { - pNew->GetCode()->AdjustReferenceOnMovedOriginIfOtherSheet(aOldPos, aCellPos); - } - - if (!rCellListeners.empty()) - { - // Original source cells will be deleted during - // sc::CellStoreType::transfer(), SvtListener is a base - // class, so we need to replace it. - auto it( ::std::find( rCellListeners.begin(), rCellListeners.end(), rCell.maCell.mpFormula)); - if (it != rCellListeners.end()) - *it = pNew; - } - - rCellStore.push_back(pNew); + case CELLTYPE_STRING: + assert(rCell.mpAttr); + rCellStore.push_back(*rCell.maCell.mpString); + break; + case CELLTYPE_VALUE: + assert(rCell.mpAttr); + rCellStore.push_back(rCell.maCell.mfValue); + break; + case CELLTYPE_EDIT: + assert(rCell.mpAttr); + rCellStore.push_back(rCell.maCell.mpEditText->Clone().release()); + break; + case CELLTYPE_FORMULA: + { + assert(rCell.mpAttr); + ScAddress aOldPos = rCell.maCell.mpFormula->aPos; + + const ScAddress aCellPos(nCol1 + j, nRow, nTab); + ScFormulaCell* pNew = rCell.maCell.mpFormula->Clone( aCellPos ); + if (pArray->IsUpdateRefs()) + { + pNew->CopyAllBroadcasters(*rCell.maCell.mpFormula); + pNew->GetCode()->AdjustReferenceOnMovedOrigin(aOldPos, aCellPos); + } + else + { + pNew->GetCode()->AdjustReferenceOnMovedOriginIfOtherSheet(aOldPos, aCellPos); + } + + if (!rCellListeners.empty()) + { + // Original source cells will be deleted during + // sc::CellStoreType::transfer(), SvtListener is a base + // class, so we need to replace it. + auto it( ::std::find( rCellListeners.begin(), rCellListeners.end(), rCell.maCell.mpFormula)); + if (it != rCellListeners.end()) + *it = pNew; + } + + rCellStore.push_back(pNew); + } + break; + default: + //assert(!rCell.mpAttr); + // This assert doesn't hold, for example + // CopyCellsFromClipHandler may omit copying cells during + // PasteSpecial for which CopyTextAttrsFromClipHandler + // still copies a CellTextAttr. So if that really is not + // expected then fix it there. + rCellStore.push_back_empty(); } - break; - default: - //assert(!rCell.mpAttr); - // This assert doesn't hold, for example - // CopyCellsFromClipHandler may omit copying cells during - // PasteSpecial for which CopyTextAttrsFromClipHandler - // still copies a CellTextAttr. So if that really is not - // expected then fix it there. - rCellStore.push_back_empty(); - } - - sc::CellTextAttrStoreType& rAttrStore = aSortedCols.at(j)->maCellTextAttrs; - if (rCell.mpAttr) - rAttrStore.push_back(*rCell.mpAttr); - else - rAttrStore.push_back_empty(); + + sc::CellTextAttrStoreType& rAttrStore = aSortedCols.at(j)->maCellTextAttrs; + if (rCell.mpAttr) + rAttrStore.push_back(*rCell.mpAttr); + else + rAttrStore.push_back_empty(); + } if (pArray->IsUpdateRefs()) { @@ -788,13 +814,12 @@ void fillSortedColumnArray( aSortedCols.at(j)->maCellDrawObjects.push_back(rCell.maDrawObjects); if (rCell.mpPattern) - aSortedCols.at(j)->setPattern(aCellPos.Row(), rCell.mpPattern); + aSortedCols.at(j)->setPattern(nRow, rCell.mpPattern); } - if (pArray->IsKeepQuery()) + if (!bOnlyDataAreaExtras && pArray->IsKeepQuery()) { // Hidden and filtered flags are first converted to segments. - SCROW nRow = nRow1 + i; aRowFlags.setRowHidden(nRow, rRow.mbHidden); aRowFlags.setRowFiltered(nRow, rRow.mbFiltered); } @@ -874,6 +899,51 @@ public: } +void ScTable::SortReorderAreaExtrasByRow( ScSortInfoArray* pArray, + SCCOL nDataCol1, SCCOL nDataCol2, + const ScDataAreaExtras& rDataAreaExtras, ScProgress* pProgress ) +{ + const SCROW nRow1 = pArray->GetStart(); + const SCROW nLastRow = pArray->GetLast(); + const SCCOL nChunkCols = std::max<SCCOL>( 1, kSortCellsChunk / (nLastRow - nRow1 + 1)); + // Before data area. + for (SCCOL nCol = rDataAreaExtras.mnStartCol; nCol < nDataCol1; nCol += nChunkCols) + { + const SCCOL nEndCol = std::min<SCCOL>( nCol + nChunkCols - 1, nDataCol1 - 1); + initDataRows( *pArray, *this, aCol, nCol, nRow1, nEndCol, nLastRow, false, + rDataAreaExtras.mbCellFormats, rDataAreaExtras.mbCellNotes, rDataAreaExtras.mbCellDrawObjects, true); + SortReorderByRow( pArray, nCol, nEndCol, pProgress, true); + } + // Behind data area. + for (SCCOL nCol = nDataCol2 + 1; nCol <= rDataAreaExtras.mnEndCol; nCol += nChunkCols) + { + const SCCOL nEndCol = std::min<SCCOL>( nCol + nChunkCols - 1, rDataAreaExtras.mnEndCol); + initDataRows( *pArray, *this, aCol, nCol, nRow1, nEndCol, nLastRow, false, + rDataAreaExtras.mbCellFormats, rDataAreaExtras.mbCellNotes, rDataAreaExtras.mbCellDrawObjects, true); + SortReorderByRow( pArray, nCol, nEndCol, pProgress, true); + } +} + +void ScTable::SortReorderAreaExtrasByColumn( const ScSortInfoArray* pArray, + SCROW nDataRow1, SCROW nDataRow2, const ScDataAreaExtras& rDataAreaExtras, ScProgress* pProgress ) +{ + const SCCOL nCol1 = static_cast<SCCOL>(pArray->GetStart()); + const SCCOL nLastCol = static_cast<SCCOL>(pArray->GetLast()); + const SCROW nChunkRows = std::max<SCROW>( 1, kSortCellsChunk / (nLastCol - nCol1 + 1)); + // Above data area. + for (SCROW nRow = rDataAreaExtras.mnStartRow; nRow < nDataRow1; nRow += nChunkRows) + { + const SCROW nEndRow = std::min<SCROW>( nRow + nChunkRows - 1, nDataRow1 - 1); + SortReorderByColumn( pArray, nRow, nEndRow, rDataAreaExtras.mbCellFormats, pProgress); + } + // Below data area. + for (SCROW nRow = nDataRow2 + 1; nRow <= rDataAreaExtras.mnEndRow; nRow += nChunkRows) + { + const SCROW nEndRow = std::min<SCROW>( nRow + nChunkRows - 1, rDataAreaExtras.mnEndRow); + SortReorderByColumn( pArray, nRow, nEndRow, rDataAreaExtras.mbCellFormats, pProgress); + } +} + void ScTable::SortReorderByColumn( const ScSortInfoArray* pArray, SCROW nRow1, SCROW nRow2, bool bPattern, ScProgress* pProgress ) { @@ -1016,14 +1086,20 @@ void ScTable::SortReorderByColumn( } } -void ScTable::SortReorderByRow( - ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, ScProgress* pProgress ) +void ScTable::SortReorderByRow( ScSortInfoArray* pArray, SCCOL nCol1, SCCOL nCol2, + ScProgress* pProgress, bool bOnlyDataAreaExtras ) { assert(!pArray->IsUpdateRefs()); if (nCol2 < nCol1) return; + // bOnlyDataAreaExtras: + // Data area extras by definition do not have any cell content so no + // formula cells either, so that handling doesn't need to be executed. + // However, there may be listeners of formulas listening to broadcasters of + // empty cells. + SCROW nRow1 = pArray->GetStart(); SCROW nRow2 = pArray->GetLast(); @@ -1033,6 +1109,7 @@ void ScTable::SortReorderByRow( // When the update ref mode is disabled, we need to detach all formula // cells in the sorted range before reordering, and re-start them // afterward. + if (!bOnlyDataAreaExtras) { sc::EndListeningContext aCxt(rDocument); DetachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2); @@ -1058,33 +1135,40 @@ void ScTable::SortReorderByRow( } // Split formula groups at the sort range boundaries (if applicable). - std::vector<SCROW> aRowBounds; - aRowBounds.reserve(2); - aRowBounds.push_back(nRow1); - aRowBounds.push_back(nRow2+1); - for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) - SplitFormulaGroups(nCol, aRowBounds); + if (!bOnlyDataAreaExtras) + { + std::vector<SCROW> aRowBounds; + aRowBounds.reserve(2); + aRowBounds.push_back(nRow1); + aRowBounds.push_back(nRow2+1); + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + SplitFormulaGroups(nCol, aRowBounds); + } // Cells in the data rows only reference values in the document. Make // a copy before updating the document. std::vector<std::unique_ptr<SortedColumn>> aSortedCols; // storage for copied cells. SortedRowFlags aRowFlags(GetDoc().GetSheetLimits()); - fillSortedColumnArray(aSortedCols, aRowFlags, aCellListeners, pArray, nTab, nCol1, nCol2, pProgress, this); + fillSortedColumnArray(aSortedCols, aRowFlags, aCellListeners, pArray, nTab, nCol1, nCol2, + pProgress, this, bOnlyDataAreaExtras); for (size_t i = 0, n = aSortedCols.size(); i < n; ++i) { SCCOL nThisCol = i + nCol1; + if (!bOnlyDataAreaExtras) { - sc::CellStoreType& rDest = aCol[nThisCol].maCells; - sc::CellStoreType& rSrc = aSortedCols[i]->maCells; - rSrc.transfer(nRow1, nRow2, rDest, nRow1); - } + { + sc::CellStoreType& rDest = aCol[nThisCol].maCells; + sc::CellStoreType& rSrc = aSortedCols[i]->maCells; + rSrc.transfer(nRow1, nRow2, rDest, nRow1); + } - { - sc::CellTextAttrStoreType& rDest = aCol[nThisCol].maCellTextAttrs; - sc::CellTextAttrStoreType& rSrc = aSortedCols[i]->maCellTextAttrs; - rSrc.transfer(nRow1, nRow2, rDest, nRow1); + { + sc::CellTextAttrStoreType& rDest = aCol[nThisCol].maCellTextAttrs; + sc::CellTextAttrStoreType& rSrc = aSortedCols[i]->maCellTextAttrs; + rSrc.transfer(nRow1, nRow2, rDest, nRow1); + } } { @@ -1122,7 +1206,7 @@ void ScTable::SortReorderByRow( aCol[nThisCol].CellStorageModified(); } - if (pArray->IsKeepQuery()) + if (!bOnlyDataAreaExtras && pArray->IsKeepQuery()) { aRowFlags.maRowsHidden.build_tree(); aRowFlags.maRowsFiltered.build_tree(); @@ -1150,13 +1234,16 @@ void ScTable::SortReorderByRow( l->Notify(aHint); } - // Re-group columns in the sorted range too. - for (SCCOL i = nCol1; i <= nCol2; ++i) - aCol[i].RegroupFormulaCells(); - + if (!bOnlyDataAreaExtras) { - sc::StartListeningContext aCxt(rDocument); - AttachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2); + // Re-group columns in the sorted range too. + for (SCCOL i = nCol1; i <= nCol2; ++i) + aCol[i].RegroupFormulaCells(); + + { + sc::StartListeningContext aCxt(rDocument); + AttachFormulaCells(aCxt, nCol1, nRow1, nCol2, nRow2); + } } } @@ -1255,7 +1342,7 @@ void ScTable::SortReorderByRowRefUpdate( std::vector<std::unique_ptr<SortedColumn>> aSortedCols; // storage for copied cells. SortedRowFlags aRowFlags(GetDoc().GetSheetLimits()); std::vector<SvtListener*> aListenersDummy; - fillSortedColumnArray(aSortedCols, aRowFlags, aListenersDummy, pArray, nTab, nCol1, nCol2, pProgress, this); + fillSortedColumnArray(aSortedCols, aRowFlags, aListenersDummy, pArray, nTab, nCol1, nCol2, pProgress, this, false); for (size_t i = 0, n = aSortedCols.size(); i < n; ++i) { @@ -1701,8 +1788,8 @@ void ScTable::Sort( if (pUndo) { // Copy over the basic sort parameters. + pUndo->maDataAreaExtras = rSortParam.aDataAreaExtras; pUndo->mbByRow = rSortParam.bByRow; - pUndo->mbPattern = rSortParam.bIncludePattern; pUndo->mbHiddenFiltered = bKeepQuery; pUndo->mbUpdateRefs = bUpdateRefs; pUndo->mbHasHeaders = rSortParam.bHasHeader; @@ -1713,14 +1800,15 @@ void ScTable::Sort( aSortParam = rSortParam; // must be assigned before calling IsSorted() if (rSortParam.bByRow) { - SCROW nLastRow = rSortParam.nRow2; - SCROW nRow1 = (rSortParam.bHasHeader ? rSortParam.nRow1 + 1 : rSortParam.nRow1); + const SCROW nLastRow = rSortParam.nRow2; + const SCROW nRow1 = (rSortParam.bHasHeader ? rSortParam.nRow1 + 1 : rSortParam.nRow1); if (nRow1 < nLastRow && !IsSorted(nRow1, nLastRow)) { if(pProgress) pProgress->SetState( 0, nLastRow-nRow1 ); - std::unique_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(aSortParam, nRow1, nLastRow, bKeepQuery, bUpdateRefs)); + std::unique_ptr<ScSortInfoArray> pArray( CreateSortInfoArray( + aSortParam, nRow1, nLastRow, bKeepQuery, bUpdateRefs)); if ( nLastRow - nRow1 > 255 ) DecoladeRow(pArray.get(), nRow1, nLastRow); @@ -1729,32 +1817,46 @@ void ScTable::Sort( if (pArray->IsUpdateRefs()) SortReorderByRowRefUpdate(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress); else - SortReorderByRow(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress); + { + SortReorderByRow(pArray.get(), aSortParam.nCol1, aSortParam.nCol2, pProgress, false); + if (rSortParam.aDataAreaExtras.anyExtrasWanted()) + SortReorderAreaExtrasByRow( pArray.get(), aSortParam.nCol1, aSortParam.nCol2, + rSortParam.aDataAreaExtras, pProgress); + } if (pUndo) { + // Stored is the first data row without header row. pUndo->maSortRange = ScRange(rSortParam.nCol1, nRow1, nTab, rSortParam.nCol2, nLastRow, nTab); + pUndo->maDataAreaExtras.mnStartRow = nRow1; pUndo->maOrderIndices = pArray->GetOrderIndices(); } } } else { - SCCOL nLastCol = rSortParam.nCol2; - SCCOL nCol1 = (rSortParam.bHasHeader ? rSortParam.nCol1 + 1 : rSortParam.nCol1); + const SCCOL nLastCol = rSortParam.nCol2; + const SCCOL nCol1 = (rSortParam.bHasHeader ? rSortParam.nCol1 + 1 : rSortParam.nCol1); if (nCol1 < nLastCol && !IsSorted(nCol1, nLastCol)) { if(pProgress) pProgress->SetState( 0, nLastCol-nCol1 ); - std::unique_ptr<ScSortInfoArray> pArray(CreateSortInfoArray(aSortParam, nCol1, nLastCol, bKeepQuery, bUpdateRefs)); + std::unique_ptr<ScSortInfoArray> pArray( CreateSortInfoArray( + aSortParam, nCol1, nLastCol, bKeepQuery, bUpdateRefs)); QuickSort(pArray.get(), nCol1, nLastCol); - SortReorderByColumn(pArray.get(), aSortParam.nRow1, aSortParam.nRow2, aSortParam.bIncludePattern, pProgress); + SortReorderByColumn(pArray.get(), rSortParam.nRow1, rSortParam.nRow2, + rSortParam.aDataAreaExtras.mbCellFormats, pProgress); + if (rSortParam.aDataAreaExtras.anyExtrasWanted() && !pArray->IsUpdateRefs()) + SortReorderAreaExtrasByColumn( pArray.get(), + rSortParam.nRow1, rSortParam.nRow2, rSortParam.aDataAreaExtras, pProgress); if (pUndo) { + // Stored is the first data column without header column. pUndo->maSortRange = ScRange(nCol1, aSortParam.nRow1, nTab, nLastCol, aSortParam.nRow2, nTab); + pUndo->maDataAreaExtras.mnStartCol = nCol1; pUndo->maOrderIndices = pArray->GetOrderIndices(); } } @@ -1779,8 +1881,14 @@ void ScTable::Reorder( const sc::ReorderParam& rParam ) SortReorderByRowRefUpdate( pArray.get(), rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), nullptr); else - SortReorderByRow( - pArray.get(), rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), nullptr); + { + SortReorderByRow( pArray.get(), + rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), nullptr, false); + if (rParam.maDataAreaExtras.anyExtrasWanted()) + SortReorderAreaExtrasByRow( pArray.get(), + rParam.maSortRange.aStart.Col(), rParam.maSortRange.aEnd.Col(), + rParam.maDataAreaExtras, nullptr); + } } else { @@ -1788,7 +1896,11 @@ void ScTable::Reorder( const sc::ReorderParam& rParam ) pArray->SetOrderIndices(rParam.maOrderIndices); SortReorderByColumn( pArray.get(), rParam.maSortRange.aStart.Row(), rParam.maSortRange.aEnd.Row(), - rParam.mbPattern, nullptr); + rParam.maDataAreaExtras.mbCellFormats, nullptr); + if (rParam.maDataAreaExtras.anyExtrasWanted() && !pArray->IsUpdateRefs()) + SortReorderAreaExtrasByColumn( pArray.get(), + rParam.maSortRange.aStart.Row(), rParam.maSortRange.aEnd.Row(), + rParam.maDataAreaExtras, nullptr); } } diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx index 106f24e593c2..b1ef4474881c 100644 --- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx @@ -71,7 +71,7 @@ void writeSort(ScXMLExport& mrExport, const ScSortParam& aParam, const ScRange& ScAddress aOutPos(aParam.nDestCol, aParam.nDestRow, aParam.nDestTab); - if (!aParam.bIncludePattern) + if (!aParam.aDataAreaExtras.mbCellFormats) mrExport.AddAttribute(XML_NAMESPACE_TABLE, XML_BIND_STYLES_TO_CONTENT, XML_FALSE); if (!aParam.bInplace) diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx index eaeb319dd1b8..7d1c50594e4c 100644 --- a/sc/source/ui/app/transobj.cxx +++ b/sc/source/ui/app/transobj.cxx @@ -50,6 +50,7 @@ #include <docfunc.hxx> #include <scmod.hxx> #include <dragdata.hxx> +#include <sortparam.hxx> #include <editeng/paperinf.hxx> #include <editeng/sizeitem.hxx> @@ -252,10 +253,23 @@ static ScRange lcl_reduceBlock(const ScDocument& rDoc, ScRange aReducedBlock, bo SCROW nStartRow = aReducedBlock.aStart.Row(); SCCOL nEndCol = aReducedBlock.aEnd.Col(); SCROW nEndRow = aReducedBlock.aEnd.Row(); - bool bShrunk = false; - rDoc.ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, - false, bIncludeVisual /*bStickyTopRow*/, bIncludeVisual /*bStickyLeftCol*/, - bIncludeVisual /*bConsiderCellNotes*/, bIncludeVisual /*bConsiderCellDrawObjects*/); + + if (bIncludeVisual) + { + ScDataAreaExtras aDataAreaExtras; + aDataAreaExtras.mbCellNotes = true; + aDataAreaExtras.mbCellDrawObjects = true; + bool bShrunk = false; + rDoc.ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, + false, true /*bStickyTopRow*/, true /*bStickyLeftCol*/, &aDataAreaExtras); + aDataAreaExtras.GetOverallRange( nStartCol, nStartRow, nEndCol, nEndRow, ScDataAreaExtras::Clip::None); + } + else + { + bool bShrunk = false; + rDoc.ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, + false, false /*bStickyTopRow*/, false /*bStickyLeftCol*/); + } if ( nPrintAreaEndRow > nEndRow ) nEndRow = nPrintAreaEndRow; diff --git a/sc/source/ui/dbgui/tpsort.cxx b/sc/source/ui/dbgui/tpsort.cxx index 87989f0069d7..c9c1c15c04ab 100644 --- a/sc/source/ui/dbgui/tpsort.cxx +++ b/sc/source/ui/dbgui/tpsort.cxx @@ -600,11 +600,11 @@ void ScTabPageSortOptions::Reset( const SfxItemSet* /* rArgSet */ ) } m_xBtnCase->set_active( aSortData.bCaseSens ); - m_xBtnFormats->set_active( aSortData.bIncludePattern ); + m_xBtnFormats->set_active( aSortData.aDataAreaExtras.mbCellFormats ); m_xBtnHeader->set_active( aSortData.bHasHeader ); m_xBtnNaturalSort->set_active( aSortData.bNaturalSort ); - m_xBtnIncComments->set_active( aSortData.bIncludeComments ); - m_xBtnIncImages->set_active( aSortData.bIncludeGraphicObjects ); + m_xBtnIncComments->set_active( aSortData.aDataAreaExtras.mbCellNotes ); + m_xBtnIncImages->set_active( aSortData.aDataAreaExtras.mbCellDrawObjects ); if ( aSortData.bByRow ) { @@ -669,9 +669,9 @@ bool ScTabPageSortOptions::FillItemSet( SfxItemSet* rArgSet ) aNewSortData.bHasHeader = m_xBtnHeader->get_active(); aNewSortData.bCaseSens = m_xBtnCase->get_active(); aNewSortData.bNaturalSort = m_xBtnNaturalSort->get_active(); - aNewSortData.bIncludeComments= m_xBtnIncComments->get_active(); - aNewSortData.bIncludeGraphicObjects = m_xBtnIncImages->get_active(); - aNewSortData.bIncludePattern = m_xBtnFormats->get_active(); + aNewSortData.aDataAreaExtras.mbCellNotes = m_xBtnIncComments->get_active(); + aNewSortData.aDataAreaExtras.mbCellDrawObjects = m_xBtnIncImages->get_active(); + aNewSortData.aDataAreaExtras.mbCellFormats = m_xBtnFormats->get_active(); aNewSortData.bInplace = !m_xBtnCopyResult->get_active(); aNewSortData.nDestCol = theOutPos.Col(); aNewSortData.nDestRow = theOutPos.Row(); diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 3cdee27ffb1d..35374ded6acf 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -522,25 +522,58 @@ bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, return false; } + const ScInputOptions aInputOption = SC_MOD()->GetInputOptions(); + const bool bUpdateRefs = aInputOption.GetSortRefUpdate(); + // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or // column (depending on direction) in any case, not just if it has headers, // so empty leading cells will be sorted to the end. + // aLocalParam.nCol/Row will encompass data content only, extras in + // aLocalParam.aDataAreaExtras. bool bShrunk = false; + aLocalParam.aDataAreaExtras.resetArea(); rDoc.ShrinkToUsedDataArea(bShrunk, nTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2, aLocalParam.nRow2, false, aLocalParam.bByRow, - !aLocalParam.bByRow, aLocalParam.bIncludeComments, - aLocalParam.bIncludeGraphicObjects, aLocalParam.bIncludePattern); + !aLocalParam.bByRow, + (aLocalParam.aDataAreaExtras.anyExtrasWanted() ? + &aLocalParam.aDataAreaExtras : nullptr)); SCROW nStartRow = aLocalParam.nRow1; if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2) ++nStartRow; - if ( aLocalParam.bIncludePattern && rDoc.HasAttrib( - aLocalParam.nCol1, nStartRow , nTab, - aLocalParam.nCol2, aLocalParam.nRow2, nTab, - HasAttrFlags::Merged | HasAttrFlags::Overlapped ) ) + SCCOL nOverallCol1 = aLocalParam.nCol1; + SCROW nOverallRow1 = aLocalParam.nRow1; + SCCOL nOverallCol2 = aLocalParam.nCol2; + SCROW nOverallRow2 = aLocalParam.nRow2; + if (aLocalParam.aDataAreaExtras.anyExtrasWanted()) + { + // Trailing empty excess columns/rows are excluded from being sorted, + // they stick at the end. Clip them. + const ScDataAreaExtras::Clip eClip = (aLocalParam.bByRow ? + ScDataAreaExtras::Clip::Row : ScDataAreaExtras::Clip::Col); + aLocalParam.aDataAreaExtras.GetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2, eClip); + // Make it permanent. + aLocalParam.aDataAreaExtras.SetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2); + + if (bUpdateRefs) + { + // With update references the entire range needs to be handled as + // one entity for references pointing within to be moved along, + // even when there's no data content. For huge ranges we may be + // DOOMed then. + aLocalParam.nCol1 = nOverallCol1; + aLocalParam.nRow1 = nOverallRow1; + aLocalParam.nCol2 = nOverallCol2; + aLocalParam.nRow2 = nOverallRow2; + } + } + + if (aLocalParam.aDataAreaExtras.mbCellFormats + && rDoc.HasAttrib( nOverallCol1, nStartRow, nTab, nOverallCol2, nOverallRow2, nTab, + HasAttrFlags::Merged | HasAttrFlags::Overlapped)) { - // merge attributes would be mixed up during sorting + // Merge attributes would be mixed up during sorting. if (!bApi) rDocShell.ErrorMessage(STR_SORT_ERR_MERGED); return false; @@ -559,8 +592,7 @@ bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, aLocalParam.nRow2-nStartRow+1); // No point adjusting row heights after the sort when all rows have the same height. - bool bUniformRowHeight = - rDoc.HasUniformRowHeight(nTab, nStartRow, aLocalParam.nRow2); + bool bUniformRowHeight = rDoc.HasUniformRowHeight(nTab, nStartRow, nOverallRow2); bool bRepeatQuery = false; // repeat existing filter? ScQueryParam aQueryParam; @@ -573,8 +605,6 @@ bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set) if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort) { - ScInputOptions aInputOption = SC_MOD()->GetInputOptions(); - bool bUpdateRefs = aInputOption.GetSortRefUpdate(); ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, true); if (!bRepeatQuery) bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, nTab); @@ -623,10 +653,10 @@ bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, if (bPaint) { PaintPartFlags nPaint = PaintPartFlags::Grid; - SCCOL nStartX = aLocalParam.nCol1; - SCROW nStartY = aLocalParam.nRow1; - SCCOL nEndX = aLocalParam.nCol2; - SCROW nEndY = aLocalParam.nRow2; + SCCOL nStartX = nOverallCol1; + SCROW nStartY = nOverallRow1; + SCCOL nEndX = nOverallCol2; + SCROW nEndY = nOverallRow2; if ( bRepeatQuery ) { nPaint |= PaintPartFlags::Left; @@ -636,8 +666,8 @@ bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam, rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint); } - if (!bUniformRowHeight && nStartRow <= aLocalParam.nRow2) - rDocShell.AdjustRowHeight(nStartRow, aLocalParam.nRow2, nTab); + if (!bUniformRowHeight && nStartRow <= nOverallRow2) + rDocShell.AdjustRowHeight(nStartRow, nOverallRow2, nTab); aModificator.SetDocumentModified(); diff --git a/sc/source/ui/undo/undosort.cxx b/sc/source/ui/undo/undosort.cxx index e881c09ea7d3..ed65c760e8f4 100644 --- a/sc/source/ui/undo/undosort.cxx +++ b/sc/source/ui/undo/undosort.cxx @@ -45,9 +45,18 @@ void UndoSort::Execute( bool bUndo ) aParam.reverse(); rDoc.Reorder(aParam); + ScRange aOverallRange( maParam.maSortRange); + if (maParam.maDataAreaExtras.anyExtrasWanted()) + { + aOverallRange.aStart.SetCol( maParam.maDataAreaExtras.mnStartCol); + aOverallRange.aStart.SetRow( maParam.maDataAreaExtras.mnStartRow); + aOverallRange.aEnd.SetCol( maParam.maDataAreaExtras.mnEndCol); + aOverallRange.aEnd.SetRow( maParam.maDataAreaExtras.mnEndRow); + } + if (maParam.mbHasHeaders) { - ScRange aMarkRange( maParam.maSortRange); + ScRange aMarkRange( aOverallRange); if (maParam.mbByRow) { if (aMarkRange.aStart.Row() > 0) @@ -62,14 +71,14 @@ void UndoSort::Execute( bool bUndo ) } else { - ScUndoUtil::MarkSimpleBlock(pDocShell, maParam.maSortRange); + ScUndoUtil::MarkSimpleBlock(pDocShell, aOverallRange); } rDoc.SetDirty(maParam.maSortRange, true); if (!aParam.mbUpdateRefs) rDoc.BroadcastCells(aParam.maSortRange, SfxHintId::ScDataChanged); - pDocShell->PostPaint(maParam.maSortRange, PaintPartFlags::Grid); + pDocShell->PostPaint(aOverallRange, PaintPartFlags::Grid); pDocShell->PostDataChanged(); } diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx index 12a9bc44e949..41d5348ca4ba 100644 --- a/sc/source/ui/unoobj/datauno.cxx +++ b/sc/source/ui/unoobj/datauno.cxx @@ -306,7 +306,7 @@ void ScSortDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq pArray[3].Value <<= aFields; pArray[4].Name = SC_UNONAME_BINDFMT; - pArray[4].Value <<= rParam.bIncludePattern; + pArray[4].Value <<= rParam.aDataAreaExtras.mbCellFormats; pArray[5].Name = SC_UNONAME_COPYOUT; pArray[5].Value <<= !rParam.bInplace; @@ -408,7 +408,7 @@ void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const uno::Sequence<b rParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); } else if (aPropName == SC_UNONAME_BINDFMT) - rParam.bIncludePattern = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + rParam.aDataAreaExtras.mbCellFormats = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); else if (aPropName == SC_UNONAME_COPYOUT) rParam.bInplace = !ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); else if (aPropName == SC_UNONAME_OUTPOS) diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx index b8ba37cc9244..4a1e7f04666b 100644 --- a/sc/source/ui/view/cellsh2.cxx +++ b/sc/source/ui/view/cellsh2.cxx @@ -395,9 +395,9 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) aSortParam.bByRow = true; aSortParam.bCaseSens = false; aSortParam.bNaturalSort = false; - aSortParam.bIncludeComments = false; - aSortParam.bIncludeGraphicObjects = true; - aSortParam.bIncludePattern = true; + aSortParam.aDataAreaExtras.mbCellNotes = false; + aSortParam.aDataAreaExtras.mbCellDrawObjects = true; + aSortParam.aDataAreaExtras.mbCellFormats = true; aSortParam.bInplace = true; aSortParam.maKeyState[0].bDoSort = true; aSortParam.maKeyState[0].nField = nCol; @@ -449,11 +449,11 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) if ( pArgs->GetItemState( SID_SORT_NATURALSORT, true, &pItem ) == SfxItemState::SET ) aSortParam.bNaturalSort = static_cast<const SfxBoolItem*>(pItem)->GetValue(); if ( pArgs->GetItemState( SID_SORT_INCCOMMENTS, true, &pItem ) == SfxItemState::SET ) - aSortParam.bIncludeComments = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + aSortParam.aDataAreaExtras.mbCellNotes = static_cast<const SfxBoolItem*>(pItem)->GetValue(); if ( pArgs->GetItemState( SID_SORT_INCIMAGES, true, &pItem ) == SfxItemState::SET ) - aSortParam.bIncludeGraphicObjects = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + aSortParam.aDataAreaExtras.mbCellDrawObjects = static_cast<const SfxBoolItem*>(pItem)->GetValue(); if ( pArgs->GetItemState( SID_SORT_ATTRIBS, true, &pItem ) == SfxItemState::SET ) - aSortParam.bIncludePattern = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + aSortParam.aDataAreaExtras.mbCellFormats = static_cast<const SfxBoolItem*>(pItem)->GetValue(); if ( pArgs->GetItemState( SID_SORT_USERDEF, true, &pItem ) == SfxItemState::SET ) { sal_uInt16 nUserIndex = static_cast<const SfxUInt16Item*>(pItem)->GetValue(); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 7fb89c3f435f..40efbbb5e6e3 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -819,9 +819,9 @@ void ScGridWindow::UpdateAutoFilterFromMenu(AutoFilterMode eMode) aSortParam.bByRow = true; aSortParam.bCaseSens = false; aSortParam.bNaturalSort = false; - aSortParam.bIncludeComments = false; - aSortParam.bIncludeGraphicObjects = true; - aSortParam.bIncludePattern = true; + aSortParam.aDataAreaExtras.mbCellNotes = false; + aSortParam.aDataAreaExtras.mbCellDrawObjects = true; + aSortParam.aDataAreaExtras.mbCellFormats = true; aSortParam.bInplace = true; aSortParam.maKeyState[0].bDoSort = true; aSortParam.maKeyState[0].nField = nCol; |