[Libreoffice-commits] core.git: 4 commits - sc/qa sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Fri Aug 29 15:25:03 PDT 2014


 sc/qa/unit/data/xlsx/pivot-table/two-data-fields.xlsx |binary
 sc/qa/unit/subsequent_export-test.cxx                 |  122 ++++++++++++++++++
 sc/source/filter/excel/xepivotxml.cxx                 |   83 ++++++++++--
 sc/source/ui/unoobj/dapiuno.cxx                       |   13 +
 4 files changed, 201 insertions(+), 17 deletions(-)

New commits:
commit 151d7a62230c98bb06628667170165f875788637
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Aug 29 18:07:29 2014 -0400

    Write test for importing and exporting of pivot table with 2 data fields.
    
    This is for xlsx format.
    
    Change-Id: I8ef2ae41cc88eeeab610e1a89726c62acb9e2fcb

diff --git a/sc/qa/unit/data/xlsx/pivot-table/two-data-fields.xlsx b/sc/qa/unit/data/xlsx/pivot-table/two-data-fields.xlsx
new file mode 100644
index 0000000..793af59
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/two-data-fields.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index d20bf73..432bc75 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -39,6 +39,7 @@
 #include <dpcache.hxx>
 #include <dpobject.hxx>
 #include <dpsave.hxx>
+#include <dputil.hxx>
 
 #include <svx/svdoole2.hxx>
 #include "tabprotection.hxx"
@@ -122,6 +123,7 @@ public:
     void testSheetProtection();
 
     void testPivotTableXLSX();
+    void testPivotTableTwoDataFieldsXLSX();
 
     CPPUNIT_TEST_SUITE(ScExportTest);
     CPPUNIT_TEST(test);
@@ -160,6 +162,7 @@ public:
 #endif
     CPPUNIT_TEST(testSheetProtection);
     CPPUNIT_TEST(testPivotTableXLSX);
+    CPPUNIT_TEST(testPivotTableTwoDataFieldsXLSX);
     CPPUNIT_TEST(testFunctionsExcel2010ODS);
 
     CPPUNIT_TEST_SUITE_END();
@@ -2121,6 +2124,125 @@ void ScExportTest::testPivotTableXLSX()
     xDocSh2->DoClose();
 }
 
+void ScExportTest::testPivotTableTwoDataFieldsXLSX()
+{
+    struct
+    {
+        bool check( const ScDocument& rDoc )
+        {
+            if (!rDoc.HasPivotTable())
+            {
+                cerr << "The document should have pivot table." << endl;
+                return false;
+            }
+
+            const ScDPCollection* pDPs = rDoc.GetDPCollection();
+            if (!pDPs)
+            {
+                cerr << "Pivot table container should exist." << endl;
+                return false;
+            }
+
+            ScRange aSrcRange(1,1,1,2,8,1); // B2:C9 on the 2nd sheet.
+            const ScDPCache* pCache = pDPs->GetSheetCaches().getExistingCache(aSrcRange);
+            if (!pCache)
+            {
+                cerr << "The document should have a pivot cache for B2:C9 on 'Src'." << endl;
+                return false;
+            }
+
+            const char* pNames[] = { "Name", "Value" };
+
+            size_t nCount = pCache->GetFieldCount();
+            if (nCount != SAL_N_ELEMENTS(pNames))
+            {
+                cout << "Incorrect number of fields in pivot cache." << endl;
+                return false;
+            }
+
+            const ScDPObject* pDPObj = rDoc.GetDPAtCursor(0,2,0); // A3
+            if (!pDPObj)
+            {
+                cerr << "A pivot table should exist over A3." << endl;
+                return false;
+            }
+
+            // Output range should be A3:C12.
+            ScRange aOutRange = pDPObj->GetOutRange();
+            if (ScRange(0,2,0,2,11,0) != aOutRange)
+            {
+                cerr << "Incorrect output range." << endl;
+                return false;
+            }
+
+            const ScDPSaveData* pSaveData = pDPObj->GetSaveData();
+            if (!pSaveData)
+            {
+                cerr << "Save data should exist in each pivot table object." << endl;
+                return false;
+            }
+
+            std::vector<const ScDPSaveDimension*> aDims;
+            pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aDims);
+            if (aDims.size() != 1 || aDims[0]->GetName() != "Name")
+            {
+                cerr << "Pivot table should have one row field labeld 'Name'" << endl;
+                return false;
+            }
+
+            pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
+            if (aDims.size() != 2 ||
+                ScDPUtil::getSourceDimensionName(aDims[0]->GetName()) != "Value" ||
+                ScDPUtil::getSourceDimensionName(aDims[1]->GetName()) != "Value")
+            {
+                cerr << "Pivot table should have two duplicated data fields both of which are named 'Value'." << endl;
+                return false;
+            }
+
+            if (aDims[0]->GetFunction() != sheet::GeneralFunction_SUM)
+            {
+                cerr << "First data field should be SUM." << endl;
+                return false;
+            }
+
+            if (aDims[1]->GetFunction() != sheet::GeneralFunction_COUNT)
+            {
+                cerr << "First data field should be COUNT." << endl;
+                return false;
+            }
+
+            pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aDims);
+            if (aDims.size() != 1 || !aDims[0]->IsDataLayout())
+            {
+                cerr << "Pivot table should have one column field which is a data layout field." << endl;
+                return false;
+            }
+
+            return true;
+        }
+
+    } aTest;
+
+    ScDocShellRef xDocSh = loadDoc("pivot-table/two-data-fields.", XLSX);
+    CPPUNIT_ASSERT(xDocSh.Is());
+    ScDocument* pDoc = &xDocSh->GetDocument();
+
+    // Initial check.
+    bool bCheck = aTest.check(*pDoc);
+    CPPUNIT_ASSERT_MESSAGE("Initial check failed.", bCheck);
+
+    ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX);
+    xDocSh->DoClose();
+    CPPUNIT_ASSERT(xDocSh2.Is());
+    pDoc = &xDocSh2->GetDocument();
+
+    // Reload check.
+    bCheck = aTest.check(*pDoc);
+    CPPUNIT_ASSERT_MESSAGE("Reload check failed.", bCheck);
+
+    xDocSh2->DoClose();
+}
+
 void ScExportTest::testFunctionsExcel2010ODS()
 {
     //testFunctionsExcel2010(ODS);
commit f37c6e0d111c2237d422be07acbb67b7d0dcbbeb
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Aug 29 17:43:00 2014 -0400

    Correctly export subtotal functions of data fields.
    
    Take note that data field may be duplicated.
    
    Change-Id: I8f787075869f38d0101da2787bac315c71d8a6e8

diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx
index 5ff871a..3f7d320 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -18,6 +18,7 @@
 
 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
 #include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
+#include <com/sun/star/sheet/GeneralFunction.hpp>
 
 #include <vector>
 
@@ -74,6 +75,40 @@ const char* toOOXMLAxisType( sheet::DataPilotFieldOrientation eOrient )
     return "";
 }
 
