sc/inc/colorscale.hxx | 3 + sc/qa/unit/data/xlsx/tdf162948.xlsx |binary sc/qa/unit/subsequent_export_test4.cxx | 46 ++++++++++++++++++------- sc/source/core/data/colorscale.cxx | 36 ++++++++++++++++--- sc/source/filter/excel/xecontent.cxx | 3 + sc/source/filter/inc/condformatbuffer.hxx | 4 +- sc/source/filter/oox/condformatbuffer.cxx | 9 ++++ sc/source/ui/condformat/condformatdlgentry.cxx | 4 ++ 8 files changed, 85 insertions(+), 20 deletions(-)
New commits: commit acc52f9bc0dbfcb5a8893b5aff2d18a2360d46e2 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Fri Oct 4 12:53:28 2024 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Fri Oct 4 15:30:55 2024 +0200 tdf#162948: Add support for gte attribute in conditional format Change-Id: I3dd1a9499ec8d3685b84f3745cf4156b75d1f76f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174470 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Tested-by: Jenkins diff --git a/sc/inc/colorscale.hxx b/sc/inc/colorscale.hxx index bc3b646fe457..373c06eda05c 100644 --- a/sc/inc/colorscale.hxx +++ b/sc/inc/colorscale.hxx @@ -48,6 +48,7 @@ private: ScConditionalFormat* mpFormat; Color maColor; ScColorScaleEntryType meType; + bool mbGreaterThanOrEqual; void setListener(); @@ -62,6 +63,8 @@ public: void SetColor(const Color&); SC_DLLPUBLIC double GetValue() const; SC_DLLPUBLIC void SetValue(double nValue); + SC_DLLPUBLIC bool GetGreaterThanOrEqual() const; + SC_DLLPUBLIC void SetGreaterThanOrEqual(bool bGreaterThanOrEqual); SC_DLLPUBLIC void SetFormula(const OUString& rFormula, ScDocument& rDoc, const ScAddress& rAddr, formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT); diff --git a/sc/qa/unit/data/xlsx/tdf162948.xlsx b/sc/qa/unit/data/xlsx/tdf162948.xlsx new file mode 100644 index 000000000000..bc04c6a53c0f Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf162948.xlsx differ diff --git a/sc/qa/unit/subsequent_export_test4.cxx b/sc/qa/unit/subsequent_export_test4.cxx index 8983756b6d41..67de68174002 100644 --- a/sc/qa/unit/subsequent_export_test4.cxx +++ b/sc/qa/unit/subsequent_export_test4.cxx @@ -111,17 +111,17 @@ void testComplexIconSetsXLSX_Impl(const ScDocument& rDoc, SCCOL nCol, ScIconSetT CPPUNIT_ASSERT_EQUAL(eType, pIconSet->GetIconSetData()->eIconSetType); } -void testCustomIconSetsXLSX_Impl(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, +void testCustomIconSetsXLSX_Impl(const ScDocument& rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, ScIconSetType eType, sal_Int32 nIndex) { - ScConditionalFormat* pFormat = rDoc.GetCondFormat(nCol, 1, 1); + ScConditionalFormat* pFormat = rDoc.GetCondFormat(nCol, nRow, nTab); CPPUNIT_ASSERT(pFormat); CPPUNIT_ASSERT_EQUAL(size_t(1), pFormat->size()); const ScFormatEntry* pEntry = pFormat->GetEntry(0); CPPUNIT_ASSERT(pEntry); CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Iconset, pEntry->GetType()); const ScIconSetFormat* pIconSet = static_cast<const ScIconSetFormat*>(pEntry); - std::unique_ptr<ScIconSetInfo> pInfo(pIconSet->GetIconSetInfo(ScAddress(nCol, nRow, 1))); + std::unique_ptr<ScIconSetInfo> pInfo(pIconSet->GetIconSetInfo(ScAddress(nCol, nRow, nTab))); if (nIndex == -1) CPPUNIT_ASSERT(!pInfo); else @@ -143,15 +143,15 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testComplexIconSetsXLSX) testComplexIconSetsXLSX_Impl(*pDoc, 5, IconSet_5Boxes); CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetCondFormList(1)->size()); - testCustomIconSetsXLSX_Impl(*pDoc, 1, 1, IconSet_3ArrowsGray, 0); - testCustomIconSetsXLSX_Impl(*pDoc, 1, 2, IconSet_3ArrowsGray, -1); - testCustomIconSetsXLSX_Impl(*pDoc, 1, 3, IconSet_3Arrows, 1); - testCustomIconSetsXLSX_Impl(*pDoc, 1, 4, IconSet_3ArrowsGray, -1); - testCustomIconSetsXLSX_Impl(*pDoc, 1, 5, IconSet_3Arrows, 2); - - testCustomIconSetsXLSX_Impl(*pDoc, 3, 1, IconSet_4RedToBlack, 3); - testCustomIconSetsXLSX_Impl(*pDoc, 3, 2, IconSet_3TrafficLights1, 1); - testCustomIconSetsXLSX_Impl(*pDoc, 3, 3, IconSet_3Arrows, 2); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 1, 1, IconSet_3ArrowsGray, 0); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 2, 1, IconSet_3ArrowsGray, -1); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 3, 1, IconSet_3Arrows, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 4, 1, IconSet_3ArrowsGray, -1); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 5, 1, IconSet_3Arrows, 2); + + testCustomIconSetsXLSX_Impl(*pDoc, 3, 1, 1, IconSet_4RedToBlack, 3); + testCustomIconSetsXLSX_Impl(*pDoc, 3, 2, 1, IconSet_3TrafficLights1, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 3, 3, 1, IconSet_3Arrows, 2); }; createScDoc("xlsx/complex_icon_set.xlsx"); @@ -160,6 +160,28 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testComplexIconSetsXLSX) verify(); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf162948) +{ + auto verify = [this]() { + ScDocument* pDoc = getScDoc(); + CPPUNIT_ASSERT_EQUAL(size_t(2), pDoc->GetCondFormList(0)->size()); + testCustomIconSetsXLSX_Impl(*pDoc, 0, 0, 0, IconSet_3Arrows, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 0, 1, 0, IconSet_3Arrows, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 0, 2, 0, IconSet_3Arrows, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 0, 3, 0, IconSet_3Arrows, 1); + + testCustomIconSetsXLSX_Impl(*pDoc, 1, 0, 0, IconSet_3Arrows, 2); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 1, 0, IconSet_3Arrows, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 2, 0, IconSet_3Arrows, 1); + testCustomIconSetsXLSX_Impl(*pDoc, 1, 3, 0, IconSet_3Arrows, 1); + }; + + createScDoc("xlsx/tdf162948.xlsx"); + verify(); + saveAndReload(u"Calc Office Open XML"_ustr); + verify(); +} + CPPUNIT_TEST_FIXTURE(ScExportTest4, testCommentTextHAlignment) { // Testing comment text alignments. diff --git a/sc/source/core/data/colorscale.cxx b/sc/source/core/data/colorscale.cxx index 24c662adffa9..9d7df4506c4f 100644 --- a/sc/source/core/data/colorscale.cxx +++ b/sc/source/core/data/colorscale.cxx @@ -154,7 +154,8 @@ bool ScFormulaListener::NeedsRepaint() const ScColorScaleEntry::ScColorScaleEntry(): mnVal(0), mpFormat(nullptr), - meType(COLORSCALE_VALUE) + meType(COLORSCALE_VALUE), + mbGreaterThanOrEqual(true) { } @@ -162,7 +163,8 @@ ScColorScaleEntry::ScColorScaleEntry(double nVal, const Color& rCol, ScColorScal mnVal(nVal), mpFormat(nullptr), maColor(rCol), - meType(eType) + meType(eType), + mbGreaterThanOrEqual(true) { } @@ -170,7 +172,8 @@ ScColorScaleEntry::ScColorScaleEntry(const ScColorScaleEntry& rEntry): mnVal(rEntry.mnVal), mpFormat(rEntry.mpFormat), maColor(rEntry.maColor), - meType(rEntry.meType) + meType(rEntry.meType), + mbGreaterThanOrEqual(true) { setListener(); if(rEntry.mpCell) @@ -185,7 +188,8 @@ ScColorScaleEntry::ScColorScaleEntry(ScDocument* pDoc, const ScColorScaleEntry& mnVal(rEntry.mnVal), mpFormat(rEntry.mpFormat), maColor(rEntry.maColor), - meType(rEntry.meType) + meType(rEntry.meType), + mbGreaterThanOrEqual(true) { setListener(); if(rEntry.mpCell) @@ -247,6 +251,16 @@ double ScColorScaleEntry::GetValue() const return mnVal; } +bool ScColorScaleEntry::GetGreaterThanOrEqual() const +{ + return mbGreaterThanOrEqual; +} + +void ScColorScaleEntry::SetGreaterThanOrEqual(bool bGreaterThanOrEqual) +{ + mbGreaterThanOrEqual = bGreaterThanOrEqual; +} + void ScColorScaleEntry::SetValue(double nValue) { mnVal = nValue; @@ -1143,15 +1157,25 @@ std::unique_ptr<ScIconSetInfo> ScIconSetFormat::GetIconSetInfo(const ScAddress& double nValMax = CalcValue(nMin, nMax, itr); ++itr; + bool bGreaterThanOrEqual = true; while(itr != end() && nVal >= nValMax) { + bGreaterThanOrEqual = (*itr)->GetGreaterThanOrEqual(); ++nIndex; nValMax = CalcValue(nMin, nMax, itr); ++itr; } - if(nVal >= nValMax) - ++nIndex; + if (bGreaterThanOrEqual) + { + if(nVal >= nValMax) + ++nIndex; + } + else + { + if(nVal > nValMax) + ++nIndex; + } std::unique_ptr<ScIconSetInfo> pInfo(new ScIconSetInfo); diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx index 35dedd6052ba..f28c3420f69b 100644 --- a/sc/source/filter/excel/xecontent.cxx +++ b/sc/source/filter/excel/xecontent.cxx @@ -1255,7 +1255,8 @@ void XclExpCfvo::SaveXml( XclExpXmlStream& rStrm ) rWorksheet->startElement( XML_cfvo, XML_type, getColorScaleType(mrEntry, mbFirst), - XML_val, aValue ); + XML_val, aValue, + XML_gte, sax_fastparser::UseIf("0", !mrEntry.GetGreaterThanOrEqual())); rWorksheet->endElement( XML_cfvo ); } diff --git a/sc/source/filter/inc/condformatbuffer.hxx b/sc/source/filter/inc/condformatbuffer.hxx index 945a05d99e94..ef60145a11fe 100644 --- a/sc/source/filter/inc/condformatbuffer.hxx +++ b/sc/source/filter/inc/condformatbuffer.hxx @@ -80,6 +80,7 @@ struct ColorScaleRuleModelEntry bool mbPercentile; bool mbNum; OUString maFormula; + bool mbGreaterThanOrEqual; ColorScaleRuleModelEntry(): maColor(), @@ -88,7 +89,8 @@ struct ColorScaleRuleModelEntry mbMax(false), mbPercent(false), mbPercentile(false), - mbNum(false) {} + mbNum(false), + mbGreaterThanOrEqual(true) {} }; class ColorScaleRule final : public WorksheetHelper diff --git a/sc/source/filter/oox/condformatbuffer.cxx b/sc/source/filter/oox/condformatbuffer.cxx index 7ceb587a090e..d40b16a6e84c 100644 --- a/sc/source/filter/oox/condformatbuffer.cxx +++ b/sc/source/filter/oox/condformatbuffer.cxx @@ -115,6 +115,13 @@ void SetCfvoData( ColorScaleRuleModelEntry* pEntry, const AttributeList& rAttrib { OUString aType = rAttribs.getString( XML_type, OUString() ); OUString aVal = rAttribs.getString(XML_val, OUString()); + OUString aGreaterThanOrEqual = rAttribs.getString(XML_gte, OUString()); + + if (!aGreaterThanOrEqual.isEmpty()) + { + if (!aGreaterThanOrEqual.toBoolean()) + pEntry->mbGreaterThanOrEqual = false; + } if (aVal != "\"\"") { @@ -324,6 +331,8 @@ ScColorScaleEntry* ConvertToModel( const ColorScaleRuleModelEntry& rEntry, ScDoc pEntry->SetFormula(rEntry.maFormula, *pDoc, rAddr, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1); } + pEntry->SetGreaterThanOrEqual(rEntry.mbGreaterThanOrEqual); + return pEntry; } diff --git a/sc/source/ui/condformat/condformatdlgentry.cxx b/sc/source/ui/condformat/condformatdlgentry.cxx index c612229c9380..0e6a55f7a023 100644 --- a/sc/source/ui/condformat/condformatdlgentry.cxx +++ b/sc/source/ui/condformat/condformatdlgentry.cxx @@ -1281,6 +1281,10 @@ ScIconSetFrmtDataEntry::ScIconSetFrmtDataEntry(weld::Container* pParent, ScIconS , mxLbEntryType(mxBuilder->weld_combo_box(u"listbox"_ustr)) , mpContainer(pParent) { + // tdf#162948: Use ">" instead of ">=". Add some spaces to keep the alignment + if (!pEntry->GetGreaterThanOrEqual()) + mxFtEntry->set_label(" > "); + mxImgIcon->set_from_icon_name(ScIconSetFormat::getIconName(eType, i)); if(pEntry) {