sc/qa/unit/data/xlsx/autofilter-colors.xlsx |binary
 sc/qa/unit/subsequent_export-test.cxx       |   29 +++++++
 sc/source/filter/excel/excrecds.cxx         |   33 +++++++-
 sc/source/filter/excel/xestyle.cxx          |  115 +++++++++++++++++++++++++---
 sc/source/filter/excel/xlstyle.cxx          |    7 +
 sc/source/filter/inc/excrecds.hxx           |   10 ++
 sc/source/filter/inc/xestyle.hxx            |    9 ++
 sc/source/filter/inc/xlstyle.hxx            |    1 
 8 files changed, 192 insertions(+), 12 deletions(-)

New commits:
commit b8cfea65ddcba33572e9687022de3c813711e298
Author:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
AuthorDate: Wed May 19 11:05:27 2021 +0200
Commit:     Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>
CommitDate: Wed May 19 15:41:34 2021 +0200

    tdf#76258 Add OOXML export for color filter
    
    Change-Id: I4c0e2fbe27de6d48a33aba230c35d3b74854e27e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115789
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <samuel.mehrbr...@allotropia.de>

diff --git a/sc/qa/unit/data/xlsx/autofilter-colors.xlsx 
b/sc/qa/unit/data/xlsx/autofilter-colors.xlsx
new file mode 100644
index 000000000000..e4f8e67b202d
Binary files /dev/null and b/sc/qa/unit/data/xlsx/autofilter-colors.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx 
b/sc/qa/unit/subsequent_export-test.cxx
index 4864266b8790..6d1b927e931a 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -221,6 +221,8 @@ public:
     void testTdf95640_xlsx_to_xlsx();
     void testDateAutofilterXLSX();
     void testAutofilterColorsODF();
+    void testAutofilterColorsOOXML();
+    void testAutofilterColorsStyleOOXML();
 
     void testRefStringXLSX();
     void testRefStringConfigXLSX();
@@ -409,6 +411,8 @@ public:
     CPPUNIT_TEST(testTdf95640_xlsx_to_xlsx);
     CPPUNIT_TEST(testDateAutofilterXLSX);
     CPPUNIT_TEST(testAutofilterColorsODF);
+    CPPUNIT_TEST(testAutofilterColorsOOXML);
+    CPPUNIT_TEST(testAutofilterColorsStyleOOXML);
 
     CPPUNIT_TEST(testRefStringXLSX);
     CPPUNIT_TEST(testRefStringConfigXLSX);
@@ -4653,6 +4657,31 @@ void ScExportTest::testAutofilterColorsODF()
     assertXPath(pDoc, 
"//table:filter/table:filter-and/table:filter-condition[2][@loext:data-type='text-color']");
 }
 
+void ScExportTest::testAutofilterColorsOOXML()
+{
+    ScDocShellRef xDocSh = loadDoc(u"autofilter-colors.", FORMAT_XLSX);
+    CPPUNIT_ASSERT(xDocSh.is());
+
+    xmlDocUniquePtr pDoc = XPathHelper::parseExport2(*this, *xDocSh, 
m_xSFactory,
+                                                     "xl/tables/table1.xml", 
FORMAT_XLSX);
+    CPPUNIT_ASSERT(pDoc);
+
+    assertXPath(pDoc, "/x:table/x:autoFilter/x:filterColumn/x:colorFilter", 
"dxfId", "4");
+}
+
+void ScExportTest::testAutofilterColorsStyleOOXML()
+{
+    ScDocShellRef xDocSh = loadDoc(u"autofilter-colors.", FORMAT_XLSX);
+    CPPUNIT_ASSERT(xDocSh.is());
+
+    xmlDocUniquePtr pDoc
+        = XPathHelper::parseExport2(*this, *xDocSh, m_xSFactory, 
"xl/styles.xml", FORMAT_XLSX);
+    CPPUNIT_ASSERT(pDoc);
+
+    assertXPath(pDoc, 
"/x:styleSheet/x:dxfs/x:dxf[5]/x:fill/x:patternFill/x:bgColor", "rgb",
+                "FFFFD7D7");
+}
+
 void ScExportTest::testTdf88657ODS()
 {
     ScDocShellRef xDocSh = loadDoc(u"tdf88657.", FORMAT_ODS);
diff --git a/sc/source/filter/excel/excrecds.cxx 
b/sc/source/filter/excel/excrecds.cxx
index b73c695391bd..c1f45823efcd 100644
--- a/sc/source/filter/excel/excrecds.cxx
+++ b/sc/source/filter/excel/excrecds.cxx
@@ -43,6 +43,7 @@
 #include <xelink.hxx>
 #include <xename.hxx>
 #include <xlname.hxx>
+#include <xestyle.hxx>
 
 #include <xcl97rec.hxx>
 #include <tabprotection.hxx>
@@ -711,6 +712,10 @@ bool XclExpAutofilter::AddEntry( const ScQueryEntry& 
rEntry )
     }
     else if(rEntry.IsQueryByNonEmpty())
         bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, 
