summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge Krot <Serge.Krot@cib.de>2020-06-29 13:23:34 +0200
committerSamuel Mehrbrodt <Samuel.Mehrbrodt@cib.de>2020-09-09 17:09:04 +0200
commita86ddd7fc0413f65ee7851eb09b15a24e5d457ba (patch)
tree12641aa5048a890e24a9305098386a1ecee7fe19
parentpdfium: only init pdfium library once and destroy on LO exit (diff)
downloadcore-a86ddd7fc0413f65ee7851eb09b15a24e5d457ba.tar.gz
core-a86ddd7fc0413f65ee7851eb09b15a24e5d457ba.zip
tdf#95640 XLSX: import/export of custom sort lists
Conflicts: sc/source/filter/excel/excrecds.cxx sc/source/filter/oox/autofilterbuffer.cxx sc/source/filter/oox/tablebuffer.cxx Change-Id: If5ffef39770bf7abd6e75e8de998d4a2b4749a0d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97399 Tested-by: Jenkins Tested-by: Serge Krot <Serge.Krot@cib.de> Reviewed-by: Serge Krot <Serge.Krot@cib.de> Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102254 Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt@cib.de>
-rw-r--r--sc/inc/dbdata.hxx4
-rw-r--r--sc/inc/document.hxx4
-rw-r--r--sc/qa/unit/data/ods/tdf95640.odsbin0 -> 8406 bytes
-rw-r--r--sc/qa/unit/data/ods/tdf95640_standard_list.odsbin0 -> 9684 bytes
-rw-r--r--sc/qa/unit/data/xlsx/tdf95640.xlsxbin0 -> 8500 bytes
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx63
-rw-r--r--sc/source/filter/excel/excrecds.cxx64
-rw-r--r--sc/source/filter/inc/autofilterbuffer.hxx30
-rw-r--r--sc/source/filter/inc/autofiltercontext.hxx39
-rw-r--r--sc/source/filter/inc/excrecds.hxx3
-rw-r--r--sc/source/filter/oox/autofilterbuffer.cxx116
-rw-r--r--sc/source/filter/oox/autofiltercontext.cxx68
-rw-r--r--sc/source/filter/oox/tablebuffer.cxx2
13 files changed, 375 insertions, 18 deletions
diff --git a/sc/inc/dbdata.hxx b/sc/inc/dbdata.hxx
index a7dc35c3b61b..24eaa3be7d18 100644
--- a/sc/inc/dbdata.hxx
+++ b/sc/inc/dbdata.hxx
@@ -172,8 +172,8 @@ public:
OUString GetSourceString() const;
OUString GetOperations() const;
- void GetSortParam(ScSortParam& rSortParam) const;
- void SetSortParam(const ScSortParam& rSortParam);
+ SC_DLLPUBLIC void GetSortParam(ScSortParam& rSortParam) const;
+ SC_DLLPUBLIC void SetSortParam(const ScSortParam& rSortParam);
/** Remember some more settings of ScSortParam, only to be called at
anonymous DB ranges as it at least overwrites bHasHeader. */
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 15fdc5074357..63009443b919 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -805,8 +805,8 @@ public:
bool bRemoveAutoFilter = false );
const ScDBData* GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, ScDBDataPortion ePortion) const;
ScDBData* GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, ScDBDataPortion ePortion);
- const ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const;
- ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
+ SC_DLLPUBLIC const ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const;
+ SC_DLLPUBLIC ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2);
void RefreshDirtyTableColumnNames();
SC_DLLPUBLIC sc::ExternalDataMapper& GetExternalDataMapper();
diff --git a/sc/qa/unit/data/ods/tdf95640.ods b/sc/qa/unit/data/ods/tdf95640.ods
new file mode 100644
index 000000000000..5d435c61cc85
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf95640.ods
Binary files differ
diff --git a/sc/qa/unit/data/ods/tdf95640_standard_list.ods b/sc/qa/unit/data/ods/tdf95640_standard_list.ods
new file mode 100644
index 000000000000..37bea8a0c93e
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf95640_standard_list.ods
Binary files differ
diff --git a/sc/qa/unit/data/xlsx/tdf95640.xlsx b/sc/qa/unit/data/xlsx/tdf95640.xlsx
new file mode 100644
index 000000000000..78c2d32c2cf6
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tdf95640.xlsx
Binary files differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index e220803967cb..b7b41d40addb 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -195,6 +195,12 @@ public:
void testPreserveTextWhitespace2XLSX();
void testTextDirectionXLSX();
+ xmlDocPtr testTdf95640(const OUString& rFileName, sal_Int32 nSourceFormat,
+ sal_Int32 nDestFormat);
+ void testTdf95640_ods_to_xlsx();
+ void testTdf95640_ods_to_xlsx_with_standard_list();
+ void testTdf95640_xlsx_to_xlsx();
+
void testRefStringXLSX();
void testRefStringConfigXLSX();
void testRefStringUnspecified();
@@ -326,6 +332,9 @@ public:
CPPUNIT_TEST(testMoveCellAnchoredShapesODS);
CPPUNIT_TEST(testMatrixMultiplicationXLSX);
CPPUNIT_TEST(testTextDirectionXLSX);
+ CPPUNIT_TEST(testTdf95640_ods_to_xlsx);
+ CPPUNIT_TEST(testTdf95640_ods_to_xlsx_with_standard_list);
+ CPPUNIT_TEST(testTdf95640_xlsx_to_xlsx);
CPPUNIT_TEST(testRefStringXLSX);
CPPUNIT_TEST(testRefStringConfigXLSX);
@@ -3954,6 +3963,60 @@ void ScExportTest::testTextDirectionXLSX()
assertXPath(pDoc, "/x:styleSheet/x:cellXfs/x:xf[3]/x:alignment", "readingOrder", "2");//RTL
}
+xmlDocPtr ScExportTest::testTdf95640(const OUString& rFileName, sal_Int32 nSourceFormat,
+ sal_Int32 nDestFormat)
+{
+ ScDocShellRef xShell = loadDoc(rFileName, nSourceFormat);
+ CPPUNIT_ASSERT(xShell);
+
+ auto pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), nDestFormat);
+ xShell->DoClose();
+
+ return XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/worksheets/sheet1.xml");
+}
+
+void ScExportTest::testTdf95640_ods_to_xlsx()
+{
+ // Roundtripping sort options with user defined list to XLSX
+ xmlDocPtr pDoc = testTdf95640("tdf95640.", FORMAT_ODS, FORMAT_XLSX);
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter", "ref", "A1:B4");
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "ref", "A2:A4");
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "customList",
+ "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec");
+}
+
+void ScExportTest::testTdf95640_ods_to_xlsx_with_standard_list()
+{
+ // Roundtripping sort options with user defined list to XLSX
+ xmlDocPtr pDoc = testTdf95640("tdf95640_standard_list.", FORMAT_ODS, FORMAT_XLSX);
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter", "ref", "A1:B4");
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "ref", "A2:A4");
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "customList",
+ "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday");
+}
+
+void ScExportTest::testTdf95640_xlsx_to_xlsx()
+{
+ // XLSX Roundtripping sort options with custom sort list - note
+ // that compared to ODS source documents above, here we _actually_
+ // can use custom lists (beyond the global user defines), like
+ // low, medium, high
+ xmlDocPtr pDoc = testTdf95640("tdf95640.", FORMAT_XLSX, FORMAT_XLSX);
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter", "ref", "A1:B4");
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "ref", "A2:A4");
+
+ assertXPath(pDoc, "//x:worksheet/x:autoFilter/x:sortState/x:sortCondition", "customList",
+ "Low,Medium,High");
+}
+
void ScExportTest::testTdf88657ODS()
{
ScDocShellRef xDocSh = loadDoc("tdf88657.", FORMAT_ODS);
diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx
index 4fbe955d8b52..d7ab5d7d95af 100644
--- a/sc/source/filter/excel/excrecds.cxx
+++ b/sc/source/filter/excel/excrecds.cxx
@@ -34,6 +34,8 @@
#include <oox/token/tokens.hxx>
#include <queryentry.hxx>
#include <queryparam.hxx>
+#include <sortparam.hxx>
+#include <userlist.hxx>
#include <root.hxx>
#include <xeescher.hxx>
@@ -927,6 +929,45 @@ ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab, const
if (maFilterList.IsEmpty () && !bConflict)
mbAutoFilter = true;
+
+ // get sort criteria
+ {
+ ScSortParam aSortParam;
+ pData->GetSortParam( aSortParam );
+
+ if (aSortParam.bUserDef)
+ {
+ // get sorted area without headers
+ maSortRef = ScRange(
+ aParam.nCol1, aParam.nRow1 + (aSortParam.bHasHeader? 1 : 0), aParam.nTab,
+ aParam.nCol2, aParam.nRow2, aParam.nTab );
+
+ // get sorted columns with custom lists
+ ScUserList* pList = ScGlobal::GetUserList();
+ const ScUserListData& rData = (*pList)[aSortParam.nUserIndex];
+
+ // get column index and sorting direction
+ SCCOLROW nField = 0;
+ bool bSortAscending=true;
+ for (const auto & rKey : aSortParam.maKeyState)
+ {
+ if (rKey.bDoSort)
+ {
+ nField = rKey.nField;
+ bSortAscending = rKey.bAscending;
+ break;
+ }
+ }
+
+ // remember sort criteria
+ const ScRange aSortedColumn(
+ nField, aParam.nRow1 + (aSortParam.bHasHeader? 1 : 0), aParam.nTab,
+ nField, aParam.nRow2, aParam.nTab );
+ const OUString aItemList = rData.GetString();
+
+ maSortCustomList.emplace_back(aSortedColumn, aItemList, !bSortAscending);
+ }
+ }
}
}
}
@@ -990,6 +1031,29 @@ void ExcAutoFilterRecs::SaveXml( XclExpXmlStream& rStrm )
// OOXTODO: XML_extLst, XML_sortState
if( !maFilterList.IsEmpty() )
maFilterList.SaveXml( rStrm );
+
+ if (!maSortCustomList.empty())
+ {
+ rWorksheet->startElement(XML_sortState, XML_ref, XclXmlUtils::ToOString(&rStrm.GetRoot().GetDoc(), maSortRef));
+
+ for (const auto & rSortCriteria : maSortCustomList)
+ {
+ if (std::get<2>(rSortCriteria))
+ rWorksheet->singleElement(XML_sortCondition,
+ XML_ref, XclXmlUtils::ToOString(&rStrm.GetRoot().GetDoc(),
+ std::get<0>(rSortCriteria)),
+ XML_descending, "1",
+ XML_customList, std::get<1>(rSortCriteria).toUtf8().getStr());
+ else
+ rWorksheet->singleElement(XML_sortCondition,
+ XML_ref, XclXmlUtils::ToOString(&rStrm.GetRoot().GetDoc(),
+ std::get<0>(rSortCriteria)),
+ XML_customList, std::get<1>(rSortCriteria).toUtf8().getStr());
+ }
+
+ rWorksheet->endElement(XML_sortState);
+ }
+
rWorksheet->endElement( XML_autoFilter );
}
diff --git a/sc/source/filter/inc/autofilterbuffer.hxx b/sc/source/filter/inc/autofilterbuffer.hxx
index c6387e5d37d4..ae8e8b4fa2a0 100644
--- a/sc/source/filter/inc/autofilterbuffer.hxx
+++ b/sc/source/filter/inc/autofilterbuffer.hxx
@@ -184,6 +184,22 @@ private:
bool mbShowButton;
};
+// class SortCondition
+
+class SortCondition : public WorkbookHelper
+{
+public:
+ explicit SortCondition( const WorkbookHelper& rHelper );
+
+ void importSortCondition( const AttributeList& rAttribs, sal_Int16 nSheet );
+
+ ScRange maRange; // Column/Row that this sort condition applies to.
+ OUString maSortCustomList; // Sort by a custom list.
+ bool mbDescending;
+};
+
+// class AutoFilter
+
class AutoFilter : public WorkbookHelper
{
public:
@@ -194,17 +210,26 @@ public:
/** Imports auto filter settings from the AUTOFILTER record. */
void importAutoFilter( SequenceInputStream& rStrm, sal_Int16 nSheet );
+ void importSortState( const AttributeList& rAttribs, sal_Int16 nSheet );
+
/** Creates a new auto filter column and stores it internally. */
FilterColumn& createFilterColumn();
+ SortCondition& createSortCondition();
+
/** Applies the filter to the passed filter descriptor. */
- void finalizeImport( const css::uno::Reference< css::sheet::XSheetFilterDescriptor3>& rxFilterDesc );
+ void finalizeImport( const css::uno::Reference< css::sheet::XDatabaseRange >& rxDatabaseRange,
+ sal_Int16 nSheet );
private:
typedef RefVector< FilterColumn > FilterColumnVector;
FilterColumnVector maFilterColumns;
ScRange maRange;
+
+ ScRange maSortRange; // The whole range of data to sort (not just the sort-by column).
+ typedef RefVector< SortCondition > SortConditionVector;
+ SortConditionVector maSortConditions;
};
class AutoFilterBuffer : public WorkbookHelper
@@ -221,7 +246,8 @@ public:
/** Applies the filters to the passed database range object.
@return True = this buffer contains valid auto filter settings. */
- bool finalizeImport( const css::uno::Reference< css::sheet::XDatabaseRange >& rxDatabaseRange );
+ bool finalizeImport( const css::uno::Reference< css::sheet::XDatabaseRange >& rxDatabaseRange,
+ sal_Int16 nSheet );
private:
/** Returns the auto filter object used to perform auto filtering. */
diff --git a/sc/source/filter/inc/autofiltercontext.hxx b/sc/source/filter/inc/autofiltercontext.hxx
index 9a58a8a998e0..ef7bb539c3e7 100644
--- a/sc/source/filter/inc/autofiltercontext.hxx
+++ b/sc/source/filter/inc/autofiltercontext.hxx
@@ -21,6 +21,7 @@
#define INCLUDED_SC_SOURCE_FILTER_INC_AUTOFILTERCONTEXT_HXX
#include "excelhandlers.hxx"
+#include "autofilterbuffer.hxx"
namespace oox {
namespace xls {
@@ -61,6 +62,44 @@ private:
FilterColumn& mrFilterColumn;
};
+// class SortConditionContext
+
+class SortConditionContext : public WorksheetContextBase
+{
+public:
+ explicit SortConditionContext( WorksheetContextBase& rFragment, SortCondition& rSortCondition );
+
+protected:
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override;
+ virtual void onStartElement( const AttributeList& rAttribs ) override;
+
+ virtual ::oox::core::ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) override;
+ virtual void onStartRecord( SequenceInputStream& rStrm ) override;
+
+private:
+ SortCondition& mrSortCondition;
+};
+
+// class SortStateContext
+
+class SortStateContext : public WorksheetContextBase
+{
+public:
+ explicit SortStateContext( WorksheetContextBase& rFragment, AutoFilter& rAutoFilter );
+
+protected:
+ virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override;
+ virtual void onStartElement( const AttributeList& rAttribs ) override;
+
+ virtual ::oox::core::ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) override;
+ virtual void onStartRecord( SequenceInputStream& rStrm ) override;
+
+private:
+ AutoFilter& mrAutoFilter;
+};
+
+// class AutoFilterContext
+
class AutoFilterContext : public WorksheetContextBase
{
public:
diff --git a/sc/source/filter/inc/excrecds.hxx b/sc/source/filter/inc/excrecds.hxx
index 74a21cbfa563..a0abbf9410cd 100644
--- a/sc/source/filter/inc/excrecds.hxx
+++ b/sc/source/filter/inc/excrecds.hxx
@@ -417,6 +417,9 @@ private:
std::unique_ptr<XclExpAutofilterinfo> m_pFilterInfo;
ScRange maRef;
bool mbAutoFilter;
+
+ ScRange maSortRef; // sort area without headers
+ std::vector< std::tuple<ScRange, OUString, bool> > maSortCustomList; // sorted column with list of sorted items
};
/** Sheet filter manager. Contains auto filters or advanced filters from all sheets. */
diff --git a/sc/source/filter/oox/autofilterbuffer.cxx b/sc/source/filter/oox/autofilterbuffer.cxx
index 9e53200092ce..8209df526283 100644
--- a/sc/source/filter/oox/autofilterbuffer.cxx
+++ b/sc/source/filter/oox/autofilterbuffer.cxx
@@ -39,6 +39,10 @@
#include <addressconverter.hxx>
#include <defnamesbuffer.hxx>
#include <biffhelper.hxx>
+#include <document.hxx>
+#include <dbdata.hxx>
+#include <sortparam.hxx>
+#include <userlist.hxx>
namespace oox {
namespace xls {
@@ -530,6 +534,25 @@ ApiFilterSettings FilterColumn::finalizeImport( sal_Int32 nMaxCount )
return aSettings;
}
+// SortCondition
+
+SortCondition::SortCondition( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper ),
+ mbDescending( false )
+{
+}
+
+void SortCondition::importSortCondition( const AttributeList& rAttribs, sal_Int16 nSheet )
+{
+ OUString aRangeStr = rAttribs.getString( XML_ref, OUString() );
+ AddressConverter::convertToCellRangeUnchecked( maRange, aRangeStr, nSheet );
+
+ maSortCustomList = rAttribs.getString( XML_customList, OUString() );
+ mbDescending = rAttribs.getBool( XML_descending, false );
+}
+
+// AutoFilter
+
AutoFilter::AutoFilter( const WorkbookHelper& rHelper ) :
WorkbookHelper( rHelper )
{
@@ -548,6 +571,12 @@ void AutoFilter::importAutoFilter( SequenceInputStream& rStrm, sal_Int16 nSheet
AddressConverter::convertToCellRangeUnchecked( maRange, aBinRange, nSheet );
}
+void AutoFilter::importSortState( const AttributeList& rAttribs, sal_Int16 nSheet )
+{
+ OUString aRangeStr = rAttribs.getString( XML_ref, OUString() );
+ AddressConverter::convertToCellRangeUnchecked( maSortRange, aRangeStr, nSheet );
+}
+
FilterColumn& AutoFilter::createFilterColumn()
{
FilterColumnVector::value_type xFilterColumn( new FilterColumn( *this ) );
@@ -555,12 +584,21 @@ FilterColumn& AutoFilter::createFilterColumn()
return *xFilterColumn;
}
-void AutoFilter::finalizeImport( const Reference<XSheetFilterDescriptor3>& rxFilterDesc )
+SortCondition& AutoFilter::createSortCondition()
{
- if( rxFilterDesc.is() )
+ SortConditionVector::value_type xSortCondition = std::make_shared<SortCondition>( *this );
+ maSortConditions.push_back( xSortCondition );
+ return *xSortCondition;
+}
+
+void AutoFilter::finalizeImport( const Reference< XDatabaseRange >& rxDatabaseRange, sal_Int16 nSheet )
+{
+ // convert filter settings using the filter descriptor of the database range
+ const Reference<XSheetFilterDescriptor3> xFilterDesc( rxDatabaseRange->getFilterDescriptor(), UNO_QUERY_THROW );
+ if( xFilterDesc.is() )
{
// set some common properties for the auto filter range
- PropertySet aDescProps( rxFilterDesc );
+ PropertySet aDescProps( xFilterDesc );
aDescProps.setProperty( PROP_IsCaseSensitive, false );
aDescProps.setProperty( PROP_SkipDuplicates, false );
aDescProps.setProperty( PROP_Orientation, TableOrientation_ROWS );
@@ -631,11 +669,71 @@ void AutoFilter::finalizeImport( const Reference<XSheetFilterDescriptor3>& rxFil
// insert all filter fields to the filter descriptor
if( !aFilterFields.empty() )
- rxFilterDesc->setFilterFields3( ContainerHelper::vectorToSequence( aFilterFields ) );
+ xFilterDesc->setFilterFields3( ContainerHelper::vectorToSequence( aFilterFields ) );
// regular expressions
bool bUseRegExp = obNeedsRegExp.get( false );
aDescProps.setProperty( PROP_UseRegularExpressions, bUseRegExp );
+
+ // sort
+ if (!maSortConditions.empty())
+ {
+ const SortConditionVector::value_type& xSortConditionPointer = *maSortConditions.begin();
+ const SortCondition& rSorConditionLoaded = *xSortConditionPointer;
+
+ ScSortParam aParam;
+ aParam.bUserDef = false;
+ aParam.nUserIndex = 0;
+ aParam.bByRow = false;
+
+ ScUserList* pUserList = ScGlobal::GetUserList();
+ if (!rSorConditionLoaded.maSortCustomList.isEmpty())
+ {
+ for (size_t i=0; pUserList && i < pUserList->size(); i++)
+ {
+ const OUString aEntry((*pUserList)[i].GetString());
+ if (aEntry.equalsIgnoreAsciiCase(rSorConditionLoaded.maSortCustomList))
+ {
+ aParam.bUserDef = true;
+ aParam.nUserIndex = i;
+ break;
+ }
+ }
+ }
+
+ if (!aParam.bUserDef)
+ {
+ pUserList->push_back(new ScUserListData(rSorConditionLoaded.maSortCustomList));
+ aParam.bUserDef = true;
+ aParam.nUserIndex = pUserList->size()-1;
+ }
+
+ // set sort parameter if we have detected it
+ if (aParam.bUserDef)
+ {
+ SCCOLROW nStartPos = aParam.bByRow ? maRange.aStart.Col() : maRange.aStart.Row();
+ if (rSorConditionLoaded.mbDescending)
+ {
+ // descending sort - need to enable 1st SortParam slot
+ assert(aParam.GetSortKeyCount() == DEFSORT);
+
+ aParam.maKeyState[0].bDoSort = true;
+ aParam.maKeyState[0].bAscending = false;
+ aParam.maKeyState[0].nField += nStartPos;
+ }
+
+ ScDocument& rDoc = getScDocument();
+ ScDBData* pDBData = rDoc.GetDBAtArea(
+ nSheet,
+ maRange.aStart.Col(), maRange.aStart.Row(),
+ maRange.aEnd.Col(), maRange.aEnd.Row());
+
+ if (pDBData)
+ pDBData->SetSortParam(aParam);
+ else
+ OSL_FAIL("AutoFilter::finalizeImport(): cannot find matching DBData");
+ }
+ }
}
}
@@ -662,7 +760,7 @@ void AutoFilterBuffer::finalizeImport( sal_Int16 nSheet )
// use the same name for the database range as used for the defined name '_FilterDatabase'
Reference< XDatabaseRange > xDatabaseRange = createUnnamedDatabaseRangeObject( aFilterRange );
// first, try to create an auto filter
- bool bHasAutoFilter = finalizeImport( xDatabaseRange );
+ bool bHasAutoFilter = finalizeImport( xDatabaseRange, nSheet );
// no success: try to create an advanced filter
if( !bHasAutoFilter && xDatabaseRange.is() )
{
@@ -709,7 +807,7 @@ void AutoFilterBuffer::finalizeImport( sal_Int16 nSheet )
}
}
-bool AutoFilterBuffer::finalizeImport( const Reference< XDatabaseRange >& rxDatabaseRange )
+bool AutoFilterBuffer::finalizeImport( const Reference< XDatabaseRange >& rxDatabaseRange, sal_Int16 nSheet )
{
AutoFilter* pAutoFilter = getActiveAutoFilter();
if( pAutoFilter && rxDatabaseRange.is() ) try
@@ -717,9 +815,9 @@ bool AutoFilterBuffer::finalizeImport( const Reference< XDatabaseRange >& rxData
// the property 'AutoFilter' enables the drop-down buttons
PropertySet aRangeProps( rxDatabaseRange );
aRangeProps.setProperty( PROP_AutoFilter, true );
- // convert filter settings using the filter descriptor of the database range
- Reference< XSheetFilterDescriptor3 > xFilterDesc( rxDatabaseRange->getFilterDescriptor(), UNO_QUERY_THROW );
- pAutoFilter->finalizeImport( xFilterDesc );
+
+ pAutoFilter->finalizeImport( rxDatabaseRange, nSheet );
+
// return true to indicate enabled autofilter
return true;
}
diff --git a/sc/source/filter/oox/autofiltercontext.cxx b/sc/source/filter/oox/autofiltercontext.cxx
index 1ec7b7138b72..814569e0b45f 100644
--- a/sc/source/filter/oox/autofiltercontext.cxx
+++ b/sc/source/filter/oox/autofiltercontext.cxx
@@ -116,6 +116,65 @@ void FilterColumnContext::onStartRecord( SequenceInputStream& rStrm )
mrFilterColumn.importFilterColumn( rStrm );
}
+// class SortConditionContext
+
+SortConditionContext::SortConditionContext( WorksheetContextBase& rParent, SortCondition& rSortCondition ) :
+ WorksheetContextBase( rParent ),
+ mrSortCondition( rSortCondition )
+{
+}
+
+ContextHandlerRef SortConditionContext::onCreateContext( sal_Int32 , const AttributeList& )
+{
+ return nullptr;
+}
+
+void SortConditionContext::onStartElement( const AttributeList& rAttribs )
+{
+ mrSortCondition.importSortCondition( rAttribs, getSheetIndex() );
+}
+
+ContextHandlerRef SortConditionContext::onCreateRecordContext( sal_Int32 , SequenceInputStream& )
+{
+ return nullptr;
+}
+
+void SortConditionContext::onStartRecord( SequenceInputStream& )
+{
+}
+
+// class SortStateContext
+
+SortStateContext::SortStateContext( WorksheetContextBase& rParent, AutoFilter& rAutoFilter ) :
+ WorksheetContextBase( rParent ),
+ mrAutoFilter( rAutoFilter )
+{
+}
+
+ContextHandlerRef SortStateContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
+{
+ if( getCurrentElement() == XLS_TOKEN( sortState ) ) switch( nElement )
+ {
+ case XLS_TOKEN( sortCondition ):
+ return new SortConditionContext( *this, mrAutoFilter.createSortCondition() );
+ }
+ return nullptr;
+}
+
+void SortStateContext::onStartElement( const AttributeList& rAttribs )
+{
+ mrAutoFilter.importSortState( rAttribs, getSheetIndex() );
+}
+
+ContextHandlerRef SortStateContext::onCreateRecordContext( sal_Int32 , SequenceInputStream& )
+{
+ return nullptr;
+}
+
+void SortStateContext::onStartRecord( SequenceInputStream& )
+{
+}
+
AutoFilterContext::AutoFilterContext( WorksheetFragmentBase& rFragment, AutoFilter& rAutoFilter ) :
WorksheetContextBase( rFragment ),
mrAutoFilter( rAutoFilter )
@@ -124,8 +183,13 @@ AutoFilterContext::AutoFilterContext( WorksheetFragmentBase& rFragment, AutoFilt
ContextHandlerRef AutoFilterContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
{
- if( (getCurrentElement() == XLS_TOKEN( autoFilter )) && (nElement == XLS_TOKEN( filterColumn )) )
- return new FilterColumnContext( *this, mrAutoFilter.createFilterColumn() );
+ if( getCurrentElement() == XLS_TOKEN( autoFilter ) ) switch( nElement )
+ {
+ case XLS_TOKEN( sortState ):
+ return new SortStateContext( *this, mrAutoFilter );
+ case XLS_TOKEN( filterColumn ):
+ return new FilterColumnContext( *this, mrAutoFilter.createFilterColumn() );
+ }
return nullptr;
}
diff --git a/sc/source/filter/oox/tablebuffer.cxx b/sc/source/filter/oox/tablebuffer.cxx
index 8c8526ce9a57..928870276276 100644
--- a/sc/source/filter/oox/tablebuffer.cxx
+++ b/sc/source/filter/oox/tablebuffer.cxx
@@ -136,7 +136,7 @@ void Table::applyAutoFilters()
PropertySet aDocProps( getDocument() );
Reference< XDatabaseRanges > xDatabaseRanges( aDocProps.getAnyProperty( PROP_DatabaseRanges ), UNO_QUERY_THROW );
Reference< XDatabaseRange > xDatabaseRange( xDatabaseRanges->getByName( maDBRangeName ), UNO_QUERY );
- maAutoFilters.finalizeImport( xDatabaseRange );
+ maAutoFilters.finalizeImport( xDatabaseRange, maModel.maRange.aStart.Tab() );
}
catch( Exception& )
{