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)
     {

Reply via email to