summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorDennis Francis <dennisfrancis.in@gmail.com>2021-09-02 14:33:55 +0530
committerMiklos Vajna <vmiklos@collabora.com>2021-09-06 08:47:50 +0200
commitf547cf17a179ebd7de5c2b4dd2d00d0027a25429 (patch)
tree764038da5e3280c93099d2ca3ef2731484ece324 /oox
parentba1e42f05e785c30d03553acd5647eebd7cdede6 (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.cxx4
-rw-r--r--oox/source/drawingml/chart/datasourcecontext.cxx23
-rw-r--r--oox/source/drawingml/chart/datasourceconverter.cxx6
-rw-r--r--oox/source/drawingml/chart/datasourcemodel.cxx4
-rw-r--r--oox/source/export/chartexport.cxx43
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() );