LibreOffice Module xmloff (master)  1
SchXMLExport.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
23 
24 #include <sax/tools/converter.hxx>
25 
26 #include <xmloff/xmlprmap.hxx>
27 
28 #include <SchXMLExport.hxx>
30 #include "ColorPropertySet.hxx"
31 #include "SchXMLTools.hxx"
32 #include "SchXMLEnumConverter.hxx"
33 
35 #include <tools/globname.hxx>
36 #include <comphelper/classids.hxx>
37 #include <comphelper/sequence.hxx>
38 
39 #include <xmloff/namespacemap.hxx>
40 #include <xmloff/xmlnamespace.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include <xmloff/families.hxx>
43 #include <xmloff/xmlaustp.hxx>
44 #include <xmloff/xmluconv.hxx>
46 #include <rtl/math.hxx>
47 #include <o3tl/sorted_vector.hxx>
48 
49 #include <vector>
50 #include <algorithm>
51 #include <queue>
52 #include <iterator>
53 #include <numeric>
54 
55 #include <com/sun/star/lang/XServiceInfo.hpp>
56 #include <com/sun/star/lang/XServiceName.hpp>
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #include <com/sun/star/uno/XComponentContext.hpp>
59 #include <com/sun/star/util/XRefreshable.hpp>
60 
61 #include <com/sun/star/chart/XAxis.hpp>
62 #include <com/sun/star/chart/XAxisSupplier.hpp>
63 #include <com/sun/star/chart/XChartDocument.hpp>
64 #include <com/sun/star/chart/ChartLegendExpansion.hpp>
65 #include <com/sun/star/chart/ChartDataRowSource.hpp>
66 #include <com/sun/star/chart/ChartAxisAssign.hpp>
67 #include <com/sun/star/chart/DataLabelPlacement.hpp>
68 #include <com/sun/star/chart/TimeIncrement.hpp>
69 #include <com/sun/star/chart/TimeInterval.hpp>
70 #include <com/sun/star/chart/TimeUnit.hpp>
71 #include <com/sun/star/chart/X3DDisplay.hpp>
72 #include <com/sun/star/chart/XStatisticDisplay.hpp>
73 #include <com/sun/star/chart/XDiagramPositioning.hpp>
74 
75 #include <com/sun/star/chart2/XAnyDescriptionAccess.hpp>
76 #include <com/sun/star/chart2/AxisType.hpp>
77 #include <com/sun/star/chart2/XChartDocument.hpp>
78 #include <com/sun/star/chart2/XDiagram.hpp>
79 #include <com/sun/star/chart2/RelativePosition.hpp>
80 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
81 #include <com/sun/star/chart2/XRegressionCurveContainer.hpp>
82 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
83 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
84 #include <com/sun/star/chart2/XDataPointCustomLabelField.hpp>
85 #include <com/sun/star/chart2/data/XDataSource.hpp>
86 #include <com/sun/star/chart2/data/XDataSink.hpp>
87 #include <com/sun/star/chart2/data/XDataProvider.hpp>
88 #include <com/sun/star/chart2/data/XDatabaseDataProvider.hpp>
89 #include <com/sun/star/chart2/data/XPivotTableDataProvider.hpp>
90 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
91 #include <com/sun/star/chart2/data/XTextualDataSequence.hpp>
92 #include <com/sun/star/chart2/data/XNumericalDataSequence.hpp>
93 
94 #include <com/sun/star/util/MeasureUnit.hpp>
95 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
96 #include <com/sun/star/drawing/XShapes.hpp>
97 #include <com/sun/star/embed/Aspects.hpp>
98 #include <com/sun/star/embed/XVisualObject.hpp>
99 #include <com/sun/star/container/XChild.hpp>
100 
101 #include <tools/diagnose_ex.h>
103 #include "PropertyMap.hxx"
104 
105 using namespace com::sun::star;
106 using namespace ::xmloff::token;
107 
108 using ::com::sun::star::uno::Sequence;
109 using ::com::sun::star::uno::Reference;
110 using ::com::sun::star::uno::Any;
111 using ::std::vector;
112 
113 
114 namespace
115 {
116  using CustomLabelSeq = Sequence<Reference<chart2::XDataPointCustomLabelField>>;
117 
118  struct SchXMLDataPointStruct
119  {
120  OUString maStyleName;
121  sal_Int32 mnRepeat;
122  chart2::RelativePosition mCustomLabelPos; // loext:custom-label-pos-x and -y
123 
124  // There is no internal equivalent for <chart:data-label>. It will be generated on the fly
125  // on export. All about data label is hold in the data point.
126  CustomLabelSeq mCustomLabelText; // <text:p> child element in <chart:data-label>
127  OUString msDataLabelStyleName; // chart:style-name attribute in <chart:data-label>
128 
129  SchXMLDataPointStruct() : mnRepeat( 1 ) {}
130  };
131 }
132 
133 
135 {
136 public:
137  // first: data sequence for label, second: data sequence for values.
138  typedef ::std::pair< css::uno::Reference< css::chart2::data::XDataSequence >,
139  css::uno::Reference< css::chart2::data::XDataSequence > > tLabelValuesDataPair;
140  typedef ::std::vector< tLabelValuesDataPair > tDataSequenceCont;
141 
142 public:
144  SvXMLAutoStylePoolP& rASPool );
145 
147  SchXMLExportHelper_Impl& operator=(const SchXMLExportHelper_Impl&) = delete;
148 
149  // auto-styles
151  void collectAutoStyles( css::uno::Reference< css::chart::XChartDocument > const & rChartDoc );
152 
154  void exportAutoStyles();
155 
167  void exportChart( css::uno::Reference< css::chart::XChartDocument > const & rChartDoc,
168  bool bIncludeTable );
169 
170  const rtl::Reference<XMLPropertySetMapper>& GetPropertySetMapper() const;
171 
172  void SetChartRangeAddress( const OUString& rAddress )
173  { msChartAddress = rAddress; }
174 
175  void InitRangeSegmentationProperties(
176  const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc );
177 
178  static css::awt::Size getPageSize(
179  const css::uno::Reference< css::chart2::XChartDocument > & xChartDoc );
180 
184  ::std::queue< OUString > maAutoStyleNameQueue;
185  void CollectAutoStyle(
186  const std::vector< XMLPropertyState >& aStates );
187  void AddAutoStyleAttribute(
188  const std::vector< XMLPropertyState >& aStates );
189 
191  void parseDocument( css::uno::Reference< css::chart::XChartDocument > const & rChartDoc,
192  bool bExportContent,
193  bool bIncludeTable = false );
194  void exportTable();
195  void exportPlotArea(
196  const css::uno::Reference< css::chart::XDiagram >& xDiagram,
197  const css::uno::Reference< css::chart2::XDiagram >& xNewDiagram,
198  const css::awt::Size & rPageSize,
199  bool bExportContent,
200  bool bIncludeTable );
201  void exportCoordinateRegion( const css::uno::Reference< css::chart::XDiagram >& xDiagram );
202  void exportAxes( const css::uno::Reference< css::chart::XDiagram > & xDiagram,
203  const css::uno::Reference< css::chart2::XDiagram > & xNewDiagram,
204  bool bExportContent );
205  void exportAxis( enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName,
206  const Reference< beans::XPropertySet >& rAxisProps, const Reference< chart2::XAxis >& rChart2Axis,
207  const OUString& rCategoriesRanges,
208  bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent, std::u16string_view sChartType );
209  void exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent );
210  void exportDateScale( const Reference< beans::XPropertySet >& rAxisProps );
211  void exportAxisTitle( const Reference< beans::XPropertySet >& rTitleProps, bool bExportContent );
212 
213  void exportSeries(
214  const css::uno::Reference< css::chart2::XDiagram > & xNewDiagram,
215  const css::awt::Size & rPageSize,
216  bool bExportContent,
217  bool bHasTwoYAxes );
218 
219  void exportPropertyMapping(
220  const css::uno::Reference< css::chart2::data::XDataSource > & xSource,
221  const Sequence< OUString >& rSupportedMappings );
222 
223  void exportCandleStickSeries(
224  const css::uno::Sequence<
225  css::uno::Reference< css::chart2::XDataSeries > > & aSeriesSeq,
226  const css::uno::Reference< css::chart2::XDiagram > & xDiagram,
227  bool bJapaneseCandleSticks,
228  bool bExportContent );
229  void exportDataPoints(
230  const css::uno::Reference< css::beans::XPropertySet > & xSeriesProperties,
231  sal_Int32 nSeriesLength,
232  const css::uno::Reference< css::chart2::XDiagram > & xDiagram,
233  bool bExportContent );
234 
235  void exportCustomLabel(const SchXMLDataPointStruct& rPoint);
236  void exportCustomLabelPosition(const chart2::RelativePosition& xCustomLabelPosition);
237 
238  void exportRegressionCurve(
239  const css::uno::Reference<css::chart2::XDataSeries>& xSeries,
240  const css::awt::Size& rPageSize,
241  bool bExportContent );
242 
243  void exportErrorBar (
244  const css::uno::Reference<beans::XPropertySet> &xSeriesProp, bool bYError,
245  bool bExportContent );
246 
248  void addPosition( const css::awt::Point & rPosition );
249  void addPosition( const css::uno::Reference< css::drawing::XShape >& xShape );
251  void addSize( const css::awt::Size & rSize, bool bIsOOoNamespace = false );
252  void addSize( const css::uno::Reference< css::drawing::XShape >& xShape );
254  void exportText( const OUString& rText );
255 
256 public:
261 
262  static constexpr OUStringLiteral gsTableName = u"local-table";
263  OUStringBuffer msStringBuffer;
264  OUString msString;
265 
266  // members filled by InitRangeSegmentationProperties (retrieved from DataProvider)
267  bool mbHasCategoryLabels; //if the categories are only automatically generated this will be false
269  OUString msChartAddress;
270  css::uno::Sequence< sal_Int32 > maSequenceMapping;
271 
272  OUString msCLSID;
273 
274  OUString maSrcShellID;
275  OUString maDestShellID;
276 
277  css::uno::Reference< css::drawing::XShapes > mxAdditionalShapes;
278 
279  tDataSequenceCont m_aDataSequencesToExport;
281 };
282 
283 namespace
284 {
285 CustomLabelSeq lcl_getCustomLabelField(sal_Int32 nDataPointIndex,
286  const uno::Reference< chart2::XDataSeries >& rSeries)
287 {
288  if (!rSeries.is())
289  return CustomLabelSeq();
290 
291  // Custom data label text will be written to the <text:p> child element of a
292  // <chart:data-label> element. That exists only since ODF 1.2.
293  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(
294  SvtSaveOptions().GetODFSaneDefaultVersion());
295  if (nCurrentODFVersion < SvtSaveOptions::ODFSVER_012)
296  return CustomLabelSeq();
297 
298  if(Reference<beans::XPropertySet> xLabels = rSeries->getDataPointByIndex(nDataPointIndex); xLabels.is())
299  {
300  if(Any aAny = xLabels->getPropertyValue("CustomLabelFields"); aAny.hasValue())
301  {
302  Sequence<uno::Reference<chart2::XDataPointCustomLabelField>> aCustomLabels;
303  aAny >>= aCustomLabels;
304  return aCustomLabels;
305  }
306  }
307  return CustomLabelSeq();
308 }
309 
310 css::chart2::RelativePosition lcl_getCustomLabelPosition(sal_Int32 nDataPointIndex,
311  const uno::Reference< chart2::XDataSeries >& rSeries)
312 {
313  if (!rSeries.is())
314  return chart2::RelativePosition();
315 
316  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
317  if ((nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) == 0) // do not export to ODF 1.3 or older
318  return chart2::RelativePosition();
319 
320  if (Reference<beans::XPropertySet> xLabels = rSeries->getDataPointByIndex(nDataPointIndex); xLabels.is())
321  {
322  if (Any aAny = xLabels->getPropertyValue("CustomLabelPosition"); aAny.hasValue())
323  {
324  chart2::RelativePosition aCustomLabelPos;
325  aAny >>= aCustomLabelPos;
326  return aCustomLabelPos;
327  }
328  }
329  return chart2::RelativePosition();
330 }
331 
332 class lcl_MatchesRole
333 {
334 public:
335  explicit lcl_MatchesRole( const OUString & aRole ) :
336  m_aRole( aRole )
337  {}
338 
339  bool operator () ( const Reference< chart2::data::XLabeledDataSequence > & xSeq ) const
340  {
341  if( !xSeq.is() )
342  return false;
343  Reference< beans::XPropertySet > xProp( xSeq->getValues(), uno::UNO_QUERY );
344  OUString aRole;
345 
346  return ( xProp.is() &&
347  (xProp->getPropertyValue( "Role" ) >>= aRole ) &&
348  m_aRole == aRole );
349  }
350 
351 private:
352  OUString m_aRole;
353 };
354 
355 Reference< chart2::data::XLabeledDataSequence > lcl_getCategories( const Reference< chart2::XDiagram > & xDiagram )
356 {
358  try
359  {
360  Reference< chart2::XCoordinateSystemContainer > xCooSysCnt(
361  xDiagram, uno::UNO_QUERY_THROW );
362  const Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq(
363  xCooSysCnt->getCoordinateSystems());
364  for( const auto& rCooSys : aCooSysSeq )
365  {
366  Reference< chart2::XCoordinateSystem > xCooSys( rCooSys );
367  SAL_WARN_IF( !xCooSys.is(), "xmloff.chart", "xCooSys is NULL" );
368  for( sal_Int32 nN = xCooSys->getDimension(); nN--; )
369  {
370  const sal_Int32 nMaxAxisIndex = xCooSys->getMaximumAxisIndexByDimension(nN);
371  for(sal_Int32 nI=0; nI<=nMaxAxisIndex; ++nI)
372  {
373  Reference< chart2::XAxis > xAxis = xCooSys->getAxisByDimension( nN, nI );
374  SAL_WARN_IF( !xAxis.is(), "xmloff.chart", "xAxis is NULL");
375  if( xAxis.is())
376  {
377  chart2::ScaleData aScaleData = xAxis->getScaleData();
378  if( aScaleData.Categories.is())
379  {
380  xResult.set( aScaleData.Categories );
381  break;
382  }
383  }
384  }
385  }
386  }
387  }
388  catch( const uno::Exception & )
389  {
390  DBG_UNHANDLED_EXCEPTION("xmloff.chart");
391  }
392 
393  return xResult;
394 }
395 
396 Reference< chart2::data::XDataSource > lcl_createDataSource(
397  const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aData )
398 {
401  Reference< chart2::data::XDataSink > xSink(
402  xContext->getServiceManager()->createInstanceWithContext(
403  "com.sun.star.chart2.data.DataSource", xContext ),
404  uno::UNO_QUERY_THROW );
405  xSink->setData( aData );
406 
407  return Reference< chart2::data::XDataSource >( xSink, uno::UNO_QUERY );
408 }
409 
410 Sequence< Reference< chart2::data::XLabeledDataSequence > > lcl_getAllSeriesSequences( const Reference< chart2::XChartDocument >& xChartDoc )
411 {
412  ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aContainer;
413  if( xChartDoc.is() )
414  {
415  Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
416  ::std::vector< Reference< chart2::XDataSeries > > aSeriesVector( SchXMLSeriesHelper::getDataSeriesFromDiagram( xDiagram ));
417  for( const auto& rSeries : aSeriesVector )
418  {
419  Reference< chart2::data::XDataSource > xDataSource( rSeries, uno::UNO_QUERY );
420  if( !xDataSource.is() )
421  continue;
422  uno::Sequence< Reference< chart2::data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() );
423  aContainer.insert( aContainer.end(), aDataSequences.begin(), aDataSequences.end() );
424  }
425  }
426 
427  return comphelper::containerToSequence( aContainer );
428 }
429 
431  lcl_getDataSequenceByRole(
432  const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aLabeledSeq,
433  const OUString & rRole )
434 {
436 
437  const Reference< chart2::data::XLabeledDataSequence > * pBegin = aLabeledSeq.getConstArray();
438  const Reference< chart2::data::XLabeledDataSequence > * pEnd = pBegin + aLabeledSeq.getLength();
440  ::std::find_if( pBegin, pEnd, lcl_MatchesRole( rRole ));
441 
442  if( pMatch != pEnd )
443  return *pMatch;
444 
445  return aNoResult;
446 }
447 
448 Reference< chart2::data::XDataSource > lcl_pressUsedDataIntoRectangularFormat( const Reference< chart2::XChartDocument >& xChartDoc, bool& rOutSourceHasCategoryLabels )
449 {
450  ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aLabeledSeqVector;
451 
452  //categories are always the first sequence
453  Reference< chart2::XDiagram > xDiagram( xChartDoc->getFirstDiagram());
454  Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xDiagram ) );
455  if( xCategories.is() )
456  aLabeledSeqVector.push_back( xCategories );
457  rOutSourceHasCategoryLabels = xCategories.is();
458 
459  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeriesSeqVector(
460  lcl_getAllSeriesSequences( xChartDoc ) );
461 
462  //the first x-values is always the next sequence //todo ... other x-values get lost for old format
464  lcl_getDataSequenceByRole( aSeriesSeqVector, "values-x" ) );
465  if( xXValues.is() )
466  aLabeledSeqVector.push_back( xXValues );
467 
468  //add all other sequences now without x-values
469  lcl_MatchesRole aHasXValues( "values-x" );
470  std::copy_if(aSeriesSeqVector.begin(), aSeriesSeqVector.end(), std::back_inserter(aLabeledSeqVector),
471  [&aHasXValues](const auto& rSeriesSeq) { return !aHasXValues( rSeriesSeq ); });
472 
473  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeq( comphelper::containerToSequence(aLabeledSeqVector) );
474 
475  return lcl_createDataSource( aSeq );
476 }
477 
478 bool lcl_isSeriesAttachedToFirstAxis(
479  const Reference< chart2::XDataSeries > & xDataSeries )
480 {
481  bool bResult=true;
482 
483  try
484  {
485  sal_Int32 nAxisIndex = 0;
486  Reference< beans::XPropertySet > xProp( xDataSeries, uno::UNO_QUERY_THROW );
487  xProp->getPropertyValue("AttachedAxisIndex") >>= nAxisIndex;
488  bResult = (0==nAxisIndex);
489  }
490  catch( const uno::Exception & )
491  {
492  DBG_UNHANDLED_EXCEPTION("xmloff.chart");
493  }
494 
495  return bResult;
496 }
497 
498 OUString lcl_ConvertRange( const OUString & rRange, const Reference< chart2::XChartDocument > & xDoc )
499 {
500  OUString aResult = rRange;
501  if( !xDoc.is() )
502  return aResult;
503  Reference< chart2::data::XRangeXMLConversion > xConversion(
504  xDoc->getDataProvider(), uno::UNO_QUERY );
505  if( xConversion.is())
506  aResult = xConversion->convertRangeToXML( rRange );
507  return aResult;
508 }
509 
510 typedef ::std::pair< OUString, OUString > tLabelAndValueRange;
511 
512 tLabelAndValueRange lcl_getLabelAndValueRangeByRole(
513  const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
514  const OUString & rRole,
515  const Reference< chart2::XChartDocument > & xDoc,
516  SchXMLExportHelper_Impl::tDataSequenceCont & rOutSequencesToExport )
517 {
518  tLabelAndValueRange aResult;
519 
521  lcl_getDataSequenceByRole( aSeqCnt, rRole ));
522  if( xLabeledSeq.is())
523  {
524  Reference< chart2::data::XDataSequence > xLabelSeq( xLabeledSeq->getLabel());
525  if( xLabelSeq.is())
526  aResult.first = lcl_ConvertRange( xLabelSeq->getSourceRangeRepresentation(), xDoc );
527 
528  Reference< chart2::data::XDataSequence > xValueSeq( xLabeledSeq->getValues());
529  if( xValueSeq.is())
530  aResult.second = lcl_ConvertRange( xValueSeq->getSourceRangeRepresentation(), xDoc );
531 
532  if( xLabelSeq.is() || xValueSeq.is())
533  rOutSequencesToExport.emplace_back( xLabelSeq, xValueSeq );
534  }
535 
536  return aResult;
537 }
538 
539 sal_Int32 lcl_getSequenceLengthByRole(
540  const Sequence< Reference< chart2::data::XLabeledDataSequence > > & aSeqCnt,
541  const OUString & rRole )
542 {
544  lcl_getDataSequenceByRole( aSeqCnt, rRole ));
545  if( xLabeledSeq.is())
546  {
547  Reference< chart2::data::XDataSequence > xSeq( xLabeledSeq->getValues());
548  return xSeq->getData().getLength();
549  }
550  return 0;
551 }
552 
553 OUString lcl_flattenStringSequence( const Sequence< OUString > & rSequence )
554 {
555  OUStringBuffer aResult;
556  bool bPrecedeWithSpace = false;
557  for( const auto& rString : rSequence )
558  {
559  if( !rString.isEmpty())
560  {
561  if( bPrecedeWithSpace )
562  aResult.append( ' ' );
563  aResult.append( rString );
564  bPrecedeWithSpace = true;
565  }
566  }
567  return aResult.makeStringAndClear();
568 }
569 
570 void lcl_getLabelStringSequence( Sequence< OUString >& rOutLabels, const Reference< chart2::data::XDataSequence > & xLabelSeq )
571 {
572  uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xLabelSeq, uno::UNO_QUERY );
573  if( xTextualDataSequence.is())
574  {
575  rOutLabels = xTextualDataSequence->getTextualData();
576  }
577  else if( xLabelSeq.is())
578  {
579  Sequence< uno::Any > aAnies( xLabelSeq->getData());
580  rOutLabels.realloc( aAnies.getLength());
581  for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
582  aAnies[i] >>= rOutLabels[i];
583  }
584 }
585 
586 sal_Int32 lcl_getMaxSequenceLength(
587  const SchXMLExportHelper_Impl::tDataSequenceCont & rContainer )
588 {
589  sal_Int32 nResult = 0;
590  for( const auto& rDataSequence : rContainer )
591  {
592  if( rDataSequence.second.is())
593  {
594  sal_Int32 nSeqLength = rDataSequence.second->getData().getLength();
595  if( nSeqLength > nResult )
596  nResult = nSeqLength;
597  }
598  }
599  return nResult;
600 }
601 
602 uno::Sequence< OUString > lcl_DataSequenceToStringSequence(
603  const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
604 {
605  uno::Sequence< OUString > aResult;
606  if(!xDataSequence.is())
607  return aResult;
608 
609  uno::Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
610  if( xTextualDataSequence.is() )
611  {
612  aResult = xTextualDataSequence->getTextualData();
613  }
614  else
615  {
616  uno::Sequence< uno::Any > aValues = xDataSequence->getData();
617  aResult.realloc(aValues.getLength());
618 
619  for(sal_Int32 nN=aValues.getLength();nN--;)
620  aValues[nN] >>= aResult[nN];
621  }
622 
623  return aResult;
624 }
625 ::std::vector< double > lcl_getAllValuesFromSequence( const Reference< chart2::data::XDataSequence > & xSeq )
626 {
627  double fNan = 0.0;
628  ::rtl::math::setNan( &fNan );
629  ::std::vector< double > aResult;
630  if(!xSeq.is())
631  return aResult;
632 
633  uno::Sequence< double > aValuesSequence;
634  Reference< chart2::data::XNumericalDataSequence > xNumSeq( xSeq, uno::UNO_QUERY );
635  if( xNumSeq.is() )
636  {
637  aValuesSequence = xNumSeq->getNumericalData();
638  }
639  else
640  {
641  Sequence< uno::Any > aAnies( xSeq->getData() );
642  aValuesSequence.realloc( aAnies.getLength() );
643  for( sal_Int32 i=0; i<aAnies.getLength(); ++i )
644  aAnies[i] >>= aValuesSequence[i];
645  }
646 
647  //special handling for x-values (if x-values do point to categories, indices are used instead )
648  Reference< beans::XPropertySet > xProp( xSeq, uno::UNO_QUERY );
649  if( xProp.is() )
650  {
651  OUString aRole;
652  xProp->getPropertyValue("Role") >>= aRole;
653  if( aRole.match("values-x") )
654  {
655  //lcl_clearIfNoValuesButTextIsContained - replace by indices if the values are not appropriate
656  bool bHasValue = std::any_of(aValuesSequence.begin(), aValuesSequence.end(),
657  [](double fValue) { return !std::isnan( fValue ); });
658  if(!bHasValue)
659  {
660  //no double value is contained
661  //is there any text?
662  uno::Sequence< OUString > aStrings( lcl_DataSequenceToStringSequence( xSeq ) );
663  bool bHasText = std::any_of(aStrings.begin(), aStrings.end(),
664  [](const OUString& rString) { return !rString.isEmpty(); });
665  if( bHasText )
666  {
667  std::iota(aValuesSequence.begin(), aValuesSequence.end(), 1);
668  }
669  }
670  }
671  }
672 
673  aResult.insert( aResult.end(), aValuesSequence.begin(), aValuesSequence.end() );
674  return aResult;
675 }
676 
677 bool lcl_SequenceHasUnhiddenData( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
678 {
679  if( !xDataSequence.is() )
680  return false;
681  uno::Reference< beans::XPropertySet > xProp( xDataSequence, uno::UNO_QUERY );
682  if( xProp.is() )
683  {
684  uno::Sequence< sal_Int32 > aHiddenValues;
685  try
686  {
687  xProp->getPropertyValue("HiddenValues") >>= aHiddenValues;
688  if( !aHiddenValues.hasElements() )
689  return true;
690  }
691  catch( const uno::Exception& )
692  {
693  return true;
694  }
695  }
696  return xDataSequence->getData().hasElements();
697 }
698 
699 typedef vector< OUString > tStringVector;
700 typedef vector< vector< double > > t2DNumberContainer;
701 
702 struct lcl_TableData
703 {
704  t2DNumberContainer aDataInRows;
705  tStringVector aDataRangeRepresentations;
706 
707  tStringVector aColumnDescriptions;
708  tStringVector aColumnDescriptions_Ranges;
709 
710  tStringVector aRowDescriptions;
711  tStringVector aRowDescriptions_Ranges;
712 
713  Sequence< Sequence< uno::Any > > aComplexColumnDescriptions;//outer index is columns - inner index is level
714  Sequence< Sequence< uno::Any > > aComplexRowDescriptions;//outer index is rows - inner index is level
715 
716  ::std::vector< sal_Int32 > aHiddenColumns;
717 };
718 
719 typedef ::std::map< sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair >
720  lcl_DataSequenceMap;
721 
722 struct lcl_SequenceToMapElement
723 {
724  std::pair<const sal_Int32, SchXMLExportHelper_Impl::tLabelValuesDataPair>
725  operator() (const SchXMLExportHelper_Impl::tLabelValuesDataPair& rContent)
726  {
727  sal_Int32 nIndex = -1;
728  if( rContent.second.is()) //has values
729  {
730  OUString aRangeRep( rContent.second->getSourceRangeRepresentation());
731  nIndex = aRangeRep.toInt32();
732  }
733  else if( rContent.first.is()) //has labels
734  nIndex = rContent.first->getSourceRangeRepresentation().copy( sizeof("label ")).toInt32();
735  return std::make_pair(nIndex, rContent);
736  }
737 };
738 
739 void lcl_ReorderInternalSequencesAccordingToTheirRangeName(
741 {
742  lcl_DataSequenceMap aIndexSequenceMap;
743  ::std::transform( rInOutSequences.begin(), rInOutSequences.end(),
744  ::std::inserter( aIndexSequenceMap, aIndexSequenceMap.begin()),
745  lcl_SequenceToMapElement());
746 
747  rInOutSequences.clear();
748  sal_Int32 nIndex = 0;
749  for( const auto& rEntry : aIndexSequenceMap )
750  {
751  if( rEntry.first >= 0 )
752  {
753  // fill empty columns
754  rInOutSequences.insert(
755  rInOutSequences.end(),
756  rEntry.first - nIndex,
757  SchXMLExportHelper_Impl::tDataSequenceCont::value_type(
758  uno::Reference< chart2::data::XDataSequence >(),
759  uno::Reference< chart2::data::XDataSequence >() ));
760  nIndex = rEntry.first;
761  rInOutSequences.push_back( rEntry.second );
762  }
763 
764  ++nIndex;
765  }
766 }
767 
768 lcl_TableData lcl_getDataForLocalTable(
769  const SchXMLExportHelper_Impl::tDataSequenceCont & aSequencesToExport,
770  const Reference< chart2::XAnyDescriptionAccess >& xAnyDescriptionAccess,
771  const OUString& rCategoriesRange,
772  bool bSeriesFromColumns,
773  const Reference< chart2::data::XRangeXMLConversion > & xRangeConversion )
774 {
775  lcl_TableData aResult;
776 
777  try
778  {
779  Sequence< OUString > aSimpleCategories;
780  if( xAnyDescriptionAccess.is() )
781  {
782  //categories
783  if( bSeriesFromColumns )
784  {
785  aSimpleCategories = xAnyDescriptionAccess->getRowDescriptions();
786  aResult.aComplexRowDescriptions = xAnyDescriptionAccess->getAnyRowDescriptions();
787  }
788  else
789  {
790  aSimpleCategories = xAnyDescriptionAccess->getColumnDescriptions();
791  aResult.aComplexColumnDescriptions = xAnyDescriptionAccess->getAnyColumnDescriptions();
792  }
793  }
794 
795  //series values and series labels
796  SchXMLExportHelper_Impl::tDataSequenceCont::size_type nNumSequences = aSequencesToExport.size();
797 
798  auto nMaxSequenceLength( lcl_getMaxSequenceLength( aSequencesToExport ));
799  if( aSimpleCategories.getLength() > nMaxSequenceLength )
800  {
801  aSimpleCategories.realloc(nMaxSequenceLength);//#i110617#
802  }
803  size_t nNumColumns( bSeriesFromColumns ? nNumSequences : nMaxSequenceLength );
804  size_t nNumRows( bSeriesFromColumns ? nMaxSequenceLength : nNumSequences );
805 
806  // resize data
807  aResult.aDataInRows.resize( nNumRows );
808  double fNan = 0.0;
809  ::rtl::math::setNan( &fNan );
810 
811  for (auto& aData: aResult.aDataInRows)
812  aData.resize(nNumColumns, fNan);
813  aResult.aColumnDescriptions.resize( nNumColumns );
814  aResult.aComplexColumnDescriptions.realloc( nNumColumns );
815  aResult.aRowDescriptions.resize( nNumRows );
816  aResult.aComplexRowDescriptions.realloc( nNumRows );
817 
818  tStringVector& rCategories = bSeriesFromColumns ? aResult.aRowDescriptions : aResult.aColumnDescriptions;
819  tStringVector& rLabels = bSeriesFromColumns ? aResult.aColumnDescriptions : aResult.aRowDescriptions;
820 
821  //categories
822  rCategories.clear();
823  rCategories.insert( rCategories.begin(), aSimpleCategories.begin(), aSimpleCategories.end() );
824  if( !rCategoriesRange.isEmpty() )
825  {
826  OUString aRange(rCategoriesRange);
827  if( xRangeConversion.is())
828  aRange = xRangeConversion->convertRangeToXML( aRange );
829  if( bSeriesFromColumns )
830  aResult.aRowDescriptions_Ranges.push_back( aRange );
831  else
832  aResult.aColumnDescriptions_Ranges.push_back( aRange );
833  }
834 
835  // iterate over all sequences
836  size_t nSeqIdx = 0;
837  Sequence< Sequence< OUString > > aComplexLabels(nNumSequences);
838  for( const auto& rDataSequence : aSequencesToExport )
839  {
840  OUString aRange;
841  Sequence< OUString >& rCurrentComplexLabel = aComplexLabels[nSeqIdx];
842  if( rDataSequence.first.is())
843  {
844  lcl_getLabelStringSequence( rCurrentComplexLabel, rDataSequence.first );
845  rLabels[nSeqIdx] = lcl_flattenStringSequence( rCurrentComplexLabel );
846  aRange = rDataSequence.first->getSourceRangeRepresentation();
847  if( xRangeConversion.is())
848  aRange = xRangeConversion->convertRangeToXML( aRange );
849  }
850  else if( rDataSequence.second.is())
851  {
852  rCurrentComplexLabel.realloc(1);
853  rLabels[nSeqIdx] = rCurrentComplexLabel[0] = lcl_flattenStringSequence(
854  rDataSequence.second->generateLabel( chart2::data::LabelOrigin_SHORT_SIDE ));
855  }
856  if( bSeriesFromColumns )
857  aResult.aColumnDescriptions_Ranges.push_back( aRange );
858  else
859  aResult.aRowDescriptions_Ranges.push_back( aRange );
860 
861  ::std::vector< double > aNumbers( lcl_getAllValuesFromSequence( rDataSequence.second ));
862  if( bSeriesFromColumns )
863  {
864  const sal_Int32 nSize( static_cast< sal_Int32 >( aNumbers.size()));
865  for( sal_Int32 nIdx=0; nIdx<nSize; ++nIdx )
866  aResult.aDataInRows[nIdx][nSeqIdx] = aNumbers[nIdx];
867  }
868  else
869  aResult.aDataInRows[nSeqIdx] = aNumbers;
870 
871  if( rDataSequence.second.is())
872  {
873  aRange = rDataSequence.second->getSourceRangeRepresentation();
874  if( xRangeConversion.is())
875  aRange = xRangeConversion->convertRangeToXML( aRange );
876  }
877  aResult.aDataRangeRepresentations.push_back( aRange );
878 
879  //is column hidden?
880  if( !lcl_SequenceHasUnhiddenData(rDataSequence.first) && !lcl_SequenceHasUnhiddenData(rDataSequence.second) )
881  aResult.aHiddenColumns.push_back(nSeqIdx);
882 
883  ++nSeqIdx;
884  }
885  Sequence< Sequence< Any > >& rComplexAnyLabels = bSeriesFromColumns ? aResult.aComplexColumnDescriptions : aResult.aComplexRowDescriptions;//#i116544#
886  rComplexAnyLabels.realloc(aComplexLabels.getLength());
887  for( sal_Int32 nN=0; nN<aComplexLabels.getLength();nN++ )
888  {
889  Sequence< OUString >& rSource = aComplexLabels[nN];
890  Sequence< Any >& rTarget = rComplexAnyLabels[nN];
891  rTarget.realloc( rSource.getLength() );
892  for( sal_Int32 i=0; i<rSource.getLength(); i++ )
893  rTarget[i] <<= rSource[i];
894  }
895  }
896  catch( const uno::Exception & )
897  {
898  TOOLS_INFO_EXCEPTION("xmloff.chart", "something went wrong during table data collection");
899  }
900 
901  return aResult;
902 }
903 
904 void lcl_exportNumberFormat( const OUString& rPropertyName, const Reference< beans::XPropertySet >& xPropSet,
906 {
907  if( xPropSet.is())
908  {
909  sal_Int32 nNumberFormat = 0;
910  Any aNumAny = xPropSet->getPropertyValue( rPropertyName );
911  if( (aNumAny >>= nNumberFormat) && (nNumberFormat != -1) )
912  rExport.addDataStyle( nNumberFormat );
913  }
914 }
915 
916 ::std::vector< Reference< chart2::data::XDataSequence > >
917  lcl_getErrorBarSequences( const Reference< beans::XPropertySet > & xErrorBarProp )
918 {
919  ::std::vector< Reference< chart2::data::XDataSequence > > aResult;
920  Reference< chart2::data::XDataSource > xErrorBarDataSource( xErrorBarProp, uno::UNO_QUERY );
921  if( !xErrorBarDataSource.is())
922  return aResult;
923 
924  const Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences(
925  xErrorBarDataSource->getDataSequences());
926  for( const auto& rSequence : aSequences )
927  {
928  try
929  {
930  if( rSequence.is())
931  {
932  Reference< chart2::data::XDataSequence > xSequence( rSequence->getValues());
933  Reference< beans::XPropertySet > xSeqProp( xSequence, uno::UNO_QUERY_THROW );
934  OUString aRole;
935  if( ( xSeqProp->getPropertyValue( "Role" ) >>= aRole ) &&
936  aRole.match( "error-bars-" ))
937  {
938  aResult.push_back( xSequence );
939  }
940  }
941  }
942  catch( const uno::Exception & )
943  {
944  TOOLS_INFO_EXCEPTION("xmloff.chart", "chart:exporting error bar ranges" );
945  }
946  }
947 
948  return aResult;
949 }
950 
951 bool lcl_exportDomainForThisSequence( const Reference< chart2::data::XDataSequence >& rValues, OUString& rFirstRangeForThisDomainIndex, SvXMLExport& rExport )
952 {
953  bool bDomainExported = false;
954  if( rValues.is())
955  {
956  Reference< chart2::XChartDocument > xNewDoc( rExport.GetModel(), uno::UNO_QUERY );
957  OUString aRange( lcl_ConvertRange( rValues->getSourceRangeRepresentation(), xNewDoc ) );
958 
959  //work around error in OOo 2.0 (problems with multiple series having a domain element)
960  if( rFirstRangeForThisDomainIndex.isEmpty() || aRange != rFirstRangeForThisDomainIndex )
961  {
963  SvXMLElementExport aDomain( rExport, XML_NAMESPACE_CHART, XML_DOMAIN, true, true );
964  bDomainExported = true;
965  }
966 
967  if( rFirstRangeForThisDomainIndex.isEmpty() )
968  rFirstRangeForThisDomainIndex = aRange;
969  }
970  return bDomainExported;
971 }
972 
973 } // anonymous namespace
974 
975 
977  : m_pImpl( new SchXMLExportHelper_Impl( rExport, rASPool ) )
978 {
979 }
980 
982 {
983 }
984 
985 const OUString& SchXMLExportHelper::getChartCLSID() const
986 {
987  return m_pImpl->msCLSID;
988 }
989 
990 void SchXMLExportHelper::SetSourceShellID( const OUString& rShellID )
991 {
992  m_pImpl->maSrcShellID = rShellID;
993 }
994 
995 void SchXMLExportHelper::SetDestinationShellID( const OUString& rShellID )
996 {
997  m_pImpl->maDestShellID = rShellID;
998 }
999 
1001 {
1002  return mxPropertySetMapper;
1003 }
1004 
1006 {
1007  if( !mxExpPropMapper.is())
1008  return;
1009 
1010  //ToDo: when embedded in calc/writer this is not necessary because the
1011  // numberformatter is shared between both documents
1013 
1014  // export chart auto styles
1016 
1017  // export auto styles for additional shapes
1018  mrExport.GetShapeExport()->exportAutoStyles();
1019  // and for text in additional shapes
1020  mrExport.GetTextParagraphExport()->exportTextAutoStyles();
1021 }
1022 
1023 // private methods
1024 
1026  SvXMLExport& rExport,
1027  SvXMLAutoStylePoolP& rASPool ) :
1028  mrExport( rExport ),
1029  mrAutoStylePool( rASPool ),
1030  mxPropertySetMapper( new XMLChartPropertySetMapper(&rExport) ),
1031  mxExpPropMapper( new XMLChartExportPropertyMapper( mxPropertySetMapper, rExport ) ),
1032  mbHasCategoryLabels( false ),
1033  mbRowSourceColumns( true ),
1034  msCLSID( SvGlobalName( SO3_SCH_CLASSID ).GetHexName() )
1035 {
1036  // register chart auto-style family
1039  OUString( XML_STYLE_FAMILY_SCH_CHART_NAME ),
1040  mxExpPropMapper.get(),
1041  OUString( XML_STYLE_FAMILY_SCH_CHART_PREFIX ));
1042 
1043  // register shape family
1047  mxExpPropMapper.get(),
1049  // register paragraph family also for shapes
1053  mxExpPropMapper.get(),
1054  OUString( 'P' ));
1055  // register text family also for shapes
1058  GetXMLToken( XML_TEXT ),
1059  mxExpPropMapper.get(),
1060  OUString( 'T' ));
1061 }
1062 
1063 void SchXMLExportHelper_Impl::collectAutoStyles( Reference< chart::XChartDocument > const & rChartDoc )
1064 {
1065  parseDocument( rChartDoc, false );
1066 }
1067 
1068 void SchXMLExportHelper_Impl::exportChart( Reference< chart::XChartDocument > const & rChartDoc,
1069  bool bIncludeTable )
1070 {
1071  parseDocument( rChartDoc, true, bIncludeTable );
1072  SAL_WARN_IF( !maAutoStyleNameQueue.empty(), "xmloff.chart", "There are still remaining autostyle names in the queue" );
1073 }
1074 
1075 static OUString lcl_GetStringFromNumberSequence( const css::uno::Sequence< sal_Int32 >& rSequenceMapping, bool bRemoveOneFromEachIndex /*should be true if having categories*/ )
1076 {
1077  OUStringBuffer aBuf;
1078  bool bHasPredecessor = false;
1079  for( sal_Int32 nIndex : rSequenceMapping )
1080  {
1081  if( bRemoveOneFromEachIndex )
1082  --nIndex;
1083  if(nIndex>=0)
1084  {
1085  if(bHasPredecessor)
1086  aBuf.append( ' ' );
1087  aBuf.append( nIndex );
1088  bHasPredecessor = true;
1089  }
1090  }
1091  return aBuf.makeStringAndClear();
1092 }
1093 
1095 void SchXMLExportHelper_Impl::parseDocument( Reference< chart::XChartDocument > const & rChartDoc,
1096  bool bExportContent,
1097  bool bIncludeTable )
1098 {
1099  Reference< chart2::XChartDocument > xNewDoc( rChartDoc, uno::UNO_QUERY );
1100  if( !rChartDoc.is() || !xNewDoc.is() )
1101  {
1102  SAL_WARN("xmloff.chart", "No XChartDocument was given for export." );
1103  return;
1104  }
1105 
1106  mxExpPropMapper->setChartDoc(xNewDoc);
1107 
1108  awt::Size aPageSize( getPageSize( xNewDoc ));
1109  if( bExportContent )
1110  addSize( aPageSize );
1111  Reference< chart::XDiagram > xDiagram = rChartDoc->getDiagram();
1112  Reference< chart2::XDiagram > xNewDiagram;
1113  if( xNewDoc.is())
1114  xNewDiagram.set( xNewDoc->getFirstDiagram());
1115 
1116  //todo remove if model changes are notified and view is updated automatically
1117  if( bExportContent )
1118  {
1119  Reference< util::XRefreshable > xRefreshable( xNewDoc, uno::UNO_QUERY );
1120  if( xRefreshable.is() )
1121  xRefreshable->refresh();
1122  }
1123 
1124  // get Properties of ChartDocument
1125  bool bHasMainTitle = false;
1126  bool bHasSubTitle = false;
1127  bool bHasLegend = false;
1128  util::DateTime aNullDate(0,0,0,0,30,12,1899, false);
1129 
1130  std::vector< XMLPropertyState > aPropertyStates;
1131 
1132  Reference< beans::XPropertySet > xDocPropSet( rChartDoc, uno::UNO_QUERY );
1133  if( xDocPropSet.is())
1134  {
1135  try
1136  {
1137  Any aAny = xDocPropSet->getPropertyValue("HasMainTitle");
1138  aAny >>= bHasMainTitle;
1139  aAny = xDocPropSet->getPropertyValue("HasSubTitle");
1140  aAny >>= bHasSubTitle;
1141  aAny = xDocPropSet->getPropertyValue("HasLegend");
1142  aAny >>= bHasLegend;
1143  if ( bIncludeTable )
1144  {
1145  aAny = xDocPropSet->getPropertyValue("NullDate");
1146  if ( !aAny.hasValue() )
1147  {
1148  Reference<container::XChild> xChild(rChartDoc, uno::UNO_QUERY );
1149  if ( xChild.is() )
1150  {
1151  Reference< beans::XPropertySet > xParentDoc( xChild->getParent(),uno::UNO_QUERY);
1152  if ( xParentDoc.is() && xParentDoc->getPropertySetInfo()->hasPropertyByName("NullDate") )
1153  aAny = xParentDoc->getPropertyValue("NullDate");
1154  }
1155  }
1156 
1157  aAny >>= aNullDate;
1158  }
1159  }
1160  catch( const beans::UnknownPropertyException & )
1161  {
1162  SAL_WARN("xmloff.chart", "Required property not found in ChartDocument" );
1163  }
1164  }
1165 
1166  if ( bIncludeTable && (aNullDate.Day != 30 || aNullDate.Month != 12 || aNullDate.Year != 1899 ) )
1167  {
1169  {
1170  OUStringBuffer sBuffer;
1171  ::sax::Converter::convertDateTime(sBuffer, aNullDate, nullptr);
1172  mrExport.AddAttribute( XML_NAMESPACE_TABLE,XML_DATE_VALUE,sBuffer.makeStringAndClear());
1174  }
1175  }
1176 
1177  // chart element
1178  std::unique_ptr<SvXMLElementExport> xElChart;
1179 
1180  // get property states for autostyles
1181  if( mxExpPropMapper.is())
1182  {
1183  Reference< beans::XPropertySet > xPropSet = rChartDoc->getArea();
1184  if( xPropSet.is())
1185  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1186  }
1187 
1188  if( bExportContent )
1189  {
1190  //export data provider in xlink:href attribute
1191  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
1192  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
1193  {
1194  OUString aDataProviderURL( ".." );
1195  if( xNewDoc->hasInternalDataProvider() )
1196  aDataProviderURL = ".";
1197  else //special handling for data base data provider necessary
1198  {
1199  Reference< chart2::data::XDatabaseDataProvider > xDBDataProvider( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1200  if( xDBDataProvider.is() )
1201  aDataProviderURL = ".";
1202  }
1203  mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aDataProviderURL );
1205  }
1206 
1207  Reference<chart2::data::XPivotTableDataProvider> xPivotTableDataProvider(xNewDoc->getDataProvider(), uno::UNO_QUERY);
1208  if (xPivotTableDataProvider.is() && nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED)
1209  {
1210  OUString sPivotTableName = xPivotTableDataProvider->getPivotTableName();
1212  }
1213 
1214  OUString sChartType( xDiagram->getDiagramType() );
1215 
1216  // attributes
1217  // determine class
1218  if( !sChartType.isEmpty())
1219  {
1220  enum XMLTokenEnum eXMLChartType = SchXMLTools::getTokenByChartType( sChartType, true /* bUseOldNames */ );
1221 
1222  SAL_WARN_IF( eXMLChartType == XML_TOKEN_INVALID, "xmloff.chart", "invalid chart class" );
1223  if( eXMLChartType == XML_TOKEN_INVALID )
1224  eXMLChartType = XML_BAR;
1225 
1226  if( eXMLChartType == XML_ADD_IN )
1227  {
1228  // sChartType is the service-name of the add-in
1231  XML_NAMESPACE_OOO, sChartType) );
1232  }
1233  else if( eXMLChartType != XML_TOKEN_INVALID )
1234  {
1237  XML_NAMESPACE_CHART, GetXMLToken(eXMLChartType )) );
1238  }
1239 
1240  //column-mapping or row-mapping
1241  if( maSequenceMapping.hasElements() )
1242  {
1244  if( mbRowSourceColumns )
1246  OUString aSequenceMappingStr( lcl_GetStringFromNumberSequence(
1247  maSequenceMapping, mbHasCategoryLabels && !xNewDoc->hasInternalDataProvider() ) );
1248 
1250  ::xmloff::token::GetXMLToken( eTransToken ),
1251  aSequenceMappingStr );
1252  }
1253  }
1254  // write style name
1255  AddAutoStyleAttribute( aPropertyStates );
1256 
1257  //element
1258  xElChart.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_CHART, true, true ));
1259  }
1260  else // autostyles
1261  {
1262  CollectAutoStyle( aPropertyStates );
1263  }
1264  // remove property states for autostyles
1265  aPropertyStates.clear();
1266 
1267  // title element
1268  if( bHasMainTitle )
1269  {
1270  // get property states for autostyles
1271  if( mxExpPropMapper.is())
1272  {
1273  Reference< beans::XPropertySet > xPropSet( rChartDoc->getTitle(), uno::UNO_QUERY );
1274  if( xPropSet.is())
1275  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1276  }
1277  if( bExportContent )
1278  {
1279  Reference< drawing::XShape > xShape = rChartDoc->getTitle();
1280  if( xShape.is()) // && "hasTitleBeenMoved"
1281  addPosition( xShape );
1282 
1283  // write style name
1284  AddAutoStyleAttribute( aPropertyStates );
1285 
1286  // element
1287  SvXMLElementExport aElTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
1288 
1289  // content (text:p)
1290  Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1291  if( xPropSet.is())
1292  {
1293  Any aAny( xPropSet->getPropertyValue( "String" ));
1294  OUString aText;
1295  aAny >>= aText;
1296  exportText( aText );
1297  }
1298  }
1299  else // autostyles
1300  {
1301  CollectAutoStyle( aPropertyStates );
1302  }
1303  // remove property states for autostyles
1304  aPropertyStates.clear();
1305  }
1306 
1307  // subtitle element
1308  if( bHasSubTitle )
1309  {
1310  // get property states for autostyles
1311  if( mxExpPropMapper.is())
1312  {
1313  Reference< beans::XPropertySet > xPropSet( rChartDoc->getSubTitle(), uno::UNO_QUERY );
1314  if( xPropSet.is())
1315  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1316  }
1317 
1318  if( bExportContent )
1319  {
1320  Reference< drawing::XShape > xShape = rChartDoc->getSubTitle();
1321  if( xShape.is())
1322  addPosition( xShape );
1323 
1324  // write style name
1325  AddAutoStyleAttribute( aPropertyStates );
1326 
1327  // element (has no subelements)
1328  SvXMLElementExport aElSubTitle( mrExport, XML_NAMESPACE_CHART, XML_SUBTITLE, true, true );
1329 
1330  // content (text:p)
1331  Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
1332  if( xPropSet.is())
1333  {
1334  Any aAny( xPropSet->getPropertyValue( "String" ));
1335  OUString aText;
1336  aAny >>= aText;
1337  exportText( aText );
1338  }
1339  }
1340  else // autostyles
1341  {
1342  CollectAutoStyle( aPropertyStates );
1343  }
1344  // remove property states for autostyles
1345  aPropertyStates.clear();
1346  }
1347 
1348  // legend element
1349  if( bHasLegend )
1350  {
1351  // get property states for autostyles
1352  if( mxExpPropMapper.is())
1353  {
1354  Reference< beans::XPropertySet > xPropSet( rChartDoc->getLegend(), uno::UNO_QUERY );
1355  if( xPropSet.is())
1356  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1357  }
1358 
1359  if( bExportContent )
1360  {
1361  Reference< beans::XPropertySet > xProp( rChartDoc->getLegend(), uno::UNO_QUERY );
1362  if( xProp.is())
1363  {
1364  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
1365 
1366  // export legend anchor position
1367  try
1368  {
1369  Any aAny( xProp->getPropertyValue("Alignment"));
1372  }
1373  catch( const beans::UnknownPropertyException & )
1374  {
1375  SAL_WARN("xmloff.chart", "Property Align not found in ChartLegend" );
1376  }
1377 
1378  // export legend overlay
1379  try
1380  {
1381  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED)
1382  {
1383  Any aAny( xProp->getPropertyValue("Overlay"));
1384  if(aAny.get<bool>())
1385  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_OVERLAY, OUString::boolean(true));
1386  }
1387  }
1388  catch( const beans::UnknownPropertyException & )
1389  {
1390  SAL_WARN("xmloff.chart", "Property Overlay not found in ChartLegend" );
1391  }
1392 
1393  // export absolute legend position
1394  Reference< drawing::XShape > xLegendShape( xProp, uno::UNO_QUERY );
1395  addPosition( xLegendShape );
1396 
1397  // export legend size
1398  if (xLegendShape.is() && nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
1399  {
1400  try
1401  {
1402  chart::ChartLegendExpansion nLegendExpansion = chart::ChartLegendExpansion_HIGH;
1403  OUString aExpansionString;
1404  Any aAny( xProp->getPropertyValue("Expansion"));
1405  bool bHasExpansion = (aAny >>= nLegendExpansion);
1406  if( bHasExpansion && SchXMLEnumConverter::getLegendExpansionConverter().exportXML( aExpansionString, aAny, mrExport.GetMM100UnitConverter() ) )
1407  {
1409  if( nLegendExpansion == chart::ChartLegendExpansion_CUSTOM)
1410  {
1411  awt::Size aSize( xLegendShape->getSize() );
1412  // tdf#131966: chart legend attributes width and height shouldn't be exported to ODF 1.2 (strict)
1413  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_013)
1414  { // ODF 1.3 OFFICE-3883
1415  addSize( aSize, false );
1416  }
1417  else if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED)
1418  {
1419  addSize( aSize, true );
1420  }
1421  OUStringBuffer aAspectRatioString;
1423  aAspectRatioString,
1424  (aSize.Height == 0
1425  ? 1.0
1426  : double(aSize.Width)/double(aSize.Height)));
1427  mrExport.AddAttribute( XML_NAMESPACE_STYLE, XML_LEGEND_EXPANSION_ASPECT_RATIO, aAspectRatioString.makeStringAndClear() );
1428  }
1429  }
1430  }
1431  catch( const beans::UnknownPropertyException & )
1432  {
1433  SAL_WARN("xmloff.chart", "Property Expansion not found in ChartLegend" );
1434  }
1435  }
1436  }
1437 
1438  // write style name
1439  AddAutoStyleAttribute( aPropertyStates );
1440 
1441  // element
1442  SvXMLElementExport aLegend( mrExport, XML_NAMESPACE_CHART, XML_LEGEND, true, true );
1443  }
1444  else // autostyles
1445  {
1446  CollectAutoStyle( aPropertyStates );
1447  }
1448  // remove property states for autostyles
1449  aPropertyStates.clear();
1450  }
1451 
1452  // plot-area element
1453  if( xDiagram.is())
1454  exportPlotArea( xDiagram, xNewDiagram, aPageSize, bExportContent, bIncludeTable );
1455 
1456  // export additional shapes
1457  if( xDocPropSet.is() )
1458  {
1459  if( bExportContent )
1460  {
1461  if( mxAdditionalShapes.is())
1462  {
1463  // can't call exportShapes with all shapes because the
1464  // initialisation happened with the complete draw page and not
1465  // the XShapes object used here. Thus the shapes have to be
1466  // exported one by one
1468  Reference< drawing::XShape > xShape;
1469  const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1470  for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1471  {
1472  mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1473  SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1474  if( ! xShape.is())
1475  continue;
1476 
1477  rShapeExport->exportShape( xShape );
1478  }
1479  // this would be the easier way if it worked:
1480  //mrExport.GetShapeExport()->exportShapes( mxAdditionalShapes );
1481  }
1482  }
1483  else
1484  {
1485  // get a sequence of non-chart shapes (inserted via clipboard)
1486  try
1487  {
1488  Any aShapesAny = xDocPropSet->getPropertyValue("AdditionalShapes");
1489  aShapesAny >>= mxAdditionalShapes;
1490  }
1491  catch( const uno::Exception & )
1492  {
1493  TOOLS_INFO_EXCEPTION("xmloff.chart", "AdditionalShapes not found" );
1494  }
1495 
1496  if( mxAdditionalShapes.is())
1497  {
1498  // seek shapes has to be called for the whole page because in
1499  // the shape export the vector of shapes is accessed via the
1500  // ZOrder which might be (actually is) larger than the number of
1501  // shapes in mxAdditionalShapes
1502  Reference< drawing::XDrawPageSupplier > xSupplier( rChartDoc, uno::UNO_QUERY );
1503  SAL_WARN_IF( !xSupplier.is(), "xmloff.chart", "Cannot retrieve draw page to initialize shape export" );
1504  if( xSupplier.is() )
1505  {
1506  Reference< drawing::XShapes > xDrawPage = xSupplier->getDrawPage();
1507  SAL_WARN_IF( !xDrawPage.is(), "xmloff.chart", "Invalid draw page for initializing shape export" );
1508  if( xDrawPage.is())
1509  mrExport.GetShapeExport()->seekShapes( xDrawPage );
1510  }
1511 
1512  // can't call collectShapesAutoStyles with all shapes because
1513  // the initialisation happened with the complete draw page and
1514  // not the XShapes object used here. Thus the shapes have to be
1515  // exported one by one
1517  Reference< drawing::XShape > xShape;
1518  const sal_Int32 nShapeCount( mxAdditionalShapes->getCount());
1519  for( sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++ )
1520  {
1521  mxAdditionalShapes->getByIndex( nShapeId ) >>= xShape;
1522  SAL_WARN_IF( !xShape.is(), "xmloff.chart", "Shape without an XShape?" );
1523  if( ! xShape.is())
1524  continue;
1525 
1526  rShapeExport->collectShapeAutoStyles( xShape );
1527  }
1528  }
1529  }
1530  }
1531 
1532  // table element
1533  // (is included as subelement of chart)
1534  if( bExportContent )
1535  {
1536  // #85929# always export table, otherwise clipboard may lose data
1537  exportTable();
1538  }
1539 }
1540 
1541 static void lcl_exportComplexLabel( const Sequence< uno::Any >& rComplexLabel, SvXMLExport& rExport )
1542 {
1543  sal_Int32 nLength = rComplexLabel.getLength();
1544  if( nLength<=1 )
1545  return;
1546  SvXMLElementExport aTextList( rExport, XML_NAMESPACE_TEXT, XML_LIST, true, true );
1547  for(const auto& rElem : rComplexLabel)
1548  {
1549  SvXMLElementExport aListItem( rExport, XML_NAMESPACE_TEXT, XML_LIST_ITEM, true, true );
1550  OUString aString;
1551  if( !(rElem >>= aString) )
1552  {
1553  double aNum;
1554  if (rElem >>= aNum)
1555  {
1556  aString = OUString::number(aNum);
1557  }
1558  }
1559  SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1560  }
1561 }
1562 
1564 {
1565  // table element
1567 
1568  try
1569  {
1570  bool bProtected = false;
1571  Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1572  if ( ( xProps->getPropertyValue("DisableDataTableDialog") >>= bProtected ) &&
1573  bProtected )
1574  {
1576  }
1577  }
1578  catch ( const uno::Exception& )
1579  {
1580  }
1581 
1582  SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, true, true );
1583 
1584  bool bHasOwnData = false;
1585  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1586  Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1587  if( xNewDoc.is())
1588  {
1589  bHasOwnData = xNewDoc->hasInternalDataProvider();
1590  xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1591  }
1592 
1593  Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1594  {
1595  Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1596  if( xChartDoc.is() )
1597  xAnyDescriptionAccess.set( xChartDoc->getData(), uno::UNO_QUERY );
1598  }
1599 
1600  if( bHasOwnData )
1601  lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1602  lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1603  , xAnyDescriptionAccess, maCategoriesRange
1604  , mbRowSourceColumns, xRangeConversion ));
1605 
1606  tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1607  const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1608 
1609  tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1610  const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1611 
1612  // declare columns
1613  {
1615  SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1616  }
1617  {
1619 
1620  sal_Int32 nNextIndex = 0;
1621  for(sal_Int32 nHiddenIndex : aData.aHiddenColumns)
1622  {
1623  //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1624  if( nHiddenIndex > nNextIndex )
1625  {
1626  sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1627  if(nRepeat>1)
1629  OUString::number( nRepeat ));
1631  }
1634  nNextIndex = nHiddenIndex+1;
1635  }
1636 
1637  sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1638  if( nEndIndex >= nNextIndex )
1639  {
1640  sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1641  if(nRepeat>1)
1643  OUString::number( nRepeat ));
1645  }
1646  }
1647 
1648  // export rows with content
1649  //export header row
1650  {
1653 
1654  //first one empty cell for the row descriptions
1655  {
1656  SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1657  SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, true, true );
1658  }
1659 
1660  //export column descriptions
1661  tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1662  const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1663  const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1664  sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1665  sal_Int32 nC = 0;
1666  for( const auto& rDesc : aData.aColumnDescriptions )
1667  {
1668  bool bExportString = true;
1669  if( nC < nComplexCount )
1670  {
1671  const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1672  if( rComplexLabel.hasElements() )
1673  {
1674  double fValue=0.0;
1675  if( rComplexLabel[0] >>=fValue )
1676  {
1677  bExportString = false;
1678 
1680  msStringBuffer, fValue);
1681  msString = msStringBuffer.makeStringAndClear();
1684  }
1685  }
1686  }
1687  if( bExportString )
1688  {
1690  }
1691 
1693  exportText( rDesc );
1694  if( nC < nComplexCount )
1695  lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1696  if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1697  {
1698  // remind the original range to allow a correct re-association when copying via clipboard
1699  if (!(*aColumnDescriptions_RangeIter).isEmpty())
1700  SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1701  ++aColumnDescriptions_RangeIter;
1702  }
1703 
1704  nC++;
1705  }
1706  SAL_WARN_IF( !bHasOwnData && (aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd" );
1707  } // closing row and header-rows elements
1708 
1709  // export value rows
1710  {
1712  tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1713  const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1714  sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1715  sal_Int32 nC = 0;
1716 
1717  for( const auto& rRow : aData.aDataInRows )
1718  {
1720 
1721  //export row descriptions
1722  {
1723  bool bExportString = true;
1724  if( nC < nComplexCount )
1725  {
1726  const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1727  if( rComplexLabel.hasElements() )
1728  {
1729  double fValue=0.0;
1730  if( rComplexLabel[0] >>=fValue )
1731  {
1732  bExportString = false;
1733 
1735  msString = msStringBuffer.makeStringAndClear();
1738  }
1739  }
1740  }
1741  if( bExportString )
1742  {
1744  }
1745 
1747  if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1748  {
1749  exportText( *aRowDescriptionsIter );
1750  if( nC < nComplexCount )
1751  lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1752  if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1753  {
1754  // remind the original range to allow a correct re-association when copying via clipboard
1755  SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1756  ++aRowDescriptions_RangeIter;
1757  }
1758  ++aRowDescriptionsIter;
1759  }
1760  }
1761 
1762  //export row values
1763  for( t2DNumberContainer::value_type::const_iterator aColIt( rRow.begin());
1764  aColIt != rRow.end(); ++aColIt )
1765  {
1767  msString = msStringBuffer.makeStringAndClear();
1771  exportText( msString ); // do not convert tabs and lfs
1772  if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1773  ( mbRowSourceColumns || (aColIt == rRow.begin()) ) )
1774  {
1775  // remind the original range to allow a correct re-association when copying via clipboard
1776  if (!(*aDataRangeIter).isEmpty())
1777  SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1778  ++aDataRangeIter;
1779  }
1780  }
1781 
1782  ++nC;
1783  }
1784  }
1785 
1786  // if range iterator was used it should have reached its end
1787  SAL_WARN_IF( !bHasOwnData && (aDataRangeIter != aDataRangeEndIter), "xmloff.chart", "bHasOwnData == false && aDataRangeIter != aDataRangeEndIter" );
1788  SAL_WARN_IF( !bHasOwnData && (aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd" );
1789 }
1790 
1791 namespace
1792 {
1793 
1794 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1795 {
1796  Reference< chart2::XCoordinateSystem > xCooSys;
1797  Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1798  if(xCooSysCnt.is())
1799  {
1800  Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1801  if(aCooSysSeq.hasElements())
1802  xCooSys = aCooSysSeq[0];
1803  }
1804  return xCooSys;
1805 }
1806 
1807 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1808  enum XMLTokenEnum eDimension, bool bPrimary=true )
1809 {
1810  Reference< chart2::XAxis > xNewAxis;
1811  try
1812  {
1813  if( xCooSys.is() )
1814  {
1815  sal_Int32 nDimensionIndex=0;
1816  switch( eDimension )
1817  {
1818  case XML_X:
1819  nDimensionIndex=0;
1820  break;
1821  case XML_Y:
1822  nDimensionIndex=1;
1823  break;
1824  case XML_Z:
1825  nDimensionIndex=2;
1826  break;
1827  default:
1828  break;
1829  }
1830 
1831  xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1832  }
1833  }
1834  catch( const uno::Exception & )
1835  {
1836  }
1837  return xNewAxis;
1838 }
1839 
1840 }
1841 
1843  const Reference< chart::XDiagram >& xDiagram,
1844  const Reference< chart2::XDiagram >& xNewDiagram,
1845  const awt::Size & rPageSize,
1846  bool bExportContent,
1847  bool bIncludeTable )
1848 {
1849  SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
1850  if( ! xDiagram.is())
1851  return;
1852 
1853  // variables for autostyles
1855  std::vector< XMLPropertyState > aPropertyStates;
1856 
1857  msStringBuffer.setLength( 0 );
1858 
1859  // plot-area element
1860 
1861  std::unique_ptr<SvXMLElementExport> xElPlotArea;
1862  // get property states for autostyles
1863  xPropSet.set( xDiagram, uno::UNO_QUERY );
1864  if( xPropSet.is())
1865  {
1866  if( mxExpPropMapper.is())
1867  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1868  }
1869  if( bExportContent )
1870  {
1871  rtl::Reference< XMLShapeExport > rShapeExport;
1872 
1873  // write style name
1874  AddAutoStyleAttribute( aPropertyStates );
1875 
1876  if( !msChartAddress.isEmpty() )
1877  {
1878  if( !bIncludeTable )
1880 
1881  Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
1882  if( xDoc.is() )
1883  {
1884  Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
1885  if( xDocProp.is())
1886  {
1887  Any aAny;
1888 
1889  try
1890  {
1891  bool bFirstCol = false, bFirstRow = false;
1892 
1893  aAny = xDocProp->getPropertyValue( "DataSourceLabelsInFirstColumn" );
1894  aAny >>= bFirstCol;
1895  aAny = xDocProp->getPropertyValue( "DataSourceLabelsInFirstRow" );
1896  aAny >>= bFirstRow;
1897 
1898  if( bFirstCol || bFirstRow )
1899  {
1902  ( bFirstCol
1903  ? ( bFirstRow
1907  }
1908  }
1909  catch( const beans::UnknownPropertyException & )
1910  {
1911  SAL_WARN("xmloff.chart", "Properties missing" );
1912  }
1913  }
1914  }
1915  }
1916 
1917  // attributes
1918  if( xDiagram.is())
1919  {
1920  addPosition( xDiagram );
1921  addSize( xDiagram );
1922  }
1923 
1924  bool bIs3DChart = false;
1925 
1926  if( xPropSet.is())
1927  {
1928  Any aAny;
1929 
1930  // 3d attributes
1931  try
1932  {
1933  aAny = xPropSet->getPropertyValue("Dim3D");
1934  aAny >>= bIs3DChart;
1935 
1936  if( bIs3DChart )
1937  {
1938  rShapeExport = mrExport.GetShapeExport();
1939  if( rShapeExport.is())
1940  rShapeExport->export3DSceneAttributes( xPropSet );
1941  }
1942  }
1943  catch( const uno::Exception & )
1944  {
1945  TOOLS_INFO_EXCEPTION("xmloff.chart", "chart:exportPlotAreaException caught");
1946  }
1947  }
1948 
1949  // plot-area element
1950  xElPlotArea.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, true, true ));
1951 
1952  //inner position rectangle element
1953  exportCoordinateRegion( xDiagram );
1954 
1955  // light sources (inside plot area element)
1956  if( bIs3DChart &&
1957  rShapeExport.is())
1958  rShapeExport->export3DLamps( xPropSet );
1959  }
1960  else // autostyles
1961  {
1962  CollectAutoStyle( aPropertyStates );
1963  }
1964  // remove property states for autostyles
1965  aPropertyStates.clear();
1966 
1967  // axis elements
1968  exportAxes( xDiagram, xNewDiagram, bExportContent );
1969 
1970  // series elements
1971  Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
1972  exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
1973 
1974  // stock-chart elements
1975  OUString sChartType ( xDiagram->getDiagramType());
1976  if( sChartType == "com.sun.star.chart.StockDiagram" )
1977  {
1978  Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
1979  if( xStockPropProvider.is())
1980  {
1981  // stock-gain-marker
1982  Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
1983  if( xStockPropSet.is())
1984  {
1985  aPropertyStates.clear();
1986  aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
1987 
1988  if( !aPropertyStates.empty() )
1989  {
1990  if( bExportContent )
1991  {
1992  AddAutoStyleAttribute( aPropertyStates );
1993 
1995  }
1996  else
1997  {
1998  CollectAutoStyle( aPropertyStates );
1999  }
2000  }
2001  }
2002 
2003  // stock-loss-marker
2004  xStockPropSet = xStockPropProvider->getDownBar();
2005  if( xStockPropSet.is())
2006  {
2007  aPropertyStates.clear();
2008  aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2009 
2010  if( !aPropertyStates.empty() )
2011  {
2012  if( bExportContent )
2013  {
2014  AddAutoStyleAttribute( aPropertyStates );
2015 
2017  }
2018  else
2019  {
2020  CollectAutoStyle( aPropertyStates );
2021  }
2022  }
2023  }
2024 
2025  // stock-range-line
2026  xStockPropSet = xStockPropProvider->getMinMaxLine();
2027  if( xStockPropSet.is())
2028  {
2029  aPropertyStates.clear();
2030  aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2031 
2032  if( !aPropertyStates.empty() )
2033  {
2034  if( bExportContent )
2035  {
2036  AddAutoStyleAttribute( aPropertyStates );
2037 
2039  }
2040  else
2041  {
2042  CollectAutoStyle( aPropertyStates );
2043  }
2044  }
2045  }
2046  }
2047  }
2048 
2049  // wall and floor element
2050  Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2051  if( !(mxExpPropMapper.is() &&
2052  xWallFloorSupplier.is()))
2053  return;
2054 
2055  // remove property states for autostyles
2056  aPropertyStates.clear();
2057 
2058  Reference< beans::XPropertySet > xWallPropSet = xWallFloorSupplier->getWall();
2059  if( xWallPropSet.is())
2060  {
2061  aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2062 
2063  if( !aPropertyStates.empty() )
2064  {
2065  // write element
2066  if( bExportContent )
2067  {
2068  // add style name attribute
2069  AddAutoStyleAttribute( aPropertyStates );
2070 
2072  }
2073  else // autostyles
2074  {
2075  CollectAutoStyle( aPropertyStates );
2076  }
2077  }
2078  }
2079 
2080  // floor element
2081  // remove property states for autostyles
2082  aPropertyStates.clear();
2083 
2084  Reference< beans::XPropertySet > xFloorPropSet = xWallFloorSupplier->getFloor();
2085  if( !xFloorPropSet.is())
2086  return;
2087 
2088  aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2089 
2090  if( aPropertyStates.empty() )
2091  return;
2092 
2093  // write element
2094  if( bExportContent )
2095  {
2096  // add style name attribute
2097  AddAutoStyleAttribute( aPropertyStates );
2098 
2099  SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, true, true );
2100  }
2101  else // autostyles
2102  {
2103  CollectAutoStyle( aPropertyStates );
2104  }
2105 }
2106 
2107 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2108 {
2109  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2110  if (nCurrentODFVersion <= SvtSaveOptions::ODFSVER_012) //do not export to ODF 1.2 or older
2111  return;
2112 
2113  Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2114  SAL_WARN_IF( !xDiaPos.is(), "xmloff.chart", "Invalid xDiaPos as parameter" );
2115  if( !xDiaPos.is() )
2116  return;
2117 
2118  awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2119  addPosition( awt::Point(aRect.X,aRect.Y) );
2120  addSize( awt::Size(aRect.Width,aRect.Height) );
2121 
2122  // ODF 1.3 OFFICE-3928
2123  SvXMLElementExport aCoordinateRegion( mrExport,
2125  XML_COORDINATE_REGION, true, true );
2126 }
2127 
2128 namespace
2129 {
2130  XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2131  {
2133  switch( nTimeUnit )
2134  {
2135  case css::chart::TimeUnit::YEAR:
2136  eToken = XML_YEARS;
2137  break;
2138  case css::chart::TimeUnit::MONTH:
2139  eToken = XML_MONTHS;
2140  break;
2141  default://days
2142  break;
2143  }
2144  return eToken;
2145  }
2146 }
2147 
2149 {
2150  if( !rAxisProps.is() )
2151  return;
2152 
2153  chart::TimeIncrement aIncrement;
2154  if( !(rAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement) )
2155  return;
2156 
2157  sal_Int32 nTimeResolution = css::chart::TimeUnit::DAY;
2158  if( aIncrement.TimeResolution >>= nTimeResolution )
2159  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2160 
2161  chart::TimeInterval aInterval;
2162  if( aIncrement.MajorTimeInterval >>= aInterval )
2163  {
2164  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, OUString::number(aInterval.Number) );
2165  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2166  }
2167  if( aIncrement.MinorTimeInterval >>= aInterval )
2168  {
2169  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, OUString::number(aInterval.Number) );
2170  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2171  }
2172 
2173  SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, true, true );//#i25706#todo: change namespace for next ODF version
2174 }
2175 
2177 {
2178  if( !rTitleProps.is() )
2179  return;
2180  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rTitleProps );
2181  if( bExportContent )
2182  {
2183  OUString aText;
2184  Any aAny( rTitleProps->getPropertyValue( "String" ));
2185  aAny >>= aText;
2186 
2187  Reference< drawing::XShape > xShape( rTitleProps, uno::UNO_QUERY );
2188  if( xShape.is())
2189  addPosition( xShape );
2190 
2191  AddAutoStyleAttribute( aPropertyStates );
2192  SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
2193 
2194  // paragraph containing title
2195  exportText( aText );
2196  }
2197  else
2198  {
2199  CollectAutoStyle( aPropertyStates );
2200  }
2201  aPropertyStates.clear();
2202 }
2203 
2204 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent )
2205 {
2206  if( !rGridProperties.is() )
2207  return;
2208  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rGridProperties );
2209  if( bExportContent )
2210  {
2211  AddAutoStyleAttribute( aPropertyStates );
2214  }
2215  else
2216  {
2217  CollectAutoStyle( aPropertyStates );
2218  }
2219  aPropertyStates.clear();
2220 }
2221 
2222 namespace
2223 {
2224 
2225 //returns true if a date scale needs to be exported
2226 bool lcl_exportAxisType( const Reference< chart2::XAxis >& rChart2Axis, SvXMLExport& rExport)
2227 {
2228  bool bExportDateScale = false;
2229  if( !rChart2Axis.is() )
2230  return bExportDateScale;
2231 
2232  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2233  if ((nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) == 0) //do not export to ODF 1.3 or older
2234  return bExportDateScale;
2235 
2236  chart2::ScaleData aScale( rChart2Axis->getScaleData() );
2237  //#i25706#todo: change namespace for next ODF version
2238  sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2239 
2240  switch(aScale.AxisType)
2241  {
2242  case chart2::AxisType::CATEGORY:
2243  if( aScale.AutoDateAxis )
2244  {
2245  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2246  bExportDateScale = true;
2247  }
2248  else
2249  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2250  break;
2251  case chart2::AxisType::DATE:
2252  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2253  bExportDateScale = true;
2254  break;
2255  default: //AUTOMATIC
2256  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2257  break;
2258  }
2259 
2260  return bExportDateScale;
2261 }
2262 
2263 void disableLinkedNumberFormat(
2264  std::vector<XMLPropertyState>& rPropStates, const rtl::Reference<XMLPropertySetMapper>& rMapper )
2265 {
2266  for (XMLPropertyState & rState : rPropStates)
2267  {
2268  if (rState.mnIndex < 0 || rMapper->GetEntryCount() <= rState.mnIndex)
2269  continue;
2270 
2271  OUString aXMLName = rMapper->GetEntryXMLName(rState.mnIndex);
2272 
2273  if (aXMLName != "link-data-style-to-source")
2274  continue;
2275 
2276  // Entry found. Set the value to false and bail out.
2277  rState.maValue <<= false;
2278  return;
2279  }
2280 
2281  // Entry not found. Insert a new entry for this.
2282  sal_Int32 nIndex = rMapper->GetEntryIndex(XML_NAMESPACE_CHART, u"link-data-style-to-source", 0);
2283  XMLPropertyState aState(nIndex);
2284  aState.maValue <<= false;
2285  rPropStates.push_back(aState);
2286 }
2287 
2288 }
2289 
2291  enum XMLTokenEnum eDimension,
2292  enum XMLTokenEnum eAxisName,
2293  const Reference< beans::XPropertySet >& rAxisProps,
2294  const Reference< chart2::XAxis >& rChart2Axis,
2295  const OUString& rCategoriesRange,
2296  bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2297  bool bExportContent, std::u16string_view sChartType )
2298 {
2299  std::vector< XMLPropertyState > aPropertyStates;
2300  std::unique_ptr<SvXMLElementExport> pAxis;
2301 
2302  // get property states for autostyles
2303  if( rAxisProps.is() && mxExpPropMapper.is() )
2304  {
2305  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2306  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED
2307  && eDimension == XML_X)
2308  {
2309  chart2::ScaleData aScaleData(rChart2Axis->getScaleData());
2310  bool bShiftedCatPos = aScaleData.ShiftedCategoryPosition;
2311  if (sChartType == u"com.sun.star.chart.BarDiagram" || sChartType == u"com.sun.star.chart.StockDiagram")
2312  {
2313  if (!bShiftedCatPos)
2314  rAxisProps->setPropertyValue("MajorOrigin", uno::makeAny(0.0));
2315  }
2316  else if (bShiftedCatPos)
2317  rAxisProps->setPropertyValue("MajorOrigin", uno::makeAny(0.5));
2318  }
2319 
2320  lcl_exportNumberFormat( "NumberFormat", rAxisProps, mrExport );
2321  aPropertyStates = mxExpPropMapper->Filter( rAxisProps );
2322 
2323  if (!maSrcShellID.isEmpty() && !maDestShellID.isEmpty() && maSrcShellID != maDestShellID)
2324  {
2325  // Disable link to source number format property when pasting to
2326  // a different doc shell. These shell ID's should be both empty
2327  // during real ODF export.
2328  disableLinkedNumberFormat(aPropertyStates, mxExpPropMapper->getPropertySetMapper());
2329  }
2330  }
2331 
2332  bool bExportDateScale = false;
2333  if( bExportContent )
2334  {
2337  AddAutoStyleAttribute( aPropertyStates ); // write style name
2338  if( !rCategoriesRange.isEmpty() )
2339  bExportDateScale = lcl_exportAxisType( rChart2Axis, mrExport );
2340 
2341  // open axis element
2342  pAxis.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, true, true ));
2343  }
2344  else
2345  {
2346  CollectAutoStyle( aPropertyStates );
2347  }
2348  aPropertyStates.clear();
2349 
2350  //date scale
2351  if( bExportDateScale )
2352  exportDateScale( rAxisProps );
2353 
2355  Reference< beans::XPropertySet > xMajorGridProps;
2356  Reference< beans::XPropertySet > xMinorGridProps;
2357  Reference< chart::XAxis > xAxis( rAxisProps, uno::UNO_QUERY );
2358  if( xAxis.is() )
2359  {
2360  xTitleProps = bHasTitle ? xAxis->getAxisTitle() : nullptr;
2361  xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : nullptr;
2362  xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : nullptr;
2363  }
2364 
2365  // axis-title
2366  exportAxisTitle( xTitleProps , bExportContent );
2367 
2368  // categories if we have a categories chart
2369  if( bExportContent && !rCategoriesRange.isEmpty() )
2370  {
2372  SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, true, true );
2373  }
2374 
2375  // grid
2376  exportGrid( xMajorGridProps, true, bExportContent );
2377  exportGrid( xMinorGridProps, false, bExportContent );
2378 }
2379 
2381  const Reference< chart::XDiagram > & xDiagram,
2382  const Reference< chart2::XDiagram > & xNewDiagram,
2383  bool bExportContent )
2384 {
2385  SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
2386  if( ! xDiagram.is())
2387  return;
2388 
2389  // get some properties from document first
2390  bool bHasXAxis = false,
2391  bHasYAxis = false,
2392  bHasZAxis = false,
2393  bHasSecondaryXAxis = false,
2394  bHasSecondaryYAxis = false;
2395  bool bHasXAxisTitle = false,
2396  bHasYAxisTitle = false,
2397  bHasZAxisTitle = false,
2398  bHasSecondaryXAxisTitle = false,
2399  bHasSecondaryYAxisTitle = false;
2400  bool bHasXAxisMajorGrid = false,
2401  bHasXAxisMinorGrid = false,
2402  bHasYAxisMajorGrid = false,
2403  bHasYAxisMinorGrid = false,
2404  bHasZAxisMajorGrid = false,
2405  bHasZAxisMinorGrid = false;
2406 
2407  // get multiple properties using XMultiPropertySet
2408  MultiPropertySetHandler aDiagramProperties (xDiagram);
2409 
2410  aDiagramProperties.Add ("HasXAxis", bHasXAxis);
2411  aDiagramProperties.Add ("HasYAxis", bHasYAxis);
2412  aDiagramProperties.Add ("HasZAxis", bHasZAxis);
2413  aDiagramProperties.Add ("HasSecondaryXAxis", bHasSecondaryXAxis);
2414  aDiagramProperties.Add ("HasSecondaryYAxis", bHasSecondaryYAxis);
2415 
2416  aDiagramProperties.Add ("HasXAxisTitle", bHasXAxisTitle);
2417  aDiagramProperties.Add ("HasYAxisTitle", bHasYAxisTitle);
2418  aDiagramProperties.Add ("HasZAxisTitle", bHasZAxisTitle);
2419  aDiagramProperties.Add ("HasSecondaryXAxisTitle", bHasSecondaryXAxisTitle);
2420  aDiagramProperties.Add ("HasSecondaryYAxisTitle", bHasSecondaryYAxisTitle);
2421 
2422  aDiagramProperties.Add ("HasXAxisGrid", bHasXAxisMajorGrid);
2423  aDiagramProperties.Add ("HasYAxisGrid", bHasYAxisMajorGrid);
2424  aDiagramProperties.Add ("HasZAxisGrid", bHasZAxisMajorGrid);
2425 
2426  aDiagramProperties.Add ("HasXAxisHelpGrid", bHasXAxisMinorGrid);
2427  aDiagramProperties.Add ("HasYAxisHelpGrid", bHasYAxisMinorGrid);
2428  aDiagramProperties.Add ("HasZAxisHelpGrid", bHasZAxisMinorGrid);
2429 
2430  if ( ! aDiagramProperties.GetProperties ())
2431  {
2432  SAL_INFO("xmloff.chart", "Required properties not found in Chart diagram");
2433  }
2434 
2435  Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2436 
2437  // write an axis element also if the axis itself is not visible, but a grid or a title
2438 
2439  OUString aCategoriesRange;
2440  Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2441  OUString sChartType = xDiagram->getDiagramType();
2442 
2443  // x axis
2444 
2445  Reference< css::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2446  if( xNewAxis.is() )
2447  {
2448  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : nullptr, uno::UNO_QUERY );
2449  if( mbHasCategoryLabels && bExportContent )
2450  {
2451  Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2452  if( xCategories.is() )
2453  {
2454  Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2455  if( xValues.is() )
2456  {
2457  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2458  maCategoriesRange = xValues->getSourceRangeRepresentation();
2459  aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2460  }
2461  }
2462  }
2463  exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent, sChartType );
2464  aCategoriesRange.clear();
2465  }
2466 
2467  // secondary x axis
2468 
2469  xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2470  if( xNewAxis.is() )
2471  {
2472  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : nullptr, uno::UNO_QUERY );
2473  exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent, sChartType );
2474  }
2475 
2476  // y axis
2477 
2478  xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2479  if( xNewAxis.is() )
2480  {
2481  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : nullptr, uno::UNO_QUERY );
2482  exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent, sChartType );
2483  }
2484 
2485  // secondary y axis
2486 
2487  xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2488  if( xNewAxis.is() )
2489  {
2490  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : nullptr, uno::UNO_QUERY );
2491  exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent, sChartType );
2492  }
2493 
2494  // z axis
2495 
2496  xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2497  if( xNewAxis.is() )
2498  {
2499  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : nullptr, uno::UNO_QUERY );
2500  exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent, sChartType );
2501  }
2502 }
2503 
2504 namespace
2505 {
2506  bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2507  {
2508  if( !xDataSequence.is() )
2509  return false;//have no data
2510 
2511  Sequence< uno::Any > aData;
2512  Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2513  if( xNumericalDataSequence.is() )
2514  {
2515  Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() );
2516  if (std::any_of(aDoubles.begin(), aDoubles.end(), [](double fDouble) { return !std::isnan( fDouble ); }))
2517  return false;//have double value
2518  }
2519  else
2520  {
2521  aData = xDataSequence->getData();
2522  double fDouble = 0.0;
2523  bool bHaveDouble = std::any_of(aData.begin(), aData.end(),
2524  [&fDouble](const uno::Any& rData) { return (rData >>= fDouble) && !std::isnan( fDouble ); });
2525  if (bHaveDouble)
2526  return false;//have double value
2527  }
2528  //no values found
2529 
2530  Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2531  if( xTextualDataSequence.is() )
2532  {
2533  uno::Sequence< OUString > aStrings( xTextualDataSequence->getTextualData() );
2534  if (std::any_of(aStrings.begin(), aStrings.end(), [](const OUString& rString) { return !rString.isEmpty(); }))
2535  return true;//have text
2536  }
2537  else
2538  {
2539  if( !aData.hasElements() )
2540  aData = xDataSequence->getData();
2541  OUString aString;
2542  bool bHaveText = std::any_of(aData.begin(), aData.end(),
2543  [&aString](const uno::Any& rData) { return (rData >>= aString) && !aString.isEmpty(); });
2544  if (bHaveText)
2545  return true;//have text
2546  }
2547  //no doubles and no texts
2548  return false;
2549  }
2550 
2551 // ODF has the line and fill properties in a <style:style> element, which is referenced by the
2552 // <chart:data-label> element. But LibreOffice has them as special label properties of the series
2553 // or point respectively. The following method generates ODF from internal API name.
2554 void lcl_createDataLabelProperties(
2555  std::vector<XMLPropertyState>& rDataLabelPropertyStates,
2556  const Reference<beans::XPropertySet>& xPropSet,
2557  const rtl::Reference<XMLChartExportPropertyMapper>& xExpPropMapper)
2558 {
2559  if (!xExpPropMapper.is() || !xPropSet.is())
2560  return;
2561 
2562  const uno::Reference<beans::XPropertySetInfo> xInfo(xPropSet->getPropertySetInfo());
2563  const uno::Reference<beans::XPropertyState> xPropState(xPropSet, uno::UNO_QUERY);
2564  const rtl::Reference<XMLPropertySetMapper>& rPropertySetMapper(
2565  xExpPropMapper->getPropertySetMapper());
2566  if (!xInfo.is() || !xPropState.is() || !rPropertySetMapper.is())
2567  return;
2568 
2569  struct API2ODFMapItem
2570  {
2571  OUString sAPIName;
2572  sal_uInt16 nNameSpace; // from include/xmloff/xmlnamespace.hxx
2573  OUString sLocalName;
2574  API2ODFMapItem(const OUString& sAPI, const sal_uInt16 nNS, const OUString& sLocal)
2575  : sAPIName(sAPI)
2576  , nNameSpace(nNS)
2577  , sLocalName(sLocal)
2578  {
2579  }
2580  };
2581 
2582  const API2ODFMapItem aLabelFoo2ODFArray[]
2583  = { API2ODFMapItem("LabelBorderStyle", XML_NAMESPACE_DRAW, "stroke"),
2584  API2ODFMapItem("LabelBorderWidth", XML_NAMESPACE_SVG, "stroke-width"),
2585  API2ODFMapItem("LabelBorderColor", XML_NAMESPACE_SVG, "stroke-color"),
2586  API2ODFMapItem("LabelBorderDashName", XML_NAMESPACE_DRAW, "stroke-dash"),
2587  API2ODFMapItem("LabelBorderTransparency", XML_NAMESPACE_SVG, "stroke-opacity"),
2588  API2ODFMapItem("LabelFillStyle", XML_NAMESPACE_DRAW, "fill"),
2589  API2ODFMapItem("LabelFillBackground", XML_NAMESPACE_DRAW, "fill-hatch-solid"),
2590  API2ODFMapItem("LabelFillHatchName", XML_NAMESPACE_DRAW, "fill-hatch-name"),
2591  API2ODFMapItem("LabelFillColor", XML_NAMESPACE_DRAW, "fill-color") };
2592 
2593  for (const auto& rIt : aLabelFoo2ODFArray)
2594  {
2595  if (!xInfo->hasPropertyByName(rIt.sAPIName)
2596  || xPropState->getPropertyState(rIt.sAPIName) != beans::PropertyState_DIRECT_VALUE)
2597  continue;
2598  sal_Int32 nTargetIndex
2599  = rPropertySetMapper->GetEntryIndex(rIt.nNameSpace, rIt.sLocalName, 0);
2600  if (nTargetIndex < 0)
2601  continue;
2602  XMLPropertyState aDataLabelStateItem(nTargetIndex,
2603  xPropSet->getPropertyValue(rIt.sAPIName));
2604  rDataLabelPropertyStates.emplace_back(aDataLabelStateItem);
2605  }
2606 }
2607 } // anonymous namespace
2608 
2610  const Reference< chart2::XDiagram > & xNewDiagram,
2611  const awt::Size & rPageSize,
2612  bool bExportContent,
2613  bool bHasTwoYAxes )
2614 {
2615  Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2616  if( ! xBCooSysCnt.is())
2617  return;
2618  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2619 
2620  OUString aFirstXDomainRange;
2621  OUString aFirstYDomainRange;
2622 
2623  std::vector< XMLPropertyState > aPropertyStates;
2624  std::vector< XMLPropertyState > aDataLabelPropertyStates;
2625 
2626  const Sequence< Reference< chart2::XCoordinateSystem > >
2627  aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2628  for( const auto& rCooSys : aCooSysSeq )
2629  {
2630  Reference< chart2::XChartTypeContainer > xCTCnt( rCooSys, uno::UNO_QUERY );
2631  if( ! xCTCnt.is())
2632  continue;
2633  const Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2634  for( const auto& rChartType : aCTSeq )
2635  {
2636  Reference< chart2::XDataSeriesContainer > xDSCnt( rChartType, uno::UNO_QUERY );
2637  if( ! xDSCnt.is())
2638  continue;
2639  // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2640  OUString aChartType( rChartType->getChartType());
2641  OUString aLabelRole = rChartType->getRoleOfSequenceForSeriesLabel();
2642 
2643  // special export for stock charts
2644  if ( aChartType == "com.sun.star.chart2.CandleStickChartType" )
2645  {
2646  bool bJapaneseCandleSticks = false;
2647  Reference< beans::XPropertySet > xCTProp( rChartType, uno::UNO_QUERY );
2648  if( xCTProp.is())
2649  xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
2651  xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2652  continue;
2653  }
2654 
2655  // export dataseries for current chart-type
2656  Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2657  for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2658  {
2659  // export series
2660  Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2661  if( xSource.is())
2662  {
2663  std::unique_ptr<SvXMLElementExport> pSeries;
2664  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2665  xSource->getDataSequences());
2666  sal_Int32 nMainSequenceIndex = -1;
2667  sal_Int32 nSeriesLength = 0;
2668  bool bHasMeanValueLine = false;
2670  tLabelValuesDataPair aSeriesLabelValuesPair;
2671 
2672  // search for main sequence and create a series element
2673  {
2674  Reference< chart2::data::XDataSequence > xValuesSeq;
2675  Reference< chart2::data::XDataSequence > xLabelSeq;
2676  sal_Int32 nSeqIdx=0;
2677  for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2678  {
2679  Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2680  if( nMainSequenceIndex==-1 )
2681  {
2682  OUString aRole;
2683  Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2684  if( xSeqProp.is())
2685  xSeqProp->getPropertyValue("Role") >>= aRole;
2686  // "main" sequence
2687  if( aRole == aLabelRole )
2688  {
2689  xValuesSeq.set( xTempValueSeq );
2690  xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2691  nMainSequenceIndex = nSeqIdx;
2692  }
2693  }
2694  sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2695  if( nSeriesLength < nSequenceLength )
2696  nSeriesLength = nSequenceLength;
2697  }
2698 
2699  // have found the main sequence, then xValuesSeq and
2700  // xLabelSeq contain those. Otherwise both are empty
2701  {
2702  sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2703  // get property states for autostyles
2704  try
2705  {
2707  aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2708  }
2709  catch( const uno::Exception & )
2710  {
2711  TOOLS_INFO_EXCEPTION("xmloff.chart", "Series not found or no XPropertySet" );
2712  continue;
2713  }
2714  if( xPropSet.is())
2715  {
2716  // determine attached axis
2717  try
2718  {
2719  Any aAny( xPropSet->getPropertyValue( "Axis" ));
2720  aAny >>= nAttachedAxis;
2721 
2722  aAny = xPropSet->getPropertyValue( "MeanValue" );
2723  aAny >>= bHasMeanValueLine;
2724  }
2725  catch( const beans::UnknownPropertyException & )
2726  {
2727  TOOLS_INFO_EXCEPTION("xmloff.chart", "Required property not found in DataRowProperties" );
2728  }
2729 
2730  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2731  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
2732  {
2733  lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
2734  lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
2735  }
2736 
2737  if( mxExpPropMapper.is())
2738  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2739  }
2740 
2741  if( bExportContent )
2742  {
2743  if( bHasTwoYAxes )
2744  {
2745  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2747  else
2749  }
2750 
2751  // write style name
2752  AddAutoStyleAttribute( aPropertyStates );
2753 
2754  if( xValuesSeq.is())
2756  lcl_ConvertRange(
2757  xValuesSeq->getSourceRangeRepresentation(),
2758  xNewDoc ));
2759  else
2760  // #i75297# allow empty series, export empty range to have all ranges on import
2762 
2763  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2764  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) // do not export to ODF 1.3 or older
2765  {
2766  if (xPropSet.is())
2767  {
2768  Any aAny = xPropSet->getPropertyValue("ShowLegendEntry");
2769  if (!aAny.get<bool>())
2770  {
2771  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDE_LEGEND, OUString::boolean(true));
2772  }
2773  }
2774  }
2775 
2776  if (xLabelSeq.is())
2777  {
2778  // Check if the label is direct string value rather than a reference.
2779  bool bHasString = false;
2780  uno::Reference<beans::XPropertySet> xLSProp(xLabelSeq, uno::UNO_QUERY);
2781  if (xLSProp.is())
2782  {
2783  try
2784  {
2785  xLSProp->getPropertyValue("HasStringLabel") >>= bHasString;
2786  }
2787  catch (const beans::UnknownPropertyException&) {}
2788  }
2789 
2790  OUString aRange = xLabelSeq->getSourceRangeRepresentation();
2791 
2792  if (bHasString)
2793  {
2796  }
2797  else
2798  {
2801  lcl_ConvertRange(
2802  xLabelSeq->getSourceRangeRepresentation(), xNewDoc));
2803  }
2804  }
2805 
2806  if( xLabelSeq.is() || xValuesSeq.is() )
2807  aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2808 
2809  // chart-type for mixed types
2810  enum XMLTokenEnum eCTToken(
2811  SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2812  //@todo: get token for current charttype
2815  XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2816 
2817  // open series element until end of for loop
2818  pSeries.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true ));
2819  }
2820  else // autostyles
2821  {
2822  CollectAutoStyle( aPropertyStates );
2823  }
2824  // remove property states for autostyles
2825  aPropertyStates.clear();
2826  }
2827  }
2828 
2829  // export domain elements if we have a series parent element
2830  if( pSeries )
2831  {
2832  // domain elements
2833  if( bExportContent )
2834  {
2835  bool bIsScatterChart = aChartType == "com.sun.star.chart2.ScatterChartType";
2836  bool bIsBubbleChart = aChartType == "com.sun.star.chart2.BubbleChartType";
2837  Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2838  if( bIsBubbleChart )
2839  {
2840  Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, "values-y" ) );
2841  if( xSequence.is() )
2842  {
2843  xYValuesForBubbleChart = xSequence->getValues();
2844  if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2845  xYValuesForBubbleChart = nullptr;
2846  }
2847  }
2848  if( bIsScatterChart || bIsBubbleChart )
2849  {
2850  Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, "values-x" ) );
2851  if( xSequence.is() )
2852  {
2853  Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2854  if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2855  m_aDataSequencesToExport.emplace_back(
2856  uno::Reference< chart2::data::XDataSequence >(), xValues );
2857  }
2858  else if( nSeriesIdx==0 )
2859  {
2860  //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2861  Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2862  if( xCategories.is() )
2863  {
2864  Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2865  if( !lcl_hasNoValuesButText( xValues ) )
2866  lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2867  }
2868  }
2869  }
2870  if( xYValuesForBubbleChart.is() )
2871  m_aDataSequencesToExport.emplace_back(
2872  uno::Reference< chart2::data::XDataSequence >(), xYValuesForBubbleChart );
2873  }
2874  }
2875 
2876  // add sequences for main sequence after domain sequences,
2877  // so that the export of the local table has the correct order
2878  if( bExportContent &&
2879  (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2880  m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2881 
2882  // statistical objects:
2883  // regression curves and mean value lines
2884  if( bHasMeanValueLine &&
2885  xPropSet.is() &&
2886  mxExpPropMapper.is() )
2887  {
2889  try
2890  {
2891  Any aPropAny( xPropSet->getPropertyValue( "DataMeanValueProperties" ));
2892  aPropAny >>= xStatProp;
2893  }
2894  catch( const uno::Exception & )
2895  {
2896  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during Export of series - optional DataMeanValueProperties not available" );
2897  }
2898 
2899  if( xStatProp.is() )
2900  {
2901  aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2902 
2903  if( !aPropertyStates.empty() )
2904  {
2905  // write element
2906  if( bExportContent )
2907  {
2908  // add style name attribute
2909  AddAutoStyleAttribute( aPropertyStates );
2910 
2912  }
2913  else // autostyles
2914  {
2915  CollectAutoStyle( aPropertyStates );
2916  }
2917  }
2918  }
2919  }
2920 
2921  if( xPropSet.is() &&
2922  mxExpPropMapper.is() )
2923  {
2924  exportRegressionCurve( aSeriesSeq[nSeriesIdx], rPageSize, bExportContent );
2925  }
2926 
2927  exportErrorBar( xPropSet,false, bExportContent ); // X ErrorBar
2928  exportErrorBar( xPropSet,true, bExportContent ); // Y ErrorBar
2929 
2931  uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
2932  nSeriesLength, xNewDiagram, bExportContent );
2933 
2934  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2935 
2936  // create <chart:data-label> child element if needed.
2937  if (xPropSet.is() && mxExpPropMapper.is())
2938  {
2939  // Generate style for <chart:data-label> child element
2940  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
2941  {
2942  lcl_createDataLabelProperties(aDataLabelPropertyStates, xPropSet,
2943  mxExpPropMapper);
2944  }
2945  }
2946  if (bExportContent)
2947  {
2948  if (!aDataLabelPropertyStates.empty())
2949  {
2950  // write style name
2951  AddAutoStyleAttribute(aDataLabelPropertyStates);
2952  // Further content does currently not exist for a <chart:data-label>
2953  // element as child of a <chart:series>.
2955  true);
2956  }
2957  }
2958  else
2959  {
2960  // add the style for the to be <chart:data-label> too
2961  if (!aDataLabelPropertyStates.empty())
2962  CollectAutoStyle(aDataLabelPropertyStates);
2963  }
2964  aDataLabelPropertyStates.clear();
2965 
2966  if (bExportContent && nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) // do not export to ODF 1.3 or older
2967  {
2968  Sequence< OUString > aSupportedMappings = rChartType->getSupportedPropertyRoles();
2969  exportPropertyMapping( xSource, aSupportedMappings );
2970  }
2971 
2972  // close series element
2973  pSeries.reset();
2974  }
2975  }
2976  aPropertyStates.clear();
2977  aDataLabelPropertyStates.clear();
2978  }
2979  }
2980 }
2981 
2983  const Reference< chart2::data::XDataSource > & xSource, const Sequence< OUString >& rSupportedMappings )
2984 {
2985  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2986  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2987  xSource->getDataSequences());
2988 
2989  for(const auto& rSupportedMapping : rSupportedMappings)
2990  {
2991  Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, rSupportedMapping ) );
2992  if(xSequence.is())
2993  {
2994  Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2995  if( xValues.is())
2996  {
2999  lcl_ConvertRange(
3000  xValues->getSourceRangeRepresentation(),
3001  xNewDoc ));
3003 
3004  // register range for data table export
3005  m_aDataSequencesToExport.emplace_back(
3006  uno::Reference< chart2::data::XDataSequence >(), xValues );
3007  }
3008  }
3009  }
3010 }
3011 
3013  const Reference< chart2::XDataSeries >& xSeries,
3014  const awt::Size& rPageSize,
3015  bool bExportContent )
3016 {
3017  OSL_ASSERT( mxExpPropMapper.is());
3018 
3019  Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, uno::UNO_QUERY );
3020  if( !xRegressionCurveContainer.is() )
3021  return;
3022 
3023  const Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
3024 
3025  for( const auto& xRegCurve : aRegCurveSeq )
3026  {
3027  std::vector< XMLPropertyState > aEquationPropertyStates;
3028  if (!xRegCurve.is())
3029  continue;
3030 
3031  Reference< beans::XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
3032  if( !xProperties.is() )
3033  continue;
3034 
3035  Reference< lang::XServiceName > xServiceName( xProperties, uno::UNO_QUERY );
3036  if( !xServiceName.is() )
3037  continue;
3038 
3039  bool bShowEquation = false;
3040  bool bShowRSquared = false;
3041  bool bExportEquation = false;
3042 
3043  OUString aService = xServiceName->getServiceName();
3044 
3045  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xProperties );
3046 
3047  // Add service name (which is regression type)
3048  sal_Int32 nIndex = GetPropertySetMapper()->FindEntryIndex(XML_SCH_CONTEXT_SPECIAL_REGRESSION_TYPE);
3049  XMLPropertyState property(nIndex, uno::makeAny(aService));
3050  aPropertyStates.push_back(property);
3051 
3052  Reference< beans::XPropertySet > xEquationProperties;
3053  xEquationProperties.set( xRegCurve->getEquationProperties() );
3054  if( xEquationProperties.is())
3055  {
3056  xEquationProperties->getPropertyValue( "ShowEquation") >>= bShowEquation;
3057  xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowRSquared;
3058 
3059  bExportEquation = ( bShowEquation || bShowRSquared );
3060  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3061  if (nCurrentVersion < SvtSaveOptions::ODFSVER_012)
3062  {
3063  bExportEquation=false;
3064  }
3065  if( bExportEquation )
3066  {
3067  // number format
3068  sal_Int32 nNumberFormat = 0;
3069  if( (xEquationProperties->getPropertyValue("NumberFormat") >>= nNumberFormat ) &&
3070  nNumberFormat != -1 )
3071  {
3072  mrExport.addDataStyle( nNumberFormat );
3073  }
3074  aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
3075  }
3076  }
3077 
3078  if( !aPropertyStates.empty() || bExportEquation )
3079  {
3080  // write element
3081  if( bExportContent )
3082  {
3083  // add style name attribute
3084  if( !aPropertyStates.empty())
3085  {
3086  AddAutoStyleAttribute( aPropertyStates );
3087  }
3088 
3089  SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, true, true );
3090  if( bExportEquation )
3091  {
3093  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, (bShowRSquared ? XML_TRUE : XML_FALSE) );
3094 
3095  // export position
3096  chart2::RelativePosition aRelativePosition;
3097  if( xEquationProperties->getPropertyValue( "RelativePosition" ) >>= aRelativePosition )
3098  {
3099  double fX = aRelativePosition.Primary * rPageSize.Width;
3100  double fY = aRelativePosition.Secondary * rPageSize.Height;
3101  awt::Point aPos;
3102  aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3103  aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3104  addPosition( aPos );
3105  }
3106 
3107  if( !aEquationPropertyStates.empty())
3108  {
3109  AddAutoStyleAttribute( aEquationPropertyStates );
3110  }
3111 
3113  }
3114  }
3115  else // autostyles
3116  {
3117  if( !aPropertyStates.empty())
3118  {
3119  CollectAutoStyle( aPropertyStates );
3120  }
3121  if( bExportEquation && !aEquationPropertyStates.empty())
3122  {
3123  CollectAutoStyle( aEquationPropertyStates );
3124  }
3125  }
3126  }
3127  }
3128 }
3129 
3131  bool bYError, bool bExportContent )
3132 {
3133  assert(mxExpPropMapper.is());
3134 
3135  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3136 
3138  if (!bYError && nCurrentVersion < SvtSaveOptions::ODFSVER_012)
3139  return;
3140 
3141  if (!xSeriesProp.is())
3142  return;
3143 
3144  bool bNegative = false, bPositive = false;
3145  sal_Int32 nErrorBarStyle = chart::ErrorBarStyle::NONE;
3146  Reference< beans::XPropertySet > xErrorBarProp;
3147 
3148  try
3149  {
3150  Any aAny = xSeriesProp->getPropertyValue( bYError ? OUString("ErrorBarY") : OUString("ErrorBarX") );
3151  aAny >>= xErrorBarProp;
3152 
3153  if ( xErrorBarProp.is() )
3154  {
3155  aAny = xErrorBarProp->getPropertyValue("ShowNegativeError" );
3156  aAny >>= bNegative;
3157 
3158  aAny = xErrorBarProp->getPropertyValue("ShowPositiveError" );
3159  aAny >>= bPositive;
3160 
3161  aAny = xErrorBarProp->getPropertyValue("ErrorBarStyle" );
3162  aAny >>= nErrorBarStyle;
3163  }
3164  }
3165  catch( const beans::UnknownPropertyException & )
3166  {
3167  TOOLS_INFO_EXCEPTION("xmloff.chart", "Required property not found in DataRowProperties" );
3168  }
3169 
3170  if( !(nErrorBarStyle != chart::ErrorBarStyle::NONE && (bNegative || bPositive)))
3171  return;
3172 
3173  if( bExportContent && nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3174  {
3175  // register data ranges for error bars for export in local table
3176  ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3177  lcl_getErrorBarSequences( xErrorBarProp ));
3178  for( const auto& rErrorBarSequence : aErrorBarSequences )
3179  {
3180  m_aDataSequencesToExport.emplace_back(
3181  uno::Reference< chart2::data::XDataSequence >(), rErrorBarSequence );
3182  }
3183  }
3184 
3185  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xErrorBarProp );
3186 
3187  if( aPropertyStates.empty() )
3188  return;
3189 
3190  // write element
3191  if( bExportContent )
3192  {
3193  // add style name attribute
3194  AddAutoStyleAttribute( aPropertyStates );
3195 
3196  if (nCurrentVersion >= SvtSaveOptions::ODFSVER_012)
3197  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, bYError ? XML_Y : XML_X );//#i114149#
3199  }
3200  else // autostyles
3201  {
3202  CollectAutoStyle( aPropertyStates );
3203  }
3204 }
3205 
3207  const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3208  const Reference< chart2::XDiagram > & xDiagram,
3209  bool bJapaneseCandleSticks,
3210  bool bExportContent )
3211 {
3212 
3213  for( const auto& xSeries : aSeriesSeq )
3214  {
3215  sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3216  ? chart::ChartAxisAssign::PRIMARY_Y
3217  : chart::ChartAxisAssign::SECONDARY_Y;
3218 
3219  Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3220  if( xSource.is())
3221  {
3222  // export series in correct order (as we don't store roles)
3223  // with japanese candlesticks: open, low, high, close
3224  // otherwise: low, high, close
3225  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3226  xSource->getDataSequences());
3227 
3228  sal_Int32 nSeriesLength =
3229  lcl_getSequenceLengthByRole( aSeqCnt, "values-last");
3230 
3231  if( bExportContent )
3232  {
3233  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3234  //@todo: export data points
3235 
3236  //TODO: moggi: same code three times
3237  // open
3238  if( bJapaneseCandleSticks )
3239  {
3240  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3241  aSeqCnt, "values-first", xNewDoc, m_aDataSequencesToExport ));
3242  if( !aRanges.second.isEmpty())
3244  if( !aRanges.first.isEmpty())
3246  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3248  else
3250  SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3251  // export empty data points
3252  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3253  }
3254 
3255  // low
3256  {
3257  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3258  aSeqCnt, "values-min", xNewDoc, m_aDataSequencesToExport ));
3259  if( !aRanges.second.isEmpty())
3261  if( !aRanges.first.isEmpty())
3263  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3265  else
3267  SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3268  // export empty data points
3269  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3270  }
3271 
3272  // high
3273  {
3274  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3275  aSeqCnt, "values-max", xNewDoc, m_aDataSequencesToExport ));
3276  if( !aRanges.second.isEmpty())
3278  if( !aRanges.first.isEmpty())
3280  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3282  else
3284  SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3285  // export empty data points
3286  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3287  }
3288 
3289  // close
3290  {
3291  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3292  aSeqCnt, "values-last", xNewDoc, m_aDataSequencesToExport ));
3293  if( !aRanges.second.isEmpty())
3295  if( !aRanges.first.isEmpty())
3297  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3299  else
3301  SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3302  // export empty data points
3303  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3304  }
3305  }
3306  else // autostyles
3307  {
3308  // for close series
3309  }
3310  // remove property states for autostyles
3311  }
3312  }
3313 }
3314 
3316  const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3317  sal_Int32 nSeriesLength,
3318  const uno::Reference< chart2::XDiagram > & xDiagram,
3319  bool bExportContent )
3320 {
3321  // data-points
3322 
3323  // write data-points only if they contain autostyles
3324  // objects with equal autostyles are grouped using the attribute
3325  // repeat="number"
3326 
3327  // Note: if only the nth data-point has autostyles there is an element
3328  // without style and repeat="n-1" attribute written in advance.
3329 
3330  // the sequence aDataPointSeq contains indices of data-points that
3331  // do have own attributes. This increases the performance substantially.
3332 
3333  // more performant version for #93600#
3334  if (!mxExpPropMapper.is())
3335  return;
3336 
3337  uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3338 
3339  std::vector< XMLPropertyState > aPropertyStates;
3340  std::vector<XMLPropertyState> aDataLabelPropertyStates;
3341 
3342  bool bVaryColorsByPoint = false;
3343  Sequence< sal_Int32 > aDataPointSeq;
3344  Sequence<sal_Int32> deletedLegendEntriesSeq;
3345  if( xSeriesProperties.is())
3346  {
3347  xSeriesProperties->getPropertyValue("AttributedDataPoints") >>= aDataPointSeq;
3348  xSeriesProperties->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint;
3349 
3350  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3351  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) // do not export to ODF 1.3 or older
3352  xSeriesProperties->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq;
3353  }
3354 
3355  sal_Int32 nSize = aDataPointSeq.getLength();
3356  SAL_WARN_IF( nSize > nSeriesLength, "xmloff.chart", "Too many point attributes" );
3357 
3358  const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3359  sal_Int32 nElement;
3360  Reference< chart2::XColorScheme > xColorScheme;
3361  if( xDiagram.is())
3362  xColorScheme.set( xDiagram->getDefaultColorScheme());
3363 
3364  ::std::vector< SchXMLDataPointStruct > aDataPointVector;
3365 
3366  sal_Int32 nLastIndex = -1;
3367 
3368  // collect elements
3369  if( bVaryColorsByPoint && xColorScheme.is() )
3370  {
3371  o3tl::sorted_vector< sal_Int32 > aAttrPointSet;
3372  aAttrPointSet.reserve(aDataPointSeq.getLength());
3373  for (auto p = pPoints; p < pPoints + aDataPointSeq.getLength(); ++p)
3374  aAttrPointSet.insert( *p );
3375  const auto aEndIt = aAttrPointSet.end();
3376  for( nElement = 0; nElement < nSeriesLength; ++nElement )
3377  {
3378  aPropertyStates.clear();
3379  aDataLabelPropertyStates.clear();
3380  uno::Reference< beans::XPropertySet > xPropSet;
3381  bool bExportNumFmt = false;
3382  if( aAttrPointSet.find( nElement ) != aEndIt )
3383  {
3384  try
3385  {
3387  xSeries, nElement, mrExport.GetModel() );
3388  bExportNumFmt = true;
3389  }
3390  catch( const uno::Exception & )
3391  {
3392  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during Export of data point" );
3393  }
3394  }
3395  else
3396  {
3397  // property set only containing the color
3398  xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3399  ::Color(ColorTransparency, xColorScheme->getColorByIndex( nElement ))));
3400  }
3401  SAL_WARN_IF( !xPropSet.is(), "xmloff.chart", "Pie Segments should have properties" );
3402  if( xPropSet.is())
3403  {
3404  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3405  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012 && bExportNumFmt)
3406  {
3407  lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3408  lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3409  }
3410 
3411  // Generate style for <chart:data-label> child element
3412  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
3413  {
3414  lcl_createDataLabelProperties(aDataLabelPropertyStates, xPropSet,
3415  mxExpPropMapper);
3416  }
3417 
3418  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED)
3419  {
3420  sal_Int32 nPlacement = 0;
3421  xPropSet->getPropertyValue("LabelPlacement") >>= nPlacement;
3422  if (nPlacement == chart::DataLabelPlacement::CUSTOM)
3423  {
3424  xPropSet->setPropertyValue("LabelPlacement",
3425  uno::Any(chart::DataLabelPlacement::OUTSIDE));
3426  }
3427  }
3428 
3429  aPropertyStates = mxExpPropMapper->Filter(xPropSet);
3430  if (!aPropertyStates.empty() || !aDataLabelPropertyStates.empty())
3431  {
3432  if (bExportContent)
3433  {
3434  // write data-point with style
3435  SchXMLDataPointStruct aPoint;
3436  if (!aPropertyStates.empty())
3437  {
3438  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3439  "Autostyle queue empty!");
3440  aPoint.maStyleName = maAutoStyleNameQueue.front();
3441  maAutoStyleNameQueue.pop();
3442  }
3443  if (!aDataLabelPropertyStates.empty())
3444  {
3445  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3446  "Autostyle queue empty!");
3447  aPoint.msDataLabelStyleName = maAutoStyleNameQueue.front();
3448  maAutoStyleNameQueue.pop();
3449  }
3450  if(bExportNumFmt)
3451  aPoint.mCustomLabelText = lcl_getCustomLabelField(nElement, xSeries);
3452  aPoint.mCustomLabelPos = lcl_getCustomLabelPosition(nElement, xSeries);
3453 
3454  aDataPointVector.push_back( aPoint );
3455  }
3456  else
3457  {
3458  if (!aPropertyStates.empty())
3459  CollectAutoStyle(aPropertyStates);
3460  if (!aDataLabelPropertyStates.empty())
3461  CollectAutoStyle(aDataLabelPropertyStates);
3462  }
3463  }
3464  }
3465  }
3466  SAL_WARN_IF( bExportContent && (static_cast<sal_Int32>(aDataPointVector.size()) != nSeriesLength), "xmloff.chart", "not enough data points on content export" );
3467  }
3468  else
3469  {
3470  for( sal_Int32 nCurrIndex : aDataPointSeq )
3471  {
3472  aPropertyStates.clear();
3473  aDataLabelPropertyStates.clear();
3474  //assuming sorted indices in pPoints
3475 
3476  if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3477  break;
3478 
3479  // write leading empty data points
3480  if( nCurrIndex - nLastIndex > 1 )
3481  {
3482  SchXMLDataPointStruct aPoint;
3483  aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3484  aDataPointVector.push_back( aPoint );
3485  }
3486 
3487  uno::Reference< beans::XPropertySet > xPropSet;
3488  // get property states
3489  try
3490  {
3492  xSeries, nCurrIndex, mrExport.GetModel() );
3493  }
3494  catch( const uno::Exception & )
3495  {
3496  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during Export of data point" );
3497  }
3498  if( xPropSet.is())
3499  {
3500  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3501  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
3502  {
3503  lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3504  lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3505  }
3506 
3507  // Generate style for <chart:data-label> child element
3508  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
3509  {
3510  lcl_createDataLabelProperties(aDataLabelPropertyStates, xPropSet,
3511  mxExpPropMapper);
3512  }
3513 
3514  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3515 
3516  if (!aPropertyStates.empty() || !aDataLabelPropertyStates.empty())
3517  {
3518  if( bExportContent )
3519  {
3520  // write data-point with style
3521  SchXMLDataPointStruct aPoint;
3522  if (!aPropertyStates.empty())
3523  {
3524  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3525  "Autostyle queue empty!");
3526  aPoint.maStyleName = maAutoStyleNameQueue.front();
3527  maAutoStyleNameQueue.pop();
3528  }
3529  aPoint.mCustomLabelText = lcl_getCustomLabelField(nCurrIndex, xSeries);
3530  aPoint.mCustomLabelPos = lcl_getCustomLabelPosition(nCurrIndex, xSeries);
3531  if (!aDataLabelPropertyStates.empty())
3532  {
3533  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3534  "Autostyle queue empty!");
3535  aPoint.msDataLabelStyleName = maAutoStyleNameQueue.front();
3536  maAutoStyleNameQueue.pop();
3537  }
3538 
3539  aDataPointVector.push_back( aPoint );
3540  nLastIndex = nCurrIndex;
3541  }
3542  else
3543  {
3544  if (!aPropertyStates.empty())
3545  CollectAutoStyle(aPropertyStates);
3546  if (!aDataLabelPropertyStates.empty())
3547  CollectAutoStyle(aDataLabelPropertyStates);
3548  }
3549  continue;
3550  }
3551  }
3552 
3553  // if we get here the property states are empty
3554  SchXMLDataPointStruct aPoint;
3555  aDataPointVector.push_back( aPoint );
3556 
3557  nLastIndex = nCurrIndex;
3558  }
3559  // final empty elements
3560  sal_Int32 nRepeat = nSeriesLength - nLastIndex - 1;
3561  if( nRepeat > 0 )
3562  {
3563  SchXMLDataPointStruct aPoint;
3564  aPoint.mnRepeat = nRepeat;
3565  aDataPointVector.push_back( aPoint );
3566  }
3567  }
3568 
3569  if (!bExportContent)
3570  return;
3571 
3572  // write elements (merge equal ones)
3573  SchXMLDataPointStruct aPoint;
3574  SchXMLDataPointStruct aLastPoint;
3575 
3576  // initialize so that it doesn't matter if
3577  // the element is counted in the first iteration
3578  aLastPoint.mnRepeat = 0;
3579  sal_Int32 nIndex = 0;
3580  for( const auto& rPoint : aDataPointVector )
3581  {
3582  aPoint = rPoint;
3583 
3584  if (aPoint.maStyleName == aLastPoint.maStyleName
3585  && aLastPoint.mCustomLabelText.getLength() < 1
3586  && aLastPoint.mCustomLabelPos.Primary == 0.0
3587  && aLastPoint.mCustomLabelPos.Secondary == 0.0
3588  && aPoint.msDataLabelStyleName == aLastPoint.msDataLabelStyleName)
3589  aPoint.mnRepeat += aLastPoint.mnRepeat;
3590  else if( aLastPoint.mnRepeat > 0 )
3591  {
3592  // write last element
3593  if( !aLastPoint.maStyleName.isEmpty() )
3594  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3595 
3596  if( aLastPoint.mnRepeat > 1 )
3598  OUString::number( aLastPoint.mnRepeat ));
3599 
3600  for (auto& deletedLegendEntry : deletedLegendEntriesSeq)
3601  {
3602  if (nIndex == deletedLegendEntry)
3603  {
3604  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDE_LEGEND, OUString::boolean(true));
3605  break;
3606  }
3607  }
3608  nIndex++;
3609  exportCustomLabelPosition(aLastPoint.mCustomLabelPos); // adds attributes
3610  SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3611  exportCustomLabel(aLastPoint);
3612  }
3613  aLastPoint = aPoint;
3614  }
3615  // write last element if it hasn't been written in last iteration
3616  if( aPoint.maStyleName != aLastPoint.maStyleName )
3617  return;
3618 
3619  if( !aLastPoint.maStyleName.isEmpty() )
3620  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3621 
3622  if( aLastPoint.mnRepeat > 1 )
3624  OUString::number( aLastPoint.mnRepeat ));
3625 
3626  for (auto& deletedLegendEntry : deletedLegendEntriesSeq)
3627  {
3628  if (nIndex == deletedLegendEntry)
3629  {
3630  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDE_LEGEND, OUString::boolean(true));
3631  break;
3632  }
3633  }
3634 
3635  exportCustomLabelPosition(aLastPoint.mCustomLabelPos); // adds attributes
3636  SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3637  exportCustomLabel(aLastPoint);
3638 }
3639 
3640 void SchXMLExportHelper_Impl::exportCustomLabel(const SchXMLDataPointStruct& rPoint)
3641 {
3642  if (rPoint.mCustomLabelText.getLength() < 1 && rPoint.msDataLabelStyleName.isEmpty())
3643  return; // nothing to export
3644 
3645  if (!rPoint.msDataLabelStyleName.isEmpty())
3646  mrExport.AddAttribute(XML_NAMESPACE_CHART, XML_STYLE_NAME, rPoint.msDataLabelStyleName);
3647  // TODO svg:x and svg:y for <chart:data-label>
3649  SvXMLElementExport aPara( mrExport, XML_NAMESPACE_TEXT, XML_P, true, false );
3650  for (const Reference<chart2::XDataPointCustomLabelField>& label : rPoint.mCustomLabelText)
3651  {
3652  // TODO add style
3653  SvXMLElementExport aSpan( mrExport, XML_NAMESPACE_TEXT, XML_SPAN, true, false);
3654  mrExport.GetDocHandler()->characters(label->getString());
3655  }
3656 }
3657 
3658 void SchXMLExportHelper_Impl::exportCustomLabelPosition( const chart2::RelativePosition & xCustomLabelPosition)
3659 {
3660  if( xCustomLabelPosition.Primary == 0.0 && xCustomLabelPosition.Secondary == 0.0 )
3661  return; // nothing to export
3662 
3663  OUStringBuffer aCustomLabelPosString;
3664  ::sax::Converter::convertDouble(aCustomLabelPosString, xCustomLabelPosition.Primary);
3665  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_CUSTOM_LABEL_POS_X, aCustomLabelPosString.makeStringAndClear());
3666 
3667  ::sax::Converter::convertDouble(aCustomLabelPosString, xCustomLabelPosition.Secondary);
3668  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_CUSTOM_LABEL_POS_Y, aCustomLabelPosString.makeStringAndClear());
3669 }
3670 
3671 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3672 {
3674  msStringBuffer, rPosition.X );
3675  msString = msStringBuffer.makeStringAndClear();
3677 
3679  msStringBuffer, rPosition.Y );
3680  msString = msStringBuffer.makeStringAndClear();
3682 }
3683 
3684 void SchXMLExportHelper_Impl::addPosition( const Reference< drawing::XShape >& xShape )
3685 {
3686  if( xShape.is())
3687  addPosition( xShape->getPosition());
3688 }
3689 
3690 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3691 {
3693  msStringBuffer, rSize.Width );
3694  msString = msStringBuffer.makeStringAndClear();
3696 
3698  msStringBuffer, rSize.Height);
3699  msString = msStringBuffer.makeStringAndClear();
3700  mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3701 }
3702 
3703 void SchXMLExportHelper_Impl::addSize( const Reference< drawing::XShape >& xShape )
3704 {
3705  if( xShape.is())
3706  addSize( xShape->getSize() );
3707 }
3708 
3709 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc )
3710 {
3711  awt::Size aSize( 8000, 7000 );
3712  uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3713  SAL_WARN_IF( !xVisualObject.is(), "xmloff.chart", "need XVisualObject for page size" );
3714  if( xVisualObject.is() )
3715  aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3716 
3717  return aSize;
3718 }
3719 
3720 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3721 {
3722  if( !aStates.empty() )
3724 }
3725 
3726 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3727 {
3728  if( !aStates.empty() )
3729  {
3730  SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3731 
3733  maAutoStyleNameQueue.pop();
3734  }
3735 }
3736 
3737 void SchXMLExportHelper_Impl::exportText( const OUString& rText )
3738 {
3739  SchXMLTools::exportText( mrExport, rText, false/*bConvertTabsLFs*/ );
3740 }
3741 
3742 
3744  OUString const& implementationName, SvXMLExportFlags nExportFlags)
3745  : SvXMLExport(xContext, implementationName, util::MeasureUnit::CM, ::xmloff::token::XML_CHART,
3746  nExportFlags)
3747  , maAutoStylePool(new SchXMLAutoStylePoolP(*this))
3748  , maExportHelper(new SchXMLExportHelper(*this, *maAutoStylePool))
3749 {
3750  if (getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
3752 }
3753 
3755 {
3756 }
3757 
3759 {
3760  maExportHelper->SetSourceShellID(GetSourceShellID());
3761  maExportHelper->SetDestinationShellID(GetDestinationShellID());
3762 
3763  Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3764  maExportHelper->m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3765  return SvXMLExport::exportDoc( eClass );
3766 }
3767 
3769 {
3770  // not available in chart
3771  SAL_INFO("xmloff.chart", "Master Style Export requested. Not available for Chart" );
3772 }
3773 
3775 {
3777 
3779  return;
3780 
3781  // there are no styles that require their own autostyles
3783  {
3784  Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3785  if( xChartDoc.is())
3786  {
3787  maExportHelper->m_pImpl->collectAutoStyles( xChartDoc );
3788  }
3789  else
3790  {
3791  SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3792  }
3793  }
3794  mbAutoStylesCollected = true;
3795 }
3796 
3798 {
3800 
3802  {
3803  Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3804  if( xChartDoc.is())
3805  {
3806  maExportHelper->m_pImpl->exportAutoStyles();
3807  }
3808  else
3809  {
3810  SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3811  }
3812  }
3813 }
3814 
3816 {
3817  Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3818  if( xChartDoc.is())
3819  {
3820  // determine if data comes from the outside
3821  bool bIncludeTable = true;
3822 
3823  Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3824  if( xNewDoc.is())
3825  {
3826  // check if we have own data. If so we must not export the complete
3827  // range string, as this is our only indicator for having own or
3828  // external data. @todo: fix this in the file format!
3829  Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3830  if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
3831  {
3832  bIncludeTable = false;
3833  }
3834  }
3835  else
3836  {
3837  Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3838  if( xServ.is())
3839  {
3840  if( xServ->supportsService( "com.sun.star.chart.ChartTableAddressSupplier" ))
3841  {
3842  Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3843  if( xProp.is())
3844  {
3845  Any aAny;
3846  try
3847  {
3848  OUString sChartAddress;
3849  aAny = xProp->getPropertyValue( "ChartRangeAddress" );
3850  aAny >>= sChartAddress;
3851  maExportHelper->m_pImpl->SetChartRangeAddress( sChartAddress );
3852 
3853  // do not include own table if there are external addresses
3854  bIncludeTable = sChartAddress.isEmpty();
3855  }
3856  catch( const beans::UnknownPropertyException & )
3857  {
3858  SAL_WARN("xmloff.chart", "Property ChartRangeAddress not supported by ChartDocument" );
3859  }
3860  }
3861  }
3862  }
3863  }
3864  maExportHelper->m_pImpl->exportChart( xChartDoc, bIncludeTable );
3865  }
3866  else
3867  {
3868  SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel" );
3869  }
3870 }
3871 
3873 {
3874  return maExportHelper->m_pImpl->GetPropertySetMapper();
3875 }
3876 
3877 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3878 {
3879  if( !xChartDoc.is())
3880  return;
3881 
3882  try
3883  {
3884  Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3885  SAL_WARN_IF( !xDataProvider.is(), "xmloff.chart", "No DataProvider" );
3886  if( xDataProvider.is())
3887  {
3888  Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3889  const Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3890  OUString sCellRange, sBrokenRange;
3891  bool bBrokenRangeAvailable = false;
3892  for( const auto& rArg : aArgs )
3893  {
3894  if ( rArg.Name == "CellRangeRepresentation" )
3895  rArg.Value >>= sCellRange;
3896  else if ( rArg.Name == "BrokenCellRangeForExport" )
3897  {
3898  if( rArg.Value >>= sBrokenRange )
3899  bBrokenRangeAvailable = true;
3900  }
3901  else if ( rArg.Name == "DataRowSource" )
3902  {
3903  chart::ChartDataRowSource eRowSource;
3904  rArg.Value >>= eRowSource;
3905  mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3906  }
3907  else if ( rArg.Name == "SequenceMapping" )
3908  rArg.Value >>= maSequenceMapping;
3909  }
3910 
3911  // #i79009# For Writer we have to export a broken version of the
3912  // range, where every row number is not too large, so that older
3913  // version can correctly read those files.
3914  msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3915  if( !msChartAddress.isEmpty() )
3916  {
3917  // convert format to XML-conform one
3918  Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3919  if( xConversion.is())
3920  msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3921  }
3922  }
3923  }
3924  catch( const uno::Exception & )
3925  {
3926  DBG_UNHANDLED_EXCEPTION("xmloff.chart");
3927  }
3928 }
3929 
3930 // first version: everything goes in one storage
3931 
3932 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3934  uno::Sequence<uno::Any> const& /*rSeq*/)
3935 {
3936  return cppu::acquire(
3937  new SchXMLExport(pCtx, "SchXMLExport.Compact",
3941 }
3942 
3943 // Oasis format
3944 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3946  uno::Sequence<uno::Any> const& /*rSeq*/)
3947 {
3948  return cppu::acquire(
3949  new SchXMLExport(pCtx, "SchXMLExport.Oasis.Compact",
3954 }
3955 
3956 // multiple storage version: one for content / styles / meta
3957 
3958 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3960  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3961 {
3962  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Styles", SvXMLExportFlags::STYLES));
3963 }
3964 
3965 // Oasis format
3966 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3968  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3969 {
3970  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Oasis.Styles",
3972 }
3973 
3974 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3976  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3977 {
3978  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Content",
3981 }
3982 
3983 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3985  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3986 {
3987  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Oasis.Content",
3991 }
3992 
3993 // Oasis format
3994 
3995 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3997  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3998 {
3999  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Oasis.Meta",
4001 }
4002 
4003 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
exports com.sun.star.lib. util
tools::SvRef< SvBaseLink > xSink
virtual void ExportAutoStyles_() override
Override this method to export the contents of .
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
sal_Int32 nIndex
static css::awt::Size getPageSize(const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc)
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisStylesExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
rtl::Reference< XMLShapeExport > const & GetShapeExport()
Definition: xmlexp.hxx:568
SchXMLExport(const css::uno::Reference< css::uno::XComponentContext > &xContext, OUString const &implementationName, SvXMLExportFlags nExportFlags)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisMetaExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
constexpr sal_uInt16 XML_NAMESPACE_CHART
virtual void ExportMasterStyles_() override
Override this method to export the contents of .
void exportGrid(const Reference< beans::XPropertySet > &rGridProperties, bool bMajor, bool bExportContent)
void exportCoordinateRegion(const css::uno::Reference< css::chart::XDiagram > &xDiagram)
void exportSeries(const css::uno::Reference< css::chart2::XDiagram > &xNewDiagram, const css::awt::Size &rPageSize, bool bExportContent, bool bHasTwoYAxes)
virtual void exportAutoDataStyles()
Definition: xmlexp.cxx:1826
static css::uno::Reference< css::beans::XPropertySet > createOldAPISeriesPropertySet(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const css::uno::Reference< css::frame::XModel > &xChartModel)
rtl::Reference< XMLTextParagraphExport > const & GetTextParagraphExport()
Definition: xmlexp.hxx:560
void parseDocument(css::uno::Reference< css::chart::XChartDocument > const &rChartDoc, bool bExportContent, bool bIncludeTable=false)
if bExportContent is false the auto-styles are collected
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlexp.hxx:394
SvXMLExportFlags
Definition: xmlexp.hxx:89
FilterGroup & rTarget
aBuf
constexpr sal_uInt16 XML_NAMESPACE_XLINK
constexpr sal_uInt16 XML_NAMESPACE_OOO
const ContentProperties & rData
const_iterator find(const Value &x) const
constexpr sal_uInt16 XML_NAMESPACE_LO_EXT
virtual void ExportContent_() override
Override this method to export the content of .
#define XML_STYLE_FAMILY_SCH_CHART_NAME
Definition: families.hxx:43
const css::uno::Reference< css::xml::sax::XDocumentHandler > & GetDocHandler() const
Definition: xmlexp.hxx:385
#define XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX
Definition: families.hxx:37
void collectAutoStyles(css::uno::Reference< css::chart::XChartDocument > const &rChartDoc)
parse chart and collect all auto-styles used in current pool
virtual ErrCode exportDoc(enum::xmloff::token::XMLTokenEnum eClass=::xmloff::token::XML_TOKEN_INVALID)
Definition: xmlexp.cxx:1229
static::std::vector< double > lcl_getAllValuesFromSequence(const Reference< chart2::data::XDataSequence > &xSeq)
::std::pair< css::uno::Reference< css::chart2::data::XDataSequence >, css::uno::Reference< css::chart2::data::XDataSequence > > tLabelValuesDataPair
void exportDateScale(const Reference< beans::XPropertySet > &rAxisProps)
rtl::Reference< SchXMLExportHelper > maExportHelper
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
virtual bool exportXML(OUString &rStrExpValue, const css::uno::Any &rValue, const SvXMLUnitConverter &rUnitConverter) const override
Exports the given value according to the XML-data-type corresponding to the derived class...
OUStringBuffer msStringBuffer
const css::uno::Reference< css::frame::XModel > & GetModel() const
Definition: xmlexp.hxx:414
rtl::Reference< XMLChartExportPropertyMapper > mxExpPropMapper
void AddAutoStyleAttribute(const std::vector< XMLPropertyState > &aStates)
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void exportAxes(const css::uno::Reference< css::chart::XDiagram > &xDiagram, const css::uno::Reference< css::chart2::XDiagram > &xNewDiagram, bool bExportContent)
virtual ~SchXMLExport() override
void AddAttribute(sal_uInt16 nPrefix, const char *pName, const OUString &rValue)
Definition: xmlexp.cxx:906
void reserve(size_type amount)
constexpr sal_uInt16 XML_NAMESPACE_DRAW
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
#define XML_STYLE_FAMILY_SCH_CHART_PREFIX
Definition: families.hxx:44
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
constexpr OUStringLiteral aData
void exportAxis(enum XMLTokenEnum eDimension, enum XMLTokenEnum eAxisName, const Reference< beans::XPropertySet > &rAxisProps, const Reference< chart2::XAxis > &rChart2Axis, const OUString &rCategoriesRanges, bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid, bool bExportContent, std::u16string_view sChartType)
void exportRegressionCurve(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, const css::awt::Size &rPageSize, bool bExportContent)
OUString const & GetDestinationShellID() const
Definition: xmlexp.cxx:1431
#define XML_STYLE_FAMILY_SD_GRAPHICS_NAME
Definition: families.hxx:36
bool mbAutoStylesCollected
Definition: xmlexp.hxx:262
SvtSaveOptions::ODFSaneDefaultVersion getSaneDefaultVersion() const
returns the deterministic version for odf export
Definition: xmlexp.cxx:2292
css::uno::Sequence< sal_Int32 > maSequenceMapping
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLStylesExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
#define DBG_UNHANDLED_EXCEPTION(...)
constexpr sal_uInt16 XML_NAMESPACE_SVG
std::unique_ptr< SchXMLExportHelper_Impl > m_pImpl
void addSize(const css::awt::Size &rSize, bool bIsOOoNamespace=false)
add svg size as attribute for current element
OUString Add(XmlStyleFamily nFamily, const ::std::vector< XMLPropertyState > &rProperties)
Add an item set to the pool and return its generated name.
void exportCustomLabelPosition(const chart2::RelativePosition &xCustomLabelPosition)
int i
constexpr sal_uInt16 XML_NAMESPACE_TEXT
static css::uno::Reference< css::beans::XPropertySet > createOldAPIDataPointPropertySet(const css::uno::Reference< css::chart2::XDataSeries > &xSeries, sal_Int32 nPointIndex, const css::uno::Reference< css::frame::XModel > &xChartModel)
constexpr sal_uInt16 XML_NAMESPACE_CHART_EXT
void exportCandleStickSeries(const css::uno::Sequence< css::uno::Reference< css::chart2::XDataSeries > > &aSeriesSeq, const css::uno::Reference< css::chart2::XDiagram > &xDiagram, bool bJapaneseCandleSticks, bool bExportContent)
OUString m_aRole
void InitRangeSegmentationProperties(const css::uno::Reference< css::chart2::XChartDocument > &xChartDoc)
virtual ~SchXMLExportHelper() override
void AddFamily(XmlStyleFamily nFamily, const OUString &rStrName, SvXMLExportPropertyMapper *pMapper, const OUString &aStrPrefix)
register a new family with its appropriate instance of a derivation of XMLPropertySetMapper for famil...
Definition: xmlaustp.cxx:273
void exportPropertyMapping(const css::uno::Reference< css::chart2::data::XDataSource > &xSource, const Sequence< OUString > &rSupportedMappings)
rtl::Reference< XMLPropertySetMapper > const & GetPropertySetMapper() const
float u
static void convertDateTime(OUStringBuffer &rBuffer, const css::util::DateTime &rDateTime, sal_Int16 const *pTimeZoneOffset, bool bAddTimeIf0AM=false)
With this class you can export a element containing its data as element o...
static XMLEnumPropertyHdl & getLegendPositionConverter()
const OUString & getChartCLSID() const
returns the string corresponding to the current FileFormat CLSID for Chart
ColorTransparency
const_iterator end() const
SchXMLExportHelper(SvXMLExport &rExport, SvXMLAutoStylePoolP &rASPool)
OUString GetQNameByKey(sal_uInt16 nKey, const OUString &rLocalName, bool bCache=true) const
void exportAutoStyles()
write the styles collected into the current pool as elements
void exportText(SvXMLExport &rExport, const OUString &rText, bool bConvertTabsLFs)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLOasisContentExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
static::std::vector< css::uno::Reference< css::chart2::XDataSeries > > getDataSeriesFromDiagram(const css::uno::Reference< css::chart2::XDiagram > &xDiagram)
const SvXMLNamespaceMap & GetNamespaceMap() const
Definition: xmlexp.hxx:391
void SetChartRangeAddress(const OUString &rAddress)
void exportText(const OUString &rText)
exports a string as a paragraph element
virtual ErrCode exportDoc(enum::xmloff::token::XMLTokenEnum eClass=::xmloff::token::XML_TOKEN_INVALID) override
void exportRangeToSomewhere(SvXMLExport &rExport, const OUString &rValue)
#define TOOLS_INFO_EXCEPTION(area, stream)
void exportPlotArea(const css::uno::Reference< css::chart::XDiagram > &xDiagram, const css::uno::Reference< css::chart2::XDiagram > &xNewDiagram, const css::awt::Size &rPageSize, bool bExportContent, bool bIncludeTable)
void Add(const OUString &sName, T &rValue)
Add a property to handle.
static constexpr OUStringLiteral gsTableName
void CollectAutoStyle(const std::vector< XMLPropertyState > &aStates)
const rtl::Reference< XMLPropertySetMapper > & GetPropertySetMapper() const
static void lcl_exportComplexLabel(const Sequence< uno::Any > &rComplexLabel, SvXMLExport &rExport)
constexpr sal_uInt16 XML_NAMESPACE_TABLE
rtl::Reference< XMLPropertySetMapper > mxPropertySetMapper
#define XML_SCH_CONTEXT_SPECIAL_REGRESSION_TYPE
Definition: PropertyMap.hxx:84
css::uno::Reference< css::drawing::XShapes > mxAdditionalShapes
SvXMLNamespaceMap & GetNamespaceMap_()
Definition: xmlexp.hxx:180
#define SAL_WARN_IF(condition, area, stream)
SchXMLExportHelper_Impl(SvXMLExport &rExport, SvXMLAutoStylePoolP &rASPool)
void SetSourceShellID(const OUString &rShellID)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3425
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Handling of tokens in XML:
void exportXML(XmlStyleFamily nFamily) const
Export all item sets ofs a certain class in the order in that they have been added.
Definition: xmlaustp.cxx:369
void addPosition(const css::awt::Point &rPosition)
add svg position as attribute for current element
void collectAutoStyles() override
OUString const & GetSourceShellID() const
Definition: xmlexp.cxx:1426
#define SAL_INFO(area, stream)
#define SO3_SCH_CLASSID
This class lets you get the values from an object that either supports the interface XPropertySet or ...
Smart struct to transport an Any with an index to the appropriate property-name.
Definition: maptype.hxx:122
SvXMLAutoStylePoolP & mrAutoStylePool
sal_uInt16 Add(const OUString &rPrefix, const OUString &rName, sal_uInt16 nKey=XML_NAMESPACE_UNKNOWN)
void * p
Reference< XComponentContext > getProcessComponentContext()
static XMLEnumPropertyHdl & getLegendExpansionConverter()
Sequence< sal_Int8 > aSeq
void exportDataPoints(const css::uno::Reference< css::beans::XPropertySet > &xSeriesProperties, sal_Int32 nSeriesLength, const css::uno::Reference< css::chart2::XDiagram > &xDiagram, bool bExportContent)
void SetDestinationShellID(const OUString &rShellID)
void exportAxisTitle(const Reference< beans::XPropertySet > &rTitleProps, bool bExportContent)
::std::queue< OUString > maAutoStyleNameQueue
first parseDocument: collect autostyles and store names in this queue second parseDocument: export co...
void exportErrorBar(const css::uno::Reference< beans::XPropertySet > &xSeriesProp, bool bYError, bool bExportContent)
void exportChart(css::uno::Reference< css::chart::XChartDocument > const &rChartDoc, bool bIncludeTable)
export the element corresponding to rChartDoc if bIncludeTable is true, the chart data is exported as element (inside the chart element).
#define SAL_WARN(area, stream)
sal_Int32 nLength
Definition: xmltoken.cxx:36
XMLTokenEnum getTokenByChartType(const OUString &rChartTypeService, bool bUseOldNames)
void exportCustomLabel(const SchXMLDataPointStruct &rPoint)
XMLTokenEnum eToken
Definition: xmltoken.cxx:40
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
std::pair< const_iterator, bool > insert(Value &&x)
SAL_DLLPUBLIC_EXPORT uno::XInterface * com_sun_star_comp_Chart_XMLContentExporter_get_implementation(uno::XComponentContext *pCtx, uno::Sequence< uno::Any > const &)
def label(st)
::std::vector< tLabelValuesDataPair > tDataSequenceCont
static OUString lcl_GetStringFromNumberSequence(const css::uno::Sequence< sal_Int32 > &rSequenceMapping, bool bRemoveOneFromEachIndex)
virtual void addDataStyle(const sal_Int32 nNumberFormat, bool bTimeFormat=false)
Definition: xmlexp.cxx:1814
css::uno::Any const SvXMLExport & rExport
Definition: ImageStyle.hxx:38
bool GetProperties()
Try to get the values for all properties added with the Add method.
SvXMLExportFlags getExportFlags() const
Definition: xmlexp.hxx:476
tDataSequenceCont m_aDataSequencesToExport
void convertMeasureToXML(OUStringBuffer &rBuffer, sal_Int32 nMeasure) const
convert measure to string: from meCoreMeasureUnit to meXMLMeasureUnit
Definition: xmluconv.cxx:191
constexpr sal_uInt16 XML_NAMESPACE_STYLE
virtual void collectAutoStyles()
Definition: xmlexp.cxx:1701