sc/inc/dpobject.hxx                         |   17 ++++++++++
 sc/qa/unit/data/xlsx/pivot_dark1.xlsx       |binary
 sc/qa/unit/pivottable_filters_test.cxx      |   47 ++++++++++++++++++++++++++++
 sc/source/core/data/dpobject.cxx            |    3 +
 sc/source/filter/excel/xepivotxml.cxx       |   40 +++++++++++++++++++++++
 sc/source/filter/inc/pivottablebuffer.hxx   |    3 +
 sc/source/filter/oox/pivottablebuffer.cxx   |   16 +++++++++
 sc/source/filter/oox/pivottablefragment.cxx |    3 +
 8 files changed, 129 insertions(+)

New commits:
commit c2eac244912a7de8637befe62387916d3fdc1f89
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Apr 18 15:41:03 2019 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Jun 19 10:01:10 2019 +0200

    tdf#124810: Roundtrip pivot table style info from XLSX.
    
    Also provide a default pivot table style for those tables that don't
    have a style info. Let's use the style settings that Excel uses.
    
    Change-Id: I8006a33a0aa0e92629f7db0a9c24a6ff52d17945
    Reviewed-on: https://gerrit.libreoffice.org/70933
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/74335
    Tested-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 9be63f26db36..4d0011c17868 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -95,6 +95,11 @@ private:
                                             // cached data
     css::uno::Reference<css::sheet::XDimensionsSupplier> xSource;
     std::unique_ptr<ScDPOutput> pOutput;
+
+    // name -> sequence of sequences of css::xml::FastAttribute or 
css::xml::Attribute
+    // see PivotTable::putToInteropGrabBag in 
sc/source/filter/oox/pivottablebuffer.cxx for details
+    std::map<OUString, css::uno::Any> maInteropGrabBag;
+
     long                    nHeaderRows;    // page fields plus filter button
     bool                    mbHeaderLayout:1;  // true : grid, false : standard
     bool                    bAllowMove:1;
@@ -253,6 +258,18 @@ public:
 
     static bool         IsOrientationAllowed( 
css::sheet::DataPilotFieldOrientation nOrient, sal_Int32 nDimFlags );
 
+    void PutInteropGrabBag(std::map<OUString, css::uno::Any>&& val)
+    {
+        maInteropGrabBag = std::move(val);
+    }
+    std::pair<bool, css::uno::Any> GetInteropGrabBagValue(const OUString& 
sName) const
+    {
+        if (const auto it = maInteropGrabBag.find(sName); it != 
maInteropGrabBag.end())
+            return { true, it->second };
+
+        return { false, css::uno::Any() };
+    }
+
 #if DUMP_PIVOT_TABLE
     void Dump() const;
     void DumpCache() const;
diff --git a/sc/qa/unit/data/xlsx/pivot_dark1.xlsx 
b/sc/qa/unit/data/xlsx/pivot_dark1.xlsx
new file mode 100644
index 000000000000..8341e5b09d6d
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot_dark1.xlsx differ
diff --git a/sc/qa/unit/pivottable_filters_test.cxx 
b/sc/qa/unit/pivottable_filters_test.cxx
index 62147268b047..b0868a5db88f 100644
--- a/sc/qa/unit/pivottable_filters_test.cxx
+++ b/sc/qa/unit/pivottable_filters_test.cxx
@@ -92,6 +92,7 @@ public:
     void testTdf124651();
     void testTdf124736();
     void tesTtdf124772NumFmt();
+    void testTdf124810();
 
     CPPUNIT_TEST_SUITE(ScPivotTableFiltersTest);
 
@@ -138,6 +139,7 @@ public:
     CPPUNIT_TEST(testTdf124651);
     CPPUNIT_TEST(testTdf124736);
     CPPUNIT_TEST(tesTtdf124772NumFmt);
+    CPPUNIT_TEST(testTdf124810);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -2554,6 +2556,51 @@ void ScPivotTableFiltersTest::tesTtdf124772NumFmt()
                 "formatCode", "\\$#,##0");
 }
 