+const char* toOOXMLSubtotalType( sheet::GeneralFunction eFunc )
+{
+    switch (eFunc)
+    {
+        case sheet::GeneralFunction_SUM:
+            return "sum";
+        case sheet::GeneralFunction_COUNT:
+            return "count";
+        case sheet::GeneralFunction_AVERAGE:
+            return "average";
+        case sheet::GeneralFunction_MAX:
+            return "max";
+        case sheet::GeneralFunction_MIN:
+            return "min";
+        case sheet::GeneralFunction_PRODUCT:
+            return "product";
+        case sheet::GeneralFunction_COUNTNUMS:
+            return "countNums";
+        case sheet::GeneralFunction_STDEV:
+            return "stdDev";
+        case sheet::GeneralFunction_STDEVP:
+            return "stdDevp";
+        case sheet::GeneralFunction_VAR:
+            return "var";
+        case sheet::GeneralFunction_VARP:
+            return "varp";
+        case sheet::GeneralFunction_NONE:
+        case sheet::GeneralFunction_AUTO:
+        default:
+            ;
+    }
+    return NULL;
+}
+
 }
 
 XclExpXmlPivotCaches::XclExpXmlPivotCaches( const XclExpRoot& rRoot ) :
@@ -354,6 +389,18 @@ void XclExpXmlPivotTables::SaveXml( XclExpXmlStream& rStrm )
     }
 }
 
+namespace {
+
+struct DataField
+{
+    long mnPos; // field index in pivot cache.
+    const ScDPSaveDimension* mpDim;
+
+    DataField( long nPos, const ScDPSaveDimension* pDim ) : mnPos(nPos), mpDim(pDim) {}
+};
+
+}
+
 void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rDPObj, sal_Int32 nCacheId )
 {
     typedef boost::unordered_map<OUString, long, OUStringHash> NameToIdMapType;
@@ -383,7 +430,7 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
     std::vector<long> aRowFields;
     std::vector<long> aColFields;
     std::vector<long> aPageFields;
-    std::vector<long> aDataFields;
+    std::vector<DataField> aDataFields;
 
     // Use dimensions in the save data to get their correct ordering.
     // Dimension order here is significant as they specify the order of
@@ -426,7 +473,7 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
                 aPageFields.push_back(nPos);
             break;
             case sheet::DataPilotFieldOrientation_DATA:
-                aDataFields.push_back(nPos);
+                aDataFields.push_back(DataField(nPos, &rDim));
             break;
             case sheet::DataPilotFieldOrientation_HIDDEN:
             default:
@@ -607,12 +654,12 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
             XML_count, OString::number(static_cast<long>(aDataFields.size())),
             FSEND);
 
