diff options
-rw-r--r-- | chart2/qa/extras/chart2import.cxx | 38 | ||||
-rw-r--r-- | chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx | bin | 0 -> 5890 bytes | |||
-rw-r--r-- | chart2/source/tools/InternalData.cxx | 11 | ||||
-rw-r--r-- | include/oox/drawingml/chart/datasourcemodel.hxx | 1 | ||||
-rw-r--r-- | oox/source/drawingml/chart/chartconverter.cxx | 29 | ||||
-rw-r--r-- | oox/source/drawingml/chart/datasourcecontext.cxx | 25 | ||||
-rw-r--r-- | oox/source/drawingml/chart/datasourcemodel.cxx | 3 | ||||
-rw-r--r-- | oox/source/export/chartexport.cxx | 8 |
8 files changed, 94 insertions, 21 deletions
diff --git a/chart2/qa/extras/chart2import.cxx b/chart2/qa/extras/chart2import.cxx index 107daed69fea..710d15ebd60e 100644 --- a/chart2/qa/extras/chart2import.cxx +++ b/chart2/qa/extras/chart2import.cxx @@ -131,6 +131,7 @@ public: void testDataPointInheritedColorDOCX(); void testExternalStrRefsXLSX(); void testSourceNumberFormatComplexCategoriesXLS(); + void testMultilevelCategoryAxis(); void testTdf123504(); void testTdf122765(); @@ -216,6 +217,7 @@ public: CPPUNIT_TEST(testDataPointInheritedColorDOCX); CPPUNIT_TEST(testExternalStrRefsXLSX); CPPUNIT_TEST(testSourceNumberFormatComplexCategoriesXLS); + CPPUNIT_TEST(testMultilevelCategoryAxis); CPPUNIT_TEST(testTdf123504); CPPUNIT_TEST(testTdf122765); @@ -1534,10 +1536,10 @@ void Chart2ImportTest::testInternalDataProvider() { // Parse mixed types, mixed role xDataSeq = rxDataProvider->createDataSequenceByValueArray("categories", "{42;\"hello\";0;\"world\"}"); xSequence = xDataSeq->getData(); - CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("42")), xSequence[0]); - CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("hello")), xSequence[1]); - CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("0")), xSequence[2]); - CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("world")), xSequence[3]); + CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 1 42")), xSequence[0]); + CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 2 hello")), xSequence[1]); + CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 3 0")), xSequence[2]); + CPPUNIT_ASSERT_EQUAL(uno::Any(OUString("Row 4 world")), xSequence[3]); } void Chart2ImportTest::testTdf90510() @@ -1946,6 +1948,34 @@ void Chart2ImportTest::testSourceNumberFormatComplexCategoriesXLS() CPPUNIT_ASSERT(nNumberFormat != 0); } +void Chart2ImportTest::testMultilevelCategoryAxis() +{ + load("/chart2/qa/extras/data/docx/", "testMultilevelCategoryAxis.docx"); + uno::Reference< chart2::XChartDocument > xChartDoc(getChartDocFromWriter(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + // Test the internal data. + CPPUNIT_ASSERT(xChartDoc->hasInternalDataProvider()); + + Reference<chart2::XInternalDataProvider> xInternalProvider(xChartDoc->getDataProvider(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xInternalProvider.is()); + + Reference<chart::XComplexDescriptionAccess> xDescAccess(xInternalProvider, uno::UNO_QUERY); + CPPUNIT_ASSERT(xDescAccess.is()); + + // Get the complex category labels. + Sequence<Sequence<OUString> > aCategories = xDescAccess->getComplexRowDescriptions(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aCategories.getLength()); + CPPUNIT_ASSERT_EQUAL(OUString("2011"), aCategories[0][0]); + CPPUNIT_ASSERT_EQUAL(OUString(""), aCategories[1][0]); + CPPUNIT_ASSERT_EQUAL(OUString("2012"), aCategories[2][0]); + CPPUNIT_ASSERT_EQUAL(OUString(""), aCategories[3][0]); + CPPUNIT_ASSERT_EQUAL(OUString("Categoria 1"), aCategories[0][1]); + CPPUNIT_ASSERT_EQUAL(OUString("Categoria 2"), aCategories[1][1]); + CPPUNIT_ASSERT_EQUAL(OUString("Categoria 3"), aCategories[2][1]); + CPPUNIT_ASSERT_EQUAL(OUString("Categoria 4"), aCategories[3][1]); +} + void Chart2ImportTest::testTdf123504() { load("/chart2/qa/extras/data/ods/", "pie_chart_100_and_0.ods"); diff --git a/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx Binary files differnew file mode 100644 index 000000000000..75605de72fc5 --- /dev/null +++ b/chart2/qa/extras/data/docx/testMultilevelCategoryAxis.docx diff --git a/chart2/source/tools/InternalData.cxx b/chart2/source/tools/InternalData.cxx index b99578fab118..b7a5118004ba 100644 --- a/chart2/source/tools/InternalData.cxx +++ b/chart2/source/tools/InternalData.cxx @@ -220,7 +220,16 @@ void InternalData::setComplexRowLabel( sal_Int32 nRowIndex, const vector< uno::A m_aRowLabels.resize(nRowIndex+1); enlargeData( 0, nRowIndex+1 ); } - m_aRowLabels[nRowIndex] = rComplexLabel; + sal_Int32 nSize = static_cast<sal_Int32>( m_aRowLabels[nRowIndex].size() ); + if( nSize >= 1 ) + { + m_aRowLabels[nRowIndex].resize(nSize+1); + m_aRowLabels[nRowIndex][nSize] = rComplexLabel[0]; + } + else + { + m_aRowLabels[nRowIndex] = rComplexLabel; + } } vector< uno::Any > InternalData::getComplexColumnLabel( sal_Int32 nColumnIndex ) const diff --git a/include/oox/drawingml/chart/datasourcemodel.hxx b/include/oox/drawingml/chart/datasourcemodel.hxx index 097bfd188720..e2d9336bf4b2 100644 --- a/include/oox/drawingml/chart/datasourcemodel.hxx +++ b/include/oox/drawingml/chart/datasourcemodel.hxx @@ -40,6 +40,7 @@ struct DataSequenceModel OUString maFormula; /// Formula reference, e.g. into a spreadsheet. OUString maFormatCode; /// Number format for double values. sal_Int32 mnPointCount; /// Number of points in this series source. + sal_Int32 mnLevelCount; /// Number of category levels. explicit DataSequenceModel(); ~DataSequenceModel(); diff --git a/oox/source/drawingml/chart/chartconverter.cxx b/oox/source/drawingml/chart/chartconverter.cxx index f86ea8adb760..538f9956abc7 100644 --- a/oox/source/drawingml/chart/chartconverter.cxx +++ b/oox/source/drawingml/chart/chartconverter.cxx @@ -56,12 +56,12 @@ static OUString lclGenerateApiString( const OUString& rString ) return "\"" + aRetString + "\""; } -static OUString lclGenerateApiArray(const std::vector<Any>& rRow) +static OUString lclGenerateApiArray(const std::vector<Any>& rRow, sal_Int32 nStart, sal_Int32 nCount) { OSL_ENSURE( !rRow.empty(), "ChartConverter::lclGenerateApiArray - missing matrix values" ); OUStringBuffer aBuffer; aBuffer.append( API_TOKEN_ARRAY_OPEN ); - for (auto aBeg = rRow.begin(), aIt = aBeg, aEnd = rRow.end(); aIt != aEnd; ++aIt) + for (auto aBeg = rRow.begin() + nStart, aIt = aBeg, aEnd = aBeg + nCount; aIt != aEnd; ++aIt) { double fValue = 0.0; OUString aString; @@ -124,21 +124,26 @@ Reference< XDataSequence > ChartConverter::createDataSequence( if( rxDataProvider.is() ) { OUString aRangeRep; - if( !rDataSeq.maData.empty() ) + if( !rDataSeq.maData.empty() ) try { // create a single-row array from constant source data - std::vector<Any> aRow(rDataSeq.mnPointCount); + // (multiple levels in the case of complex categories) + std::vector<Any> aRow(rDataSeq.mnLevelCount * rDataSeq.mnPointCount); for (auto const& elem : rDataSeq.maData) aRow.at(elem.first) = elem.second; - aRangeRep = lclGenerateApiArray(aRow); - } - - if( !aRangeRep.isEmpty() ) try - { - // create the data sequence - xDataSeq = rxDataProvider->createDataSequenceByValueArray(rRole, aRangeRep); - return xDataSeq; + for (sal_Int32 i = rDataSeq.mnLevelCount-1; i >= 0; i--) + { + aRangeRep = lclGenerateApiArray( aRow, i * rDataSeq.mnPointCount, rDataSeq.mnPointCount); + + if (!aRangeRep.isEmpty()) + { + // create or add a new level to the data sequence + xDataSeq = rxDataProvider->createDataSequenceByValueArray(rRole, aRangeRep); + if (i == 0) + return xDataSeq; + } + } } catch( Exception& ) { diff --git a/oox/source/drawingml/chart/datasourcecontext.cxx b/oox/source/drawingml/chart/datasourcecontext.cxx index e50723b378d0..7fa7b12852a7 100644 --- a/oox/source/drawingml/chart/datasourcecontext.cxx +++ b/oox/source/drawingml/chart/datasourcecontext.cxx @@ -180,6 +180,7 @@ ContextHandlerRef StringSequenceContext::onCreateContext( sal_Int32 nElement, co switch( nElement ) { case C_TOKEN( f ): + case C_TOKEN( multiLvlStrCache ): return this; } break; @@ -206,6 +207,28 @@ ContextHandlerRef StringSequenceContext::onCreateContext( sal_Int32 nElement, co } break; + case C_TOKEN( multiLvlStrCache ): + switch (nElement) + { + case C_TOKEN( ptCount ): + mrModel.mnPointCount = rAttribs.getInteger(XML_val, -1); + mrModel.mnLevelCount--; // normalize level count + return nullptr; + case C_TOKEN( lvl ): + mrModel.mnLevelCount++; + return this; + } + break; + + case C_TOKEN( lvl ): + switch (nElement) + { + case C_TOKEN(pt): + mnPtIndex = rAttribs.getInteger(XML_idx, -1); + return this; + } + break; + case C_TOKEN( pt ): switch( nElement ) { @@ -226,7 +249,7 @@ void StringSequenceContext::onCharacters( const OUString& rChars ) break; case C_TOKEN( v ): if( mnPtIndex >= 0 ) - mrModel.maData[ mnPtIndex ] <<= rChars; + mrModel.maData[ (mrModel.mnLevelCount-1) * mrModel.mnPointCount + mnPtIndex ] <<= rChars; break; } } diff --git a/oox/source/drawingml/chart/datasourcemodel.cxx b/oox/source/drawingml/chart/datasourcemodel.cxx index c5c054e67a99..ecb9afe4f2cb 100644 --- a/oox/source/drawingml/chart/datasourcemodel.cxx +++ b/oox/source/drawingml/chart/datasourcemodel.cxx @@ -24,7 +24,8 @@ namespace drawingml { namespace chart { DataSequenceModel::DataSequenceModel() : - mnPointCount( -1 ) + mnPointCount( -1 ), + mnLevelCount( 1 ) { } diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index dd9d19651e29..ec19bc4042ad 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -515,8 +515,12 @@ Sequence< Sequence< OUString > > ChartExport::getSplitCategoriesList( const OUSt aFinalSplitSource[nLevelCount - i - 1].realloc(aAnyCategories.getLength()); for (auto const& elemLabel : aAnyCategories) { - aFinalSplitSource[nLevelCount - i - 1][nElemLabel] = elemLabel[i].get<OUString>(); - nElemLabel++; + // make sure elemLabel[i] exists! + if (elemLabel.getLength() > i) + { + aFinalSplitSource[nLevelCount - i - 1][nElemLabel] = elemLabel[i].get<OUString>(); + nElemLabel++; + } } } return aFinalSplitSource; |