EXC_AFOPER_NONE, 0.0, nullptr, true );
+    else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
+    {
+        AddColorEntry(rEntry);
+    }
     // other conditions
     else
     {
@@ -794,6 +799,17 @@ void XclExpAutofilter::AddMultiValueEntry( const 
ScQueryEntry& rEntry )
     }
 }
 
+void XclExpAutofilter::AddColorEntry(const ScQueryEntry& rEntry)
+{
+    meType = ColorValue;
+    const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
+    for (const auto& rItem : rItems)
+    {
+        maColorValues.push_back(
+            std::make_pair(rItem.maColor, rItem.meType == 
ScQueryEntry::ByBackgroundColor));
+    }
+}
+
 void XclExpAutofilter::WriteBody( XclExpStream& rStrm )
 {
     rStrm << nCol << nFlags;
@@ -835,8 +851,21 @@ void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm )
             aCond[ 0 ].SaveXml( rStrm );
             aCond[ 1 ].SaveXml( rStrm );
             rWorksheet->endElement( XML_customFilters );
-            // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
-            // XML_extLst, XML_filters, XML_iconFilter, XML_top10
+            // OOXTODO: XML_dynamicFilter, XML_extLst, XML_filters, 
XML_iconFilter
+        }
+        break;
+        case ColorValue:
+        {
+            if (!maColorValues.empty())
+            {
+                Color color = maColorValues[0].first;
+                sal_Int32 nDxfId;
+                if (maColorValues[0].second) // is background color
+                    nDxfId = GetDxfs().GetDxfByBackColor(color);
+                else
+                    nDxfId = GetDxfs().GetDxfByForeColor(color);
+                rWorksheet->singleElement(XML_colorFilter, XML_dxfId, 
OString::number(nDxfId));
+            }
         }
         break;
         case BlankValue:
diff --git a/sc/source/filter/excel/xestyle.cxx 
b/sc/source/filter/excel/xestyle.cxx
index d3830d7ad9b0..df4afbaf5eca 100644
--- a/sc/source/filter/excel/xestyle.cxx
+++ b/sc/source/filter/excel/xestyle.cxx
@@ -46,6 +46,8 @@
 #include <xestring.hxx>
 #include <xltools.hxx>
 #include <conditio.hxx>
+#include <dbdata.hxx>
+#include <filterentries.hxx>
 
 #include <o3tl/safeint.hxx>
 #include <oox/export/utils.hxx>
@@ -1865,7 +1867,18 @@ void XclExpCellBorder::SaveXml( XclExpXmlStream& rStrm ) 
const
 
 XclExpCellArea::XclExpCellArea() :
     mnForeColorId( XclExpPalette::GetColorIdFromIndex( mnForeColor ) ),
-    mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) )
+    mnBackColorId( XclExpPalette::GetColorIdFromIndex( mnBackColor ) ),
+    maForeColor(0),
+    maBackColor(0)
+{
+}
+
+XclExpCellArea::XclExpCellArea(Color aForeColor, Color aBackColor)
+    : XclCellArea(EXC_PATT_SOLID)
+    , mnForeColorId(0)
+    , mnBackColorId(0)
+    , maForeColor(aForeColor)
+    , maBackColor(aBackColor)
 {
 }
 
@@ -1942,15 +1955,42 @@ void XclExpCellArea::SaveXml( XclExpXmlStream& rStrm ) 
const
 
     XclExpPalette& rPalette = rStrm.GetRoot().GetPalette();
 