+void ScPivotTableFiltersTest::testTdf124810()
+{
+    {
+        // First, test that we roundtrip existing pivot table style 
information from XLSX.
+        ScDocShellRef xDocSh = loadDoc("pivot_dark1.", FORMAT_XLSX);
+        CPPUNIT_ASSERT(xDocSh.is());
+
+        xmlDocPtr pTable = XPathHelper::parseExport2(*this, *xDocSh, 
m_xSFactory,
+            "xl/pivotTables/pivotTable1.xml", FORMAT_XLSX);
+        xDocSh->DoClose();
+        CPPUNIT_ASSERT(pTable);
+
+        // All attributes must have been roundtripped correctly (testdoc uses 
some non-default values)
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"name",
+                    "PivotStyleDark1");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showRowHeaders", "1");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showColHeaders", "1");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showRowStripes", "1");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showColStripes", "0");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showLastColumn", "0");
+    }
+
+    {
+        // Now check that we export default style information when there's no 
such information in
+        // original document. Just use some ODS as source. This might be 
changed when we start
+        // exporting better pivot table style information.
+        ScDocShellRef xDocSh = loadDoc("tdf124651_simplePivotTable.", 
FORMAT_ODS);
+        CPPUNIT_ASSERT(xDocSh.is());
+
+        xmlDocPtr pTable = XPathHelper::parseExport2(*this, *xDocSh, 
m_xSFactory,
+            "xl/pivotTables/pivotTable1.xml", FORMAT_XLSX);
+        xDocSh->DoClose();
+        CPPUNIT_ASSERT(pTable);
+
+        // The default style for pivot tables in Excel 2007 through 2016 is 
PivotStyleLight16
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"name",
+                    "PivotStyleLight16");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showRowHeaders", "1");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showColHeaders", "1");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showRowStripes", "0");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showColStripes", "0");
+        assertXPath(pTable, "/x:pivotTableDefinition/x:pivotTableStyleInfo", 
"showLastColumn", "1");
+    }
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(ScPivotTableFiltersTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index bc6bf4a0d1d6..92f795ceb2a9 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -321,6 +321,7 @@ ScDPObject::ScDPObject(const ScDPObject& r) :
     aTableTag( r.aTableTag ),
     aOutRange( r.aOutRange ),
     mpTableData(static_cast<ScDPTableData*>(nullptr)),
+    maInteropGrabBag(r.maInteropGrabBag),
     nHeaderRows( r.nHeaderRows ),
     mbHeaderLayout( r.mbHeaderLayout ),
     bAllowMove(false),
@@ -353,6 +354,7 @@ ScDPObject& ScDPObject::operator= (const ScDPObject& r)
         aTableName = r.aTableName;
         aTableTag = r.aTableTag;
         aOutRange = r.aOutRange;
+        maInteropGrabBag = r.maInteropGrabBag;
         nHeaderRows = r.nHeaderRows;
         mbHeaderLayout = r.mbHeaderLayout;
         bAllowMove = false;
@@ -793,6 +795,7 @@ void ScDPObject::Clear()
     pImpDesc.reset();
     pServDesc.reset();
     ClearTableData();
+    maInteropGrabBag.clear();
 }
 
 void ScDPObject::ClearTableData()
diff --git a/sc/source/filter/excel/xepivotxml.cxx 
b/sc/source/filter/excel/xepivotxml.cxx
index c866c690a3c3..cfa173cca627 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -709,6 +709,37 @@ sal_Int32 GetSubtotalAttrToken(ScGeneralFunction eFunc)
     return XML_defaultSubtotal;
 }
 
+// An item is expected to contain sequences of css::xml::FastAttribute and 
css::xml::Attribute
+void WriteGrabBagItemToStream(XclExpXmlStream& rStrm, sal_Int32 tokenId, const 
css::uno::Any& rItem)
+{
+    if (css::uno::Sequence<css::uno::Any> aSeqs; rItem >>= aSeqs)
+    {
+        auto& pStrm = rStrm.GetCurrentStream();
+        pStrm->write("<")->writeId(tokenId);
+
+        css::uno::Sequence<css::xml::FastAttribute> aFastSeq;
+        css::uno::Sequence<css::xml::Attribute> aUnkSeq;
+        for (const auto& a : aSeqs)
+        {
+            if (a >>= aFastSeq)
+            {
+                for (const auto& rAttr : aFastSeq)
+                    rStrm.WriteAttributes(rAttr.Token, rAttr.Value.toUtf8(), 
FSEND);
+            }
+            else if (a >>= aUnkSeq)
+            {
+                for (const auto& rAttr : aUnkSeq)
+                    pStrm->write(" ")
+                        ->write(rAttr.Name)
+                        ->write("=\"")
+                        ->writeEscaped(rAttr.Value)
+                        ->write("\"");
+            }
+        }
+
+        pStrm->write("/>");
+    }
+}
 }
 
 void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const 
ScDPObject& rDPObj, sal_Int32 nCacheId )
@@ -1135,6 +1166,15 @@ void XclExpXmlPivotTables::SavePivotTableXml( 
XclExpXmlStream& rStrm, const ScDP
         pPivotStrm->endElement(XML_dataFields);
     }
 
+    // Now add style info (use grab bag, or just a set which is default on 
Excel 2007 through 2016)
+    if (const auto [bHas, aVal] = 
rDPObj.GetInteropGrabBagValue("pivotTableStyleInfo"); bHas)
+        WriteGrabBagItemToStream(rStrm, XML_pivotTableStyleInfo, aVal);
+    else
+        pPivotStrm->singleElement(XML_pivotTableStyleInfo, XML_name, 
"PivotStyleLight16",
+                                  XML_showRowHeaders, "1", XML_showColHeaders, 
"1",
+                                  XML_showRowStripes, "0", XML_showColStripes, 
"0",
+                                  XML_showLastColumn, "1", FSEND);
+
     OUStringBuffer aBuf("../pivotCache/pivotCacheDefinition");
     aBuf.append(nCacheId);
     aBuf.append(".xml");
