diff options
author | Gülşah Köse <gulsah.kose@collabora.com> | 2019-03-25 21:08:22 +0300 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2019-05-04 10:21:44 +0200 |
commit | 8c637b47d9de4b3a64c33a9c2ffe7ed220be2467 (patch) | |
tree | 1657f72af2c99ebd0cdc027730fbb31e81eeefe7 | |
parent | c2ebd00b653c77985af36accde4b647b5279cb28 (diff) |
tdf#122590 Import and export xlsx x14:cfRule element for type = cellis.
Change-Id: I3d940269ec25657b64c714400a2828781dd9dd3e
Reviewed-on: https://gerrit.libreoffice.org/69713
Tested-by: Jenkins
Reviewed-by: Andras Timar <andras.timar@collabora.com>
22 files changed, 432 insertions, 32 deletions
diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx index 4651f7453b04..49c05fbbb3c7 100644 --- a/sc/inc/conditio.hxx +++ b/sc/inc/conditio.hxx @@ -27,6 +27,7 @@ #include <formula/grammar.hxx> #include "scdllapi.h" #include "rangelst.hxx" +#include "tokenarray.hxx" #include <svl/listener.hxx> @@ -231,6 +232,7 @@ public: enum class Type { Condition, + ExtCondition, Colorscale, Databar, Iconset, @@ -265,6 +267,9 @@ inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, case ScFormatEntry::Type::Condition: stream << "Condition"; break; + case ScFormatEntry::Type::ExtCondition: + stream << "ExtCondition"; + break; case ScFormatEntry::Type::Colorscale: stream << "Colorscale"; break; @@ -322,6 +327,7 @@ class SC_DLLPUBLIC ScConditionEntry : public ScFormatEntry bool bRelRef2; bool bFirstRun; std::unique_ptr<ScFormulaListener> mpListener; + Type eConditionType; //It can be Condition or ExtCondition static void SimplifyCompiledFormula( std::unique_ptr<ScTokenArray>& rFormula, double& rVal, @@ -346,7 +352,8 @@ public: ScDocument* pDocument, const ScAddress& rPos, const OUString& rExprNmsp1, const OUString& rExprNmsp2, formula::FormulaGrammar::Grammar eGrammar1, - formula::FormulaGrammar::Grammar eGrammar2 ); + formula::FormulaGrammar::Grammar eGrammar2, + Type eType = Type::Condition ); ScConditionEntry( ScConditionMode eOper, const ScTokenArray* pArr1, const ScTokenArray* pArr2, ScDocument* pDocument, const ScAddress& rPos ); @@ -391,7 +398,7 @@ public: bool MarkUsedExternalReferences() const; - virtual Type GetType() const override { return Type::Condition; } + virtual Type GetType() const override { return eConditionType; } virtual ScFormatEntry* Clone(ScDocument* pDoc) const override; @@ -442,7 +449,8 @@ private: // single condition entry for conditional formatting class SC_DLLPUBLIC ScCondFormatEntry : public ScConditionEntry { - OUString aStyleName; + OUString aStyleName; + Type eCondFormatType = Type::Condition; public: ScCondFormatEntry( ScConditionMode eOper, @@ -452,7 +460,8 @@ public: const OUString& rExprNmsp1 = EMPTY_OUSTRING, const OUString& rExprNmsp2 = EMPTY_OUSTRING, formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT, - formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT ); + formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT, + Type eType = Type::Condition); ScCondFormatEntry( ScConditionMode eOper, const ScTokenArray* pArr1, const ScTokenArray* pArr2, ScDocument* pDocument, const ScAddress& rPos, @@ -466,6 +475,7 @@ public: const OUString& GetStyle() const { return aStyleName; } void UpdateStyleName(const OUString& rNew) { aStyleName=rNew; } virtual ScFormatEntry* Clone(ScDocument* pDoc) const override; + virtual Type GetType() const override { return eCondFormatType; } protected: virtual void DataChanged() const override; diff --git a/sc/qa/unit/data/xlsx/condFormat_cellis.xlsx b/sc/qa/unit/data/xlsx/condFormat_cellis.xlsx Binary files differnew file mode 100644 index 000000000000..6bbd0b5e33f5 --- /dev/null +++ b/sc/qa/unit/data/xlsx/condFormat_cellis.xlsx diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index 2db10074d785..f4fa59c0c827 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -91,6 +91,7 @@ public: void testPasswordExportODS(); void testConditionalFormatExportODS(); void testConditionalFormatExportXLSX(); + void testCondFormatExportCellIs(); void testTdf99856_dataValidationTest(); void testProtectionKeyODS_UTF16LErtlSHA1(); void testProtectionKeyODS_UTF8SHA1(); @@ -226,6 +227,7 @@ public: CPPUNIT_TEST(testTdf111876); CPPUNIT_TEST(testPasswordExportODS); CPPUNIT_TEST(testConditionalFormatExportODS); + CPPUNIT_TEST(testCondFormatExportCellIs); CPPUNIT_TEST(testConditionalFormatExportXLSX); CPPUNIT_TEST(testTdf99856_dataValidationTest); CPPUNIT_TEST(testProtectionKeyODS_UTF16LErtlSHA1); @@ -501,6 +503,42 @@ void ScExportTest::testConditionalFormatExportODS() xDocSh->DoClose(); } +void ScExportTest::testCondFormatExportCellIs() +{ + ScDocShellRef xShell = loadDoc("condFormat_cellis.", FORMAT_XLSX); + CPPUNIT_ASSERT(xShell.is()); + ScDocShellRef xDocSh = saveAndReload(&(*xShell), FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rDoc.GetCondFormList(0)->size()); + + ScConditionalFormat* pFormat = rDoc.GetCondFormat(0, 0, 0); + CPPUNIT_ASSERT(pFormat); + + const ScFormatEntry* pEntry = pFormat->GetEntry(0); + CPPUNIT_ASSERT(pEntry); + CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); + + const ScCondFormatEntry* pCondition = static_cast<const ScCondFormatEntry*>(pEntry); + CPPUNIT_ASSERT_EQUAL( ScConditionMode::Equal, pCondition->GetOperation()); + + OUString aStr = pCondition->GetExpression(ScAddress(0, 0, 0), 0); + CPPUNIT_ASSERT_EQUAL( OUString("$Sheet2.$A$1"), aStr ); + + pEntry = pFormat->GetEntry(1); + CPPUNIT_ASSERT(pEntry); + CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); + + pCondition = static_cast<const ScCondFormatEntry*>(pEntry); + CPPUNIT_ASSERT_EQUAL( ScConditionMode::Equal, pCondition->GetOperation()); + + aStr = pCondition->GetExpression(ScAddress(0, 0, 0), 0); + CPPUNIT_ASSERT_EQUAL( OUString("$Sheet2.$A$2"), aStr ); + + xDocSh->DoClose(); +} + void ScExportTest::testConditionalFormatExportXLSX() { ScDocShellRef xShell = loadDoc("new_cond_format_test_export.", FORMAT_XLSX); diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx index af6daec5f255..dd39afb3b341 100644 --- a/sc/qa/unit/subsequent_filters-test.cxx +++ b/sc/qa/unit/subsequent_filters-test.cxx @@ -144,6 +144,7 @@ public: void testNewCondFormatODS(); void testNewCondFormatXLSX(); void testCondFormatThemeColorXLSX(); + void testCondFormatImportCellIs(); void testCondFormatThemeColor2XLSX(); // negative bar color and axis color void testCondFormatThemeColor3XLSX(); // theme index 2 and 3 are switched void testComplexIconSetsXLSX(); @@ -303,6 +304,7 @@ public: CPPUNIT_TEST(testNewCondFormatODS); CPPUNIT_TEST(testNewCondFormatXLSX); CPPUNIT_TEST(testCondFormatThemeColorXLSX); + CPPUNIT_TEST(testCondFormatImportCellIs); CPPUNIT_TEST(testCondFormatThemeColor2XLSX); CPPUNIT_TEST(testCondFormatThemeColor3XLSX); CPPUNIT_TEST(testComplexIconSetsXLSX); @@ -2260,6 +2262,40 @@ void ScFiltersTest::testNewCondFormatXLSX() xDocSh->DoClose(); } +void ScFiltersTest::testCondFormatImportCellIs() +{ + ScDocShellRef xDocSh = ScBootstrapFixture::loadDoc("condFormat_cellis.", FORMAT_XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to load condFormat_cellis.xlsx", xDocSh.is()); + + ScDocument& rDoc = xDocSh->GetDocument(); + CPPUNIT_ASSERT_EQUAL(size_t(1), rDoc.GetCondFormList(0)->size()); + + ScConditionalFormat* pFormat = rDoc.GetCondFormat(0, 0, 0); + CPPUNIT_ASSERT(pFormat); + + const ScFormatEntry* pEntry = pFormat->GetEntry(0); + CPPUNIT_ASSERT(pEntry); + CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); + + const ScCondFormatEntry* pCondition = static_cast<const ScCondFormatEntry*>(pEntry); + CPPUNIT_ASSERT_EQUAL( ScConditionMode::Equal, pCondition->GetOperation()); + + OUString aStr = pCondition->GetExpression(ScAddress(0, 0, 0), 0); + CPPUNIT_ASSERT_EQUAL( OUString("$Sheet2.$A$1"), aStr ); + + pEntry = pFormat->GetEntry(1); + CPPUNIT_ASSERT(pEntry); + CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::ExtCondition, pEntry->GetType()); + + pCondition = static_cast<const ScCondFormatEntry*>(pEntry); + CPPUNIT_ASSERT_EQUAL( ScConditionMode::Equal, pCondition->GetOperation()); + + aStr = pCondition->GetExpression(ScAddress(0, 0, 0), 0); + CPPUNIT_ASSERT_EQUAL( OUString("$Sheet2.$A$2"), aStr ); + + xDocSh->DoClose(); +} + void ScFiltersTest::testCondFormatThemeColorXLSX() { ScDocShellRef xDocSh = ScBootstrapFixture::loadDoc("condformat_theme_color.", FORMAT_XLSX); diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 359a76986da9..ae29cb2d8dd3 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -189,6 +189,7 @@ ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) : bRelRef2(r.bRelRef2), bFirstRun(true), mpListener(new ScFormulaListener(r.mpDoc)), + eConditionType( r.eConditionType ), pCondFormat(r.pCondFormat) { // ScTokenArray copy ctor creates a flat copy @@ -221,6 +222,7 @@ ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntr bRelRef2(r.bRelRef2), bFirstRun(true), mpListener(new ScFormulaListener(pDocument)), + eConditionType( r.eConditionType), pCondFormat(r.pCondFormat) { // Real copy of the formulas (for Ref Undo) @@ -236,7 +238,8 @@ ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntr ScConditionEntry::ScConditionEntry( ScConditionMode eOper, const OUString& rExpr1, const OUString& rExpr2, ScDocument* pDocument, const ScAddress& rPos, const OUString& rExprNmsp1, const OUString& rExprNmsp2, - FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) : + FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2, + Type eType ) : ScFormatEntry(pDocument), eOp(eOper), nOptions(0), @@ -253,6 +256,7 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper, bRelRef2(false), bFirstRun(true), mpListener(new ScFormulaListener(pDocument)), + eConditionType(eType), pCondFormat(nullptr) { Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, false ); @@ -1457,9 +1461,11 @@ ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper, const OUString& rStyle, const OUString& rExprNmsp1, const OUString& rExprNmsp2, FormulaGrammar::Grammar eGrammar1, - FormulaGrammar::Grammar eGrammar2 ) : - ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ), - aStyleName( rStyle ) + FormulaGrammar::Grammar eGrammar2, + ScFormatEntry::Type eType ) : + ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, eType ), + aStyleName( rStyle ), + eCondFormatType( eType ) { } @@ -1474,13 +1480,15 @@ ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper, ScCondFormatEntry::ScCondFormatEntry( const ScCondFormatEntry& r ) : ScConditionEntry( r ), - aStyleName( r.aStyleName ) + aStyleName( r.aStyleName ), + eCondFormatType( r.eCondFormatType) { } ScCondFormatEntry::ScCondFormatEntry( ScDocument* pDocument, const ScCondFormatEntry& r ) : ScConditionEntry( pDocument, r ), - aStyleName( r.aStyleName ) + aStyleName( r.aStyleName ), + eCondFormatType( r.eCondFormatType) { } @@ -1785,7 +1793,8 @@ const OUString& ScConditionalFormat::GetCellStyle( ScRefCellValue& rCell, const { for (const auto& rxEntry : maEntries) { - if(rxEntry->GetType() == ScFormatEntry::Type::Condition) + if(rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) { const ScCondFormatEntry& rEntry = static_cast<const ScCondFormatEntry&>(*rxEntry); if (rEntry.IsCellValid(rCell, rPos)) @@ -1807,7 +1816,9 @@ ScCondFormatData ScConditionalFormat::GetData( ScRefCellValue& rCell, const ScAd ScCondFormatData aData; for(const auto& rxEntry : maEntries) { - if(rxEntry->GetType() == ScFormatEntry::Type::Condition && aData.aStyleName.isEmpty()) + if( (rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) && + aData.aStyleName.isEmpty()) { const ScCondFormatEntry& rEntry = static_cast<const ScCondFormatEntry&>(*rxEntry); if (rEntry.IsCellValid(rCell, rPos)) @@ -1847,14 +1858,16 @@ void ScConditionalFormat::DoRepaint() void ScConditionalFormat::CompileAll() { for(auto& rxEntry : maEntries) - if(rxEntry->GetType() == ScFormatEntry::Type::Condition) + if(rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) static_cast<ScCondFormatEntry&>(*rxEntry).CompileAll(); } void ScConditionalFormat::CompileXML() { for(auto& rxEntry : maEntries) - if(rxEntry->GetType() == ScFormatEntry::Type::Condition) + if(rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) static_cast<ScCondFormatEntry&>(*rxEntry).CompileXML(); } @@ -1977,7 +1990,8 @@ void ScConditionalFormat::DeleteArea( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCR void ScConditionalFormat::RenameCellStyle(const OUString& rOld, const OUString& rNew) { for(const auto& rxEntry : maEntries) - if(rxEntry->GetType() == ScFormatEntry::Type::Condition) + if(rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) { ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*rxEntry); if(rFormat.GetStyle() == rOld) @@ -1989,7 +2003,8 @@ bool ScConditionalFormat::MarkUsedExternalReferences() const { bool bAllMarked = false; for(const auto& rxEntry : maEntries) - if(rxEntry->GetType() == ScFormatEntry::Type::Condition) + if(rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) { const ScCondFormatEntry& rFormat = static_cast<const ScCondFormatEntry&>(*rxEntry); bAllMarked = rFormat.MarkUsedExternalReferences(); @@ -2020,7 +2035,8 @@ void ScConditionalFormat::CalcAll() { for(const auto& rxEntry : maEntries) { - if (rxEntry->GetType() == ScFormatEntry::Type::Condition) + if (rxEntry->GetType() == ScFormatEntry::Type::Condition || + rxEntry->GetType() == ScFormatEntry::Type::ExtCondition) { ScCondFormatEntry& rFormat = static_cast<ScCondFormatEntry&>(*rxEntry); rFormat.CalcAll(); diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 2cff749ce135..73c21a0376fb 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -640,7 +640,8 @@ void ScTable::CopyConditionalFormat( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCRO { OUString aStyleName; const ScFormatEntry* pEntry = pNewFormatTmp->GetEntry(i); - if(pEntry->GetType() == ScFormatEntry::Type::Condition) + if(pEntry->GetType() == ScFormatEntry::Type::Condition || + pEntry->GetType() == ScFormatEntry::Type::ExtCondition) aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle(); else if(pEntry->GetType() == ScFormatEntry::Type::Date) aStyleName = static_cast<const ScCondDateFormatEntry*>(pEntry)->GetStyleName(); @@ -2194,7 +2195,8 @@ void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCC for (size_t nEntry=0; nEntry<nEntryCount; nEntry++) { const ScFormatEntry* pEntry = pFormat->GetEntry(nEntry); - if(pEntry->GetType() != ScFormatEntry::Type::Condition) + if(pEntry->GetType() != ScFormatEntry::Type::Condition || + pEntry->GetType() != ScFormatEntry::Type::ExtCondition) continue; OUString aStyleName = static_cast<const ScCondFormatEntry*>(pEntry)->GetStyle(); diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx index 9ca8310d28a3..f71d48337baf 100644 --- a/sc/source/filter/excel/xecontent.cxx +++ b/sc/source/filter/excel/xecontent.cxx @@ -1287,6 +1287,15 @@ XclExpCondfmt::XclExpCondfmt( const XclExpRoot& rRoot, const ScConditionalFormat { if(pFormatEntry->GetType() == ScFormatEntry::Type::Condition) maCFList.AppendNewRecord( new XclExpCF( GetRoot(), static_cast<const ScCondFormatEntry&>(*pFormatEntry), ++rIndex ) ); + else if(pFormatEntry->GetType() == ScFormatEntry::Type::ExtCondition) + { + const ScCondFormatEntry& rFormat = static_cast<const ScCondFormatEntry&>(*pFormatEntry); + XclExpExtCondFormatData aExtEntry; + aExtEntry.nPriority = ++rIndex; + aExtEntry.aGUID = generateGUIDString(); + aExtEntry.pEntry = &rFormat; + aExtEntries.push_back(aExtEntry); + } else if(pFormatEntry->GetType() == ScFormatEntry::Type::Colorscale) maCFList.AppendNewRecord( new XclExpColorScale( GetRoot(), static_cast<const ScColorScaleFormat&>(*pFormatEntry), ++rIndex ) ); else if(pFormatEntry->GetType() == ScFormatEntry::Type::Databar) diff --git a/sc/source/filter/excel/xeextlst.cxx b/sc/source/filter/excel/xeextlst.cxx index bde5ec191685..69168fa8184e 100644 --- a/sc/source/filter/excel/xeextlst.cxx +++ b/sc/source/filter/excel/xeextlst.cxx @@ -9,9 +9,17 @@ #include <xeextlst.hxx> #include <xeroot.hxx> +#include <stlsheet.hxx> +#include <ftools.hxx> +#include <xestyle.hxx> +#include <stlpool.hxx> +#include <scitems.hxx> +#include <svl/itemset.hxx> +#include <svl/intitem.hxx> #include <oox/export/utils.hxx> #include <oox/token/namespaces.hxx> +#include <comphelper/processfactory.hxx> using namespace ::oox; @@ -135,6 +143,65 @@ void XclExpExtCfvo::SaveXml( XclExpXmlStream& rStrm ) rWorksheet->endElementNS(XML_x14, XML_cfvo); } +XclExpExtCF::XclExpExtCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormat ): + XclExpRoot(rRoot), + mrFormat(rFormat) +{ +} + +void XclExpExtCF::SaveXml( XclExpXmlStream& rStrm ) +{ + OUString aStyleName = mrFormat.GetStyle(); + SfxStyleSheetBase* pStyle = GetDoc().GetStyleSheetPool()->Find(aStyleName); + SfxItemSet& rSet = pStyle->GetItemSet(); + + std::unique_ptr<ScTokenArray> pTokenArray(mrFormat.CreateFlatCopiedTokenArray(0)); + aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormat.GetValidSrcPos(), pTokenArray.get()); + + std::unique_ptr<XclExpColor> pColor(new XclExpColor); + if(!pColor->FillFromItemSet( rSet )) + pColor.reset(); + + std::unique_ptr<XclExpCellBorder> pBorder(new XclExpCellBorder); + if (!pBorder->FillFromItemSet( rSet, GetPalette(), GetBiff()) ) + pBorder.reset(); + + std::unique_ptr<XclExpCellAlign> pAlign(new XclExpCellAlign); + if (!pAlign->FillFromItemSet( rSet, false, GetBiff())) + pAlign.reset(); + + std::unique_ptr<XclExpCellProt> pCellProt(new XclExpCellProt); + if (!pCellProt->FillFromItemSet( rSet )) + pCellProt.reset(); + + std::unique_ptr<XclExpDxfFont> pFont(new XclExpDxfFont(GetRoot(), rSet)); + + std::unique_ptr<XclExpNumFmt> pNumFormat; + const SfxPoolItem *pPoolItem = nullptr; + if( rSet.GetItemState( ATTR_VALUE_FORMAT, true, &pPoolItem ) == SfxItemState::SET ) + { + sal_uInt32 nScNumFmt = static_cast< const SfxUInt32Item* >(pPoolItem)->GetValue(); + XclExpNumFmtBuffer& rNumFmtBuffer = GetRoot().GetNumFmtBuffer(); + sal_uInt32 nXclNumFmt = rNumFmtBuffer.Insert(nScNumFmt); + pNumFormat.reset(new XclExpNumFmt(nScNumFmt, nXclNumFmt, rNumFmtBuffer.GetFormatCode(nScNumFmt))); + } + + XclExpDxf rDxf( GetRoot(), + std::move(pAlign), + std::move(pBorder), + std::move(pFont), + std::move(pNumFormat), + std::move(pCellProt), + std::move(pColor) ); + + sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); + + rWorksheet->startElementNS( XML_xm, XML_f ); + rWorksheet->writeEscaped( aFormula ); + rWorksheet->endElementNS( XML_xm, XML_f ); + rDxf.SaveXmlExt( rStrm ); +} + XclExpExtDataBar::XclExpExtDataBar( const XclExpRoot& rRoot, const ScDataBarFormat& rFormat, const ScAddress& rPos ): XclExpRoot(rRoot) { @@ -169,6 +236,62 @@ const char* getAxisPosition(databar::ScAxisPosition eAxisPosition) return ""; } +const char* GetOperatorString(ScConditionMode eMode) +{ + const char* pRet = nullptr; + switch(eMode) + { + case ScConditionMode::Equal: + pRet = "equal"; + break; + case ScConditionMode::Less: + pRet = "lessThan"; + break; + case ScConditionMode::Greater: + pRet = "greaterThan"; + break; + case ScConditionMode::EqLess: + pRet = "lessThanOrEqual"; + break; + case ScConditionMode::EqGreater: + pRet = "greaterThanOrEqual"; + break; + case ScConditionMode::NotEqual: + pRet = "notEqual"; + break; + case ScConditionMode::Between: + pRet = "between"; + break; + case ScConditionMode::NotBetween: + pRet = "notBetween"; + break; + case ScConditionMode::Duplicate: + pRet = nullptr; + break; + case ScConditionMode::NotDuplicate: + pRet = nullptr; + break; + case ScConditionMode::BeginsWith: + pRet = "beginsWith"; + break; + case ScConditionMode::EndsWith: + pRet = "endsWith"; + break; + case ScConditionMode::ContainsText: + pRet = "containsText"; + break; + case ScConditionMode::NotContainsText: + pRet = "notContains"; + break; + case ScConditionMode::Direct: + break; + case ScConditionMode::NONE: + default: + break; + } + return pRet; +} + } void XclExpExtDataBar::SaveXml( XclExpXmlStream& rStrm ) @@ -234,7 +357,8 @@ XclExpExtCfRule::XclExpExtCfRule( const XclExpRoot& rRoot, const ScFormatEntry& XclExpRoot(rRoot), maId(rId), pType(nullptr), - mnPriority(nPriority) + mnPriority(nPriority), + mOperator(nullptr) { switch (rFormat.GetType()) { @@ -252,6 +376,14 @@ XclExpExtCfRule::XclExpExtCfRule( const XclExpRoot& rRoot, const ScFormatEntry& pType = "iconSet"; } break; + case ScFormatEntry::Type::ExtCondition: + { + const ScCondFormatEntry& rCondFormat = static_cast<const ScCondFormatEntry&>(rFormat); + mxEntry.reset(new XclExpExtCF(*this, rCondFormat)); + pType = "cellIs"; + mOperator = GetOperatorString( rCondFormat.GetOperation() ); + } + break; default: break; } @@ -266,6 +398,7 @@ void XclExpExtCfRule::SaveXml( XclExpXmlStream& rStrm ) rWorksheet->startElementNS( XML_x14, XML_cfRule, XML_type, pType, XML_priority, mnPriority == -1 ? nullptr : OString::number(mnPriority).getStr(), + XML_operator, mOperator, XML_id, maId ); mxEntry->SaveXml( rStrm ); @@ -314,6 +447,9 @@ XclExpExtConditionalFormatting::XclExpExtConditionalFormatting( const XclExpRoot case ScFormatEntry::Type::Databar: maCfRules.AppendNewRecord(new XclExpExtCfRule( *this, *pEntry, aAddr, rItem.aGUID, rItem.nPriority)); break; + case ScFormatEntry::Type::ExtCondition: + maCfRules.AppendNewRecord(new XclExpExtCfRule( *this, *pEntry, aAddr, rItem.aGUID, rItem.nPriority)); + break; default: break; } @@ -432,4 +568,5 @@ XclExpExtRef XclExtLst::GetItem( XclExpExtType eType ) return XclExpExtRef(); } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/filter/excel/xestyle.cxx b/sc/source/filter/excel/xestyle.cxx index 60edeabfc4e6..6c8ba0549852 100644 --- a/sc/source/filter/excel/xestyle.cxx +++ b/sc/source/filter/excel/xestyle.cxx @@ -3079,6 +3079,27 @@ void XclExpDxf::SaveXml( XclExpXmlStream& rStrm ) rStyleSheet->endElement( XML_dxf ); } +void XclExpDxf::SaveXmlExt( XclExpXmlStream& rStrm ) +{ + sax_fastparser::FSHelperPtr& rStyleSheet = rStrm.GetCurrentStream(); + rStyleSheet->startElementNS( XML_x14, XML_dxf ); + + if (mpFont) + mpFont->SaveXml(rStrm); + if (mpNumberFmt) + mpNumberFmt->SaveXml(rStrm); + if (mpColor) + mpColor->SaveXml(rStrm); + if (mpAlign) + mpAlign->SaveXml(rStrm); + if (mpBorder) + mpBorder->SaveXml(rStrm); + if (mpProt) + mpProt->SaveXml(rStrm); + rStyleSheet->endElementNS( XML_x14, XML_dxf );; +} + + XclExpXmlStyleSheet::XclExpXmlStyleSheet( const XclExpRoot& rRoot ) : XclExpRoot( rRoot ) { diff --git a/sc/source/filter/inc/extlstcontext.hxx b/sc/source/filter/inc/extlstcontext.hxx index 567ab3c93b5b..a00e3236fad7 100644 --- a/sc/source/filter/inc/extlstcontext.hxx +++ b/sc/source/filter/inc/extlstcontext.hxx @@ -17,6 +17,8 @@ #include <vector> #include <memory> +extern sal_Int32 rStyleIdx; // Holds index of the <extlst> <cfRule> style (Will be reseted finalize import) + struct ScDataBarFormatData; namespace oox { class AttributeList; } namespace oox { namespace xls { class WorkbookFragment; } } @@ -50,8 +52,12 @@ public: virtual void onEndElement() override; private: - OUString aChars; + OUString aChars; // Characters of between xml elements. + OUString rStyle; // Style of the corresponding condition + ScConditionMode eOperator; // Used only when cfRule type is "cellIs" + bool isPreviousElementF; // Used to distinguish alone <sqref> from <f> and <sqref> std::vector<std::unique_ptr<ScFormatEntry> > maEntries; + std::vector< OUString > rFormulas; // It holds formulas for a range, there can be more formula for same range. std::unique_ptr<IconSetRule> mpCurrentRule; }; diff --git a/sc/source/filter/inc/stylesbuffer.hxx b/sc/source/filter/inc/stylesbuffer.hxx index aa0a4557bd5f..c3bd431b3f83 100644 --- a/sc/source/filter/inc/stylesbuffer.hxx +++ b/sc/source/filter/inc/stylesbuffer.hxx @@ -803,6 +803,7 @@ public: XfRef createStyleXf(); /** Creates a new empty differential formatting object. */ DxfRef createDxf(); + DxfRef createExtDxf(); /** Appends a new color to the color palette. */ void importPaletteColor( const AttributeList& rAttribs ); @@ -851,6 +852,7 @@ public: ::ScStyleSheet* getCellStyleSheet( sal_Int32 nXfId ) const; /** Creates the style sheet described by the DXF with the passed identifier. */ OUString createDxfStyle( sal_Int32 nDxfId ) const; + OUString createExtDxfStyle( sal_Int32 nDxfId ) const; void writeFontToItemSet( SfxItemSet& rItemSet, sal_Int32 nFontId, bool bSkipPoolDefs ) const; sal_uInt32 writeNumFmtToItemSet( SfxItemSet& rItemSet, sal_uInt32 nNumFmtId, bool bSkipPoolDefs ) const; @@ -861,6 +863,7 @@ public: /** Writes the cell formatting attributes of the specified XF to the passed property set. */ void writeCellXfToDoc( ScDocumentImport& rDoc, const ScRange& rRange, sal_Int32 nXfId ) const; + RefVector< Dxf > getExtDxfs() { return maExtDxfs; } private: typedef RefVector< Font > FontVector; @@ -879,6 +882,7 @@ private: XfVector maStyleXfs; /// List of cell styles. CellStyleBuffer maCellStyles; /// All built-in and user defined cell styles. DxfVector maDxfs; /// List of differential cell styles. + DxfVector maExtDxfs; /// List of differential extlst cell styles. mutable DxfStyleMap maDxfStyles; /// Maps DXF identifiers to Calc style sheet names. }; diff --git a/sc/source/filter/inc/stylesfragment.hxx b/sc/source/filter/inc/stylesfragment.hxx index 9d342f59c50a..a102303c5871 100644 --- a/sc/source/filter/inc/stylesfragment.hxx +++ b/sc/source/filter/inc/stylesfragment.hxx @@ -101,13 +101,14 @@ class DxfContext : public WorkbookContextBase public: template< typename ParentType > explicit DxfContext( ParentType& rParent, const DxfRef& rxDxf ) : - WorkbookContextBase( rParent ), mxDxf( rxDxf ) {} + WorkbookContextBase( rParent ), mxDxf( rxDxf ), mxExtDxf( rxDxf ) {} protected: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override; private: DxfRef mxDxf; + DxfRef mxExtDxf; }; class StylesFragment : public WorkbookFragmentBase diff --git a/sc/source/filter/inc/xeextlst.hxx b/sc/source/filter/inc/xeextlst.hxx index 8b9354b9ebe7..9eff88ec3fb0 100644 --- a/sc/source/filter/inc/xeextlst.hxx +++ b/sc/source/filter/inc/xeextlst.hxx @@ -87,6 +87,17 @@ private: sal_Int32 nIndex; }; +class XclExpExtCF : public XclExpRecordBase, protected XclExpRoot +{ +public: + explicit XclExpExtCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormat ); + virtual void SaveXml( XclExpXmlStream& rStrm ) override; + +private: + OUString aFormula; + const ScCondFormatEntry mrFormat; +}; + class XclExpExtDataBar : public XclExpRecordBase, protected XclExpRoot { public: @@ -133,6 +144,7 @@ private: OString const maId; const char* pType; sal_Int32 const mnPriority; + const char* mOperator; }; typedef std::shared_ptr<XclExpExt> XclExpExtRef; diff --git a/sc/source/filter/inc/xestyle.hxx b/sc/source/filter/inc/xestyle.hxx index 994108939fb8..e5dfb8f2939b 100644 --- a/sc/source/filter/inc/xestyle.hxx +++ b/sc/source/filter/inc/xestyle.hxx @@ -284,14 +284,14 @@ public: virtual void Save( XclExpStream& rStrm ) override; virtual void SaveXml( XclExpXmlStream& rStrm ) override; + OUString GetFormatCode ( sal_uInt32 nScNumFmt ); + private: /** Writes the FORMAT record with index nXclIx and format string rFormatStr. */ void WriteFormatRecord( XclExpStream& rStrm, sal_uInt16 nXclNumFmt, const OUString& rFormatStr ); /** Writes the FORMAT record represented by rFormat. */ void WriteFormatRecord( XclExpStream& rStrm, const XclExpNumFmt& rFormat ); - OUString GetFormatCode ( sal_uInt32 nScNumFmt ); - private: typedef ::std::vector< XclExpNumFmt > XclExpNumFmtVec; @@ -700,6 +700,7 @@ public: virtual ~XclExpDxf() override; virtual void SaveXml( XclExpXmlStream& rStrm ) override; + virtual void SaveXmlExt( XclExpXmlStream& rStrm); private: std::unique_ptr<XclExpCellAlign> mpAlign; diff --git a/sc/source/filter/oox/condformatbuffer.cxx b/sc/source/filter/oox/condformatbuffer.cxx index b6392bed7a8d..5750cce50592 100644 --- a/sc/source/filter/oox/condformatbuffer.cxx +++ b/sc/source/filter/oox/condformatbuffer.cxx @@ -39,6 +39,7 @@ #include <document.hxx> #include <tokenarray.hxx> #include <tokenuno.hxx> +#include <extlstcontext.hxx> namespace oox { namespace xls { @@ -1096,7 +1097,7 @@ void CondFormatBuffer::finalizeImport() { for( const auto& rxCondFormat : maCondFormats ) { - if ( rxCondFormat.get() ) + if ( rxCondFormat.get()) rxCondFormat.get()->finalizeImport(); } for ( const auto& rxCfRule : maCfRules ) @@ -1128,6 +1129,8 @@ void CondFormatBuffer::finalizeImport() pFormat->AddEntry(rxEntry->Clone(pDoc)); } } + + rStyleIdx = 0; // Resets <extlst> <cfRule> style index. } CondFormatRef CondFormatBuffer::importCondFormatting( SequenceInputStream& rStrm ) diff --git a/sc/source/filter/oox/extlstcontext.cxx b/sc/source/filter/oox/extlstcontext.cxx index d0840dddf6a4..1d1bc8341fd5 100644 --- a/sc/source/filter/oox/extlstcontext.cxx +++ b/sc/source/filter/oox/extlstcontext.cxx @@ -20,11 +20,16 @@ #include <document.hxx> #include <worksheetfragment.hxx> #include <workbookfragment.hxx> +#include <stylesbuffer.hxx> +#include <stylesfragment.hxx> #include <rangeutl.hxx> #include <sal/log.hxx> using ::oox::core::ContextHandlerRef; +using ::oox::xls::CondFormatBuffer; + +sal_Int32 rStyleIdx = 0; namespace oox { namespace xls { @@ -79,6 +84,7 @@ void ExtCfRuleContext::onStartElement( const AttributeList& rAttribs ) ExtConditionalFormattingContext::ExtConditionalFormattingContext(WorksheetContextBase& rFragment): WorksheetContextBase(rFragment) { + isPreviousElementF = false; } ContextHandlerRef ExtConditionalFormattingContext::onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs) @@ -98,6 +104,7 @@ ContextHandlerRef ExtConditionalFormattingContext::onCreateContext(sal_Int32 nEl { OUString aType = rAttribs.getString(XML_type, OUString()); OUString aId = rAttribs.getString(XML_id, OUString()); + if (aType == "dataBar") { // an ext entry does not need to have an existing corresponding entry @@ -119,12 +126,22 @@ ContextHandlerRef ExtConditionalFormattingContext::onCreateContext(sal_Int32 nEl maEntries.push_back(std::make_unique<ScIconSetFormat>(pDoc)); return new IconSetContext(*this, mpCurrentRule.get()); } + else if (aType == "cellIs") + { + sal_Int32 aToken = rAttribs.getToken( XML_operator, XML_TOKEN_INVALID ); + eOperator = CondFormatBuffer::convertToInternalOperator(aToken); + return this; + } else { SAL_WARN("sc", "unhandled XLS14_TOKEN(cfRule) with type: " << aType); } } - else if (nElement == XM_TOKEN(sqref)) + else if (nElement == XLS14_TOKEN( dxf )) + { + return new DxfContext( *this, getStyles().createExtDxf() ); + } + else if (nElement == XM_TOKEN( sqref ) || nElement == XM_TOKEN( f )) { return this; } @@ -132,26 +149,43 @@ ContextHandlerRef ExtConditionalFormattingContext::onCreateContext(sal_Int32 nEl return nullptr; } -void ExtConditionalFormattingContext::onStartElement(const AttributeList& /*rAttribs*/) +void ExtConditionalFormattingContext::onStartElement(const AttributeList& /*Attribs*/) +{ +} + +void ExtConditionalFormattingContext::onCharacters(const OUString& rCharacters) { switch (getCurrentElement()) { + case XM_TOKEN(f): + { + aChars = rCharacters; + isPreviousElementF = true; + } + break; case XM_TOKEN(sqref): { + aChars = rCharacters; } break; } -} -void ExtConditionalFormattingContext::onCharacters(const OUString& rCharacters) -{ - aChars = rCharacters; } void ExtConditionalFormattingContext::onEndElement() { switch (getCurrentElement()) { + case XM_TOKEN(f): + { + rFormulas.push_back(aChars); + } + break; + case XLS14_TOKEN( cfRule ): + { + getStyles().getExtDxfs().forEachMem( &Dxf::finalizeImport ); + } + break; case XM_TOKEN(sqref): { ScRangeList aRange; @@ -167,8 +201,26 @@ void ExtConditionalFormattingContext::onEndElement() aRange[i].aEnd.SetTab(nTab); } + if(isPreviousElementF) // sqref can be alone in some cases. + { + for(const OUString& rFormula : rFormulas) + { + ScAddress rPos = aRange.GetTopLeftCorner(); + rStyle = getStyles().createExtDxfStyle(rStyleIdx); + ScCondFormatEntry* pEntry = new ScCondFormatEntry(eOperator, rFormula, "", pDoc, + rPos, rStyle, "", "", + formula::FormulaGrammar::GRAM_OOXML , + formula::FormulaGrammar::GRAM_OOXML, + ScFormatEntry::Type::ExtCondition ); + maEntries.push_back(std::unique_ptr<ScFormatEntry>(pEntry)); + rStyleIdx++; + } + rFormulas.clear(); + } + std::vector< std::unique_ptr<ExtCfCondFormat> >& rExtFormats = getCondFormats().importExtCondFormat(); rExtFormats.push_back(std::make_unique<ExtCfCondFormat>(aRange, maEntries)); + isPreviousElementF = false; } break; default: diff --git a/sc/source/filter/oox/stylesbuffer.cxx b/sc/source/filter/oox/stylesbuffer.cxx index bb5e6f934f19..5e808c8c9a8e 100644 --- a/sc/source/filter/oox/stylesbuffer.cxx +++ b/sc/source/filter/oox/stylesbuffer.cxx @@ -2753,6 +2753,13 @@ DxfRef StylesBuffer::createDxf() return xDxf; } +DxfRef StylesBuffer::createExtDxf() +{ + DxfRef xDxf( new Dxf( *this ) ); + maExtDxfs.push_back( xDxf ); + return xDxf; +} + void StylesBuffer::importPaletteColor( const AttributeList& rAttribs ) { maPalette.importPaletteColor( rAttribs ); @@ -2903,6 +2910,34 @@ OUString StylesBuffer::createDxfStyle( sal_Int32 nDxfId ) const rStyleSheet.GetItemSet(); pDxf->fillToItemSet(rStyleItemSet); + + } + + // on error: fallback to default style + if (rStyleName.isEmpty()) + rStyleName = maCellStyles.getDefaultStyleName(); + + return rStyleName; +} + +OUString StylesBuffer::createExtDxfStyle( sal_Int32 nDxfId ) const +{ + OUString rStyleName; + + if (Dxf* pDxf = maExtDxfs.get(nDxfId).get()) + { + rStyleName = "ExtConditionalStyle_" + OUString::number(nDxfId + 1); + + // Create a cell style. This may overwrite an existing style if + // one with the same name exists. + ScStyleSheet& rStyleSheet = ScfTools::MakeCellStyleSheet( + *getScDocument().GetStyleSheetPool(), rStyleName, true); + + rStyleSheet.ResetParent(); + SfxItemSet& rStyleItemSet = + rStyleSheet.GetItemSet(); + + pDxf->fillToItemSet(rStyleItemSet); } // on error: fallback to default style diff --git a/sc/source/filter/oox/stylesfragment.cxx b/sc/source/filter/oox/stylesfragment.cxx index 9efcbc45e703..2c2c9968703d 100644 --- a/sc/source/filter/oox/stylesfragment.cxx +++ b/sc/source/filter/oox/stylesfragment.cxx @@ -157,6 +157,19 @@ ContextHandlerRef DxfContext::onCreateContext( sal_Int32 nElement, const Attribu } break; } + + if( mxExtDxf.get() ) switch( getCurrentElement() ) + { + case XLS14_TOKEN( dxf ): + switch( nElement ) + { + case XLS_TOKEN( font ): return new FontContext( *this, mxExtDxf->createFont() ); + case XLS_TOKEN( border ): return new BorderContext( *this, mxExtDxf->createBorder() ); + case XLS_TOKEN( fill ): return new FillContext( *this, mxExtDxf->createFill() ); + case XLS_TOKEN( numFmt ): mxExtDxf->importNumFmt( rAttribs ); break; + } + break; + } return nullptr; } diff --git a/sc/source/ui/condformat/condformatdlg.cxx b/sc/source/ui/condformat/condformatdlg.cxx index 0059f550059b..0d0551129039 100644 --- a/sc/source/ui/condformat/condformatdlg.cxx +++ b/sc/source/ui/condformat/condformatdlg.cxx @@ -76,6 +76,7 @@ void ScCondFormatList::init(ScDocument* pDoc, ScCondFormatDlg* pDialogParent, switch(pEntry->GetType()) { case ScFormatEntry::Type::Condition: + case ScFormatEntry::Type::ExtCondition: { const ScCondFormatEntry* pConditionEntry = static_cast<const ScCondFormatEntry*>( pEntry ); if(pConditionEntry->GetOperation() != ScConditionMode::Direct) diff --git a/sc/source/ui/condformat/condformathelper.cxx b/sc/source/ui/condformat/condformathelper.cxx index 0699acf476ba..2ab5d955db15 100644 --- a/sc/source/ui/condformat/condformathelper.cxx +++ b/sc/source/ui/condformat/condformathelper.cxx @@ -133,6 +133,7 @@ OUString ScCondFormatHelper::GetExpression(const ScConditionalFormat& rFormat, c switch(rFormat.GetEntry(0)->GetType()) { case ScFormatEntry::Type::Condition: + case ScFormatEntry::Type::ExtCondition: { const ScConditionEntry* pEntry = static_cast<const ScConditionEntry*>(rFormat.GetEntry(0)); ScConditionMode eMode = pEntry->GetOperation(); diff --git a/sc/source/ui/unoobj/condformatuno.cxx b/sc/source/ui/unoobj/condformatuno.cxx index 69dd2b708453..765e19a23c9a 100644 --- a/sc/source/ui/unoobj/condformatuno.cxx +++ b/sc/source/ui/unoobj/condformatuno.cxx @@ -413,6 +413,7 @@ uno::Reference<beans::XPropertySet> createConditionEntry(const ScFormatEntry* pE switch (pEntry->GetType()) { case ScFormatEntry::Type::Condition: + case ScFormatEntry::Type::ExtCondition: return new ScConditionEntryObj(xParent, static_cast<const ScCondFormatEntry*>(pEntry)); break; diff --git a/sc/source/ui/unoobj/fmtuno.cxx b/sc/source/ui/unoobj/fmtuno.cxx index 7a473cc58c67..40af3ba2d59b 100644 --- a/sc/source/ui/unoobj/fmtuno.cxx +++ b/sc/source/ui/unoobj/fmtuno.cxx @@ -162,7 +162,8 @@ ScTableConditionalFormat::ScTableConditionalFormat( { ScCondFormatEntryItem aItem; const ScFormatEntry* pFrmtEntry = pFormat->GetEntry(i); - if(pFrmtEntry->GetType() != ScFormatEntry::Type::Condition) + if(pFrmtEntry->GetType() != ScFormatEntry::Type::Condition || + pFrmtEntry->GetType() != ScFormatEntry::Type::ExtCondition) continue; const ScCondFormatEntry* pFormatEntry = static_cast<const ScCondFormatEntry*>(pFrmtEntry); |