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