[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-5-2+backports' - sc/qa sc/source

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Fri May 10 10:33:27 UTC 2019


 sc/qa/unit/data/xlsx/tdf89139_pivot_table.xlsx |binary
 sc/qa/unit/subsequent_export-test.cxx          |   18 ++
 sc/source/filter/excel/xepivotxml.cxx          |  152 +++++++++++++++++++++----
 3 files changed, 150 insertions(+), 20 deletions(-)

New commits:
commit 9cad0ab61f066caed34a9792c3026c334fe711dd
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Aug 24 13:18:44 2017 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Fri May 10 12:32:50 2019 +0200

    tdf#89139: list all items in pivot table definition, incl. hidden
    
    Reviewed-on: https://gerrit.libreoffice.org/41509
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/41588
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit 711cdc36c42a3a9b8d0369c6fd853b8c071bb71a)
    
    Change-Id: I14ce935185a6e0e3739fcf01fdefa031d814e821
    Reviewed-on: https://gerrit.libreoffice.org/72059
    Reviewed-by: Ilhan Yesil <ilhanyesil at gmx.de>
    Tested-by: Ilhan Yesil <ilhanyesil at gmx.de>

diff --git a/sc/qa/unit/data/xlsx/tdf89139_pivot_table.xlsx b/sc/qa/unit/data/xlsx/tdf89139_pivot_table.xlsx
new file mode 100644
index 000000000000..83d5b3dc1556
Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf89139_pivot_table.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index ba3e5dc610af..93ae6ba4184a 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -110,6 +110,7 @@ public:
     void testCellNoteExportXLS();
     void testFormatExportODS();
 
+    void testPivotTableExportXLSX();
     void testCustomColumnWidthExportXLSX();
     void testXfDefaultValuesXLSX();
     void testColumnWidthResaveXLSX();
@@ -199,6 +200,7 @@ public:
     CPPUNIT_TEST(testCellNoteExportXLS);
     CPPUNIT_TEST(testFormatExportODS);
 
+    CPPUNIT_TEST(testPivotTableExportXLSX);
     CPPUNIT_TEST(testCustomColumnWidthExportXLSX);
     CPPUNIT_TEST(testXfDefaultValuesXLSX);
     CPPUNIT_TEST(testColumnWidthResaveXLSX);
@@ -483,6 +485,22 @@ void ScExportTest::testFormatExportODS()
     xDocSh->DoClose();
 }
 
+void ScExportTest::testPivotTableExportXLSX()
+{
+    // tdf#89139: pivot table definition needs to list items, including hidden
+
+    ScDocShellRef xShell = loadDoc("tdf89139_pivot_table.", FORMAT_XLSX);
+    CPPUNIT_ASSERT(xShell.Is());
+
+    std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_XLSX);
+    xmlDocPtr pTable = XPathHelper::parseExport(pXPathFile, m_xSFactory, "xl/pivotTables/pivotTable1.xml");
+    CPPUNIT_ASSERT(pTable);
+
+    assertXPath(pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[3]/x:items", "count", "4");
+    assertXPath(pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[3]/x:items/x:item", 4);
+    assertXPath(pTable, "/x:pivotTableDefinition/x:pivotFields/x:pivotField[3]/x:items/x:item[3]", "h", "1");
+}
+
 void ScExportTest::testCustomColumnWidthExportXLSX()
 {
     //tdf#100946 FILESAVE Excel on OS X ignored column widths in XLSX last saved by LO
diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx
index 31e46b70cf46..e8a520092a07 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -441,6 +441,47 @@ struct DataField
     DataField( long nPos, const ScDPSaveDimension* pDim ) : mnPos(nPos), mpDim(pDim) {}
 };
 
+/** Returns a OOXML subtotal function name string. See ECMA-376-1:2016 18.18.43 */
+OString GetSubtotalFuncName(sal_uInt16 eFunc)
+{
+    switch (eFunc)
+    {
+    case sheet::GeneralFunction_SUM:       return "sum";
+    case sheet::GeneralFunction_COUNT:     return "count";
+    case sheet::GeneralFunction_AVERAGE:   return "avg";
+    case sheet::GeneralFunction_MAX:       return "max";
+    case sheet::GeneralFunction_MIN:       return "min";
+    case sheet::GeneralFunction_PRODUCT:   return "product";
+    case sheet::GeneralFunction_COUNTNUMS: return "countA";
+    case sheet::GeneralFunction_STDEV:     return "stdDev";
+    case sheet::GeneralFunction_STDEVP:    return "stdDevP";
+    case sheet::GeneralFunction_VAR:       return "var";
+    case sheet::GeneralFunction_VARP:      return "varP";
+    default:;
+    }
+    return "default";
+}
+
+sal_Int32 GetSubtotalAttrToken(sal_uInt16 eFunc)
+{
+    switch (eFunc)
+    {
+    case sheet::GeneralFunction_SUM:       return XML_sumSubtotal;
+    case sheet::GeneralFunction_COUNT:     return XML_countSubtotal;
+    case sheet::GeneralFunction_AVERAGE:   return XML_avgSubtotal;
+    case sheet::GeneralFunction_MAX:       return XML_maxSubtotal;
+    case sheet::GeneralFunction_MIN:       return XML_minSubtotal;
+    case sheet::GeneralFunction_PRODUCT:   return XML_productSubtotal;
+    case sheet::GeneralFunction_COUNTNUMS: return XML_countASubtotal;
+    case sheet::GeneralFunction_STDEV:     return XML_stdDevSubtotal;
+    case sheet::GeneralFunction_STDEVP:    return XML_stdDevPSubtotal;
+    case sheet::GeneralFunction_VAR:       return XML_varSubtotal;
+    case sheet::GeneralFunction_VARP:      return XML_varPSubtotal;
+    default:;
+    }
+    return XML_defaultSubtotal;
+}
+
 }
 
 void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rDPObj, sal_Int32 nCacheId )
