diff options
author | Dennis Francis <dennisfrancis.in@gmail.com> | 2021-09-02 14:33:55 +0530 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2021-09-06 08:47:50 +0200 |
commit | f547cf17a179ebd7de5c2b4dd2d00d0027a25429 (patch) | |
tree | 764038da5e3280c93099d2ca3ef2731484ece324 /oox | |
parent | ba1e42f05e785c30d03553acd5647eebd7cdede6 (diff) |
[API CHANGE] oox: fix import of chart date categories
Before this fix, date categories imported in oox's DataSourceContext were
stored as formatted strings according to number format code in <c:formatCode>
under the <c:cat> tree. As a result chart2 could not recognize them
as dates. This causes problems like:
* The axis that is linked to date categories cannot use the
scaling/range-selection(min/max)/increments specs mentioned as axis
properties. This results in distorted/unreadable chart renders w.r.t
the date axis.
* No re-formatting is attempted as per the number format provided for axis.
This patch introduces a role qualifer argument to the XDataProvider
interface method createDataSequenceByValueArray to support categories of
date type via this method.
When exporting to oox, write date categories and format code under
<c:cat>
<c:numRef>
<c:numCache>
This patch also fixes some discrepancies in date axis interval
computation (auto mode) found by already existing unit tests.
Change-Id: Ibc53b0a56fdddba80ba452d5567ce98d80460ea7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121525
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Diffstat (limited to 'oox')
-rw-r--r-- | oox/source/drawingml/chart/chartconverter.cxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/chart/datasourcecontext.cxx | 23 | ||||
-rw-r--r-- | oox/source/drawingml/chart/datasourceconverter.cxx | 6 | ||||
-rw-r--r-- | oox/source/drawingml/chart/datasourcemodel.cxx | 4 | ||||
-rw-r--r-- | oox/source/export/chartexport.cxx | 43 |
5 files changed, 61 insertions, 19 deletions
diff --git a/oox/source/drawingml/chart/chartconverter.cxx b/oox/source/drawingml/chart/chartconverter.cxx index a864aac47e47..af49c561ae51 100644 --- a/oox/source/drawingml/chart/chartconverter.cxx +++ b/oox/source/drawingml/chart/chartconverter.cxx @@ -116,7 +116,7 @@ void ChartConverter::createDataProvider( const Reference< XChartDocument >& rxCh Reference< XDataSequence > ChartConverter::createDataSequence( const Reference< XDataProvider >& rxDataProvider, const DataSequenceModel& rDataSeq, - const OUString& rRole ) + const OUString& rRole, const OUString& rRoleQualifier ) { Reference< XDataSequence > xDataSeq; if( rxDataProvider.is() ) @@ -137,7 +137,7 @@ Reference< XDataSequence > ChartConverter::createDataSequence( if (!aRangeRep.isEmpty()) { // create or add a new level to the data sequence - xDataSeq = rxDataProvider->createDataSequenceByValueArray(rRole, aRangeRep); + xDataSeq = rxDataProvider->createDataSequenceByValueArray(rRole, aRangeRep, rRoleQualifier); if (i == 0) return xDataSeq; } diff --git a/oox/source/drawingml/chart/datasourcecontext.cxx b/oox/source/drawingml/chart/datasourcecontext.cxx index 1b64089d4281..f4660f5db708 100644 --- a/oox/source/drawingml/chart/datasourcecontext.cxx +++ b/oox/source/drawingml/chart/datasourcecontext.cxx @@ -99,7 +99,7 @@ void DoubleSequenceContext::onCharacters( const OUString& rChars ) if( mnPtIndex >= 0 ) { /* Import categories as String even though it could - * be values. + * be values except when the format code indicates that they are dates. * n#810508: xVal needs to be imported as double * TODO: NumberFormat conversion, remove the check then. */ @@ -118,6 +118,8 @@ void DoubleSequenceContext::onCharacters( const OUString& rChars ) SvNumFormatType nType; pNumFrmt->PutEntry( aFormatCode, nCheckPos, nType, nKey ); bNoKey = (nCheckPos != 0); + if (!bNoKey) + mrModel.meFormatType = nType; } if( bNoKey ) { @@ -126,13 +128,18 @@ void DoubleSequenceContext::onCharacters( const OUString& rChars ) else { double fValue = rChars.toDouble(); - const ::Color* pColor = nullptr; - OUString aFormattedValue; - // tdf#91250: use UNLIMITED_PRECISION in case of GENERAL Number Format of category axis labels - if( pNumFrmt->GetStandardPrec() != SvNumberFormatter::UNLIMITED_PRECISION ) - pNumFrmt->ChangeStandardPrec(SvNumberFormatter::UNLIMITED_PRECISION); - pNumFrmt->GetOutputString( fValue, nKey, aFormattedValue, &pColor ); - mrModel.maData[ mnPtIndex ] <<= aFormattedValue; + if (mrModel.meFormatType == SvNumFormatType::DATE) + mrModel.maData[ mnPtIndex ] <<= fValue; + else + { + const ::Color* pColor = nullptr; + OUString aFormattedValue; + // tdf#91250: use UNLIMITED_PRECISION in case of GENERAL Number Format of category axis labels + if( pNumFrmt->GetStandardPrec() != SvNumberFormatter::UNLIMITED_PRECISION ) + pNumFrmt->ChangeStandardPrec(SvNumberFormatter::UNLIMITED_PRECISION); + pNumFrmt->GetOutputString( fValue, nKey, aFormattedValue, &pColor ); + mrModel.maData[ mnPtIndex ] <<= aFormattedValue; + } } } else diff --git a/oox/source/drawingml/chart/datasourceconverter.cxx b/oox/source/drawingml/chart/datasourceconverter.cxx index 72399426538d..92cacb4286bf 100644 --- a/oox/source/drawingml/chart/datasourceconverter.cxx +++ b/oox/source/drawingml/chart/datasourceconverter.cxx @@ -23,6 +23,7 @@ #include <oox/drawingml/chart/chartconverter.hxx> #include <oox/drawingml/chart/datasourcemodel.hxx> #include <oox/token/properties.hxx> +#include <svl/zforlist.hxx> namespace oox::drawingml::chart { @@ -69,7 +70,10 @@ Reference< XDataSequence > DataSequenceConverter::createDataSequence( const OUSt mrModel.maData.insert(std::make_pair<sal_Int32, Any>(0, Any(aTitle.makeStringAndClear()))); } } - xDataSeq = getChartConverter().createDataSequence(getChartDocument()->getDataProvider(), mrModel, rRole); + + bool bDateCategories = (mrModel.meFormatType == SvNumFormatType::DATE) && (rRole == "categories"); + xDataSeq = getChartConverter().createDataSequence(getChartDocument()->getDataProvider(), mrModel, + rRole, bDateCategories ? OUString("date") : OUString("")); // set sequence role PropertySet aSeqProp( xDataSeq ); diff --git a/oox/source/drawingml/chart/datasourcemodel.cxx b/oox/source/drawingml/chart/datasourcemodel.cxx index e83b6b3558a5..51514437d33d 100644 --- a/oox/source/drawingml/chart/datasourcemodel.cxx +++ b/oox/source/drawingml/chart/datasourcemodel.cxx @@ -18,12 +18,14 @@ */ #include <oox/drawingml/chart/datasourcemodel.hxx> +#include <svl/zforlist.hxx> namespace oox::drawingml::chart { DataSequenceModel::DataSequenceModel() : mnPointCount( -1 ), - mnLevelCount( 1 ) + mnLevelCount( 1 ), + meFormatType( SvNumFormatType::UNDEFINED ) { } diff --git a/oox/source/export/chartexport.cxx b/oox/source/export/chartexport.cxx index c39f2f146681..8bbd4ecd1990 100644 --- a/oox/source/export/chartexport.cxx +++ b/oox/source/export/chartexport.cxx @@ -158,8 +158,9 @@ private: } -static Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram ) +static Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram, bool& bHasDateCategories ) { + bHasDateCategories = false; Reference< chart2::data::XLabeledDataSequence > xResult; try { @@ -182,6 +183,7 @@ static Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const chart2::ScaleData aScaleData = xAxis->getScaleData(); if( aScaleData.Categories.is()) { + bHasDateCategories = aScaleData.AxisType == chart2::AxisType::DATE; xResult.set( aScaleData.Categories ); break; } @@ -220,7 +222,8 @@ static bool lcl_hasCategoryLabels( const Reference< chart2::XChartDocument >& xC { //categories are always the first sequence Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram()); - Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) ); + bool bDateCategories; + Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram, bDateCategories ) ); return xCategories.is(); } @@ -2861,7 +2864,26 @@ void ChartExport::exportSeriesCategory( const Reference< chart2::data::XDataSequ else { // export single category axis labels - pFS->startElement(FSNS(XML_c, XML_strRef)); + bool bWriteDateCategories = mbHasDateCategories && (nValueType == XML_cat); + OUString aNumberFormatString; + if (bWriteDateCategories) + { + Reference< css::chart::XAxisXSupplier > xAxisXSupp( mxDiagram, uno::UNO_QUERY ); + if( xAxisXSupp.is()) + { + Reference< XPropertySet > xAxisProp = xAxisXSupp->getXAxis(); + if (GetProperty(xAxisProp, "NumberFormat")) + { + sal_Int32 nKey = 0; + mAny >>= nKey; + aNumberFormatString = getNumberFormatCode(nKey); + } + } + if (aNumberFormatString.isEmpty()) + bWriteDateCategories = false; + } + + pFS->startElement(FSNS(XML_c, bWriteDateCategories ? XML_numRef : XML_strRef)); pFS->startElement(FSNS(XML_c, XML_f)); pFS->writeEscaped(aCellRange); @@ -2870,7 +2892,14 @@ void ChartExport::exportSeriesCategory( const Reference< chart2::data::XDataSequ ::std::vector< OUString > aCategories; lcl_fillCategoriesIntoStringVector(xValueSeq, aCategories); sal_Int32 ptCount = aCategories.size(); - pFS->startElement(FSNS(XML_c, XML_strCache)); + pFS->startElement(FSNS(XML_c, bWriteDateCategories ? XML_numCache : XML_strCache)); + if (bWriteDateCategories) + { + pFS->startElement(FSNS(XML_c, XML_formatCode)); + pFS->writeEscaped(aNumberFormatString); + pFS->endElement(FSNS(XML_c, XML_formatCode)); + } + pFS->singleElement(FSNS(XML_c, XML_ptCount), XML_val, OString::number(ptCount)); for (sal_Int32 i = 0; i < ptCount; i++) { @@ -2881,8 +2910,8 @@ void ChartExport::exportSeriesCategory( const Reference< chart2::data::XDataSequ pFS->endElement(FSNS(XML_c, XML_pt)); } - pFS->endElement(FSNS(XML_c, XML_strCache)); - pFS->endElement(FSNS(XML_c, XML_strRef)); + pFS->endElement(FSNS(XML_c, bWriteDateCategories ? XML_numCache : XML_strCache)); + pFS->endElement(FSNS(XML_c, bWriteDateCategories ? XML_numRef : XML_strRef)); } pFS->endElement( FSNS( XML_c, nValueType ) ); @@ -3025,7 +3054,7 @@ void ChartExport::InitPlotArea( ) if( mbHasCategoryLabels && mxNewDiagram.is()) { - Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( mxNewDiagram ) ); + Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( mxNewDiagram, mbHasDateCategories ) ); if( xCategories.is() ) { mxCategoriesValues.set( xCategories->getValues() ); |