-    if( mnPattern == EXC_PATT_NONE || ( mnForeColor == 0 && mnBackColor == 0 ) 
)
+    if (mnPattern == EXC_PATT_NONE
+        || (mnForeColor == 0 && mnBackColor == 0 && maForeColor == 0 && 
maBackColor == 0))
+    {
         rStyleSheet->singleElement(XML_patternFill, XML_patternType, 
ToPatternType(mnPattern));
+    }
     else
     {
         rStyleSheet->startElement(XML_patternFill, XML_patternType, 
ToPatternType(mnPattern));
-        rStyleSheet->singleElement( XML_fgColor,
-                XML_rgb, 
XclXmlUtils::ToOString(rPalette.GetColor(mnForeColor)) );
-        rStyleSheet->singleElement( XML_bgColor,
-                XML_rgb, 
XclXmlUtils::ToOString(rPalette.GetColor(mnBackColor)) );
+        if (maForeColor != 0 || maBackColor != 0)
+        {
+            if (maForeColor != 0)
+            {
+                rStyleSheet->singleElement(XML_fgColor, XML_rgb,
+                                           
XclXmlUtils::ToOString(maForeColor));
+            }
+
+            if (maBackColor != 0)
+            {
+                rStyleSheet->singleElement(XML_bgColor, XML_rgb,
+                                           
XclXmlUtils::ToOString(maBackColor));
+            }
+        }
+        else
+        {
+            if (mnForeColor != 0)
+            {
+                rStyleSheet->singleElement(XML_fgColor, XML_rgb,
+                                           
XclXmlUtils::ToOString(rPalette.GetColor(mnForeColor)));
+            }
+            if (mnBackColor != 0)
+            {
+                rStyleSheet->singleElement(XML_bgColor, XML_rgb,
+                                           
XclXmlUtils::ToOString(rPalette.GetColor(mnBackColor)));
+            }
+        }
+
         rStyleSheet->endElement( XML_patternFill );
     }
 
@@ -3013,9 +3053,42 @@ XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot )
     xFormatter->FillKeywordTableForExcel( *mpKeywordTable );
 
     SCTAB nTables = rRoot.GetDoc().GetTableCount();
-    sal_Int32 nIndex = 0;
+    sal_Int32 nForeColorIndex = 0;
+    sal_Int32 nBackColorIndex = 0;
+    sal_Int32 nCondFormattingIndex = 0;
     for(SCTAB nTab = 0; nTab < nTables; ++nTab)
     {
+        // Color filters
+        const ScDBData* pData = 
rRoot.GetDoc().GetDBCollection()->GetDBNearCursor(0, 0, 0);
+        if (pData)
+        {
+            ScRange aRange;
+            pData->GetArea(aRange);
+            ScFilterEntries aFilterEntries;
+            rRoot.GetDoc().GetFilterEntriesArea(aRange.aStart.Col(), 
aRange.aStart.Row(),
+                                                aRange.aEnd.Row(), nTab, true, 
aFilterEntries);
+
+            for (auto& rColor : aFilterEntries.getBackgroundColors())
+            {
+                if (!maBackColorToDxfId.emplace(rColor, 
nBackColorIndex).second)
+                    continue;
+
+                std::unique_ptr<XclExpCellArea> pExpCellArea(new 
XclExpCellArea(0, rColor));
+                maDxf.push_back(std::make_unique<XclExpDxf>(rRoot, 
std::move(pExpCellArea)));
+                nBackColorIndex++;
+            }
+            for (auto& rColor : aFilterEntries.getTextColors())
+            {
+                if (!maForeColorToDxfId.emplace(rColor, 
nForeColorIndex).second)
+                    continue;
+
+                std::unique_ptr<XclExpCellArea> pExpCellArea(new 
XclExpCellArea(rColor, 0));
+                maDxf.push_back(std::make_unique<XclExpDxf>(rRoot, 
std::move(pExpCellArea)));
+                nForeColorIndex++;
+            }
+        }
+
+        // Conditional formatting
         ScConditionalFormatList* pList = rRoot.GetDoc().GetCondFormList(nTab);
         if (pList)
         {
@@ -3044,7 +3117,7 @@ XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot )
                         aStyleName = pEntry->GetStyleName();
                     }
 