-        std::vector<long>::iterator it = aDataFields.begin(), itEnd = aDataFields.end();
+        std::vector<DataField>::iterator it = aDataFields.begin(), itEnd = aDataFields.end();
         for (; it != itEnd; ++it)
         {
-            long nDimIdx = *it;
+            long nDimIdx = it->mnPos;
             assert(aCachedDims[nDimIdx]); // the loop above should have screened for NULL's.
-            const ScDPSaveDimension& rDim = *aCachedDims[nDimIdx];
+            const ScDPSaveDimension& rDim = *it->mpDim;
             const OUString* pName = rDim.GetLayoutName();
             pPivotStrm->write("<")->writeId(XML_dataField);
             if (pName)
@@ -620,6 +667,11 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
 
             rStrm.WriteAttributes(XML_fld, OString::number(nDimIdx).getStr(), FSEND);
 
+            sheet::GeneralFunction eFunc = static_cast<sheet::GeneralFunction>(rDim.GetFunction());
+            const char* pSubtotal = toOOXMLSubtotalType(eFunc);
+            if (pSubtotal)
+                rStrm.WriteAttributes(XML_subtotal, pSubtotal, FSEND);
+
             pPivotStrm->write("/>");
         }
 
commit 3b856f028735d292c9b02168704d4a07e2f43cd5
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Aug 29 17:18:09 2014 -0400

    Use the source dimension name when searching for a dimension.
    
    Otherwise we might miss the right dimension object.  This fixes the bug where
    the subtotal function of the second data field was not set correctly when
    importing from xlsx.
    
    Change-Id: Id6ecb07b86cf6803a3f6f7604267ce2f5f9a4067

diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx
index 5cc6f06..cd4e0a2 100644
--- a/sc/source/ui/unoobj/dapiuno.cxx
+++ b/sc/source/ui/unoobj/dapiuno.cxx
@@ -38,6 +38,7 @@
 #include "dpgroup.hxx"
 #include "dpdimsave.hxx"
 #include "hints.hxx"
+#include <dputil.hxx>
 
 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
@@ -1481,13 +1482,17 @@ ScDPSaveDimension* ScDataPilotChildObjBase::GetDPDimension( ScDPObject** ppDPObj
                 return pSaveData->GetDimensionByName( maFieldId.maFieldName );
 
             // find dimension with specified index (search in duplicated dimensions)
-            const boost::ptr_vector<ScDPSaveDimension>& rDimensions = pSaveData->GetDimensions();
+            const ScDPSaveData::DimsType& rDims = pSaveData->GetDimensions();
 
             sal_Int32 nFoundIdx = 0;
-            boost::ptr_vector<ScDPSaveDimension>::const_iterator it;
-            for(it = rDimensions.begin(); it != rDimensions.end(); ++it)
+            ScDPSaveData::DimsType::const_iterator it;
+            for (it = rDims.begin(); it != rDims.end(); ++it)
             {
-                if( !it->IsDataLayout() && (it->GetName() == maFieldId.maFieldName) )
+                if (it->IsDataLayout())
+                    continue;
+
+                OUString aSrcName = ScDPUtil::getSourceDimensionName(it->GetName());
+                if (aSrcName == maFieldId.maFieldName)
                 {
                     if( nFoundIdx == maFieldId.mnFieldIdx )
                         return const_cast<ScDPSaveDimension*>(&(*it));
commit bfaf4401b440b56d6e226a4dca32a18e84949d52
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Aug 29 16:23:57 2014 -0400

    Export data layout field to xlsx correctly.
    
    Excel uses a field index of -2 to indicate a data layout field.
    
    Change-Id: I6b18c0bcff439eb4425ef0b0d0b841633dc81dd7

diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx
index cef5a85..5ff871a 100644
--- a/sc/source/filter/excel/xepivotxml.cxx
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -395,16 +395,21 @@ void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDP
         const ScDPSaveDimension& rDim = rDims[i];
 
         long nPos = -1; // position in cache
-        OUString aSrcName = ScDPUtil::getSourceDimensionName(rDim.GetName());
-        NameToIdMapType::iterator it = aNameToIdMap.find(aSrcName);
-        if (it != aNameToIdMap.end())
-            nPos = it->second;
+        if (rDim.IsDataLayout())
+            nPos = -2; // Excel uses an index of -2 to indicate a data layout field.
+        else
+        {
+            OUString aSrcName = ScDPUtil::getSourceDimensionName(rDim.GetName());
+            NameToIdMapType::iterator it = aNameToIdMap.find(aSrcName);
+            if (it != aNameToIdMap.end())
+                nPos = it->second;
 
-        if (nPos == -1)
-            continue;
+            if (nPos == -1)
+                continue;
 
-        if (!aCachedDims[nPos])
-            continue;
+            if (!aCachedDims[nPos])
+                continue;
+        }
 
         sheet::DataPilotFieldOrientation eOrient =
             static_cast<sheet::DataPilotFieldOrientation>(rDim.GetOrientation());


More information about the Libreoffice-commits mailing list