summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2021-09-12 20:15:01 +0200
committerMike Kaganski <mike.kaganski@collabora.com>2021-09-15 18:54:15 +0200
commitfff92a72443842dda94a36fba753673066aeb399 (patch)
treea295f4ee783e5ae47f4a47da40d78cf290fa249d
parent5cdca67efae1fc8da7bc19bcb940e9a12ae84f94 (diff)
Resolves: tdf#144135 Rework Sort with area extras
Since commit 774a61afa9fc281290e7bfad4e28c05978b82d73 CommitDate: Wed Apr 14 08:46:03 2021 +0200 tdf#126678 - Consider "Include formats" option during sort a sheet formatted with visible attributes like cell background colour up to the end if for Sort all columns and/or rows are selected lead to an excessive memory allocation and slow execution time if it didn't get killed by the operating system before due to memory exhaustion. The same could had happened already before if graphics or comments were to be included that could had resulted in a similar large range. However, cell formats across sheets are more likely. This changes the strategy how the to be sorted data range is determined (range only with data) and additional area extras ranges without data that are only to be rearranged. Those are then processed in chunks (limited to ~512MB per chunk). Cell formats that are identical within one column's rows range do not even need to be covered as they are not rearranged, in the best case leading to all trailing formats' ranges being excluded from the sort. Additionally optimize the cell gathering of formats, graphics and comments such that for the area extras they are only collected if actually requested. The overall performance gain is in an order of magnitudes even if some extras are to be collected. Change-Id: If3abbaeaa615aaff7d88a82a5b3fc7ac633d770d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122013 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins (cherry picked from commit 0a9b68c9f9880655576e3220d8b70064b367dbee) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121981 Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sc/inc/column.hxx17
-rw-r--r--sc/inc/document.hxx23
-rw-r--r--sc/inc/sortparam.hxx69
-rw-r--r--sc/inc/table.hxx24
-rw-r--r--sc/qa/unit/ucalc_sort.cxx8
-rw-r--r--sc/source/core/data/column2.cxx81
-rw-r--r--sc/source/core/data/document.cxx5
-rw-r--r--sc/source/core/data/sortparam.cxx41
-rw-r--r--sc/source/core/data/table1.cxx56
-rw-r--r--sc/source/core/data/table3.cxx338
-rw-r--r--sc/source/filter/xml/XMLExportDatabaseRanges.cxx2
-rw-r--r--sc/source/ui/app/transobj.cxx22
-rw-r--r--sc/source/ui/dbgui/tpsort.cxx12
-rw-r--r--sc/source/ui/docshell/dbdocfun.cxx64
-rw-r--r--sc/source/ui/undo/undosort.cxx15
-rw-r--r--sc/source/ui/unoobj/datauno.cxx4
-rw-r--r--sc/source/ui/view/cellsh2.cxx12
-rw-r--r--sc/source/ui/view/gridwin.cxx6
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;