[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