diff --git a/sc/source/filter/inc/pivottablebuffer.hxx 
b/sc/source/filter/inc/pivottablebuffer.hxx
index 75f8b78006ef..8b769a68308e 100644
--- a/sc/source/filter/inc/pivottablebuffer.hxx
+++ b/sc/source/filter/inc/pivottablebuffer.hxx
@@ -297,6 +297,8 @@ public:
     void                importPageField( const AttributeList& rAttribs );
     /** Reads the settings of a field located in the data dimension from the 
dataField element. */
     void                importDataField( const AttributeList& rAttribs );
+    /** Puts the attributes to the named grab bag value. */
+    void putToInteropGrabBag(const OUString& sName, const AttributeList& 
rAttribs);
 
     /** Reads global pivot table settings from the PTDEFINITION record. */
     void                importPTDefinition( SequenceInputStream& rStrm );
@@ -379,6 +381,7 @@ private:
     PivotCache*           mpPivotCache;       /// The pivot cache this table 
is based on.
     css::uno::Reference< css::sheet::XDataPilotDescriptor >
                           mxDPDescriptor;     /// Descriptor of the DataPilot 
object.
+    std::map<OUString, css::uno::Any> maInteropGrabBag;
 
 };
 
diff --git a/sc/source/filter/oox/pivottablebuffer.cxx 
b/sc/source/filter/oox/pivottablebuffer.cxx
index 3363068464ca..c23b0a039ee8 100644
--- a/sc/source/filter/oox/pivottablebuffer.cxx
+++ b/sc/source/filter/oox/pivottablebuffer.cxx
@@ -38,6 +38,7 @@
 #include <com/sun/star/sheet/XDataPilotField.hpp>
 #include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
 #include <com/sun/star/sheet/XSheetOperation.hpp>
+#include <com/sun/star/xml/sax/XFastAttributeList.hpp>
 #include <osl/diagnose.hxx>
 #include <sal/log.hxx>
 #include <oox/helper/binaryinputstream.hxx>
@@ -1036,6 +1037,18 @@ void PivotTable::importDataField( const AttributeList& 
rAttribs )
     maDataFields.push_back( aModel );
 }
 
+void PivotTable::putToInteropGrabBag(const OUString& sName, const 
AttributeList& rAttribs)
+{
+    if (auto xFastAttributeList = rAttribs.getFastAttributeList())
+    {
+        // Store both known and unknown attribute sequences to the grab bag as 
is
+        css::uno::Sequence<css::xml::FastAttribute> aFast = 
xFastAttributeList->getFastAttributes();
+        css::uno::Sequence<css::xml::Attribute> aUnk = 
xFastAttributeList->getUnknownAttributes();
+        css::uno::Sequence<css::uno::Any> aVal{ css::uno::Any(aFast), 
css::uno::Any(aUnk) };
+        maInteropGrabBag[sName] <<= aVal;
+    }
+}
+
 void PivotTable::importPTDefinition( SequenceInputStream& rStrm )
 {
     sal_uInt32 nFlags1, nFlags2, nFlags3;
@@ -1277,6 +1290,9 @@ void PivotTable::finalizeImport()
                 if( !maPageFields.empty() )
                     aPos.Row = ::std::max< sal_Int32 >( static_cast< sal_Int32 
>( aPos.Row - maPageFields.size() - 1 ), 0 );
 
+                // save interop grab bag
+                mpDPObject->PutInteropGrabBag(std::move(maInteropGrabBag));
+
                 // insert the DataPilot table into the sheet
                 xDPTables->insertNewByName( maDefModel.maName, aPos, 
mxDPDescriptor );
             }
diff --git a/sc/source/filter/oox/pivottablefragment.cxx 
b/sc/source/filter/oox/pivottablefragment.cxx
index 5bac8f3c68be..099cd6770073 100644
--- a/sc/source/filter/oox/pivottablefragment.cxx
+++ b/sc/source/filter/oox/pivottablefragment.cxx
@@ -182,6 +182,9 @@ ContextHandlerRef PivotTableFragment::onCreateContext( 
sal_Int32 nElement, const
                 case XLS_TOKEN( pageFields ):   return this;
                 case XLS_TOKEN( dataFields ):   return this;
                 case XLS_TOKEN( filters ):      return this;
+                case XLS_TOKEN(pivotTableStyleInfo):
+                    mrPivotTable.putToInteropGrabBag("pivotTableStyleInfo", 
rAttribs);
+                    break;
             }
         break;
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to