@@ -528,18 +569,18 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
         XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
         XML_name, XclXmlUtils::ToOString(rDPObj.GetName()).getStr(),
         XML_cacheId, OString::number(nCacheId).getStr(),
-        XML_applyNumberFormats, BS(false),
-        XML_applyBorderFormats, BS(false),
-        XML_applyFontFormats, BS(false),
-        XML_applyPatternFormats, BS(false),
-        XML_applyAlignmentFormats, BS(false),
-        XML_applyWidthHeightFormats, BS(false),
+        XML_applyNumberFormats, XclXmlUtils::ToPsz10(false),
+        XML_applyBorderFormats, XclXmlUtils::ToPsz10(false),
+        XML_applyFontFormats, XclXmlUtils::ToPsz10(false),
+        XML_applyPatternFormats, XclXmlUtils::ToPsz10(false),
+        XML_applyAlignmentFormats, XclXmlUtils::ToPsz10(false),
+        XML_applyWidthHeightFormats, XclXmlUtils::ToPsz10(false),
         XML_dataCaption, "Values",
-        XML_useAutoFormatting, BS(false),
-        XML_itemPrintTitles, BS(true),
-        XML_indent, BS(false),
-        XML_outline, BS(true),
-        XML_outlineData, BS(true),
+        XML_useAutoFormatting, XclXmlUtils::ToPsz10(false),
+        XML_itemPrintTitles, XclXmlUtils::ToPsz10(true),
+        XML_indent, XclXmlUtils::ToPsz10(false),
+        XML_outline, XclXmlUtils::ToPsz10(true),
+        XML_outlineData, XclXmlUtils::ToPsz10(true),
         FSEND);
 
     // NB: Excel's range does not include page field area (if any).
@@ -582,12 +623,13 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
         XML_count, OString::number(static_cast<long>(aCachedDims.size())).getStr(),
         FSEND);
 
