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