diff options
author | Balazs Varga <balazs.varga991@gmail.com> | 2021-06-02 09:17:02 +0200 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2021-06-21 10:46:17 +0200 |
commit | 11cc770ad2af1f31c1e5c9512e5688dff38f009b (patch) | |
tree | d6fe3d8bcee57f73cb57c5362383757cc92e03c7 /sc | |
parent | b30e329bfac7279d888908273baec8c7d8dd32ee (diff) |
tdf#142607 XLSX export: keep formatted dates in standard filter
Do not convert the formatted string filter criteria values
to 'double' if they are numbers (dates). Also export the equal
relation criteria into XML_filters tag instead of
XML_customFilters.
Previously the formatted dates replaced with numbers in
standard filter criteria, first during the export, and after
the import, in the standard filter dialog window.
Note: fix and optimize also filtering by formatted dates by
allowing CanOptimizeQueryStringToNumber() to create double
values for them. This unifies the same dates with different
date formatting.
Follow-up to commit 1f755525189884e4b2824889a6b9dea8933402db
"tdf#142402 sc UI: store formatted values in standard filter".
Change-Id: If4c22e8b0142720ccfda038f89367061058693aa
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116566
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/qa/unit/data/ods/tdf142607.ods | bin | 0 -> 9525 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export-test.cxx | 20 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 5 | ||||
-rw-r--r-- | sc/source/filter/excel/excrecds.cxx | 74 | ||||
-rw-r--r-- | sc/source/filter/inc/excrecds.hxx | 6 |
5 files changed, 56 insertions, 49 deletions
diff --git a/sc/qa/unit/data/ods/tdf142607.ods b/sc/qa/unit/data/ods/tdf142607.ods Binary files differnew file mode 100644 index 000000000000..91649056e728 --- /dev/null +++ b/sc/qa/unit/data/ods/tdf142607.ods diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index ae2784a832e7..31c0aae3dd71 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -205,6 +205,7 @@ public: void testPreserveTextWhitespaceXLSX(); void testPreserveTextWhitespace2XLSX(); void testTdf113646(); + void testDateStandardfilterXLSX(); CPPUNIT_TEST_SUITE(ScExportTest); CPPUNIT_TEST(test); @@ -308,6 +309,7 @@ public: CPPUNIT_TEST(testHyperlinkXLSX); CPPUNIT_TEST(testMoveCellAnchoredShapesODS); CPPUNIT_TEST(testTdf113646); + CPPUNIT_TEST(testDateStandardfilterXLSX); CPPUNIT_TEST_SUITE_END(); private: @@ -4184,6 +4186,24 @@ void ScExportTest::testTdf113646() xShell->DoClose(); } +void ScExportTest::testDateStandardfilterXLSX() +{ + // XLSX Roundtripping standard filter with date + ScDocShellRef xDocSh = loadDoc(u"tdf142607.", FORMAT_ODS); + CPPUNIT_ASSERT(xDocSh.is()); + + xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, "xl/worksheets/sheet1.xml", FORMAT_XLSX); + CPPUNIT_ASSERT(pDoc); + + assertXPath(pDoc, "//x:autoFilter", "ref", "A1:B6"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "day", "03"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "month", "12"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "year", "2011"); + assertXPath(pDoc, "//x:autoFilter/x:filterColumn/x:filters/x:dateGroupItem[1]", "dateTimeGrouping", "day"); + + xDocSh->DoClose(); +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 47d1ea2b852d..f8e9aada25b7 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -3055,8 +3055,9 @@ public: { if (rItem.meType != ScQueryEntry::ByString && rItem.meType != ScQueryEntry::ByDate) return; - - if (rItem.mbFormattedValue) + // return only if the type is ByString and the values are formatted, in other cases + // we have to optimize the filter in CanOptimizeQueryStringToNumber(). + if (rItem.mbFormattedValue && rItem.meType == ScQueryEntry::ByString) return; sal_uInt32 nIndex = 0; diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx index c1f45823efcd..8c66caebdea5 100644 --- a/sc/source/filter/excel/excrecds.cxx +++ b/sc/source/filter/excel/excrecds.cxx @@ -528,8 +528,7 @@ XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress& rStartPos, SCCOL nS ExcFilterCondition::ExcFilterCondition() : nType( EXC_AFTYPE_NOTUSED ), - nOper( EXC_AFOPER_EQUAL ), - fVal( 0.0 ) + nOper( EXC_AFOPER_EQUAL ) { } @@ -542,32 +541,23 @@ std::size_t ExcFilterCondition::GetTextBytes() const return pText ? (1 + pText->GetBufferSize()) : 0; } -void ExcFilterCondition::SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, double fV, const OUString* pT ) +void ExcFilterCondition::SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, const OUString* pT ) { nType = nTp; nOper = nOp; - fVal = fV; pText.reset( pT ? new XclExpString( *pT, XclStrFlags::EightBitLength ) : nullptr); } void ExcFilterCondition::Save( XclExpStream& rStrm ) { rStrm << nType << nOper; - switch( nType ) + if (nType == EXC_AFTYPE_STRING) { - case EXC_AFTYPE_DOUBLE: - rStrm << fVal; - break; - case EXC_AFTYPE_STRING: - OSL_ENSURE( pText, "ExcFilterCondition::Save() -- pText is NULL!" ); - rStrm << sal_uInt32(0) << static_cast<sal_uInt8>(pText->Len()) << sal_uInt16(0) << sal_uInt8(0); - break; - case EXC_AFTYPE_BOOLERR: - rStrm << sal_uInt8(0) << static_cast<sal_uInt8>((fVal != 0) ? 1 : 0) << sal_uInt32(0) << sal_uInt16(0); - break; - default: - rStrm << sal_uInt32(0) << sal_uInt32(0); + OSL_ENSURE(pText, "ExcFilterCondition::Save() -- pText is NULL!"); + rStrm << sal_uInt32(0) << static_cast<sal_uInt8>(pText->Len()) << sal_uInt16(0) << sal_uInt8(0); } + else + rStrm << sal_uInt32(0) << sal_uInt32(0); } static const char* lcl_GetOperator( sal_uInt8 nOper ) @@ -585,15 +575,12 @@ static const char* lcl_GetOperator( sal_uInt8 nOper ) } } -static OString lcl_GetValue( sal_uInt8 nType, double fVal, const XclExpString* pStr ) +static OString lcl_GetValue( sal_uInt8 nType, const XclExpString* pStr ) { - switch( nType ) - { - case EXC_AFTYPE_STRING: return XclXmlUtils::ToOString( *pStr ); - case EXC_AFTYPE_DOUBLE: return OString::number( fVal ); - case EXC_AFTYPE_BOOLERR: return OString::number( fVal != 0 ? 1 : 0 ); - default: return OString(); - } + if (nType == EXC_AFTYPE_STRING) + return XclXmlUtils::ToOString(*pStr); + else + return OString(); } void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm ) @@ -603,7 +590,7 @@ void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm ) rStrm.GetCurrentStream()->singleElement( XML_customFilter, XML_operator, lcl_GetOperator( nOper ), - XML_val, lcl_GetValue(nType, fVal, pText.get()) ); + XML_val, lcl_GetValue(nType, pText.get()) ); } void ExcFilterCondition::SaveText( XclExpStream& rStrm ) @@ -627,7 +614,7 @@ XclExpAutofilter::XclExpAutofilter( const XclExpRoot& rRoot, sal_uInt16 nC ) : } bool XclExpAutofilter::AddCondition( ScQueryConnect eConn, sal_uInt8 nType, sal_uInt8 nOp, - double fVal, const OUString* pText, bool bSimple ) + const OUString* pText, bool bSimple ) { if( !aCond[ 1 ].IsEmpty() ) return false; @@ -639,7 +626,7 @@ bool XclExpAutofilter::AddCondition( ScQueryConnect eConn, sal_uInt8 nType, sal_ if( bSimple ) nFlags |= (nInd == 0) ? EXC_AFFLAG_SIMPLE1 : EXC_AFFLAG_SIMPLE2; - aCond[ nInd ].SetCondition( nType, nOp, fVal, pText ); + aCond[ nInd ].SetCondition( nType, nOp, pText ); AddRecSize( aCond[ nInd ].GetTextBytes() ); @@ -702,16 +689,14 @@ bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry ) } } - bool bLen = sText.getLength() > 0; - // empty/nonempty fields if (rEntry.IsQueryByEmpty()) { - bConflict = !AddCondition(rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, 0.0, nullptr, true); + bConflict = !AddCondition(rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, nullptr, true); bHasBlankValue = true; } else if(rEntry.IsQueryByNonEmpty()) - bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, 0.0, nullptr, true ); + bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, nullptr, true ); else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor()) { AddColorEntry(rEntry); @@ -719,13 +704,6 @@ bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry ) // other conditions else { - double fVal = 0.0; - sal_uInt32 nIndex = 0; - bool bIsNum = !bLen || GetFormatter().IsNumberFormat( sText, nIndex, fVal ); - OUString* pText = nullptr; - if (!bIsNum) - pText = &sText; - // top10 flags sal_uInt16 nNewFlags = 0x0000; switch( rEntry.eOp ) @@ -751,14 +729,24 @@ bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry ) { if( bNewTop10 ) { - if( fVal < 0 ) fVal = 0; - if( fVal >= 501 ) fVal = 500; + sal_uInt32 nIndex = 0; + double fVal = 0.0; + if (GetFormatter().IsNumberFormat(sText, nIndex, fVal)) + { + if (fVal < 0) fVal = 0; + if (fVal >= 501) fVal = 500; + } nFlags |= (nNewFlags | static_cast<sal_uInt16>(fVal) << 7); } // normal condition else { - sal_uInt8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING; + if (GetOutput() != EXC_OUTPUT_BINARY && rEntry.eOp == SC_EQUAL) + { + AddMultiValueEntry(rEntry); + return false; + } + sal_uInt8 nOper = EXC_AFOPER_NONE; switch( rEntry.eOp ) @@ -779,7 +767,7 @@ bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry ) nOper = EXC_AFOPER_NOTEQUAL; break; default:; } - bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText ); + bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_STRING, nOper, &sText); } } } diff --git a/sc/source/filter/inc/excrecds.hxx b/sc/source/filter/inc/excrecds.hxx index e997be8958e6..2e4885a8856d 100644 --- a/sc/source/filter/inc/excrecds.hxx +++ b/sc/source/filter/inc/excrecds.hxx @@ -338,7 +338,6 @@ class ExcFilterCondition private: sal_uInt8 nType; sal_uInt8 nOper; - double fVal; std::unique_ptr<XclExpString> pText; @@ -350,7 +349,7 @@ public: bool IsEmpty() const { return (nType == EXC_AFTYPE_NOTUSED); } std::size_t GetTextBytes() const; - void SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, double fV, const OUString* pT ); + void SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, const OUString* pT ); void Save( XclExpStream& rStrm ); void SaveXml( XclExpXmlStream& rStrm ); @@ -376,8 +375,7 @@ private: std::vector<std::pair<::Color, bool>> maColorValues; // first->Color, second->bIsBackgroundColor (vs. TextColor) bool AddCondition( ScQueryConnect eConn, sal_uInt8 nType, - sal_uInt8 nOp, double fVal, const OUString* pText, - bool bSimple = false ); + sal_uInt8 nOp, const OUString* pText, bool bSimple = false ); virtual void WriteBody( XclExpStream& rStrm ) override; |