-                    if (maStyleNameToDxfId.emplace(aStyleName, nIndex).second)
+                    if (maStyleNameToDxfId.emplace(aStyleName, 
nCondFormattingIndex).second)
                     {
                         SfxStyleSheetBase* pStyle = 
rRoot.GetDoc().GetStyleSheetPool()->Find(aStyleName, SfxStyleFamily::Para);
                         if(!pStyle)
@@ -3089,7 +3162,7 @@ XclExpDxfs::XclExpDxfs( const XclExpRoot& rRoot )
 
                         maDxf.push_back(std::make_unique<XclExpDxf>( rRoot, 
std::move(pAlign), std::move(pBorder),
                                 std::move(pFont), std::move(pNumFormat), 
std::move(pCellProt), std::move(pColor) ));
-                        ++nIndex;
+                        ++nCondFormattingIndex;
                     }
 
                 }
@@ -3106,6 +3179,22 @@ sal_Int32 XclExpDxfs::GetDxfId( const OUString& 
rStyleName )
     return -1;
 }
 
+sal_Int32 XclExpDxfs::GetDxfByBackColor(Color& aColor)
+{
+    std::map<Color, sal_Int32>::iterator itr = maBackColorToDxfId.find(aColor);
+    if (itr != maBackColorToDxfId.end())
+        return itr->second;
+    return -1;
+}
+
+sal_Int32 XclExpDxfs::GetDxfByForeColor(Color& aColor)
+{
+    std::map<Color, sal_Int32>::iterator itr = maForeColorToDxfId.find(aColor);
+    if (itr != maForeColorToDxfId.end())
+        return itr->second;
+    return -1;
+}
+
 void XclExpDxfs::SaveXml( XclExpXmlStream& rStrm )
 {
     if(maDxf.empty())
@@ -3135,6 +3224,12 @@ XclExpDxf::XclExpDxf( const XclExpRoot& rRoot, 
std::unique_ptr<XclExpCellAlign>
 {
 }
 
+XclExpDxf::XclExpDxf(const XclExpRoot& rRoot, std::unique_ptr<XclExpCellArea> 
pCellArea)
+    : XclExpRoot(rRoot)
+    , mpCellArea(std::move(pCellArea))
+{
+}
+
 XclExpDxf::~XclExpDxf()
 {
 }
@@ -3156,6 +3251,8 @@ void XclExpDxf::SaveXml( XclExpXmlStream& rStrm )
         mpBorder->SaveXml(rStrm);
     if (mpProt)
         mpProt->SaveXml(rStrm);
+    if (mpCellArea)
+        mpCellArea->SaveXml(rStrm);
     rStyleSheet->endElement( XML_dxf );
 }
 
diff --git a/sc/source/filter/excel/xlstyle.cxx 
b/sc/source/filter/excel/xlstyle.cxx
index 84d146c922fb..e0b8c07458a5 100644
--- a/sc/source/filter/excel/xlstyle.cxx
+++ b/sc/source/filter/excel/xlstyle.cxx
@@ -1693,6 +1693,13 @@ XclCellArea::XclCellArea() :
 {
 }
 
+XclCellArea::XclCellArea(sal_uInt8 nPattern) :
+    mnForeColor( EXC_COLOR_WINDOWTEXT ),
+    mnBackColor( EXC_COLOR_WINDOWBACK ),
+    mnPattern( nPattern )
+{
+}
+
 bool XclCellArea::IsTransparent() const
 {
     return (mnPattern == EXC_PATT_NONE) && (mnBackColor == 
EXC_COLOR_WINDOWBACK);
diff --git a/sc/source/filter/inc/excrecds.hxx 
b/sc/source/filter/inc/excrecds.hxx
index e8224a41a69a..e997be8958e6 100644
--- a/sc/source/filter/inc/excrecds.hxx
+++ b/sc/source/filter/inc/excrecds.hxx
@@ -360,13 +360,20 @@ public:
 class XclExpAutofilter : public XclExpRecord, protected XclExpRoot
 {
 private:
-    enum FilterType { FilterCondition, MultiValue, BlankValue };
+    enum FilterType
+    {
+        FilterCondition,
+        MultiValue,
+        BlankValue,
+        ColorValue
+    };
     FilterType              meType;
     sal_uInt16              nCol;
     sal_uInt16              nFlags;
     bool                    bHasBlankValue;
     ExcFilterCondition      aCond[ 2 ];
     std::vector<std::pair<OUString, bool>> maMultiValues; // first->values, 
second->bDateFormat
+    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,
@@ -383,6 +390,7 @@ public:
     bool                    HasCondition() const;
     bool                    AddEntry( const ScQueryEntry& rEntry );
     void                    AddMultiValueEntry( const ScQueryEntry& rEntry );
+    void AddColorEntry( const ScQueryEntry& rEntry );
 
     virtual void            SaveXml( XclExpXmlStream& rStrm ) override;
 };
diff --git a/sc/source/filter/inc/xestyle.hxx b/sc/source/filter/inc/xestyle.hxx
index 9cc653f9aba6..70bd9b7fa0b2 100644
--- a/sc/source/filter/inc/xestyle.hxx
+++ b/sc/source/filter/inc/xestyle.hxx
@@ -373,8 +373,11 @@ struct XclExpCellArea : public XclCellArea
 {
     sal_uInt32          mnForeColorId;  /// Foreground color ID.
     sal_uInt32          mnBackColorId;  /// Background color ID.
+    Color maForeColor; // Actual foreground color
+    Color maBackColor; // Actual background color
 
     explicit            XclExpCellArea();
+    explicit            XclExpCellArea(Color aForeColor, Color aBackColor);
 
     /** Fills the area attributes from the passed item set.
         @return  true = At least one area item is set. */
@@ -724,6 +727,7 @@ public:
     XclExpDxf( const XclExpRoot& rRoot, std::unique_ptr<XclExpCellAlign> 
pAlign, std::unique_ptr<XclExpCellBorder> pBorder,
             std::unique_ptr<XclExpDxfFont> pFont, 
std::unique_ptr<XclExpNumFmt> pNumberFmt,
             std::unique_ptr<XclExpCellProt> pProt, 
std::unique_ptr<XclExpColor> pColor);
+    XclExpDxf( const XclExpRoot& rRoot, std::unique_ptr<XclExpCellArea> 
pCellArea);
     virtual ~XclExpDxf() override;
 
     virtual void SaveXml( XclExpXmlStream& rStrm ) override;
@@ -736,6 +740,7 @@ private:
     std::unique_ptr<XclExpNumFmt> mpNumberFmt;
     std::unique_ptr<XclExpCellProt> mpProt;
     std::unique_ptr<XclExpColor> mpColor;
+    std::unique_ptr<XclExpCellArea> mpCellArea;
 };
 
 class XclExpDxfs : public XclExpRecordBase, protected XclExpRoot
@@ -744,11 +749,15 @@ public:
     XclExpDxfs( const XclExpRoot& rRoot );
 
     sal_Int32 GetDxfId(const OUString& rName);
+    sal_Int32 GetDxfByBackColor(Color& aColor);
+    sal_Int32 GetDxfByForeColor(Color& aColor);
 
     virtual void SaveXml( XclExpXmlStream& rStrm) override;
 private:
     typedef std::vector< std::unique_ptr<XclExpDxf> > DxfContainer;
     std::map<OUString, sal_Int32> maStyleNameToDxfId;
+    std::map<Color, sal_Int32> maBackColorToDxfId;
+    std::map<Color, sal_Int32> maForeColorToDxfId;
     DxfContainer maDxf;
     std::unique_ptr<NfKeywordTable>   mpKeywordTable; /// Replacement table.
 };
diff --git a/sc/source/filter/inc/xlstyle.hxx b/sc/source/filter/inc/xlstyle.hxx
index bf7a107a26e4..3581f77f0162 100644
--- a/sc/source/filter/inc/xlstyle.hxx
+++ b/sc/source/filter/inc/xlstyle.hxx
@@ -547,6 +547,7 @@ struct XclCellArea
     sal_uInt8           mnPattern;      /// Fill pattern.
 
     explicit            XclCellArea();
+    explicit            XclCellArea(sal_uInt8 nPattern);
 
     /** Returns true, if the area represents transparent state. */
     bool                IsTransparent() const;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to