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  //todo?
1554  }
1555  SchXMLTools::exportText( rExport, aString, false /*bConvertTabsLFs*/ );
1556  }
1557 }
1558 
1560 {
1561  // table element
1563 
1564  try
1565  {
1566  bool bProtected = false;
1567  Reference< beans::XPropertySet > xProps( mrExport.GetModel(), uno::UNO_QUERY_THROW );
1568  if ( ( xProps->getPropertyValue("DisableDataTableDialog") >>= bProtected ) &&
1569  bProtected )
1570  {
1572  }
1573  }
1574  catch ( const uno::Exception& )
1575  {
1576  }
1577 
1578  SvXMLElementExport aTable( mrExport, XML_NAMESPACE_TABLE, XML_TABLE, true, true );
1579 
1580  bool bHasOwnData = false;
1581  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
1582  Reference< chart2::data::XRangeXMLConversion > xRangeConversion;
1583  if( xNewDoc.is())
1584  {
1585  bHasOwnData = xNewDoc->hasInternalDataProvider();
1586  xRangeConversion.set( xNewDoc->getDataProvider(), uno::UNO_QUERY );
1587  }
1588 
1589  Reference< chart2::XAnyDescriptionAccess > xAnyDescriptionAccess;
1590  {
1591  Reference< chart::XChartDocument > xChartDoc( mrExport.GetModel(), uno::UNO_QUERY );
1592  if( xChartDoc.is() )
1593  xAnyDescriptionAccess.set( xChartDoc->getData(), uno::UNO_QUERY );
1594  }
1595 
1596  if( bHasOwnData )
1597  lcl_ReorderInternalSequencesAccordingToTheirRangeName( m_aDataSequencesToExport );
1598  lcl_TableData aData( lcl_getDataForLocalTable( m_aDataSequencesToExport
1599  , xAnyDescriptionAccess, maCategoriesRange
1600  , mbRowSourceColumns, xRangeConversion ));
1601 
1602  tStringVector::const_iterator aDataRangeIter( aData.aDataRangeRepresentations.begin());
1603  const tStringVector::const_iterator aDataRangeEndIter( aData.aDataRangeRepresentations.end());
1604 
1605  tStringVector::const_iterator aRowDescriptions_RangeIter( aData.aRowDescriptions_Ranges.begin());
1606  const tStringVector::const_iterator aRowDescriptions_RangeEnd( aData.aRowDescriptions_Ranges.end());
1607 
1608  // declare columns
1609  {
1611  SvXMLElementExport aHeaderColumn( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_COLUMN, true, true );
1612  }
1613  {
1615 
1616  sal_Int32 nNextIndex = 0;
1617  for(sal_Int32 nHiddenIndex : aData.aHiddenColumns)
1618  {
1619  //i91578 display of hidden values (copy paste scenario; export hidden flag thus it can be used during migration to locale table upon paste )
1620  if( nHiddenIndex > nNextIndex )
1621  {
1622  sal_Int64 nRepeat = static_cast< sal_Int64 >( nHiddenIndex - nNextIndex );
1623  if(nRepeat>1)
1625  OUString::number( nRepeat ));
1627  }
1630  nNextIndex = nHiddenIndex+1;
1631  }
1632 
1633  sal_Int32 nEndIndex = aData.aColumnDescriptions.size()-1;
1634  if( nEndIndex >= nNextIndex )
1635  {
1636  sal_Int64 nRepeat = static_cast< sal_Int64 >( nEndIndex - nNextIndex + 1 );
1637  if(nRepeat>1)
1639  OUString::number( nRepeat ));
1641  }
1642  }
1643 
1644  // export rows with content
1645  //export header row
1646  {
1649 
1650  //first one empty cell for the row descriptions
1651  {
1652  SvXMLElementExport aEmptyCell( mrExport, XML_NAMESPACE_TABLE, XML_TABLE_CELL, true, true );
1653  SvXMLElementExport aEmptyParagraph( mrExport, XML_NAMESPACE_TEXT, XML_P, true, true );
1654  }
1655 
1656  //export column descriptions
1657  tStringVector::const_iterator aColumnDescriptions_RangeIter( aData.aColumnDescriptions_Ranges.begin());
1658  const tStringVector::const_iterator aColumnDescriptions_RangeEnd( aData.aColumnDescriptions_Ranges.end());
1659  const Sequence< Sequence< uno::Any > >& rComplexColumnDescriptions = aData.aComplexColumnDescriptions;
1660  sal_Int32 nComplexCount = rComplexColumnDescriptions.getLength();
1661  sal_Int32 nC = 0;
1662  for( const auto& rDesc : aData.aColumnDescriptions )
1663  {
1664  bool bExportString = true;
1665  if( nC < nComplexCount )
1666  {
1667  const Sequence< uno::Any >& rComplexLabel = rComplexColumnDescriptions[nC];
1668  if( rComplexLabel.hasElements() )
1669  {
1670  double fValue=0.0;
1671  if( rComplexLabel[0] >>=fValue )
1672  {
1673  bExportString = false;
1674 
1676  msStringBuffer, fValue);
1677  msString = msStringBuffer.makeStringAndClear();
1680  }
1681  }
1682  }
1683  if( bExportString )
1684  {
1686  }
1687 
1689  exportText( rDesc );
1690  if( nC < nComplexCount )
1691  lcl_exportComplexLabel( rComplexColumnDescriptions[nC], mrExport );
1692  if( !bHasOwnData && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd )
1693  {
1694  // remind the original range to allow a correct re-association when copying via clipboard
1695  if (!(*aColumnDescriptions_RangeIter).isEmpty())
1696  SchXMLTools::exportRangeToSomewhere( mrExport, *aColumnDescriptions_RangeIter );
1697  ++aColumnDescriptions_RangeIter;
1698  }
1699 
1700  nC++;
1701  }
1702  SAL_WARN_IF( !bHasOwnData && (aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aColumnDescriptions_RangeIter != aColumnDescriptions_RangeEnd" );
1703  } // closing row and header-rows elements
1704 
1705  // export value rows
1706  {
1708  tStringVector::const_iterator aRowDescriptionsIter( aData.aRowDescriptions.begin());
1709  const Sequence< Sequence< uno::Any > >& rComplexRowDescriptions = aData.aComplexRowDescriptions;
1710  sal_Int32 nComplexCount = rComplexRowDescriptions.getLength();
1711  sal_Int32 nC = 0;
1712 
1713  for( const auto& rRow : aData.aDataInRows )
1714  {
1716 
1717  //export row descriptions
1718  {
1719  bool bExportString = true;
1720  if( nC < nComplexCount )
1721  {
1722  const Sequence< uno::Any >& rComplexLabel = rComplexRowDescriptions[nC];
1723  if( rComplexLabel.hasElements() )
1724  {
1725  double fValue=0.0;
1726  if( rComplexLabel[0] >>=fValue )
1727  {
1728  bExportString = false;
1729 
1731  msString = msStringBuffer.makeStringAndClear();
1734  }
1735  }
1736  }
1737  if( bExportString )
1738  {
1740  }
1741 
1743  if( aRowDescriptionsIter != aData.aRowDescriptions.end())
1744  {
1745  exportText( *aRowDescriptionsIter );
1746  if( nC < nComplexCount )
1747  lcl_exportComplexLabel( rComplexRowDescriptions[nC], mrExport );
1748  if( !bHasOwnData && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd )
1749  {
1750  // remind the original range to allow a correct re-association when copying via clipboard
1751  SchXMLTools::exportRangeToSomewhere( mrExport, *aRowDescriptions_RangeIter );
1752  ++aRowDescriptions_RangeIter;
1753  }
1754  ++aRowDescriptionsIter;
1755  }
1756  }
1757 
1758  //export row values
1759  for( t2DNumberContainer::value_type::const_iterator aColIt( rRow.begin());
1760  aColIt != rRow.end(); ++aColIt )
1761  {
1763  msString = msStringBuffer.makeStringAndClear();
1767  exportText( msString ); // do not convert tabs and lfs
1768  if( ( !bHasOwnData && aDataRangeIter != aDataRangeEndIter ) &&
1769  ( mbRowSourceColumns || (aColIt == rRow.begin()) ) )
1770  {
1771  // remind the original range to allow a correct re-association when copying via clipboard
1772  if (!(*aDataRangeIter).isEmpty())
1773  SchXMLTools::exportRangeToSomewhere( mrExport, *aDataRangeIter );
1774  ++aDataRangeIter;
1775  }
1776  }
1777 
1778  ++nC;
1779  }
1780  }
1781 
1782  // if range iterator was used it should have reached its end
1783  SAL_WARN_IF( !bHasOwnData && (aDataRangeIter != aDataRangeEndIter), "xmloff.chart", "bHasOwnData == false && aDataRangeIter != aDataRangeEndIter" );
1784  SAL_WARN_IF( !bHasOwnData && (aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd), "xmloff.chart", "bHasOwnData == false && aRowDescriptions_RangeIter != aRowDescriptions_RangeEnd" );
1785 }
1786 
1787 namespace
1788 {
1789 
1790 Reference< chart2::XCoordinateSystem > lcl_getCooSys( const Reference< chart2::XDiagram > & xNewDiagram )
1791 {
1792  Reference< chart2::XCoordinateSystem > xCooSys;
1793  Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xNewDiagram, uno::UNO_QUERY );
1794  if(xCooSysCnt.is())
1795  {
1796  Sequence< Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems() );
1797  if(aCooSysSeq.hasElements())
1798  xCooSys = aCooSysSeq[0];
1799  }
1800  return xCooSys;
1801 }
1802 
1803 Reference< chart2::XAxis > lcl_getAxis( const Reference< chart2::XCoordinateSystem >& xCooSys,
1804  enum XMLTokenEnum eDimension, bool bPrimary=true )
1805 {
1806  Reference< chart2::XAxis > xNewAxis;
1807  try
1808  {
1809  if( xCooSys.is() )
1810  {
1811  sal_Int32 nDimensionIndex=0;
1812  switch( eDimension )
1813  {
1814  case XML_X:
1815  nDimensionIndex=0;
1816  break;
1817  case XML_Y:
1818  nDimensionIndex=1;
1819  break;
1820  case XML_Z:
1821  nDimensionIndex=2;
1822  break;
1823  default:
1824  break;
1825  }
1826 
1827  xNewAxis = xCooSys->getAxisByDimension( nDimensionIndex, bPrimary ? 0 : 1 );
1828  }
1829  }
1830  catch( const uno::Exception & )
1831  {
1832  }
1833  return xNewAxis;
1834 }
1835 
1836 }
1837 
1839  const Reference< chart::XDiagram >& xDiagram,
1840  const Reference< chart2::XDiagram >& xNewDiagram,
1841  const awt::Size & rPageSize,
1842  bool bExportContent,
1843  bool bIncludeTable )
1844 {
1845  SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
1846  if( ! xDiagram.is())
1847  return;
1848 
1849  // variables for autostyles
1851  std::vector< XMLPropertyState > aPropertyStates;
1852 
1853  msStringBuffer.setLength( 0 );
1854 
1855  // plot-area element
1856 
1857  std::unique_ptr<SvXMLElementExport> xElPlotArea;
1858  // get property states for autostyles
1859  xPropSet.set( xDiagram, uno::UNO_QUERY );
1860  if( xPropSet.is())
1861  {
1862  if( mxExpPropMapper.is())
1863  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
1864  }
1865  if( bExportContent )
1866  {
1867  rtl::Reference< XMLShapeExport > rShapeExport;
1868 
1869  // write style name
1870  AddAutoStyleAttribute( aPropertyStates );
1871 
1872  if( !msChartAddress.isEmpty() )
1873  {
1874  if( !bIncludeTable )
1876 
1877  Reference< chart::XChartDocument > xDoc( mrExport.GetModel(), uno::UNO_QUERY );
1878  if( xDoc.is() )
1879  {
1880  Reference< beans::XPropertySet > xDocProp( xDoc, uno::UNO_QUERY );
1881  if( xDocProp.is())
1882  {
1883  Any aAny;
1884 
1885  try
1886  {
1887  bool bFirstCol = false, bFirstRow = false;
1888 
1889  aAny = xDocProp->getPropertyValue( "DataSourceLabelsInFirstColumn" );
1890  aAny >>= bFirstCol;
1891  aAny = xDocProp->getPropertyValue( "DataSourceLabelsInFirstRow" );
1892  aAny >>= bFirstRow;
1893 
1894  if( bFirstCol || bFirstRow )
1895  {
1898  ( bFirstCol
1899  ? ( bFirstRow
1903  }
1904  }
1905  catch( const beans::UnknownPropertyException & )
1906  {
1907  SAL_WARN("xmloff.chart", "Properties missing" );
1908  }
1909  }
1910  }
1911  }
1912 
1913  // attributes
1914  if( xDiagram.is())
1915  {
1916  addPosition( xDiagram );
1917  addSize( xDiagram );
1918  }
1919 
1920  bool bIs3DChart = false;
1921 
1922  if( xPropSet.is())
1923  {
1924  Any aAny;
1925 
1926  // 3d attributes
1927  try
1928  {
1929  aAny = xPropSet->getPropertyValue("Dim3D");
1930  aAny >>= bIs3DChart;
1931 
1932  if( bIs3DChart )
1933  {
1934  rShapeExport = mrExport.GetShapeExport();
1935  if( rShapeExport.is())
1936  rShapeExport->export3DSceneAttributes( xPropSet );
1937  }
1938  }
1939  catch( const uno::Exception & )
1940  {
1941  TOOLS_INFO_EXCEPTION("xmloff.chart", "chart:exportPlotAreaException caught");
1942  }
1943  }
1944 
1945  // plot-area element
1946  xElPlotArea.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_PLOT_AREA, true, true ));
1947 
1948  //inner position rectangle element
1949  exportCoordinateRegion( xDiagram );
1950 
1951  // light sources (inside plot area element)
1952  if( bIs3DChart &&
1953  rShapeExport.is())
1954  rShapeExport->export3DLamps( xPropSet );
1955  }
1956  else // autostyles
1957  {
1958  CollectAutoStyle( aPropertyStates );
1959  }
1960  // remove property states for autostyles
1961  aPropertyStates.clear();
1962 
1963  // axis elements
1964  exportAxes( xDiagram, xNewDiagram, bExportContent );
1965 
1966  // series elements
1967  Reference< chart2::XAxis > xSecondYAxis = lcl_getAxis( lcl_getCooSys( xNewDiagram ), XML_Y, false );
1968  exportSeries( xNewDiagram, rPageSize, bExportContent, xSecondYAxis.is() );
1969 
1970  // stock-chart elements
1971  OUString sChartType ( xDiagram->getDiagramType());
1972  if( sChartType == "com.sun.star.chart.StockDiagram" )
1973  {
1974  Reference< chart::XStatisticDisplay > xStockPropProvider( xDiagram, uno::UNO_QUERY );
1975  if( xStockPropProvider.is())
1976  {
1977  // stock-gain-marker
1978  Reference< beans::XPropertySet > xStockPropSet = xStockPropProvider->getUpBar();
1979  if( xStockPropSet.is())
1980  {
1981  aPropertyStates.clear();
1982  aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
1983 
1984  if( !aPropertyStates.empty() )
1985  {
1986  if( bExportContent )
1987  {
1988  AddAutoStyleAttribute( aPropertyStates );
1989 
1991  }
1992  else
1993  {
1994  CollectAutoStyle( aPropertyStates );
1995  }
1996  }
1997  }
1998 
1999  // stock-loss-marker
2000  xStockPropSet = xStockPropProvider->getDownBar();
2001  if( xStockPropSet.is())
2002  {
2003  aPropertyStates.clear();
2004  aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2005 
2006  if( !aPropertyStates.empty() )
2007  {
2008  if( bExportContent )
2009  {
2010  AddAutoStyleAttribute( aPropertyStates );
2011 
2013  }
2014  else
2015  {
2016  CollectAutoStyle( aPropertyStates );
2017  }
2018  }
2019  }
2020 
2021  // stock-range-line
2022  xStockPropSet = xStockPropProvider->getMinMaxLine();
2023  if( xStockPropSet.is())
2024  {
2025  aPropertyStates.clear();
2026  aPropertyStates = mxExpPropMapper->Filter( xStockPropSet );
2027 
2028  if( !aPropertyStates.empty() )
2029  {
2030  if( bExportContent )
2031  {
2032  AddAutoStyleAttribute( aPropertyStates );
2033 
2035  }
2036  else
2037  {
2038  CollectAutoStyle( aPropertyStates );
2039  }
2040  }
2041  }
2042  }
2043  }
2044 
2045  // wall and floor element
2046  Reference< chart::X3DDisplay > xWallFloorSupplier( xDiagram, uno::UNO_QUERY );
2047  if( !(mxExpPropMapper.is() &&
2048  xWallFloorSupplier.is()))
2049  return;
2050 
2051  // remove property states for autostyles
2052  aPropertyStates.clear();
2053 
2054  Reference< beans::XPropertySet > xWallPropSet = xWallFloorSupplier->getWall();
2055  if( xWallPropSet.is())
2056  {
2057  aPropertyStates = mxExpPropMapper->Filter( xWallPropSet );
2058 
2059  if( !aPropertyStates.empty() )
2060  {
2061  // write element
2062  if( bExportContent )
2063  {
2064  // add style name attribute
2065  AddAutoStyleAttribute( aPropertyStates );
2066 
2068  }
2069  else // autostyles
2070  {
2071  CollectAutoStyle( aPropertyStates );
2072  }
2073  }
2074  }
2075 
2076  // floor element
2077  // remove property states for autostyles
2078  aPropertyStates.clear();
2079 
2080  Reference< beans::XPropertySet > xFloorPropSet = xWallFloorSupplier->getFloor();
2081  if( !xFloorPropSet.is())
2082  return;
2083 
2084  aPropertyStates = mxExpPropMapper->Filter( xFloorPropSet );
2085 
2086  if( aPropertyStates.empty() )
2087  return;
2088 
2089  // write element
2090  if( bExportContent )
2091  {
2092  // add style name attribute
2093  AddAutoStyleAttribute( aPropertyStates );
2094 
2095  SvXMLElementExport aFloor( mrExport, XML_NAMESPACE_CHART, XML_FLOOR, true, true );
2096  }
2097  else // autostyles
2098  {
2099  CollectAutoStyle( aPropertyStates );
2100  }
2101 }
2102 
2103 void SchXMLExportHelper_Impl::exportCoordinateRegion( const uno::Reference< chart::XDiagram >& xDiagram )
2104 {
2105  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2106  if (nCurrentODFVersion <= SvtSaveOptions::ODFSVER_012) //do not export to ODF 1.2 or older
2107  return;
2108 
2109  Reference< chart::XDiagramPositioning > xDiaPos( xDiagram, uno::UNO_QUERY );
2110  SAL_WARN_IF( !xDiaPos.is(), "xmloff.chart", "Invalid xDiaPos as parameter" );
2111  if( !xDiaPos.is() )
2112  return;
2113 
2114  awt::Rectangle aRect( xDiaPos->calculateDiagramPositionExcludingAxes() );
2115  addPosition( awt::Point(aRect.X,aRect.Y) );
2116  addSize( awt::Size(aRect.Width,aRect.Height) );
2117 
2118  // ODF 1.3 OFFICE-3928
2119  SvXMLElementExport aCoordinateRegion( mrExport,
2121  XML_COORDINATE_REGION, true, true );
2122 }
2123 
2124 namespace
2125 {
2126  XMLTokenEnum lcl_getTimeUnitToken( sal_Int32 nTimeUnit )
2127  {
2129  switch( nTimeUnit )
2130  {
2131  case css::chart::TimeUnit::YEAR:
2132  eToken = XML_YEARS;
2133  break;
2134  case css::chart::TimeUnit::MONTH:
2135  eToken = XML_MONTHS;
2136  break;
2137  default://days
2138  break;
2139  }
2140  return eToken;
2141  }
2142 }
2143 
2145 {
2146  if( !rAxisProps.is() )
2147  return;
2148 
2149  chart::TimeIncrement aIncrement;
2150  if( !(rAxisProps->getPropertyValue("TimeIncrement") >>= aIncrement) )
2151  return;
2152 
2153  sal_Int32 nTimeResolution = css::chart::TimeUnit::DAY;
2154  if( aIncrement.TimeResolution >>= nTimeResolution )
2155  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_BASE_TIME_UNIT, lcl_getTimeUnitToken( nTimeResolution ) );
2156 
2157  chart::TimeInterval aInterval;
2158  if( aIncrement.MajorTimeInterval >>= aInterval )
2159  {
2160  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_VALUE, OUString::number(aInterval.Number) );
2161  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MAJOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2162  }
2163  if( aIncrement.MinorTimeInterval >>= aInterval )
2164  {
2165  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_VALUE, OUString::number(aInterval.Number) );
2166  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_MINOR_INTERVAL_UNIT, lcl_getTimeUnitToken( aInterval.TimeUnit ) );
2167  }
2168 
2169  SvXMLElementExport aDateScale( mrExport, XML_NAMESPACE_CHART_EXT, XML_DATE_SCALE, true, true );//#i25706#todo: change namespace for next ODF version
2170 }
2171 
2173 {
2174  if( !rTitleProps.is() )
2175  return;
2176  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rTitleProps );
2177  if( bExportContent )
2178  {
2179  OUString aText;
2180  Any aAny( rTitleProps->getPropertyValue( "String" ));
2181  aAny >>= aText;
2182 
2183  Reference< drawing::XShape > xShape( rTitleProps, uno::UNO_QUERY );
2184  if( xShape.is())
2185  addPosition( xShape );
2186 
2187  AddAutoStyleAttribute( aPropertyStates );
2188  SvXMLElementExport aTitle( mrExport, XML_NAMESPACE_CHART, XML_TITLE, true, true );
2189 
2190  // paragraph containing title
2191  exportText( aText );
2192  }
2193  else
2194  {
2195  CollectAutoStyle( aPropertyStates );
2196  }
2197  aPropertyStates.clear();
2198 }
2199 
2200 void SchXMLExportHelper_Impl::exportGrid( const Reference< beans::XPropertySet >& rGridProperties, bool bMajor, bool bExportContent )
2201 {
2202  if( !rGridProperties.is() )
2203  return;
2204  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( rGridProperties );
2205  if( bExportContent )
2206  {
2207  AddAutoStyleAttribute( aPropertyStates );
2210  }
2211  else
2212  {
2213  CollectAutoStyle( aPropertyStates );
2214  }
2215  aPropertyStates.clear();
2216 }
2217 
2218 namespace
2219 {
2220 
2221 //returns true if a date scale needs to be exported
2222 bool lcl_exportAxisType( const Reference< chart2::XAxis >& rChart2Axis, SvXMLExport& rExport)
2223 {
2224  bool bExportDateScale = false;
2225  if( !rChart2Axis.is() )
2226  return bExportDateScale;
2227 
2228  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2229  if ((nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) == 0) //do not export to ODF 1.3 or older
2230  return bExportDateScale;
2231 
2232  chart2::ScaleData aScale( rChart2Axis->getScaleData() );
2233  //#i25706#todo: change namespace for next ODF version
2234  sal_uInt16 nNameSpace = XML_NAMESPACE_CHART_EXT;
2235 
2236  switch(aScale.AxisType)
2237  {
2238  case chart2::AxisType::CATEGORY:
2239  if( aScale.AutoDateAxis )
2240  {
2241  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2242  bExportDateScale = true;
2243  }
2244  else
2245  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_TEXT );
2246  break;
2247  case chart2::AxisType::DATE:
2248  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_DATE );
2249  bExportDateScale = true;
2250  break;
2251  default: //AUTOMATIC
2252  rExport.AddAttribute( nNameSpace, XML_AXIS_TYPE, XML_AUTO );
2253  break;
2254  }
2255 
2256  return bExportDateScale;
2257 }
2258 
2259 void disableLinkedNumberFormat(
2260  std::vector<XMLPropertyState>& rPropStates, const rtl::Reference<XMLPropertySetMapper>& rMapper )
2261 {
2262  for (XMLPropertyState & rState : rPropStates)
2263  {
2264  if (rState.mnIndex < 0 || rMapper->GetEntryCount() <= rState.mnIndex)
2265  continue;
2266 
2267  OUString aXMLName = rMapper->GetEntryXMLName(rState.mnIndex);
2268 
2269  if (aXMLName != "link-data-style-to-source")
2270  continue;
2271 
2272  // Entry found. Set the value to false and bail out.
2273  rState.maValue <<= false;
2274  return;
2275  }
2276 
2277  // Entry not found. Insert a new entry for this.
2278  sal_Int32 nIndex = rMapper->GetEntryIndex(XML_NAMESPACE_CHART, u"link-data-style-to-source", 0);
2279  XMLPropertyState aState(nIndex);
2280  aState.maValue <<= false;
2281  rPropStates.push_back(aState);
2282 }
2283 
2284 }
2285 
2287  enum XMLTokenEnum eDimension,
2288  enum XMLTokenEnum eAxisName,
2289  const Reference< beans::XPropertySet >& rAxisProps,
2290  const Reference< chart2::XAxis >& rChart2Axis,
2291  const OUString& rCategoriesRange,
2292  bool bHasTitle, bool bHasMajorGrid, bool bHasMinorGrid,
2293  bool bExportContent, std::u16string_view sChartType )
2294 {
2295  std::vector< XMLPropertyState > aPropertyStates;
2296  std::unique_ptr<SvXMLElementExport> pAxis;
2297 
2298  // get property states for autostyles
2299  if( rAxisProps.is() && mxExpPropMapper.is() )
2300  {
2301  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2302  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED
2303  && eDimension == XML_X)
2304  {
2305  chart2::ScaleData aScaleData(rChart2Axis->getScaleData());
2306  bool bShiftedCatPos = aScaleData.ShiftedCategoryPosition;
2307  if (sChartType == u"com.sun.star.chart.BarDiagram" || sChartType == u"com.sun.star.chart.StockDiagram")
2308  {
2309  if (!bShiftedCatPos)
2310  rAxisProps->setPropertyValue("MajorOrigin", uno::makeAny(0.0));
2311  }
2312  else if (bShiftedCatPos)
2313  rAxisProps->setPropertyValue("MajorOrigin", uno::makeAny(0.5));
2314  }
2315 
2316  lcl_exportNumberFormat( "NumberFormat", rAxisProps, mrExport );
2317  aPropertyStates = mxExpPropMapper->Filter( rAxisProps );
2318 
2319  if (!maSrcShellID.isEmpty() && !maDestShellID.isEmpty() && maSrcShellID != maDestShellID)
2320  {
2321  // Disable link to source number format property when pasting to
2322  // a different doc shell. These shell ID's should be both empty
2323  // during real ODF export.
2324  disableLinkedNumberFormat(aPropertyStates, mxExpPropMapper->getPropertySetMapper());
2325  }
2326  }
2327 
2328  bool bExportDateScale = false;
2329  if( bExportContent )
2330  {
2333  AddAutoStyleAttribute( aPropertyStates ); // write style name
2334  if( !rCategoriesRange.isEmpty() )
2335  bExportDateScale = lcl_exportAxisType( rChart2Axis, mrExport );
2336 
2337  // open axis element
2338  pAxis.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_AXIS, true, true ));
2339  }
2340  else
2341  {
2342  CollectAutoStyle( aPropertyStates );
2343  }
2344  aPropertyStates.clear();
2345 
2346  //date scale
2347  if( bExportDateScale )
2348  exportDateScale( rAxisProps );
2349 
2351  Reference< beans::XPropertySet > xMajorGridProps;
2352  Reference< beans::XPropertySet > xMinorGridProps;
2353  Reference< chart::XAxis > xAxis( rAxisProps, uno::UNO_QUERY );
2354  if( xAxis.is() )
2355  {
2356  xTitleProps = bHasTitle ? xAxis->getAxisTitle() : nullptr;
2357  xMajorGridProps = bHasMajorGrid ? xAxis->getMajorGrid() : nullptr;
2358  xMinorGridProps = bHasMinorGrid ? xAxis->getMinorGrid() : nullptr;
2359  }
2360 
2361  // axis-title
2362  exportAxisTitle( xTitleProps , bExportContent );
2363 
2364  // categories if we have a categories chart
2365  if( bExportContent && !rCategoriesRange.isEmpty() )
2366  {
2368  SvXMLElementExport aCategories( mrExport, XML_NAMESPACE_CHART, XML_CATEGORIES, true, true );
2369  }
2370 
2371  // grid
2372  exportGrid( xMajorGridProps, true, bExportContent );
2373  exportGrid( xMinorGridProps, false, bExportContent );
2374 }
2375 
2377  const Reference< chart::XDiagram > & xDiagram,
2378  const Reference< chart2::XDiagram > & xNewDiagram,
2379  bool bExportContent )
2380 {
2381  SAL_WARN_IF( !xDiagram.is(), "xmloff.chart", "Invalid XDiagram as parameter" );
2382  if( ! xDiagram.is())
2383  return;
2384 
2385  // get some properties from document first
2386  bool bHasXAxis = false,
2387  bHasYAxis = false,
2388  bHasZAxis = false,
2389  bHasSecondaryXAxis = false,
2390  bHasSecondaryYAxis = false;
2391  bool bHasXAxisTitle = false,
2392  bHasYAxisTitle = false,
2393  bHasZAxisTitle = false,
2394  bHasSecondaryXAxisTitle = false,
2395  bHasSecondaryYAxisTitle = false;
2396  bool bHasXAxisMajorGrid = false,
2397  bHasXAxisMinorGrid = false,
2398  bHasYAxisMajorGrid = false,
2399  bHasYAxisMinorGrid = false,
2400  bHasZAxisMajorGrid = false,
2401  bHasZAxisMinorGrid = false;
2402 
2403  // get multiple properties using XMultiPropertySet
2404  MultiPropertySetHandler aDiagramProperties (xDiagram);
2405 
2406  aDiagramProperties.Add ("HasXAxis", bHasXAxis);
2407  aDiagramProperties.Add ("HasYAxis", bHasYAxis);
2408  aDiagramProperties.Add ("HasZAxis", bHasZAxis);
2409  aDiagramProperties.Add ("HasSecondaryXAxis", bHasSecondaryXAxis);
2410  aDiagramProperties.Add ("HasSecondaryYAxis", bHasSecondaryYAxis);
2411 
2412  aDiagramProperties.Add ("HasXAxisTitle", bHasXAxisTitle);
2413  aDiagramProperties.Add ("HasYAxisTitle", bHasYAxisTitle);
2414  aDiagramProperties.Add ("HasZAxisTitle", bHasZAxisTitle);
2415  aDiagramProperties.Add ("HasSecondaryXAxisTitle", bHasSecondaryXAxisTitle);
2416  aDiagramProperties.Add ("HasSecondaryYAxisTitle", bHasSecondaryYAxisTitle);
2417 
2418  aDiagramProperties.Add ("HasXAxisGrid", bHasXAxisMajorGrid);
2419  aDiagramProperties.Add ("HasYAxisGrid", bHasYAxisMajorGrid);
2420  aDiagramProperties.Add ("HasZAxisGrid", bHasZAxisMajorGrid);
2421 
2422  aDiagramProperties.Add ("HasXAxisHelpGrid", bHasXAxisMinorGrid);
2423  aDiagramProperties.Add ("HasYAxisHelpGrid", bHasYAxisMinorGrid);
2424  aDiagramProperties.Add ("HasZAxisHelpGrid", bHasZAxisMinorGrid);
2425 
2426  if ( ! aDiagramProperties.GetProperties ())
2427  {
2428  SAL_INFO("xmloff.chart", "Required properties not found in Chart diagram");
2429  }
2430 
2431  Reference< chart2::XCoordinateSystem > xCooSys( lcl_getCooSys(xNewDiagram) );
2432 
2433  // write an axis element also if the axis itself is not visible, but a grid or a title
2434 
2435  OUString aCategoriesRange;
2436  Reference< chart::XAxisSupplier > xAxisSupp( xDiagram, uno::UNO_QUERY );
2437  OUString sChartType = xDiagram->getDiagramType();
2438 
2439  // x axis
2440 
2441  Reference< css::chart2::XAxis > xNewAxis = lcl_getAxis( xCooSys, XML_X );
2442  if( xNewAxis.is() )
2443  {
2444  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(0) : nullptr, uno::UNO_QUERY );
2445  if( mbHasCategoryLabels && bExportContent )
2446  {
2447  Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2448  if( xCategories.is() )
2449  {
2450  Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2451  if( xValues.is() )
2452  {
2453  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2454  maCategoriesRange = xValues->getSourceRangeRepresentation();
2455  aCategoriesRange = lcl_ConvertRange( maCategoriesRange, xNewDoc );
2456  }
2457  }
2458  }
2459  exportAxis( XML_X, XML_PRIMARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasXAxisTitle, bHasXAxisMajorGrid, bHasXAxisMinorGrid, bExportContent, sChartType );
2460  aCategoriesRange.clear();
2461  }
2462 
2463  // secondary x axis
2464 
2465  xNewAxis = lcl_getAxis( xCooSys, XML_X, false );
2466  if( xNewAxis.is() )
2467  {
2468  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(0) : nullptr, uno::UNO_QUERY );
2469  exportAxis( XML_X, XML_SECONDARY_X, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryXAxisTitle, false, false, bExportContent, sChartType );
2470  }
2471 
2472  // y axis
2473 
2474  xNewAxis = lcl_getAxis( xCooSys, XML_Y );
2475  if( xNewAxis.is() )
2476  {
2477  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(1) : nullptr, uno::UNO_QUERY );
2478  exportAxis( XML_Y, XML_PRIMARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasYAxisTitle, bHasYAxisMajorGrid, bHasYAxisMinorGrid, bExportContent, sChartType );
2479  }
2480 
2481  // secondary y axis
2482 
2483  xNewAxis = lcl_getAxis( xCooSys, XML_Y, false );
2484  if( xNewAxis.is() )
2485  {
2486  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getSecondaryAxis(1) : nullptr, uno::UNO_QUERY );
2487  exportAxis( XML_Y, XML_SECONDARY_Y, xAxisProps, xNewAxis, aCategoriesRange, bHasSecondaryYAxisTitle, false, false, bExportContent, sChartType );
2488  }
2489 
2490  // z axis
2491 
2492  xNewAxis = lcl_getAxis( xCooSys, XML_Z );
2493  if( xNewAxis.is() )
2494  {
2495  Reference< beans::XPropertySet > xAxisProps( xAxisSupp.is() ? xAxisSupp->getAxis(2) : nullptr, uno::UNO_QUERY );
2496  exportAxis( XML_Z, XML_PRIMARY_Z, xAxisProps, xNewAxis, aCategoriesRange, bHasZAxisTitle, bHasZAxisMajorGrid, bHasZAxisMinorGrid, bExportContent, sChartType );
2497  }
2498 }
2499 
2500 namespace
2501 {
2502  bool lcl_hasNoValuesButText( const uno::Reference< chart2::data::XDataSequence >& xDataSequence )
2503  {
2504  if( !xDataSequence.is() )
2505  return false;//have no data
2506 
2507  Sequence< uno::Any > aData;
2508  Reference< chart2::data::XNumericalDataSequence > xNumericalDataSequence( xDataSequence, uno::UNO_QUERY );
2509  if( xNumericalDataSequence.is() )
2510  {
2511  Sequence< double > aDoubles( xNumericalDataSequence->getNumericalData() );
2512  if (std::any_of(aDoubles.begin(), aDoubles.end(), [](double fDouble) { return !std::isnan( fDouble ); }))
2513  return false;//have double value
2514  }
2515  else
2516  {
2517  aData = xDataSequence->getData();
2518  double fDouble = 0.0;
2519  bool bHaveDouble = std::any_of(aData.begin(), aData.end(),
2520  [&fDouble](const uno::Any& rData) { return (rData >>= fDouble) && !std::isnan( fDouble ); });
2521  if (bHaveDouble)
2522  return false;//have double value
2523  }
2524  //no values found
2525 
2526  Reference< chart2::data::XTextualDataSequence > xTextualDataSequence( xDataSequence, uno::UNO_QUERY );
2527  if( xTextualDataSequence.is() )
2528  {
2529  uno::Sequence< OUString > aStrings( xTextualDataSequence->getTextualData() );
2530  if (std::any_of(aStrings.begin(), aStrings.end(), [](const OUString& rString) { return !rString.isEmpty(); }))
2531  return true;//have text
2532  }
2533  else
2534  {
2535  if( !aData.hasElements() )
2536  aData = xDataSequence->getData();
2537  OUString aString;
2538  bool bHaveText = std::any_of(aData.begin(), aData.end(),
2539  [&aString](const uno::Any& rData) { return (rData >>= aString) && !aString.isEmpty(); });
2540  if (bHaveText)
2541  return true;//have text
2542  }
2543  //no doubles and no texts
2544  return false;
2545  }
2546 
2547 // ODF has the line and fill properties in a <style:style> element, which is referenced by the
2548 // <chart:data-label> element. But LibreOffice has them as special label properties of the series
2549 // or point respectively. The following method generates ODF from internal API name.
2550 void lcl_createDataLabelProperties(
2551  std::vector<XMLPropertyState>& rDataLabelPropertyStates,
2552  const Reference<beans::XPropertySet>& xPropSet,
2553  const rtl::Reference<XMLChartExportPropertyMapper>& xExpPropMapper)
2554 {
2555  if (!xExpPropMapper.is() || !xPropSet.is())
2556  return;
2557 
2558  const uno::Reference<beans::XPropertySetInfo> xInfo(xPropSet->getPropertySetInfo());
2559  const uno::Reference<beans::XPropertyState> xPropState(xPropSet, uno::UNO_QUERY);
2560  const rtl::Reference<XMLPropertySetMapper>& rPropertySetMapper(
2561  xExpPropMapper->getPropertySetMapper());
2562  if (!xInfo.is() || !xPropState.is() || !rPropertySetMapper.is())
2563  return;
2564 
2565  struct API2ODFMapItem
2566  {
2567  OUString sAPIName;
2568  sal_uInt16 nNameSpace; // from include/xmloff/xmlnamespace.hxx
2569  OUString sLocalName;
2570  API2ODFMapItem(const OUString& sAPI, const sal_uInt16 nNS, const OUString& sLocal)
2571  : sAPIName(sAPI)
2572  , nNameSpace(nNS)
2573  , sLocalName(sLocal)
2574  {
2575  }
2576  };
2577 
2578  const API2ODFMapItem aLabelFoo2ODFArray[]
2579  = { API2ODFMapItem("LabelBorderStyle", XML_NAMESPACE_DRAW, "stroke"),
2580  API2ODFMapItem("LabelBorderWidth", XML_NAMESPACE_SVG, "stroke-width"),
2581  API2ODFMapItem("LabelBorderColor", XML_NAMESPACE_SVG, "stroke-color"),
2582  API2ODFMapItem("LabelBorderDashName", XML_NAMESPACE_DRAW, "stroke-dash"),
2583  API2ODFMapItem("LabelBorderTransparency", XML_NAMESPACE_SVG, "stroke-opacity"),
2584  API2ODFMapItem("LabelFillStyle", XML_NAMESPACE_DRAW, "fill"),
2585  API2ODFMapItem("LabelFillBackground", XML_NAMESPACE_DRAW, "fill-hatch-solid"),
2586  API2ODFMapItem("LabelFillHatchName", XML_NAMESPACE_DRAW, "fill-hatch-name"),
2587  API2ODFMapItem("LabelFillColor", XML_NAMESPACE_DRAW, "fill-color") };
2588 
2589  for (const auto& rIt : aLabelFoo2ODFArray)
2590  {
2591  if (!xInfo->hasPropertyByName(rIt.sAPIName)
2592  || xPropState->getPropertyState(rIt.sAPIName) != beans::PropertyState_DIRECT_VALUE)
2593  continue;
2594  sal_Int32 nTargetIndex
2595  = rPropertySetMapper->GetEntryIndex(rIt.nNameSpace, rIt.sLocalName, 0);
2596  if (nTargetIndex < 0)
2597  continue;
2598  XMLPropertyState aDataLabelStateItem(nTargetIndex,
2599  xPropSet->getPropertyValue(rIt.sAPIName));
2600  rDataLabelPropertyStates.emplace_back(aDataLabelStateItem);
2601  }
2602 }
2603 } // anonymous namespace
2604 
2606  const Reference< chart2::XDiagram > & xNewDiagram,
2607  const awt::Size & rPageSize,
2608  bool bExportContent,
2609  bool bHasTwoYAxes )
2610 {
2611  Reference< chart2::XCoordinateSystemContainer > xBCooSysCnt( xNewDiagram, uno::UNO_QUERY );
2612  if( ! xBCooSysCnt.is())
2613  return;
2614  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2615 
2616  OUString aFirstXDomainRange;
2617  OUString aFirstYDomainRange;
2618 
2619  std::vector< XMLPropertyState > aPropertyStates;
2620  std::vector< XMLPropertyState > aDataLabelPropertyStates;
2621 
2622  const Sequence< Reference< chart2::XCoordinateSystem > >
2623  aCooSysSeq( xBCooSysCnt->getCoordinateSystems());
2624  for( const auto& rCooSys : aCooSysSeq )
2625  {
2626  Reference< chart2::XChartTypeContainer > xCTCnt( rCooSys, uno::UNO_QUERY );
2627  if( ! xCTCnt.is())
2628  continue;
2629  const Sequence< Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes());
2630  for( const auto& rChartType : aCTSeq )
2631  {
2632  Reference< chart2::XDataSeriesContainer > xDSCnt( rChartType, uno::UNO_QUERY );
2633  if( ! xDSCnt.is())
2634  continue;
2635  // note: if xDSCnt.is() then also aCTSeq[nCTIdx]
2636  OUString aChartType( rChartType->getChartType());
2637  OUString aLabelRole = rChartType->getRoleOfSequenceForSeriesLabel();
2638 
2639  // special export for stock charts
2640  if ( aChartType == "com.sun.star.chart2.CandleStickChartType" )
2641  {
2642  bool bJapaneseCandleSticks = false;
2643  Reference< beans::XPropertySet > xCTProp( rChartType, uno::UNO_QUERY );
2644  if( xCTProp.is())
2645  xCTProp->getPropertyValue("Japanese") >>= bJapaneseCandleSticks;
2647  xDSCnt->getDataSeries(), xNewDiagram, bJapaneseCandleSticks, bExportContent );
2648  continue;
2649  }
2650 
2651  // export dataseries for current chart-type
2652  Sequence< Reference< chart2::XDataSeries > > aSeriesSeq( xDSCnt->getDataSeries());
2653  for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeriesSeq.getLength(); ++nSeriesIdx )
2654  {
2655  // export series
2656  Reference< chart2::data::XDataSource > xSource( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY );
2657  if( xSource.is())
2658  {
2659  std::unique_ptr<SvXMLElementExport> pSeries;
2660  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2661  xSource->getDataSequences());
2662  sal_Int32 nMainSequenceIndex = -1;
2663  sal_Int32 nSeriesLength = 0;
2664  bool bHasMeanValueLine = false;
2666  tLabelValuesDataPair aSeriesLabelValuesPair;
2667 
2668  // search for main sequence and create a series element
2669  {
2670  Reference< chart2::data::XDataSequence > xValuesSeq;
2671  Reference< chart2::data::XDataSequence > xLabelSeq;
2672  sal_Int32 nSeqIdx=0;
2673  for( ; nSeqIdx<aSeqCnt.getLength(); ++nSeqIdx )
2674  {
2675  Reference< chart2::data::XDataSequence > xTempValueSeq( aSeqCnt[nSeqIdx]->getValues() );
2676  if( nMainSequenceIndex==-1 )
2677  {
2678  OUString aRole;
2679  Reference< beans::XPropertySet > xSeqProp( xTempValueSeq, uno::UNO_QUERY );
2680  if( xSeqProp.is())
2681  xSeqProp->getPropertyValue("Role") >>= aRole;
2682  // "main" sequence
2683  if( aRole == aLabelRole )
2684  {
2685  xValuesSeq.set( xTempValueSeq );
2686  xLabelSeq.set( aSeqCnt[nSeqIdx]->getLabel());
2687  nMainSequenceIndex = nSeqIdx;
2688  }
2689  }
2690  sal_Int32 nSequenceLength = (xTempValueSeq.is()? xTempValueSeq->getData().getLength() : sal_Int32(0));
2691  if( nSeriesLength < nSequenceLength )
2692  nSeriesLength = nSequenceLength;
2693  }
2694 
2695  // have found the main sequence, then xValuesSeq and
2696  // xLabelSeq contain those. Otherwise both are empty
2697  {
2698  sal_Int32 nAttachedAxis = chart::ChartAxisAssign::PRIMARY_Y;
2699  // get property states for autostyles
2700  try
2701  {
2703  aSeriesSeq[nSeriesIdx], mrExport.GetModel() );
2704  }
2705  catch( const uno::Exception & )
2706  {
2707  TOOLS_INFO_EXCEPTION("xmloff.chart", "Series not found or no XPropertySet" );
2708  continue;
2709  }
2710  if( xPropSet.is())
2711  {
2712  // determine attached axis
2713  try
2714  {
2715  Any aAny( xPropSet->getPropertyValue( "Axis" ));
2716  aAny >>= nAttachedAxis;
2717 
2718  aAny = xPropSet->getPropertyValue( "MeanValue" );
2719  aAny >>= bHasMeanValueLine;
2720  }
2721  catch( const beans::UnknownPropertyException & )
2722  {
2723  TOOLS_INFO_EXCEPTION("xmloff.chart", "Required property not found in DataRowProperties" );
2724  }
2725 
2726  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2727  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
2728  {
2729  lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
2730  lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
2731  }
2732 
2733  if( mxExpPropMapper.is())
2734  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
2735  }
2736 
2737  if( bExportContent )
2738  {
2739  if( bHasTwoYAxes )
2740  {
2741  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
2743  else
2745  }
2746 
2747  // write style name
2748  AddAutoStyleAttribute( aPropertyStates );
2749 
2750  if( xValuesSeq.is())
2752  lcl_ConvertRange(
2753  xValuesSeq->getSourceRangeRepresentation(),
2754  xNewDoc ));
2755  else
2756  // #i75297# allow empty series, export empty range to have all ranges on import
2758 
2759  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2760  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) // do not export to ODF 1.3 or older
2761  {
2762  if (xPropSet.is())
2763  {
2764  Any aAny = xPropSet->getPropertyValue("ShowLegendEntry");
2765  if (!aAny.get<bool>())
2766  {
2767  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDE_LEGEND, OUString::boolean(true));
2768  }
2769  }
2770  }
2771 
2772  if (xLabelSeq.is())
2773  {
2774  // Check if the label is direct string value rather than a reference.
2775  bool bHasString = false;
2776  uno::Reference<beans::XPropertySet> xLSProp(xLabelSeq, uno::UNO_QUERY);
2777  if (xLSProp.is())
2778  {
2779  try
2780  {
2781  xLSProp->getPropertyValue("HasStringLabel") >>= bHasString;
2782  }
2783  catch (const beans::UnknownPropertyException&) {}
2784  }
2785 
2786  OUString aRange = xLabelSeq->getSourceRangeRepresentation();
2787 
2788  if (bHasString)
2789  {
2792  }
2793  else
2794  {
2797  lcl_ConvertRange(
2798  xLabelSeq->getSourceRangeRepresentation(), xNewDoc));
2799  }
2800  }
2801 
2802  if( xLabelSeq.is() || xValuesSeq.is() )
2803  aSeriesLabelValuesPair = tLabelValuesDataPair( xLabelSeq, xValuesSeq );
2804 
2805  // chart-type for mixed types
2806  enum XMLTokenEnum eCTToken(
2807  SchXMLTools::getTokenByChartType( aChartType, false /* bUseOldNames */ ));
2808  //@todo: get token for current charttype
2811  XML_NAMESPACE_CHART, GetXMLToken( eCTToken )));
2812 
2813  // open series element until end of for loop
2814  pSeries.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true ));
2815  }
2816  else // autostyles
2817  {
2818  CollectAutoStyle( aPropertyStates );
2819  }
2820  // remove property states for autostyles
2821  aPropertyStates.clear();
2822  }
2823  }
2824 
2825  // export domain elements if we have a series parent element
2826  if( pSeries )
2827  {
2828  // domain elements
2829  if( bExportContent )
2830  {
2831  bool bIsScatterChart = aChartType == "com.sun.star.chart2.ScatterChartType";
2832  bool bIsBubbleChart = aChartType == "com.sun.star.chart2.BubbleChartType";
2833  Reference< chart2::data::XDataSequence > xYValuesForBubbleChart;
2834  if( bIsBubbleChart )
2835  {
2836  Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, "values-y" ) );
2837  if( xSequence.is() )
2838  {
2839  xYValuesForBubbleChart = xSequence->getValues();
2840  if( !lcl_exportDomainForThisSequence( xYValuesForBubbleChart, aFirstYDomainRange, mrExport ) )
2841  xYValuesForBubbleChart = nullptr;
2842  }
2843  }
2844  if( bIsScatterChart || bIsBubbleChart )
2845  {
2846  Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, "values-x" ) );
2847  if( xSequence.is() )
2848  {
2849  Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2850  if( lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport ) )
2851  m_aDataSequencesToExport.emplace_back(
2852  uno::Reference< chart2::data::XDataSequence >(), xValues );
2853  }
2854  else if( nSeriesIdx==0 )
2855  {
2856  //might be that the categories are used as x-values (e.g. for date axis) -> export them accordingly
2857  Reference< chart2::data::XLabeledDataSequence > xCategories( lcl_getCategories( xNewDiagram ) );
2858  if( xCategories.is() )
2859  {
2860  Reference< chart2::data::XDataSequence > xValues( xCategories->getValues() );
2861  if( !lcl_hasNoValuesButText( xValues ) )
2862  lcl_exportDomainForThisSequence( xValues, aFirstXDomainRange, mrExport );
2863  }
2864  }
2865  }
2866  if( xYValuesForBubbleChart.is() )
2867  m_aDataSequencesToExport.emplace_back(
2868  uno::Reference< chart2::data::XDataSequence >(), xYValuesForBubbleChart );
2869  }
2870  }
2871 
2872  // add sequences for main sequence after domain sequences,
2873  // so that the export of the local table has the correct order
2874  if( bExportContent &&
2875  (aSeriesLabelValuesPair.first.is() || aSeriesLabelValuesPair.second.is()))
2876  m_aDataSequencesToExport.push_back( aSeriesLabelValuesPair );
2877 
2878  // statistical objects:
2879  // regression curves and mean value lines
2880  if( bHasMeanValueLine &&
2881  xPropSet.is() &&
2882  mxExpPropMapper.is() )
2883  {
2885  try
2886  {
2887  Any aPropAny( xPropSet->getPropertyValue( "DataMeanValueProperties" ));
2888  aPropAny >>= xStatProp;
2889  }
2890  catch( const uno::Exception & )
2891  {
2892  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during Export of series - optional DataMeanValueProperties not available" );
2893  }
2894 
2895  if( xStatProp.is() )
2896  {
2897  aPropertyStates = mxExpPropMapper->Filter( xStatProp );
2898 
2899  if( !aPropertyStates.empty() )
2900  {
2901  // write element
2902  if( bExportContent )
2903  {
2904  // add style name attribute
2905  AddAutoStyleAttribute( aPropertyStates );
2906 
2908  }
2909  else // autostyles
2910  {
2911  CollectAutoStyle( aPropertyStates );
2912  }
2913  }
2914  }
2915  }
2916 
2917  if( xPropSet.is() &&
2918  mxExpPropMapper.is() )
2919  {
2920  exportRegressionCurve( aSeriesSeq[nSeriesIdx], rPageSize, bExportContent );
2921  }
2922 
2923  exportErrorBar( xPropSet,false, bExportContent ); // X ErrorBar
2924  exportErrorBar( xPropSet,true, bExportContent ); // Y ErrorBar
2925 
2927  uno::Reference< beans::XPropertySet >( aSeriesSeq[nSeriesIdx], uno::UNO_QUERY ),
2928  nSeriesLength, xNewDiagram, bExportContent );
2929 
2930  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
2931 
2932  // create <chart:data-label> child element if needed.
2933  if (xPropSet.is() && mxExpPropMapper.is())
2934  {
2935  // Generate style for <chart:data-label> child element
2936  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
2937  {
2938  lcl_createDataLabelProperties(aDataLabelPropertyStates, xPropSet,
2939  mxExpPropMapper);
2940  }
2941  }
2942  if (bExportContent)
2943  {
2944  if (!aDataLabelPropertyStates.empty())
2945  {
2946  // write style name
2947  AddAutoStyleAttribute(aDataLabelPropertyStates);
2948  // Further content does currently not exist for a <chart:data-label>
2949  // element as child of a <chart:series>.
2951  true);
2952  }
2953  }
2954  else
2955  {
2956  // add the style for the to be <chart:data-label> too
2957  if (!aDataLabelPropertyStates.empty())
2958  CollectAutoStyle(aDataLabelPropertyStates);
2959  }
2960  aDataLabelPropertyStates.clear();
2961 
2962  if (bExportContent && nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) // do not export to ODF 1.3 or older
2963  {
2964  Sequence< OUString > aSupportedMappings = rChartType->getSupportedPropertyRoles();
2965  exportPropertyMapping( xSource, aSupportedMappings );
2966  }
2967 
2968  // close series element
2969  pSeries.reset();
2970  }
2971  }
2972  aPropertyStates.clear();
2973  aDataLabelPropertyStates.clear();
2974  }
2975  }
2976 }
2977 
2979  const Reference< chart2::data::XDataSource > & xSource, const Sequence< OUString >& rSupportedMappings )
2980 {
2981  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
2982  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
2983  xSource->getDataSequences());
2984 
2985  for(const auto& rSupportedMapping : rSupportedMappings)
2986  {
2987  Reference< chart2::data::XLabeledDataSequence > xSequence( lcl_getDataSequenceByRole( aSeqCnt, rSupportedMapping ) );
2988  if(xSequence.is())
2989  {
2990  Reference< chart2::data::XDataSequence > xValues( xSequence->getValues() );
2991  if( xValues.is())
2992  {
2995  lcl_ConvertRange(
2996  xValues->getSourceRangeRepresentation(),
2997  xNewDoc ));
2999 
3000  // register range for data table export
3001  m_aDataSequencesToExport.emplace_back(
3002  uno::Reference< chart2::data::XDataSequence >(), xValues );
3003  }
3004  }
3005  }
3006 }
3007 
3009  const Reference< chart2::XDataSeries >& xSeries,
3010  const awt::Size& rPageSize,
3011  bool bExportContent )
3012 {
3013  OSL_ASSERT( mxExpPropMapper.is());
3014 
3015  Reference< chart2::XRegressionCurveContainer > xRegressionCurveContainer( xSeries, uno::UNO_QUERY );
3016  if( !xRegressionCurveContainer.is() )
3017  return;
3018 
3019  const Sequence< Reference< chart2::XRegressionCurve > > aRegCurveSeq = xRegressionCurveContainer->getRegressionCurves();
3020 
3021  for( const auto& xRegCurve : aRegCurveSeq )
3022  {
3023  std::vector< XMLPropertyState > aEquationPropertyStates;
3024  if (!xRegCurve.is())
3025  continue;
3026 
3027  Reference< beans::XPropertySet > xProperties( xRegCurve , uno::UNO_QUERY );
3028  if( !xProperties.is() )
3029  continue;
3030 
3031  Reference< lang::XServiceName > xServiceName( xProperties, uno::UNO_QUERY );
3032  if( !xServiceName.is() )
3033  continue;
3034 
3035  bool bShowEquation = false;
3036  bool bShowRSquared = false;
3037  bool bExportEquation = false;
3038 
3039  OUString aService = xServiceName->getServiceName();
3040 
3041  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xProperties );
3042 
3043  // Add service name (which is regression type)
3044  sal_Int32 nIndex = GetPropertySetMapper()->FindEntryIndex(XML_SCH_CONTEXT_SPECIAL_REGRESSION_TYPE);
3045  XMLPropertyState property(nIndex, uno::makeAny(aService));
3046  aPropertyStates.push_back(property);
3047 
3048  Reference< beans::XPropertySet > xEquationProperties;
3049  xEquationProperties.set( xRegCurve->getEquationProperties() );
3050  if( xEquationProperties.is())
3051  {
3052  xEquationProperties->getPropertyValue( "ShowEquation") >>= bShowEquation;
3053  xEquationProperties->getPropertyValue( "ShowCorrelationCoefficient") >>= bShowRSquared;
3054 
3055  bExportEquation = ( bShowEquation || bShowRSquared );
3056  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3057  if (nCurrentVersion < SvtSaveOptions::ODFSVER_012)
3058  {
3059  bExportEquation=false;
3060  }
3061  if( bExportEquation )
3062  {
3063  // number format
3064  sal_Int32 nNumberFormat = 0;
3065  if( (xEquationProperties->getPropertyValue("NumberFormat") >>= nNumberFormat ) &&
3066  nNumberFormat != -1 )
3067  {
3068  mrExport.addDataStyle( nNumberFormat );
3069  }
3070  aEquationPropertyStates = mxExpPropMapper->Filter( xEquationProperties );
3071  }
3072  }
3073 
3074  if( !aPropertyStates.empty() || bExportEquation )
3075  {
3076  // write element
3077  if( bExportContent )
3078  {
3079  // add style name attribute
3080  if( !aPropertyStates.empty())
3081  {
3082  AddAutoStyleAttribute( aPropertyStates );
3083  }
3084 
3085  SvXMLElementExport aRegressionExport( mrExport, XML_NAMESPACE_CHART, XML_REGRESSION_CURVE, true, true );
3086  if( bExportEquation )
3087  {
3089  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DISPLAY_R_SQUARE, (bShowRSquared ? XML_TRUE : XML_FALSE) );
3090 
3091  // export position
3092  chart2::RelativePosition aRelativePosition;
3093  if( xEquationProperties->getPropertyValue( "RelativePosition" ) >>= aRelativePosition )
3094  {
3095  double fX = aRelativePosition.Primary * rPageSize.Width;
3096  double fY = aRelativePosition.Secondary * rPageSize.Height;
3097  awt::Point aPos;
3098  aPos.X = static_cast< sal_Int32 >( ::rtl::math::round( fX ));
3099  aPos.Y = static_cast< sal_Int32 >( ::rtl::math::round( fY ));
3100  addPosition( aPos );
3101  }
3102 
3103  if( !aEquationPropertyStates.empty())
3104  {
3105  AddAutoStyleAttribute( aEquationPropertyStates );
3106  }
3107 
3109  }
3110  }
3111  else // autostyles
3112  {
3113  if( !aPropertyStates.empty())
3114  {
3115  CollectAutoStyle( aPropertyStates );
3116  }
3117  if( bExportEquation && !aEquationPropertyStates.empty())
3118  {
3119  CollectAutoStyle( aEquationPropertyStates );
3120  }
3121  }
3122  }
3123  }
3124 }
3125 
3127  bool bYError, bool bExportContent )
3128 {
3129  assert(mxExpPropMapper.is());
3130 
3131  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3132 
3134  if (!bYError && nCurrentVersion < SvtSaveOptions::ODFSVER_012)
3135  return;
3136 
3137  if (!xSeriesProp.is())
3138  return;
3139 
3140  bool bNegative = false, bPositive = false;
3141  sal_Int32 nErrorBarStyle = chart::ErrorBarStyle::NONE;
3142  Reference< beans::XPropertySet > xErrorBarProp;
3143 
3144  try
3145  {
3146  Any aAny = xSeriesProp->getPropertyValue( bYError ? OUString("ErrorBarY") : OUString("ErrorBarX") );
3147  aAny >>= xErrorBarProp;
3148 
3149  if ( xErrorBarProp.is() )
3150  {
3151  aAny = xErrorBarProp->getPropertyValue("ShowNegativeError" );
3152  aAny >>= bNegative;
3153 
3154  aAny = xErrorBarProp->getPropertyValue("ShowPositiveError" );
3155  aAny >>= bPositive;
3156 
3157  aAny = xErrorBarProp->getPropertyValue("ErrorBarStyle" );
3158  aAny >>= nErrorBarStyle;
3159  }
3160  }
3161  catch( const beans::UnknownPropertyException & )
3162  {
3163  TOOLS_INFO_EXCEPTION("xmloff.chart", "Required property not found in DataRowProperties" );
3164  }
3165 
3166  if( !(nErrorBarStyle != chart::ErrorBarStyle::NONE && (bNegative || bPositive)))
3167  return;
3168 
3169  if( bExportContent && nErrorBarStyle == chart::ErrorBarStyle::FROM_DATA )
3170  {
3171  // register data ranges for error bars for export in local table
3172  ::std::vector< Reference< chart2::data::XDataSequence > > aErrorBarSequences(
3173  lcl_getErrorBarSequences( xErrorBarProp ));
3174  for( const auto& rErrorBarSequence : aErrorBarSequences )
3175  {
3176  m_aDataSequencesToExport.emplace_back(
3177  uno::Reference< chart2::data::XDataSequence >(), rErrorBarSequence );
3178  }
3179  }
3180 
3181  std::vector< XMLPropertyState > aPropertyStates = mxExpPropMapper->Filter( xErrorBarProp );
3182 
3183  if( aPropertyStates.empty() )
3184  return;
3185 
3186  // write element
3187  if( bExportContent )
3188  {
3189  // add style name attribute
3190  AddAutoStyleAttribute( aPropertyStates );
3191 
3192  if (nCurrentVersion >= SvtSaveOptions::ODFSVER_012)
3193  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_DIMENSION, bYError ? XML_Y : XML_X );//#i114149#
3195  }
3196  else // autostyles
3197  {
3198  CollectAutoStyle( aPropertyStates );
3199  }
3200 }
3201 
3203  const Sequence< Reference< chart2::XDataSeries > > & aSeriesSeq,
3204  const Reference< chart2::XDiagram > & xDiagram,
3205  bool bJapaneseCandleSticks,
3206  bool bExportContent )
3207 {
3208 
3209  for( const auto& xSeries : aSeriesSeq )
3210  {
3211  sal_Int32 nAttachedAxis = lcl_isSeriesAttachedToFirstAxis( xSeries )
3212  ? chart::ChartAxisAssign::PRIMARY_Y
3213  : chart::ChartAxisAssign::SECONDARY_Y;
3214 
3215  Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
3216  if( xSource.is())
3217  {
3218  // export series in correct order (as we don't store roles)
3219  // with japanese candlesticks: open, low, high, close
3220  // otherwise: low, high, close
3221  Sequence< Reference< chart2::data::XLabeledDataSequence > > aSeqCnt(
3222  xSource->getDataSequences());
3223 
3224  sal_Int32 nSeriesLength =
3225  lcl_getSequenceLengthByRole( aSeqCnt, "values-last");
3226 
3227  if( bExportContent )
3228  {
3229  Reference< chart2::XChartDocument > xNewDoc( mrExport.GetModel(), uno::UNO_QUERY );
3230  //@todo: export data points
3231 
3232  //TODO: moggi: same code three times
3233  // open
3234  if( bJapaneseCandleSticks )
3235  {
3236  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3237  aSeqCnt, "values-first", xNewDoc, m_aDataSequencesToExport ));
3238  if( !aRanges.second.isEmpty())
3240  if( !aRanges.first.isEmpty())
3242  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3244  else
3246  SvXMLElementExport aOpenSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3247  // export empty data points
3248  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3249  }
3250 
3251  // low
3252  {
3253  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3254  aSeqCnt, "values-min", xNewDoc, m_aDataSequencesToExport ));
3255  if( !aRanges.second.isEmpty())
3257  if( !aRanges.first.isEmpty())
3259  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3261  else
3263  SvXMLElementExport aLowSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3264  // export empty data points
3265  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3266  }
3267 
3268  // high
3269  {
3270  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3271  aSeqCnt, "values-max", xNewDoc, m_aDataSequencesToExport ));
3272  if( !aRanges.second.isEmpty())
3274  if( !aRanges.first.isEmpty())
3276  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3278  else
3280  SvXMLElementExport aHighSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3281  // export empty data points
3282  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3283  }
3284 
3285  // close
3286  {
3287  tLabelAndValueRange aRanges( lcl_getLabelAndValueRangeByRole(
3288  aSeqCnt, "values-last", xNewDoc, m_aDataSequencesToExport ));
3289  if( !aRanges.second.isEmpty())
3291  if( !aRanges.first.isEmpty())
3293  if( nAttachedAxis == chart::ChartAxisAssign::SECONDARY_Y )
3295  else
3297  SvXMLElementExport aCloseSeries( mrExport, XML_NAMESPACE_CHART, XML_SERIES, true, true );
3298  // export empty data points
3299  exportDataPoints( nullptr, nSeriesLength, xDiagram, bExportContent );
3300  }
3301  }
3302  else // autostyles
3303  {
3304  // for close series
3305  }
3306  // remove property states for autostyles
3307  }
3308  }
3309 }
3310 
3312  const uno::Reference< beans::XPropertySet > & xSeriesProperties,
3313  sal_Int32 nSeriesLength,
3314  const uno::Reference< chart2::XDiagram > & xDiagram,
3315  bool bExportContent )
3316 {
3317  // data-points
3318 
3319  // write data-points only if they contain autostyles
3320  // objects with equal autostyles are grouped using the attribute
3321  // repeat="number"
3322 
3323  // Note: if only the nth data-point has autostyles there is an element
3324  // without style and repeat="n-1" attribute written in advance.
3325 
3326  // the sequence aDataPointSeq contains indices of data-points that
3327  // do have own attributes. This increases the performance substantially.
3328 
3329  // more performant version for #93600#
3330  if (!mxExpPropMapper.is())
3331  return;
3332 
3333  uno::Reference< chart2::XDataSeries > xSeries( xSeriesProperties, uno::UNO_QUERY );
3334 
3335  std::vector< XMLPropertyState > aPropertyStates;
3336  std::vector<XMLPropertyState> aDataLabelPropertyStates;
3337 
3338  bool bVaryColorsByPoint = false;
3339  Sequence< sal_Int32 > aDataPointSeq;
3340  Sequence<sal_Int32> deletedLegendEntriesSeq;
3341  if( xSeriesProperties.is())
3342  {
3343  xSeriesProperties->getPropertyValue("AttributedDataPoints") >>= aDataPointSeq;
3344  xSeriesProperties->getPropertyValue("VaryColorsByPoint") >>= bVaryColorsByPoint;
3345 
3346  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3347  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED) // do not export to ODF 1.3 or older
3348  xSeriesProperties->getPropertyValue("DeletedLegendEntries") >>= deletedLegendEntriesSeq;
3349  }
3350 
3351  sal_Int32 nSize = aDataPointSeq.getLength();
3352  SAL_WARN_IF( nSize > nSeriesLength, "xmloff.chart", "Too many point attributes" );
3353 
3354  const sal_Int32 * pPoints = aDataPointSeq.getConstArray();
3355  sal_Int32 nElement;
3356  Reference< chart2::XColorScheme > xColorScheme;
3357  if( xDiagram.is())
3358  xColorScheme.set( xDiagram->getDefaultColorScheme());
3359 
3360  ::std::vector< SchXMLDataPointStruct > aDataPointVector;
3361 
3362  sal_Int32 nLastIndex = -1;
3363 
3364  // collect elements
3365  if( bVaryColorsByPoint && xColorScheme.is() )
3366  {
3367  o3tl::sorted_vector< sal_Int32 > aAttrPointSet;
3368  aAttrPointSet.reserve(aDataPointSeq.getLength());
3369  for (auto p = pPoints; p < pPoints + aDataPointSeq.getLength(); ++p)
3370  aAttrPointSet.insert( *p );
3371  const auto aEndIt = aAttrPointSet.end();
3372  for( nElement = 0; nElement < nSeriesLength; ++nElement )
3373  {
3374  aPropertyStates.clear();
3375  aDataLabelPropertyStates.clear();
3376  uno::Reference< beans::XPropertySet > xPropSet;
3377  bool bExportNumFmt = false;
3378  if( aAttrPointSet.find( nElement ) != aEndIt )
3379  {
3380  try
3381  {
3383  xSeries, nElement, mrExport.GetModel() );
3384  bExportNumFmt = true;
3385  }
3386  catch( const uno::Exception & )
3387  {
3388  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during Export of data point" );
3389  }
3390  }
3391  else
3392  {
3393  // property set only containing the color
3394  xPropSet.set( new ::xmloff::chart::ColorPropertySet(
3395  xColorScheme->getColorByIndex( nElement )));
3396  }
3397  SAL_WARN_IF( !xPropSet.is(), "xmloff.chart", "Pie Segments should have properties" );
3398  if( xPropSet.is())
3399  {
3400  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3401  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012 && bExportNumFmt)
3402  {
3403  lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3404  lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3405  }
3406 
3407  // Generate style for <chart:data-label> child element
3408  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
3409  {
3410  lcl_createDataLabelProperties(aDataLabelPropertyStates, xPropSet,
3411  mxExpPropMapper);
3412  }
3413 
3414  if (nCurrentODFVersion & SvtSaveOptions::ODFSVER_EXTENDED)
3415  {
3416  sal_Int32 nPlacement = 0;
3417  xPropSet->getPropertyValue("LabelPlacement") >>= nPlacement;
3418  if (nPlacement == chart::DataLabelPlacement::CUSTOM)
3419  {
3420  xPropSet->setPropertyValue("LabelPlacement",
3421  uno::Any(chart::DataLabelPlacement::OUTSIDE));
3422  }
3423  }
3424 
3425  aPropertyStates = mxExpPropMapper->Filter(xPropSet);
3426  if (!aPropertyStates.empty() || !aDataLabelPropertyStates.empty())
3427  {
3428  if (bExportContent)
3429  {
3430  // write data-point with style
3431  SchXMLDataPointStruct aPoint;
3432  if (!aPropertyStates.empty())
3433  {
3434  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3435  "Autostyle queue empty!");
3436  aPoint.maStyleName = maAutoStyleNameQueue.front();
3437  maAutoStyleNameQueue.pop();
3438  }
3439  if (!aDataLabelPropertyStates.empty())
3440  {
3441  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3442  "Autostyle queue empty!");
3443  aPoint.msDataLabelStyleName = maAutoStyleNameQueue.front();
3444  maAutoStyleNameQueue.pop();
3445  }
3446  if(bExportNumFmt)
3447  aPoint.mCustomLabelText = lcl_getCustomLabelField(nElement, xSeries);
3448  aPoint.mCustomLabelPos = lcl_getCustomLabelPosition(nElement, xSeries);
3449 
3450  aDataPointVector.push_back( aPoint );
3451  }
3452  else
3453  {
3454  if (!aPropertyStates.empty())
3455  CollectAutoStyle(aPropertyStates);
3456  if (!aDataLabelPropertyStates.empty())
3457  CollectAutoStyle(aDataLabelPropertyStates);
3458  }
3459  }
3460  }
3461  }
3462  SAL_WARN_IF( bExportContent && (static_cast<sal_Int32>(aDataPointVector.size()) != nSeriesLength), "xmloff.chart", "not enough data points on content export" );
3463  }
3464  else
3465  {
3466  for( sal_Int32 nCurrIndex : aDataPointSeq )
3467  {
3468  aPropertyStates.clear();
3469  aDataLabelPropertyStates.clear();
3470  //assuming sorted indices in pPoints
3471 
3472  if( nCurrIndex<0 || nCurrIndex>=nSeriesLength )
3473  break;
3474 
3475  // write leading empty data points
3476  if( nCurrIndex - nLastIndex > 1 )
3477  {
3478  SchXMLDataPointStruct aPoint;
3479  aPoint.mnRepeat = nCurrIndex - nLastIndex - 1;
3480  aDataPointVector.push_back( aPoint );
3481  }
3482 
3483  uno::Reference< beans::XPropertySet > xPropSet;
3484  // get property states
3485  try
3486  {
3488  xSeries, nCurrIndex, mrExport.GetModel() );
3489  }
3490  catch( const uno::Exception & )
3491  {
3492  TOOLS_INFO_EXCEPTION("xmloff.chart", "Exception caught during Export of data point" );
3493  }
3494  if( xPropSet.is())
3495  {
3496  const SvtSaveOptions::ODFSaneDefaultVersion nCurrentODFVersion(SvtSaveOptions().GetODFSaneDefaultVersion());
3497  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
3498  {
3499  lcl_exportNumberFormat( "NumberFormat", xPropSet, mrExport );
3500  lcl_exportNumberFormat( "PercentageNumberFormat", xPropSet, mrExport );
3501  }
3502 
3503  // Generate style for <chart:data-label> child element
3504  if (nCurrentODFVersion >= SvtSaveOptions::ODFSVER_012)
3505  {
3506  lcl_createDataLabelProperties(aDataLabelPropertyStates, xPropSet,
3507  mxExpPropMapper);
3508  }
3509 
3510  aPropertyStates = mxExpPropMapper->Filter( xPropSet );
3511 
3512  if (!aPropertyStates.empty() || !aDataLabelPropertyStates.empty())
3513  {
3514  if( bExportContent )
3515  {
3516  // write data-point with style
3517  SchXMLDataPointStruct aPoint;
3518  if (!aPropertyStates.empty())
3519  {
3520  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3521  "Autostyle queue empty!");
3522  aPoint.maStyleName = maAutoStyleNameQueue.front();
3523  maAutoStyleNameQueue.pop();
3524  }
3525  aPoint.mCustomLabelText = lcl_getCustomLabelField(nCurrIndex, xSeries);
3526  aPoint.mCustomLabelPos = lcl_getCustomLabelPosition(nCurrIndex, xSeries);
3527  if (!aDataLabelPropertyStates.empty())
3528  {
3529  SAL_WARN_IF(maAutoStyleNameQueue.empty(), "xmloff.chart",
3530  "Autostyle queue empty!");
3531  aPoint.msDataLabelStyleName = maAutoStyleNameQueue.front();
3532  maAutoStyleNameQueue.pop();
3533  }
3534 
3535  aDataPointVector.push_back( aPoint );
3536  nLastIndex = nCurrIndex;
3537  }
3538  else
3539  {
3540  if (!aPropertyStates.empty())
3541  CollectAutoStyle(aPropertyStates);
3542  if (!aDataLabelPropertyStates.empty())
3543  CollectAutoStyle(aDataLabelPropertyStates);
3544  }
3545  continue;
3546  }
3547  }
3548 
3549  // if we get here the property states are empty
3550  SchXMLDataPointStruct aPoint;
3551  aDataPointVector.push_back( aPoint );
3552 
3553  nLastIndex = nCurrIndex;
3554  }
3555  // final empty elements
3556  sal_Int32 nRepeat = nSeriesLength - nLastIndex - 1;
3557  if( nRepeat > 0 )
3558  {
3559  SchXMLDataPointStruct aPoint;
3560  aPoint.mnRepeat = nRepeat;
3561  aDataPointVector.push_back( aPoint );
3562  }
3563  }
3564 
3565  if (!bExportContent)
3566  return;
3567 
3568  // write elements (merge equal ones)
3569  SchXMLDataPointStruct aPoint;
3570  SchXMLDataPointStruct aLastPoint;
3571 
3572  // initialize so that it doesn't matter if
3573  // the element is counted in the first iteration
3574  aLastPoint.mnRepeat = 0;
3575  sal_Int32 nIndex = 0;
3576  for( const auto& rPoint : aDataPointVector )
3577  {
3578  aPoint = rPoint;
3579 
3580  if (aPoint.maStyleName == aLastPoint.maStyleName
3581  && aLastPoint.mCustomLabelText.getLength() < 1
3582  && aLastPoint.mCustomLabelPos.Primary == 0.0
3583  && aLastPoint.mCustomLabelPos.Secondary == 0.0
3584  && aPoint.msDataLabelStyleName == aLastPoint.msDataLabelStyleName)
3585  aPoint.mnRepeat += aLastPoint.mnRepeat;
3586  else if( aLastPoint.mnRepeat > 0 )
3587  {
3588  // write last element
3589  if( !aLastPoint.maStyleName.isEmpty() )
3590  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3591 
3592  if( aLastPoint.mnRepeat > 1 )
3594  OUString::number( ( aLastPoint.mnRepeat ) ));
3595 
3596  for (auto& deletedLegendEntry : deletedLegendEntriesSeq)
3597  {
3598  if (nIndex == deletedLegendEntry)
3599  {
3600  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDE_LEGEND, OUString::boolean(true));
3601  break;
3602  }
3603  }
3604  nIndex++;
3605  exportCustomLabelPosition(aLastPoint.mCustomLabelPos); // adds attributes
3606  SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3607  exportCustomLabel(aLastPoint);
3608  }
3609  aLastPoint = aPoint;
3610  }
3611  // write last element if it hasn't been written in last iteration
3612  if( aPoint.maStyleName != aLastPoint.maStyleName )
3613  return;
3614 
3615  if( !aLastPoint.maStyleName.isEmpty() )
3616  mrExport.AddAttribute( XML_NAMESPACE_CHART, XML_STYLE_NAME, aLastPoint.maStyleName );
3617 
3618  if( aLastPoint.mnRepeat > 1 )
3620  OUString::number( ( aLastPoint.mnRepeat ) ));
3621 
3622  for (auto& deletedLegendEntry : deletedLegendEntriesSeq)
3623  {
3624  if (nIndex == deletedLegendEntry)
3625  {
3626  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_HIDE_LEGEND, OUString::boolean(true));
3627  break;
3628  }
3629  }
3630 
3631  exportCustomLabelPosition(aLastPoint.mCustomLabelPos); // adds attributes
3632  SvXMLElementExport aPointElem( mrExport, XML_NAMESPACE_CHART, XML_DATA_POINT, true, true );
3633  exportCustomLabel(aLastPoint);
3634 }
3635 
3636 void SchXMLExportHelper_Impl::exportCustomLabel(const SchXMLDataPointStruct& rPoint)
3637 {
3638  if (rPoint.mCustomLabelText.getLength() < 1 && rPoint.msDataLabelStyleName.isEmpty())
3639  return; // nothing to export
3640 
3641  if (!rPoint.msDataLabelStyleName.isEmpty())
3642  mrExport.AddAttribute(XML_NAMESPACE_CHART, XML_STYLE_NAME, rPoint.msDataLabelStyleName);
3643  // TODO svg:x and svg:y for <chart:data-label>
3645  SvXMLElementExport aPara( mrExport, XML_NAMESPACE_TEXT, XML_P, true, false );
3646  for (const Reference<chart2::XDataPointCustomLabelField>& label : rPoint.mCustomLabelText)
3647  {
3648  // TODO add style
3649  SvXMLElementExport aSpan( mrExport, XML_NAMESPACE_TEXT, XML_SPAN, true, false);
3650  mrExport.GetDocHandler()->characters(label->getString());
3651  }
3652 }
3653 
3654 void SchXMLExportHelper_Impl::exportCustomLabelPosition( const chart2::RelativePosition & xCustomLabelPosition)
3655 {
3656  if( xCustomLabelPosition.Primary == 0.0 && xCustomLabelPosition.Secondary == 0.0 )
3657  return; // nothing to export
3658 
3659  OUStringBuffer aCustomLabelPosString;
3660  ::sax::Converter::convertDouble(aCustomLabelPosString, xCustomLabelPosition.Primary);
3661  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_CUSTOM_LABEL_POS_X, aCustomLabelPosString.makeStringAndClear());
3662 
3663  ::sax::Converter::convertDouble(aCustomLabelPosString, xCustomLabelPosition.Secondary);
3664  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_CUSTOM_LABEL_POS_Y, aCustomLabelPosString.makeStringAndClear());
3665 }
3666 
3667 void SchXMLExportHelper_Impl::addPosition( const awt::Point & rPosition )
3668 {
3670  msStringBuffer, rPosition.X );
3671  msString = msStringBuffer.makeStringAndClear();
3673 
3675  msStringBuffer, rPosition.Y );
3676  msString = msStringBuffer.makeStringAndClear();
3678 }
3679 
3680 void SchXMLExportHelper_Impl::addPosition( const Reference< drawing::XShape >& xShape )
3681 {
3682  if( xShape.is())
3683  addPosition( xShape->getPosition());
3684 }
3685 
3686 void SchXMLExportHelper_Impl::addSize( const awt::Size & rSize, bool bIsOOoNamespace)
3687 {
3689  msStringBuffer, rSize.Width );
3690  msString = msStringBuffer.makeStringAndClear();
3692 
3694  msStringBuffer, rSize.Height);
3695  msString = msStringBuffer.makeStringAndClear();
3696  mrExport.AddAttribute( bIsOOoNamespace ? XML_NAMESPACE_CHART_EXT : XML_NAMESPACE_SVG, XML_HEIGHT, msString );
3697 }
3698 
3699 void SchXMLExportHelper_Impl::addSize( const Reference< drawing::XShape >& xShape )
3700 {
3701  if( xShape.is())
3702  addSize( xShape->getSize() );
3703 }
3704 
3705 awt::Size SchXMLExportHelper_Impl::getPageSize( const Reference< chart2::XChartDocument > & xChartDoc )
3706 {
3707  awt::Size aSize( 8000, 7000 );
3708  uno::Reference< embed::XVisualObject > xVisualObject( xChartDoc, uno::UNO_QUERY );
3709  SAL_WARN_IF( !xVisualObject.is(), "xmloff.chart", "need XVisualObject for page size" );
3710  if( xVisualObject.is() )
3711  aSize = xVisualObject->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
3712 
3713  return aSize;
3714 }
3715 
3716 void SchXMLExportHelper_Impl::CollectAutoStyle( const std::vector< XMLPropertyState >& aStates )
3717 {
3718  if( !aStates.empty() )
3720 }
3721 
3722 void SchXMLExportHelper_Impl::AddAutoStyleAttribute( const std::vector< XMLPropertyState >& aStates )
3723 {
3724  if( !aStates.empty() )
3725  {
3726  SAL_WARN_IF( maAutoStyleNameQueue.empty(), "xmloff.chart", "Autostyle queue empty!" );
3727 
3729  maAutoStyleNameQueue.pop();
3730  }
3731 }
3732 
3733 void SchXMLExportHelper_Impl::exportText( const OUString& rText )
3734 {
3735  SchXMLTools::exportText( mrExport, rText, false/*bConvertTabsLFs*/ );
3736 }
3737 
3738 
3740  OUString const& implementationName, SvXMLExportFlags nExportFlags)
3741  : SvXMLExport(xContext, implementationName, util::MeasureUnit::CM, ::xmloff::token::XML_CHART,
3742  nExportFlags)
3743  , maAutoStylePool(new SchXMLAutoStylePoolP(*this))
3744  , maExportHelper(new SchXMLExportHelper(*this, *maAutoStylePool))
3745 {
3746  if (getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
3748 }
3749 
3751 {
3752 }
3753 
3755 {
3756  maExportHelper->SetSourceShellID(GetSourceShellID());
3757  maExportHelper->SetDestinationShellID(GetDestinationShellID());
3758 
3759  Reference< chart2::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3760  maExportHelper->m_pImpl->InitRangeSegmentationProperties( xChartDoc );
3761  return SvXMLExport::exportDoc( eClass );
3762 }
3763 
3765 {
3766  // not available in chart
3767  SAL_INFO("xmloff.chart", "Master Style Export requested. Not available for Chart" );
3768 }
3769 
3771 {
3773 
3775  return;
3776 
3777  // there are no styles that require their own autostyles
3779  {
3780  Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3781  if( xChartDoc.is())
3782  {
3783  maExportHelper->m_pImpl->collectAutoStyles( xChartDoc );
3784  }
3785  else
3786  {
3787  SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3788  }
3789  }
3790  mbAutoStylesCollected = true;
3791 }
3792 
3794 {
3796 
3798  {
3799  Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3800  if( xChartDoc.is())
3801  {
3802  maExportHelper->m_pImpl->exportAutoStyles();
3803  }
3804  else
3805  {
3806  SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel (must be XChartDocument)" );
3807  }
3808  }
3809 }
3810 
3812 {
3813  Reference< chart::XChartDocument > xChartDoc( GetModel(), uno::UNO_QUERY );
3814  if( xChartDoc.is())
3815  {
3816  // determine if data comes from the outside
3817  bool bIncludeTable = true;
3818 
3819  Reference< chart2::XChartDocument > xNewDoc( xChartDoc, uno::UNO_QUERY );
3820  if( xNewDoc.is())
3821  {
3822  // check if we have own data. If so we must not export the complete
3823  // range string, as this is our only indicator for having own or
3824  // external data. @todo: fix this in the file format!
3825  Reference< lang::XServiceInfo > xDPServiceInfo( xNewDoc->getDataProvider(), uno::UNO_QUERY );
3826  if( ! (xDPServiceInfo.is() && xDPServiceInfo->getImplementationName() == "com.sun.star.comp.chart.InternalDataProvider" ))
3827  {
3828  bIncludeTable = false;
3829  }
3830  }
3831  else
3832  {
3833  Reference< lang::XServiceInfo > xServ( xChartDoc, uno::UNO_QUERY );
3834  if( xServ.is())
3835  {
3836  if( xServ->supportsService( "com.sun.star.chart.ChartTableAddressSupplier" ))
3837  {
3838  Reference< beans::XPropertySet > xProp( xServ, uno::UNO_QUERY );
3839  if( xProp.is())
3840  {
3841  Any aAny;
3842  try
3843  {
3844  OUString sChartAddress;
3845  aAny = xProp->getPropertyValue( "ChartRangeAddress" );
3846  aAny >>= sChartAddress;
3847  maExportHelper->m_pImpl->SetChartRangeAddress( sChartAddress );
3848 
3849  // do not include own table if there are external addresses
3850  bIncludeTable = sChartAddress.isEmpty();
3851  }
3852  catch( const beans::UnknownPropertyException & )
3853  {
3854  SAL_WARN("xmloff.chart", "Property ChartRangeAddress not supported by ChartDocument" );
3855  }
3856  }
3857  }
3858  }
3859  }
3860  maExportHelper->m_pImpl->exportChart( xChartDoc, bIncludeTable );
3861  }
3862  else
3863  {
3864  SAL_WARN("xmloff.chart", "Couldn't export chart due to wrong XModel" );
3865  }
3866 }
3867 
3869 {
3870  return maExportHelper->m_pImpl->GetPropertySetMapper();
3871 }
3872 
3873 void SchXMLExportHelper_Impl::InitRangeSegmentationProperties( const Reference< chart2::XChartDocument > & xChartDoc )
3874 {
3875  if( !xChartDoc.is())
3876  return;
3877 
3878  try
3879  {
3880  Reference< chart2::data::XDataProvider > xDataProvider( xChartDoc->getDataProvider() );
3881  SAL_WARN_IF( !xDataProvider.is(), "xmloff.chart", "No DataProvider" );
3882  if( xDataProvider.is())
3883  {
3884  Reference< chart2::data::XDataSource > xDataSource( lcl_pressUsedDataIntoRectangularFormat( xChartDoc, mbHasCategoryLabels ));
3885  const Sequence< beans::PropertyValue > aArgs( xDataProvider->detectArguments( xDataSource ));
3886  OUString sCellRange, sBrokenRange;
3887  bool bBrokenRangeAvailable = false;
3888  for( const auto& rArg : aArgs )
3889  {
3890  if ( rArg.Name == "CellRangeRepresentation" )
3891  rArg.Value >>= sCellRange;
3892  else if ( rArg.Name == "BrokenCellRangeForExport" )
3893  {
3894  if( rArg.Value >>= sBrokenRange )
3895  bBrokenRangeAvailable = true;
3896  }
3897  else if ( rArg.Name == "DataRowSource" )
3898  {
3899  chart::ChartDataRowSource eRowSource;
3900  rArg.Value >>= eRowSource;
3901  mbRowSourceColumns = ( eRowSource == chart::ChartDataRowSource_COLUMNS );
3902  }
3903  else if ( rArg.Name == "SequenceMapping" )
3904  rArg.Value >>= maSequenceMapping;
3905  }
3906 
3907  // #i79009# For Writer we have to export a broken version of the
3908  // range, where every row number is not too large, so that older
3909  // version can correctly read those files.
3910  msChartAddress = (bBrokenRangeAvailable ? sBrokenRange : sCellRange);
3911  if( !msChartAddress.isEmpty() )
3912  {
3913  // convert format to XML-conform one
3914  Reference< chart2::data::XRangeXMLConversion > xConversion( xDataProvider, uno::UNO_QUERY );
3915  if( xConversion.is())
3916  msChartAddress = xConversion->convertRangeToXML( msChartAddress );
3917  }
3918  }
3919  }
3920  catch( const uno::Exception & )
3921  {
3922  DBG_UNHANDLED_EXCEPTION("xmloff.chart");
3923  }
3924 }
3925 
3926 // first version: everything goes in one storage
3927 
3928 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3930  uno::Sequence<uno::Any> const& /*rSeq*/)
3931 {
3932  return cppu::acquire(
3933  new SchXMLExport(pCtx, "SchXMLExport.Compact",
3937 }
3938 
3939 // Oasis format
3940 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3942  uno::Sequence<uno::Any> const& /*rSeq*/)
3943 {
3944  return cppu::acquire(
3945  new SchXMLExport(pCtx, "SchXMLExport.Oasis.Compact",
3950 }
3951 
3952 // multiple storage version: one for content / styles / meta
3953 
3954 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3956  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3957 {
3958  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Styles", SvXMLExportFlags::STYLES));
3959 }
3960 
3961 // Oasis format
3962 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3964  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3965 {
3966  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Oasis.Styles",
3968 }
3969 
3970 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3972  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3973 {
3974  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Content",
3977 }
3978 
3979 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3981  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3982 {
3983  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Oasis.Content",
3987 }
3988 
3989 // Oasis format
3990 
3991 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface*
3993  uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/)
3994 {
3995  return cppu::acquire(new SchXMLExport(pCtx, "SchXMLExport.Oasis.Meta",
3997 }
3998 
3999 /* 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:1831
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:1234
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:909
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:1436
#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:2297
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
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:85
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:3406
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:1431
#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:1819
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:1706