-    for (const ScDPSaveDimension* pDim : aCachedDims)
+    for (size_t i = 0; i < nFieldCount; ++i)
     {
+        const ScDPSaveDimension* pDim = aCachedDims[i];
         if (!pDim)
         {
             pPivotStrm->singleElement(XML_pivotField,
-                XML_showAll, BS(false),
+                XML_showAll, XclXmlUtils::ToPsz10(false),
                 FSEND);
             continue;
         }
@@ -598,7 +640,7 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
         if (eOrient == sheet::DataPilotFieldOrientation_HIDDEN)
         {
             pPivotStrm->singleElement(XML_pivotField,
-                XML_showAll, BS(false),
+                XML_showAll, XclXmlUtils::ToPsz10(false),
                 FSEND);
             continue;
         }
@@ -606,20 +648,90 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
         if (eOrient == sheet::DataPilotFieldOrientation_DATA)
         {
             pPivotStrm->singleElement(XML_pivotField,
-                XML_dataField, BS(true),
-                XML_showAll, BS(false),
+                XML_dataField, XclXmlUtils::ToPsz10(true),
+                XML_showAll, XclXmlUtils::ToPsz10(false),
                 FSEND);
 
             continue;
         }
 
-        pPivotStrm->startElement(XML_pivotField,
-            XML_axis, toOOXMLAxisType(eOrient),
-            XML_showAll, BS(false),
+        // Dump field items.
+        std::vector<ScDPLabelData::Member> aMembers;
+        {
+            // We need to get the members in actual order, getting which requires non-const reference here
+            auto& dpo = const_cast<ScDPObject&>(rDPObj);
+            dpo.GetMembers(i, dpo.GetUsedHierarchy(i), aMembers);
+        }
+
+        const ScDPCache::ScDPItemDataVec& rCacheFieldItems = rCache.GetDimMemberValues(i);
+        const auto iCacheFieldItems_begin = rCacheFieldItems.begin(), iCacheFieldItems_end = rCacheFieldItems.end();
+        // The pair contains the member index in cache and if it is hidden
+        std::vector< std::pair<size_t, bool> > aMemberSequence;
+        std::set<size_t> aUsedCachePositions;
+        for (const auto & rMember : aMembers)
+        {
+            auto it = std::find_if(iCacheFieldItems_begin, iCacheFieldItems_end,
+                [&rMember](const ScDPItemData& arg) -> bool { return arg.GetString() == rMember.maName; });
+            if (it != iCacheFieldItems_end)
+            {
+                size_t nCachePos = it - iCacheFieldItems_begin;
+                aMemberSequence.push_back(std::make_pair(nCachePos, !rMember.mbVisible));
+                aUsedCachePositions.insert(nCachePos);
+            }
+        }
+        // Now add all remaining cache items as hidden
+        for (size_t nItem = 0; nItem < rCacheFieldItems.size(); ++nItem)
+        {
+            if (aUsedCachePositions.find(nItem) == aUsedCachePositions.end())
+                aMemberSequence.push_back(std::make_pair(nItem, true));
+        }
+
+        auto pAttList = sax_fastparser::FastSerializerHelper::createAttrList();
+        pAttList->add(XML_axis, toOOXMLAxisType(eOrient));
+        pAttList->add(XML_showAll, XclXmlUtils::ToPsz10(false));
+
+        long nSubTotalCount = pDim->GetSubTotalsCount();
+        std::vector<OString> aSubtotalSequence;
+        bool bHasDefaultSubtotal = false;
+        for (long nSubTotal = 0; nSubTotal < nSubTotalCount; ++nSubTotal)
+        {
+            sal_uInt16 eFunc = pDim->GetSubTotalFunc(nSubTotal);
+            aSubtotalSequence.push_back(GetSubtotalFuncName(eFunc));
+            sal_Int32 nAttToken = GetSubtotalAttrToken(eFunc);
+            if (nAttToken == XML_defaultSubtotal)
+                bHasDefaultSubtotal = true;
+            else if (!pAttList->hasAttribute(nAttToken))
+                pAttList->add(nAttToken, XclXmlUtils::ToPsz10(true));
+        }
+        // XML_defaultSubtotal is true by default; only write it if it's false
+        if (!bHasDefaultSubtotal)
+            pAttList->add(XML_defaultSubtotal, XclXmlUtils::ToPsz10(false));
+
+        sax_fastparser::XFastAttributeListRef xAttributeList(pAttList);
+        pPivotStrm->startElement(XML_pivotField, xAttributeList);
+
+        pPivotStrm->startElement(XML_items,
+            XML_count, OString::number(static_cast<long>(aMemberSequence.size() + aSubtotalSequence.size())),
             FSEND);
 
-        // TODO : Dump field items.
+        for (const auto & nMember : aMemberSequence)
+        {
+            auto pItemAttList = sax_fastparser::FastSerializerHelper::createAttrList();
+            if (nMember.second)
+                pItemAttList->add(XML_h, XclXmlUtils::ToPsz10(true));
+            pItemAttList->add(XML_x, OString::number(static_cast<long>(nMember.first)));
+            sax_fastparser::XFastAttributeListRef xItemAttributeList(pItemAttList);
+            pPivotStrm->singleElement(XML_item, xItemAttributeList);
+        }
+
+        for (const OString& sSubtotal : aSubtotalSequence)
+        {
+            pPivotStrm->singleElement(XML_item,
+                XML_t, sSubtotal,
+                FSEND);
+        }
 
+        pPivotStrm->endElement(XML_items);
         pPivotStrm->endElement(XML_pivotField);
     }
 


More information about the Libreoffice-commits mailing list