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