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