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