/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "charttest.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace com::sun::star::table { class XCellRange; } namespace com::sun::star::util { class XNumberFormats; } class PivotChartTest : public ChartTest { public: PivotChartTest() : ChartTest() {} void testRoundtrip(); void testChangePivotTable(); void testPivotChartWithOneColumnField(); void testPivotChartWithOneRowField(); void testPivotTableDataProvider_PivotTableFields(); void testPivotChartRowFieldInOutlineMode(); void testPivotChartWithDateRowField(); CPPUNIT_TEST_SUITE(PivotChartTest); CPPUNIT_TEST(testRoundtrip); CPPUNIT_TEST(testChangePivotTable); CPPUNIT_TEST(testPivotChartWithOneColumnField); CPPUNIT_TEST(testPivotChartWithOneRowField); CPPUNIT_TEST(testPivotTableDataProvider_PivotTableFields); CPPUNIT_TEST(testPivotChartRowFieldInOutlineMode); CPPUNIT_TEST(testPivotChartWithDateRowField); CPPUNIT_TEST_SUITE_END(); }; namespace { void lclModifyOrientation(uno::Reference const & xDescriptor, std::u16string_view sFieldName, sheet::DataPilotFieldOrientation eOrientation) { uno::Reference xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); sal_Int32 nCount = xIndexAccess->getCount(); for (sal_Int32 i = 0; i < nCount; ++i) { uno::Reference xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); OUString aName = xNamed->getName(); uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); if (aName == sFieldName) xPropSet->setPropertyValue("Orientation", uno::makeAny(eOrientation)); } } void lclModifyFunction(uno::Reference const & xDescriptor, std::u16string_view sFieldName, sheet::GeneralFunction eFunction) { uno::Reference xPilotIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); sal_Int32 nCount = xPilotIndexAccess->getCount(); for (sal_Int32 i = 0; i < nCount; ++i) { uno::Reference xNamed(xPilotIndexAccess->getByIndex(i), UNO_QUERY_THROW); OUString aName = xNamed->getName(); uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); if (aName == sFieldName) xPropSet->setPropertyValue("Function", uno::makeAny(eFunction)); } } void lclModifyLayoutInfo(uno::Reference const & xDescriptor, std::u16string_view sFieldName, sheet::DataPilotFieldLayoutInfo aLayoutInfo) { uno::Reference xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); sal_Int32 nCount = xIndexAccess->getCount(); for (sal_Int32 i = 0; i < nCount; ++i) { uno::Reference xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); OUString aName = xNamed->getName(); uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); if (aName == sFieldName) { uno::Any aValue; aValue <<= aLayoutInfo; xPropSet->setPropertyValue("LayoutInfo", aValue); } } } void lclModifySubtotals(uno::Reference const & xDescriptor, std::u16string_view sFieldName, uno::Sequence const & rSubtotalFunctions) { uno::Reference xIndexAccess(xDescriptor->getDataPilotFields(), UNO_SET_THROW); sal_Int32 nCount = xIndexAccess->getCount(); for (sal_Int32 i = 0; i < nCount; ++i) { uno::Reference xNamed(xIndexAccess->getByIndex(i), UNO_QUERY_THROW); OUString aName = xNamed->getName(); uno::Reference xPropSet(xNamed, UNO_QUERY_THROW); if (aName == sFieldName) { uno::Any aValue; aValue <<= rSubtotalFunctions; xPropSet->setPropertyValue("Subtotals", aValue); } } } void lclModifyColumnGrandTotal(uno::Reference const & xDataPilotDescriptor, bool bTotal) { uno::Reference xProperties(xDataPilotDescriptor, uno::UNO_QUERY_THROW); xProperties->setPropertyValue("ColumnGrand", uno::makeAny(bTotal)); } void lclModifyRowGrandTotal(uno::Reference const & xDataPilotDescriptor, bool bTotal) { uno::Reference xProperties(xDataPilotDescriptor, uno::UNO_QUERY_THROW); xProperties->setPropertyValue("RowGrand", uno::makeAny(bTotal)); } void lclCheckSequence(std::vector const & reference, uno::Sequence const & values, double delta) { CPPUNIT_ASSERT_EQUAL(reference.size(), size_t(values.getLength())); for (size_t i = 0; i < reference.size(); ++i) { CPPUNIT_ASSERT_DOUBLES_EQUAL( reference[i], values[i].get(), delta); } } void lclCheckCategories(std::vector const & reference, uno::Reference const & xSequence) { uno::Reference xTextualDataSequence(xSequence, uno::UNO_QUERY_THROW); uno::Sequence aText = xTextualDataSequence->getTextualData(); CPPUNIT_ASSERT_EQUAL(reference.size(), size_t(aText.getLength())); for (size_t i = 0; i < reference.size(); ++i) { CPPUNIT_ASSERT_EQUAL(reference[i], aText[i]); } } OUString lclGetLabel(Reference const & xChartDoc, sal_Int32 nSeriesIndex) { Reference xLabelDataSequence = getLabelDataSequenceFromDoc(xChartDoc, nSeriesIndex); return xLabelDataSequence->getData()[0].get(); } uno::Reference lclGetPivotTableByName(sal_Int32 nIndex, OUString const & sPivotTableName, uno::Reference const & xComponent) { uno::Reference xDoc(xComponent, UNO_QUERY_THROW); uno::Reference xSheetIndexAccess(xDoc->getSheets(), UNO_QUERY_THROW); uno::Any aAny = xSheetIndexAccess->getByIndex(nIndex); uno::Reference xSheet; CPPUNIT_ASSERT(aAny >>= xSheet); uno::Reference xDataPilotTablesSupplier(xSheet, uno::UNO_QUERY_THROW); uno::Reference xDataPilotTables = xDataPilotTablesSupplier->getDataPilotTables(); return uno::Reference(xDataPilotTables->getByName(sPivotTableName), UNO_QUERY_THROW); } uno::Sequence> lclGetCategories(Reference const & xChartDoc) { uno::Sequence aArguments( comphelper::InitPropertySequence( {{"CellRangeRepresentation", uno::Any(OUString("PT@categories"))}} )); uno::Reference xDataProvider(xChartDoc->getDataProvider(), uno::UNO_SET_THROW); return xDataProvider->createDataSource(aArguments)->getDataSequences(); } struct Value { OUString maString; double mfValue; bool mbIsValue; Value(OUString const & rString) : maString(rString) , mfValue(0.0) , mbIsValue(false) {} Value(double fValue) : mfValue(fValue) , mbIsValue(true) {} }; uno::Reference< sheet::XDataPilotTables> lclGetDataPilotTables(sal_Int32 nIndex, uno::Reference const & xSheetDoc) { uno::Reference xSpreadsheets = xSheetDoc->getSheets(); uno::Reference oIndexAccess(xSpreadsheets, uno::UNO_QUERY_THROW); uno::Reference xSheet; CPPUNIT_ASSERT(oIndexAccess->getByIndex(nIndex) >>= xSheet); // create the test objects uno::Reference< sheet::XDataPilotTablesSupplier> xDataPilotTablesSupplier(xSheet, uno::UNO_QUERY_THROW); return xDataPilotTablesSupplier->getDataPilotTables(); } table::CellRangeAddress lclCreateTestData(uno::Reference const & xSheetDoc) { CPPUNIT_ASSERT_MESSAGE("no calc document!", xSheetDoc.is()); std::vector aHeaders { "Country", "City", "Type", "Sales T1", "Sales T2", "Sales T3", "Sales T4", "Date" }; std::vector> aData { { {"FR"}, {"Paris"}, {"A"}, {123.0}, {223.0}, {323.0}, {423.0}, {"12/14/15"} }, { {"EN"}, {"London"}, {"A"}, {456.0}, {556.0}, {656.0}, {756.0}, {"12/11/15"} }, { {"DE"}, {"Berlin"}, {"A"}, {468.0}, {568.0}, {668.0}, {768.0}, {"12/11/15"} }, { {"FR"}, {"Nantes"}, {"A"}, {694.0}, {794.0}, {894.0}, {994.0}, {"12/11/15"} }, { {"EN"}, {"Glasgow"}, {"A"}, {298.0}, {398.0}, {498.0}, {598.0}, {"12/11/15"} }, { {"DE"}, {"Munich"}, {"A"}, {369.0}, {469.0}, {569.0}, {669.0}, {"12/11/15"} }, { {"FR"}, {"Paris"}, {"B"}, {645.0}, {745.0}, {845.0}, {945.0}, {"12/11/15"} }, { {"EN"}, {"London"}, {"B"}, {687.0}, {787.0}, {887.0}, {987.0}, {"03/21/17"} }, { {"DE"}, {"Munich"}, {"B"}, {253.0}, {353.0}, {453.0}, {553.0}, {"12/17/15"} }, { {"FR"}, {"Nantes"}, {"B"}, {474.0}, {574.0}, {674.0}, {774.0}, {"01/20/16"} }, { {"EN"}, {"Liverpool"}, {"B"}, {562.0}, {662.0}, {762.0}, {862.0}, {"01/20/16"} }, { {"DE"}, {"Berlin"}, {"B"}, {648.0}, {748.0}, {848.0}, {948.0}, {"01/20/16"} } }; // Getting spreadsheet uno::Reference xSpreadsheets = xSheetDoc->getSheets(); uno::Reference oIndexAccess(xSpreadsheets, uno::UNO_QUERY_THROW); uno::Reference xSheet; CPPUNIT_ASSERT(oIndexAccess->getByIndex(0) >>= xSheet); uno::Reference oPivotTableSheet; xSpreadsheets->insertNewByName("Pivot Table", 1); CPPUNIT_ASSERT(oIndexAccess->getByIndex(1) >>= oPivotTableSheet); sal_Int32 currentRow = 0; for (size_t column = 0; column < aHeaders.size(); ++column) { xSheet->getCellByPosition(column, currentRow)->setFormula(aHeaders[column]); } currentRow++; for (std::vector const & rRowOfData : aData) { for (size_t column = 0; column < rRowOfData.size(); ++column) { Value const & rValue = rRowOfData[column]; uno::Reference xCell(xSheet->getCellByPosition(column, currentRow)); if (rValue.mbIsValue) xCell->setValue(rValue.mfValue); else xCell->setFormula(rValue.maString); } currentRow++; } sal_Int32 nEndCol = sal_Int32(aHeaders.size() - 1); sal_Int32 nEndRow = sal_Int32(1/*HEADER*/ + aData.size() - 1); // Apply date format to the last column uno::Reference xNumberFormatsSupplier(xSheetDoc, UNO_QUERY_THROW); uno::Reference xNumberFormats = xNumberFormatsSupplier->getNumberFormats(); uno::Reference xNumberFormatTypes(xNumberFormats, UNO_QUERY_THROW); lang::Locale aLocale; sal_Int32 nDateKey = xNumberFormatTypes->getStandardFormat(util::NumberFormat::DATE, aLocale); uno::Reference xCellRange = xSheet->getCellRangeByPosition(nEndCol, 1, nEndCol, nEndRow); uno::Reference xCellProp(xCellRange, UNO_QUERY_THROW); xCellProp->setPropertyValue("NumberFormat", uno::makeAny(nDateKey)); table::CellRangeAddress sCellRangeAddress; sCellRangeAddress.Sheet = 0; sCellRangeAddress.StartColumn = 0; sCellRangeAddress.StartRow = 0; sCellRangeAddress.EndColumn = nEndCol; sCellRangeAddress.EndRow = nEndRow; return sCellRangeAddress; } } // end anonymous namespace void PivotChartTest::testRoundtrip() { uno::Sequence xSequence; Reference xChartDoc; std::vector aReference1 { 10162.033139, 16614.523063, 27944.146101 }; std::vector aReference2 { 101879.458079, 178636.929704, 314626.484864 }; load(u"/chart2/qa/extras/data/ods/", "PivotChartRoundTrip.ods"); xChartDoc = getPivotChartDocFromSheet(1, mxComponent); CPPUNIT_ASSERT(xChartDoc.is()); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getNumberOfDataSeries(xChartDoc)); // Check the data series { xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference1, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Exp."), lclGetLabel(xChartDoc, 0)); } { xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData(); lclCheckSequence(aReference2, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Rev."), lclGetLabel(xChartDoc, 1)); } // Modify the pivot table { uno::Reference xDataPilotTable = lclGetPivotTableByName(1, "DataPilot1", mxComponent); uno::Reference xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); lclModifyOrientation(xDataPilotDescriptor, u"Exp.", sheet::DataPilotFieldOrientation_HIDDEN); } CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); // Check again the data series { xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference2, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); } reload("calc8"); xChartDoc = getPivotChartDocFromSheet(1, mxComponent); CPPUNIT_ASSERT(xChartDoc.is()); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); // Check again the data series { xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference2, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); } } void PivotChartTest::testChangePivotTable() { uno::Sequence xSequence; Reference xChartDoc; load(u"/chart2/qa/extras/data/ods/", "PivotTableExample.ods"); // Check we have the Pivot Table OUString sPivotTableName("DataPilot1"); uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); CPPUNIT_ASSERT(xDataPilotTable.is()); // Check that we don't have any pivot chart in the document uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); uno::Reference xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); // Create a new pivot chart xTablePivotCharts->addNewByName("Chart", awt::Rectangle{0, 0, 9000, 9000}, sPivotTableName); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); // Get the pivot chart document so we can access its data xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); CPPUNIT_ASSERT(xChartDoc.is()); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getNumberOfDataSeries(xChartDoc)); // Check first data series { std::vector aReference { 10162.033139, 16614.523063, 27944.146101 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Exp."), lclGetLabel(xChartDoc, 0)); } // Check second data series { std::vector aReference { 101879.458079, 178636.929704, 314626.484864 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Rev."), lclGetLabel(xChartDoc, 1)); } // Modify the pivot table, move "Group Segment" to Column fields, // add "Service Month" to Row fields, remove "Rev." Data field { uno::Reference xDataPilotDescriptor(xDataPilotTable, UNO_QUERY_THROW); lclModifyOrientation(xDataPilotDescriptor, u"Service Month", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"Group Segment", sheet::DataPilotFieldOrientation_COLUMN); lclModifyOrientation(xDataPilotDescriptor, u"Rev.", sheet::DataPilotFieldOrientation_HIDDEN); } // Check the pivot chart again as we expect it has been updated when we updated the pivot table CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc)); // Check the first data series { std::vector aReference { 2855.559, 1780.326, 2208.713, 2130.064, 1187.371 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0)); } // Check the second data series { std::vector aReference { 4098.908, 2527.286, 4299.716, 2362.225, 3326.389 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1)); } // Check the third data series { std::vector aReference { 4926.303, 5684.060, 4201.398, 7290.795, 5841.591 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2)); } // Remove "Service Month" so row fields are empty - check we handle empty rows { uno::Reference xDataPilotDescriptor(xDataPilotTable, uno::UNO_QUERY_THROW); lclModifyOrientation(xDataPilotDescriptor, u"Service Month", sheet::DataPilotFieldOrientation_HIDDEN); } // Check the pivot chart again as we expect it has been updated when we updated the pivot table CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc)); // Check the first data series { std::vector aReference { 10162.033139 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0)); } // Check the second data series { std::vector aReference { 16614.523063 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1)); } // Check the third data series { std::vector aReference { 27944.146101 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2)); } // Enable column totals and check the data is still unchanged { uno::Reference xProperties(xDataPilotTable, uno::UNO_QUERY_THROW); xProperties->setPropertyValue("ColumnGrand", uno::makeAny(true)); } CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc)); // Check the first data series { std::vector aReference { 10162.033139 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Big"), lclGetLabel(xChartDoc, 0)); } // Check the second data series { std::vector aReference { 16614.523063 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Medium"), lclGetLabel(xChartDoc, 1)); } // Check the third data series { std::vector aReference { 27944.146101 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData(); lclCheckSequence(aReference, xSequence, 1E-3); CPPUNIT_ASSERT_EQUAL(OUString("Small"), lclGetLabel(xChartDoc, 2)); } } void PivotChartTest::testPivotChartWithOneColumnField() { // We put one field as COLUMN field only and one DATA field. We expect we will get as many data series // in the pivot table as many distinct column values we have (with this example data 3: DE, EN, FR). // SETUP DATA and PIVOT TABLE if (!mxComponent.is()) mxComponent = loadFromDesktop("private:factory/scalc"); uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); OUString sPivotTableName("DataPilotTable"); table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc); uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); xDataPilotDescriptor->setSourceRange(sCellRangeAddress); lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_COLUMN); lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA); lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM); xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); // TEST uno::Sequence xSequence; Reference xChartDoc; // Check we have the Pivot Table uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); CPPUNIT_ASSERT(xDataPilotTable.is()); // Check that we don't have any pivot chart in the document uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); uno::Reference xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); // Create a new pivot chart xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); // Get the pivot chart document so we can access its data xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); CPPUNIT_ASSERT(xChartDoc.is()); CPPUNIT_ASSERT_EQUAL(sal_Int32(3), getNumberOfDataSeries(xChartDoc)); // Check data series 1 { std::vector aReference { 1738.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("DE"), lclGetLabel(xChartDoc, 0)); } // Check data series 2 { std::vector aReference { 2003.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 1)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("EN"), lclGetLabel(xChartDoc, 1)); } // Check data series 3 { std::vector aReference { 1936.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 2)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("FR"), lclGetLabel(xChartDoc, 2)); } } void PivotChartTest::testPivotChartWithOneRowField() { // We put one field as ROW field only and one DATA field. We expect we will get one data series // in the pivot table. // SETUP DATA and PIVOT TABLE if (!mxComponent.is()) mxComponent = loadFromDesktop("private:factory/scalc"); uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); OUString sPivotTableName("DataPilotTable"); table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc); uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); xDataPilotDescriptor->setSourceRange(sCellRangeAddress); lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA); lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM); xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); // TEST uno::Sequence xSequence; Reference xChartDoc; // Check we have the Pivot Table uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); CPPUNIT_ASSERT(xDataPilotTable.is()); // Check that we don't have any pivot chart in the document uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); uno::Reference xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); // Create a new pivot chart xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); // Get the pivot chart document so we can access its data xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); CPPUNIT_ASSERT(xChartDoc.is()); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); // Check data series 1 { std::vector aReference { 1738.0, 2003.0, 1936.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); } } void PivotChartTest::testPivotTableDataProvider_PivotTableFields() { // SETUP DATA and PIVOT TABLE if (!mxComponent.is()) mxComponent = loadFromDesktop("private:factory/scalc"); uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); OUString sPivotTableName("DataPilotTable"); table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc); uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); xDataPilotDescriptor->setSourceRange(sCellRangeAddress); lclModifyOrientation(xDataPilotDescriptor, u"City", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_COLUMN); lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_COLUMN); lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA); lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM); lclModifyOrientation(xDataPilotDescriptor, u"Sales T2", sheet::DataPilotFieldOrientation_DATA); lclModifyFunction(xDataPilotDescriptor, u"Sales T2", sheet::GeneralFunction_SUM); lclModifyColumnGrandTotal(xDataPilotDescriptor, true); lclModifyRowGrandTotal(xDataPilotDescriptor, true); xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); // TEST Reference xChartDoc; // Check we have the Pivot Table uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); CPPUNIT_ASSERT(xDataPilotTable.is()); // refetch the XDataPilotDescriptor xDataPilotDescriptor.set(xDataPilotTable, uno::UNO_QUERY_THROW); // Check that we don't have any pivot chart in the document uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); uno::Reference xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); // Create a new pivot chart xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); // Get the pivot chart document so we can access its data xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); CPPUNIT_ASSERT(xChartDoc.is()); uno::Reference xPivotTableDataProvider(xChartDoc->getDataProvider(), UNO_QUERY_THROW); uno::Sequence aFieldEntries; aFieldEntries = xPivotTableDataProvider->getColumnFields(); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("Country"), aFieldEntries[0].Name); CPPUNIT_ASSERT_EQUAL(OUString("Type"), aFieldEntries[1].Name); aFieldEntries = xPivotTableDataProvider->getRowFields(); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("City"), aFieldEntries[0].Name); CPPUNIT_ASSERT_EQUAL(OUString("Data"), aFieldEntries[1].Name); aFieldEntries = xPivotTableDataProvider->getDataFields(); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T1"), aFieldEntries[0].Name); CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T2"), aFieldEntries[1].Name); // Data to column fields lclModifyOrientation(xDataPilotDescriptor, u"Data", sheet::DataPilotFieldOrientation_COLUMN); // Change the order of column fields: expected data, type, country lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_HIDDEN); lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_HIDDEN); lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_COLUMN); lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_COLUMN); // set the XPivotTableDataProvider again as the old one was exchanged xPivotTableDataProvider.set(xChartDoc->getDataProvider(), uno::UNO_QUERY_THROW); aFieldEntries = xPivotTableDataProvider->getColumnFields(); CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aFieldEntries.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("Data"), aFieldEntries[0].Name); CPPUNIT_ASSERT_EQUAL(OUString("Type"), aFieldEntries[1].Name); CPPUNIT_ASSERT_EQUAL(OUString("Country"), aFieldEntries[2].Name); aFieldEntries = xPivotTableDataProvider->getRowFields(); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aFieldEntries.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("City"), aFieldEntries[0].Name); aFieldEntries = xPivotTableDataProvider->getDataFields(); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aFieldEntries.getLength()); CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T1"), aFieldEntries[0].Name); CPPUNIT_ASSERT_EQUAL(OUString("Sum - Sales T2"), aFieldEntries[1].Name); } void PivotChartTest::testPivotChartRowFieldInOutlineMode() { // SETUP DATA and PIVOT TABLE if (!mxComponent.is()) mxComponent = loadFromDesktop("private:factory/scalc"); uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); OUString sPivotTableName("DataPilotTable"); table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc); uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); xDataPilotDescriptor->setSourceRange(sCellRangeAddress); lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"City", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA); lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM); xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); // TEST uno::Sequence xSequence; Reference xChartDoc; // Check we have the Pivot Table uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); CPPUNIT_ASSERT(xDataPilotTable.is()); // refetch the XDataPilotDescriptor xDataPilotDescriptor.set(xDataPilotTable, uno::UNO_QUERY_THROW); // Check that we don't have any pivot chart in the document uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); uno::Reference xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); // Create a new pivot chart xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); // Get the pivot chart document so we can access its data xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); CPPUNIT_ASSERT(xChartDoc.is()); // Test case with defaults // Check when using defaults the data is as expected CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); { std::vector aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); } // Check the categories { lclCheckCategories({ "DE", "", "EN", "", "", "FR", ""}, lclGetCategories(xChartDoc)[0]->getValues()); lclCheckCategories({ "Berlin", "Munich", "Glasgow", "Liverpool", "London", "Nantes", "Paris"}, lclGetCategories(xChartDoc)[1]->getValues()); } sheet::DataPilotFieldLayoutInfo aLayoutInfoValue; // Test case where we enable subtotals (auto) and set the outline subtotals at the bottom // We don't expect any change in data as every extra subtotal row should be ignored // Enable subtotals - set to auto uno::Sequence aGeneralFunctionSequence{ sheet::GeneralFunction_AUTO }; lclModifySubtotals(xDataPilotDescriptor, u"Country", aGeneralFunctionSequence); // Set Subtotals layout to bottom + add empty lines aLayoutInfoValue.AddEmptyLines = true; aLayoutInfoValue.LayoutMode = sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM; lclModifyLayoutInfo(xDataPilotDescriptor, u"Country", aLayoutInfoValue); // Check data is unchanged CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); { std::vector aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); } // Check categories { lclCheckCategories({ "DE", "", "EN", "", "", "FR", ""}, lclGetCategories(xChartDoc)[0]->getValues()); lclCheckCategories({ "Berlin", "Munich", "Glasgow", "Liverpool", "London", "Nantes", "Paris"}, lclGetCategories(xChartDoc)[1]->getValues()); } // Test case where we enable subtotals (auto) and set the outline subtotals at the top // We don't expect any change in data as every extra subtotal row should be ignored // Enable subtotals - set to auto aGeneralFunctionSequence.getArray()[0] = sheet::GeneralFunction_AUTO; lclModifySubtotals(xDataPilotDescriptor, u"Country", aGeneralFunctionSequence); // Set Subtotals layout to top + add empty lines aLayoutInfoValue.AddEmptyLines = true; aLayoutInfoValue.LayoutMode = sheet::DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP; lclModifyLayoutInfo(xDataPilotDescriptor, u"Country", aLayoutInfoValue); // Check data is unchanged CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getNumberOfDataSeries(xChartDoc)); { std::vector aReference { 1116.0, 622.0, 298.0, 562.0, 1143.0, 1168.0, 768.0 }; xSequence = getDataSequenceFromDocByRole(xChartDoc, u"values-y", 0)->getData(); lclCheckSequence(aReference, xSequence, 1E-4); CPPUNIT_ASSERT_EQUAL(OUString("Total"), lclGetLabel(xChartDoc, 0)); } // Check categories { lclCheckCategories({ "DE", "", "EN", "", "", "FR", ""}, lclGetCategories(xChartDoc)[0]->getValues()); lclCheckCategories({ "Berlin", "Munich", "Glasgow", "Liverpool", "London", "Nantes", "Paris"}, lclGetCategories(xChartDoc)[1]->getValues()); } } void PivotChartTest::testPivotChartWithDateRowField() { // SETUP DATA and PIVOT TABLE if (!mxComponent.is()) mxComponent = loadFromDesktop("private:factory/scalc"); uno::Reference xSheetDoc(mxComponent, uno::UNO_QUERY_THROW); OUString sPivotTableName("DataPilotTable"); table::CellRangeAddress sCellRangeAddress = lclCreateTestData(xSheetDoc); uno::Reference xDataPilotTables = lclGetDataPilotTables(0, xSheetDoc); uno::Reference xDataPilotDescriptor = xDataPilotTables->createDataPilotDescriptor(); xDataPilotDescriptor->setSourceRange(sCellRangeAddress); lclModifyOrientation(xDataPilotDescriptor, u"Date", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"City", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"Country", sheet::DataPilotFieldOrientation_ROW); lclModifyOrientation(xDataPilotDescriptor, u"Type", sheet::DataPilotFieldOrientation_COLUMN); lclModifyOrientation(xDataPilotDescriptor, u"Sales T1", sheet::DataPilotFieldOrientation_DATA); lclModifyFunction(xDataPilotDescriptor, u"Sales T1", sheet::GeneralFunction_SUM); lclModifyColumnGrandTotal(xDataPilotDescriptor, true); lclModifyRowGrandTotal(xDataPilotDescriptor, true); xDataPilotTables->insertNewByName(sPivotTableName, table::CellAddress{1, 0, 0}, xDataPilotDescriptor); // TEST Reference xChartDoc; // Check we have the Pivot Table uno::Reference xDataPilotTable = lclGetPivotTableByName(1, sPivotTableName, mxComponent); CPPUNIT_ASSERT(xDataPilotTable.is()); // refetch the XDataPilotDescriptor xDataPilotDescriptor.set(xDataPilotTable, uno::UNO_QUERY_THROW); // Check that we don't have any pivot chart in the document uno::Reference xTablePivotCharts = getTablePivotChartsFromSheet(1, mxComponent); uno::Reference xIndexAccess(xTablePivotCharts, UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xIndexAccess->getCount()); // Create a new pivot chart xTablePivotCharts->addNewByName("PivotChart", awt::Rectangle{ 9000, 9000, 21000, 18000 }, sPivotTableName); CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount()); // Get the pivot chart document so we can access its data xChartDoc.set(getPivotChartDocFromSheet(xTablePivotCharts, 0)); CPPUNIT_ASSERT(xChartDoc.is()); // Check if Date category is date formatted. lclCheckCategories( { "12/11/15", "", "", "", "", "", "12/14/15", "12/17/15", "01/20/16", "", "", "03/21/17" }, lclGetCategories( xChartDoc )[0]->getValues() ); } CPPUNIT_TEST_SUITE_REGISTRATION(PivotChartTest); CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */