1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
23 #include <InternalDataProvider.hxx>
24 #include <LabeledDataSequence.hxx>
25 #include <DataSource.hxx>
26 #include <XMLRangeHelper.hxx>
27 #include <CommonFunctors.hxx>
28 #include <UncachedDataSequence.hxx>
29 #include <DataSourceHelper.hxx>
30 #include <ChartModel.hxx>
31 #include <ChartModelHelper.hxx>
32 #include <DiagramHelper.hxx>
33 #include <Diagram.hxx>
34 #include <ExplicitCategoriesProvider.hxx>
35 #include <BaseCoordinateSystem.hxx>
36 #include <DataSeries.hxx>
38 #include <com/sun/star/chart2/data/XDataSequence.hpp>
39 #include <com/sun/star/chart/ChartDataRowSource.hpp>
40 #include <cppuhelper/supportsservice.hxx>
41 #include <comphelper/sequenceashashmap.hxx>
42 #include <comphelper/property.hxx>
43 #include <o3tl/string_view.hxx>
44 #include <comphelper/diagnose_ex.hxx>
50 namespace com::sun::star::chart2
{ class XChartDocument
; }
52 using namespace ::com::sun::star
;
54 using ::com::sun::star::uno::Reference
;
55 using ::com::sun::star::uno::Sequence
;
63 constexpr OUString lcl_aCategoriesRangeName
= u
"categories"_ustr
;
64 const char lcl_aCategoriesLevelRangeNamePrefix
[] = "categoriesL "; //L <-> level
65 const char lcl_aCategoriesPointRangeNamePrefix
[] = "categoriesP "; //P <-> point
66 constexpr OUString lcl_aCategoriesRoleName
= u
"categories"_ustr
;
67 const char lcl_aLabelRangePrefix
[] = "label ";
68 constexpr OUString lcl_aCompleteRange
= u
"all"_ustr
;
70 typedef std::multimap
< OUString
, uno::WeakReference
< chart2::data::XDataSequence
> >
73 std::vector
< OUString
> lcl_AnyToStringSequence( const std::vector
< uno::Any
>& aAnySeq
)
75 std::vector
< OUString
> aResult
;
76 aResult
.resize( aAnySeq
.size() );
78 for (const uno::Any
& aAny
: aAnySeq
)
79 aResult
[i
++] = CommonFunctors::AnyToString()(aAny
);
83 std::vector
< uno::Any
> lcl_StringToAnyVector( const css::uno::Sequence
< OUString
>& aStringSeq
)
85 std::vector
< uno::Any
> aResult
;
86 aResult
.resize( aStringSeq
.getLength() );
88 for (const OUString
& aStr
: aStringSeq
)
89 aResult
[i
++] = CommonFunctors::makeAny
<OUString
>()(aStr
);
93 struct lcl_setModified
95 void operator() ( const lcl_tSequenceMap::value_type
& rMapEntry
)
97 // convert weak reference to reference
98 Reference
< chart2::data::XDataSequence
> xSeq( rMapEntry
.second
);
101 Reference
< util::XModifiable
> xMod( xSeq
, uno::UNO_QUERY
);
103 xMod
->setModified( true );
108 struct lcl_internalizeSeries
110 lcl_internalizeSeries( InternalData
& rInternalData
,
111 InternalDataProvider
& rProvider
,
112 bool bConnectToModel
, bool bDataInColumns
) :
113 m_rInternalData( rInternalData
),
114 m_rProvider( rProvider
),
115 m_bConnectToModel( bConnectToModel
),
116 m_bDataInColumns( bDataInColumns
)
118 void operator() ( const rtl::Reference
< DataSeries
> & xSeries
)
120 const std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > & aOldSeriesData
= xSeries
->getDataSequences2();
121 std::vector
< uno::Reference
< chart2::data::XLabeledDataSequence
> > aNewSeriesData( aOldSeriesData
.size() );
122 for( std::size_t i
=0; i
<aOldSeriesData
.size(); ++i
)
124 sal_Int32
nNewIndex( m_bDataInColumns
? m_rInternalData
.appendColumn() : m_rInternalData
.appendRow() );
125 OUString
aIdentifier( OUString::number( nNewIndex
));
126 //@todo: deal also with genericXDataSequence
127 Reference
< chart2::data::XNumericalDataSequence
> xValues( aOldSeriesData
[i
]->getValues(), uno::UNO_QUERY
);
128 Reference
< chart2::data::XTextualDataSequence
> xLabel( aOldSeriesData
[i
]->getLabel(), uno::UNO_QUERY
);
129 Reference
< chart2::data::XDataSequence
> xNewValues
;
133 auto aValues( comphelper::sequenceToContainer
<std::vector
< double >>( xValues
->getNumericalData()));
134 if( m_bDataInColumns
)
135 m_rInternalData
.setColumnValues( nNewIndex
, aValues
);
137 m_rInternalData
.setRowValues( nNewIndex
, aValues
);
138 if( m_bConnectToModel
)
140 xNewValues
.set( m_rProvider
.createDataSequenceByRangeRepresentation( aIdentifier
));
141 comphelper::copyProperties(
142 Reference
< beans::XPropertySet
>( xValues
, uno::UNO_QUERY
),
143 Reference
< beans::XPropertySet
>( xNewValues
, uno::UNO_QUERY
));
149 if( m_bDataInColumns
)
150 m_rInternalData
.setComplexColumnLabel( nNewIndex
, lcl_StringToAnyVector( xLabel
->getTextualData() ) );
152 m_rInternalData
.setComplexRowLabel( nNewIndex
, lcl_StringToAnyVector( xLabel
->getTextualData() ) );
153 if( m_bConnectToModel
)
155 Reference
< chart2::data::XDataSequence
> xNewLabel(
156 m_rProvider
.createDataSequenceByRangeRepresentation( lcl_aLabelRangePrefix
+ aIdentifier
));
157 comphelper::copyProperties(
158 Reference
< beans::XPropertySet
>( xLabel
, uno::UNO_QUERY
),
159 Reference
< beans::XPropertySet
>( xNewLabel
, uno::UNO_QUERY
));
160 aNewSeriesData
[i
].set( new LabeledDataSequence( xNewValues
, xNewLabel
) );
165 if( m_bConnectToModel
)
166 aNewSeriesData
[i
].set( new LabeledDataSequence( xNewValues
) );
169 if( m_bConnectToModel
)
170 xSeries
->setData( aNewSeriesData
);
174 InternalData
& m_rInternalData
;
175 InternalDataProvider
& m_rProvider
;
176 bool m_bConnectToModel
;
177 bool m_bDataInColumns
;
180 struct lcl_copyFromLevel
184 explicit lcl_copyFromLevel( sal_Int32 nLevel
) : m_nLevel( nLevel
)
187 uno::Any
operator() ( const std::vector
< uno::Any
>& rVector
)
190 if( m_nLevel
< static_cast< sal_Int32
>(rVector
.size()) )
191 aRet
= rVector
[m_nLevel
];
199 struct lcl_getStringFromLevelVector
203 explicit lcl_getStringFromLevelVector( sal_Int32 nLevel
) : m_nLevel( nLevel
)
206 OUString
operator() ( const std::vector
< uno::Any
>& rVector
)
209 if( m_nLevel
< static_cast< sal_Int32
>(rVector
.size()) )
210 aString
= CommonFunctors::AnyToString()(rVector
[m_nLevel
]);
218 struct lcl_setAnyAtLevel
222 explicit lcl_setAnyAtLevel( sal_Int32 nLevel
) : m_nLevel( nLevel
)
225 std::vector
< uno::Any
> operator() ( const std::vector
< uno::Any
>& rVector
, const uno::Any
& rNewValue
)
227 std::vector
< uno::Any
> aRet( rVector
);
228 if( m_nLevel
>= static_cast< sal_Int32
>(aRet
.size()) )
229 aRet
.resize( m_nLevel
+1 );
230 aRet
[ m_nLevel
]=rNewValue
;
238 struct lcl_setAnyAtLevelFromStringSequence
242 explicit lcl_setAnyAtLevelFromStringSequence( sal_Int32 nLevel
) : m_nLevel( nLevel
)
245 std::vector
< uno::Any
> operator() ( const std::vector
< uno::Any
>& rVector
, const OUString
& rNewValue
)
247 std::vector
< uno::Any
> aRet( rVector
);
248 if( m_nLevel
>= static_cast< sal_Int32
>(aRet
.size()) )
249 aRet
.resize( m_nLevel
+1 );
250 aRet
[ m_nLevel
] <<= rNewValue
;
258 struct lcl_insertAnyAtLevel
262 explicit lcl_insertAnyAtLevel( sal_Int32 nLevel
) : m_nLevel( nLevel
)
265 void operator() ( std::vector
< uno::Any
>& rVector
)
267 if( m_nLevel
>= static_cast< sal_Int32
>(rVector
.size()) )
269 rVector
.resize( m_nLevel
+ 1 );
273 rVector
.insert( rVector
.begin() + m_nLevel
, uno::Any() );
281 struct lcl_removeAnyAtLevel
285 explicit lcl_removeAnyAtLevel( sal_Int32 nLevel
) : m_nLevel( nLevel
)
288 void operator() ( std::vector
< uno::Any
>& rVector
)
290 if( m_nLevel
< static_cast<sal_Int32
>(rVector
.size()) )
292 rVector
.erase(rVector
.begin() + m_nLevel
);
300 } // anonymous namespace
302 InternalDataProvider::InternalDataProvider()
303 : m_bDataInColumns( true )
306 InternalDataProvider::InternalDataProvider(
307 const rtl::Reference
< ChartModel
> & xModel
,
308 bool bConnectToModel
,
309 bool bDefaultDataInColumns
)
310 : m_bDataInColumns( bDefaultDataInColumns
)
316 rtl::Reference
< Diagram
> xDiagram( xModel
->getFirstChartDiagram() );
321 OUString aRangeString
;
322 bool bFirstCellAsLabel
= true;
323 bool bHasCategories
= true;
324 uno::Sequence
< sal_Int32
> aSequenceMapping
;
325 const bool bSomethingDetected(
326 DataSourceHelper::detectRangeSegmentation(
327 xModel
, aRangeString
, aSequenceMapping
, m_bDataInColumns
, bFirstCellAsLabel
, bHasCategories
));
329 // #i120559# if no data was available, restore default
330 if(!bSomethingDetected
&& m_bDataInColumns
!= bDefaultDataInColumns
)
332 m_bDataInColumns
= bDefaultDataInColumns
;
338 std::vector
< std::vector
< uno::Any
> > aNewCategories
;//inner count is level
340 ExplicitCategoriesProvider
aExplicitCategoriesProvider(ChartModelHelper::getFirstCoordinateSystem(xModel
), *xModel
);
342 const std::vector
< Reference
< chart2::data::XLabeledDataSequence
> >& rSplitCategoriesList( aExplicitCategoriesProvider
.getSplitCategoriesList() );
343 sal_Int32 nLevelCount
= rSplitCategoriesList
.size();
344 for( sal_Int32 nL
= 0; nL
<nLevelCount
; nL
++ )
346 Reference
< chart2::data::XLabeledDataSequence
> xLDS( rSplitCategoriesList
[nL
] );
349 Sequence
< uno::Any
> aDataSeq
;
350 Reference
< chart2::data::XDataSequence
> xSeq( xLDS
->getValues() );
352 aDataSeq
= xSeq
->getData();
353 sal_Int32 nLength
= aDataSeq
.getLength();
354 sal_Int32 nCatLength
= static_cast< sal_Int32
>(aNewCategories
.size());
355 if( nCatLength
< nLength
)
356 aNewCategories
.resize( nLength
);
357 else if( nLength
< nCatLength
)
358 aDataSeq
.realloc( nCatLength
);
359 transform( aNewCategories
.begin(), aNewCategories
.end(), aDataSeq
.getConstArray(),
360 aNewCategories
.begin(), lcl_setAnyAtLevel(nL
) );
364 Sequence
< OUString
> aSimplecategories
= aExplicitCategoriesProvider
.getSimpleCategories();
365 sal_Int32 nLength
= aSimplecategories
.getLength();
366 aNewCategories
.reserve( nLength
);
367 for( sal_Int32 nN
=0; nN
<nLength
; nN
++)
369 aNewCategories
.push_back( { uno::Any(aSimplecategories
[nN
]) } );
374 if( m_bDataInColumns
)
375 m_aInternalData
.setComplexRowLabels( std::move(aNewCategories
) );
377 m_aInternalData
.setComplexColumnLabels( std::move(aNewCategories
) );
378 if( bConnectToModel
)
379 xDiagram
->setCategories(
380 new LabeledDataSequence(
381 createDataSequenceByRangeRepresentation( lcl_aCategoriesRangeName
))
386 std::vector
< rtl::Reference
< DataSeries
> > aSeriesVector( ChartModelHelper::getDataSeries( xModel
));
387 lcl_internalizeSeries
ftor( m_aInternalData
, *this, bConnectToModel
, m_bDataInColumns
);
388 for( const auto& rxScreen
: aSeriesVector
)
392 catch( const uno::Exception
& )
394 DBG_UNHANDLED_EXCEPTION("chart2");
399 InternalDataProvider::InternalDataProvider( const InternalDataProvider
& rOther
) :
400 impl::InternalDataProvider_Base(rOther
),
401 m_aSequenceMap( rOther
.m_aSequenceMap
),
402 m_aInternalData( rOther
.m_aInternalData
),
403 m_bDataInColumns( rOther
.m_bDataInColumns
)
406 InternalDataProvider::~InternalDataProvider()
409 void InternalDataProvider::addDataSequenceToMap(
410 const OUString
& rRangeRepresentation
,
411 const Reference
< chart2::data::XDataSequence
> & xSequence
)
413 m_aSequenceMap
.emplace(
414 rRangeRepresentation
,
415 uno::WeakReference
< chart2::data::XDataSequence
>( xSequence
));
418 void InternalDataProvider::deleteMapReferences( const OUString
& rRangeRepresentation
)
420 // set sequence to deleted by setting its range to an empty string
421 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( rRangeRepresentation
));
422 for( tSequenceMap::iterator
aIt( aRange
.first
); aIt
!= aRange
.second
; ++aIt
)
424 Reference
< chart2::data::XDataSequence
> xSeq( aIt
->second
);
427 Reference
< container::XNamed
> xNamed( xSeq
, uno::UNO_QUERY
);
429 xNamed
->setName( OUString());
433 m_aSequenceMap
.erase( aRange
.first
, aRange
.second
);
436 void InternalDataProvider::adaptMapReferences(
437 const OUString
& rOldRangeRepresentation
,
438 const OUString
& rNewRangeRepresentation
)
440 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( rOldRangeRepresentation
));
441 tSequenceMap aNewElements
;
442 for( tSequenceMap::iterator
aIt( aRange
.first
); aIt
!= aRange
.second
; ++aIt
)
444 Reference
< chart2::data::XDataSequence
> xSeq( aIt
->second
);
447 Reference
< container::XNamed
> xNamed( xSeq
, uno::UNO_QUERY
);
449 xNamed
->setName( rNewRangeRepresentation
);
451 aNewElements
.emplace( rNewRangeRepresentation
, aIt
->second
);
453 // erase map values for old index
454 m_aSequenceMap
.erase( aRange
.first
, aRange
.second
);
455 // add new entries for values with new index
456 m_aSequenceMap
.insert( aNewElements
.begin(), aNewElements
.end() );
459 void InternalDataProvider::increaseMapReferences(
460 sal_Int32 nBegin
, sal_Int32 nEnd
)
462 for( sal_Int32 nIndex
= nEnd
- 1; nIndex
>= nBegin
; --nIndex
)
464 adaptMapReferences( OUString::number( nIndex
),
465 OUString::number( nIndex
+ 1 ));
466 adaptMapReferences( lcl_aLabelRangePrefix
+ OUString::number( nIndex
),
467 lcl_aLabelRangePrefix
+ OUString::number( nIndex
+ 1 ));
471 void InternalDataProvider::decreaseMapReferences(
472 sal_Int32 nBegin
, sal_Int32 nEnd
)
474 for( sal_Int32 nIndex
= nBegin
; nIndex
< nEnd
; ++nIndex
)
476 adaptMapReferences( OUString::number( nIndex
),
477 OUString::number( nIndex
- 1 ));
478 adaptMapReferences( lcl_aLabelRangePrefix
+ OUString::number( nIndex
),
479 lcl_aLabelRangePrefix
+ OUString::number( nIndex
- 1 ));
483 rtl::Reference
< UncachedDataSequence
> InternalDataProvider::createDataSequenceAndAddToMap(
484 const OUString
& rRangeRepresentation
)
486 rtl::Reference
<UncachedDataSequence
> xSeq
= createDataSequenceFromArray(rRangeRepresentation
, u
"", u
"");
490 xSeq
.set(new UncachedDataSequence(this, rRangeRepresentation
));
491 addDataSequenceToMap(rRangeRepresentation
, xSeq
);
495 rtl::Reference
<UncachedDataSequence
>
496 InternalDataProvider::createDataSequenceFromArray( const OUString
& rArrayStr
, std::u16string_view rRole
, std::u16string_view rRoleQualifier
)
498 if (rArrayStr
.indexOf('{') != 0 || rArrayStr
[rArrayStr
.getLength()-1] != '}')
500 // Not an array string.
504 bool bAllNumeric
= true;
505 rtl::Reference
<UncachedDataSequence
> xSeq
;
507 const sal_Unicode
* p
= rArrayStr
.getStr();
508 const sal_Unicode
* pEnd
= p
+ rArrayStr
.getLength();
509 const sal_Unicode
* pElem
= nullptr;
512 std::vector
<OUString
> aRawElems
;
513 ++p
; // Skip the first '{'.
514 --pEnd
; // Skip the last '}'.
515 bool bInQuote
= false;
516 for (; p
!= pEnd
; ++p
)
518 // Skip next "" within the title text: it's an escaped double quotation mark.
519 if (bInQuote
&& *p
== '"' && *(p
+ 1) == '"')
527 bInQuote
= !bInQuote
;
537 aElem
= OUString(pElem
, p
-pElem
);
539 if (!aElem
.isEmpty())
541 // Restore also escaped double quotation marks
542 aRawElems
.push_back(aElem
.replaceAll("\"\"", "\""));
551 else if (*p
== ';' && !bInQuote
)
553 // element separator.
555 aElem
= OUString(pElem
, p
-pElem
);
556 aRawElems
.push_back(aElem
);
566 aElem
= OUString(pElem
, p
-pElem
);
567 aRawElems
.push_back(aElem
);
570 if (rRole
== u
"values-y" || rRole
== u
"values-first" || rRole
== u
"values-last" ||
571 rRole
== u
"values-min" || rRole
== u
"values-max" || rRole
== u
"values-size" ||
572 rRole
== u
"error-bars-y-positive" || rRole
== u
"error-bars-y-negative")
574 // Column values. Append a new data column and populate it.
576 std::vector
<double> aValues
;
577 aValues
.reserve(aRawElems
.size());
578 for (const OUString
& aRawElem
: aRawElems
)
580 if (aRawElem
.isEmpty())
581 aValues
.push_back(NAN
);
583 aValues
.push_back(aRawElem
.toDouble());
585 sal_Int32 n
= m_aInternalData
.appendColumn();
587 m_aInternalData
.setColumnValues(n
, aValues
);
589 OUString aRangeRep
= OUString::number(n
);
590 xSeq
.set(new UncachedDataSequence(this, aRangeRep
));
591 addDataSequenceToMap(aRangeRep
, xSeq
);
593 else if (rRole
== u
"values-x")
595 std::vector
<double> aValues
;
596 aValues
.reserve(aRawElems
.size());
599 for (const OUString
& aRawElem
: aRawElems
)
601 if (!aRawElem
.isEmpty())
602 aValues
.push_back(aRawElem
.toDouble());
604 aValues
.push_back(NAN
);
609 for (size_t i
= 0; i
< aRawElems
.size(); ++i
)
610 aValues
.push_back(i
+1);
613 sal_Int32 n
= m_aInternalData
.appendColumn();
614 m_aInternalData
.setColumnValues(n
, aValues
);
616 OUString aRangeRep
= OUString::number(n
);
617 xSeq
.set(new UncachedDataSequence(this, aRangeRep
));
618 addDataSequenceToMap(aRangeRep
, xSeq
);
620 else if (rRole
== u
"categories")
624 // Store date categories as numbers.
625 bool bStoreNumeric
= rRoleQualifier
== u
"date";
627 for (size_t i
= 0; i
< aRawElems
.size(); ++i
)
631 bool bGetDouble
= bAllNumeric
&& !aRawElems
[i
].isEmpty();
632 fValue
= bGetDouble
? aRawElems
[i
].toDouble() :
633 std::numeric_limits
<double>::quiet_NaN();
635 std::vector
<uno::Any
> aLabels(1,
636 bStoreNumeric
? uno::Any(fValue
) : uno::Any(aRawElems
[i
]));
637 m_aInternalData
.setComplexRowLabel(i
, std::move(aLabels
));
640 xSeq
.set(new UncachedDataSequence(this, lcl_aCategoriesRangeName
));
641 addDataSequenceToMap(lcl_aCategoriesRangeName
, xSeq
);
643 else if (rRole
== u
"label")
645 // Data series label. There should be only one element. This always
646 // goes to the last data column.
647 sal_Int32 nColSize
= m_aInternalData
.getColumnCount();
648 if (!aRawElems
.empty() && nColSize
)
650 // Do not overwrite an existing label (attempted by series with no data values)
651 if (!m_aInternalData
.getComplexColumnLabel(nColSize
-1)[0].hasValue())
653 std::vector
<uno::Any
> aLabels(1, uno::Any(aRawElems
[0]));
654 m_aInternalData
.setComplexColumnLabel(nColSize
-1, std::move(aLabels
));
657 OUString aRangeRep
= lcl_aLabelRangePrefix
+ OUString::number(nColSize
-1);
658 xSeq
.set(new UncachedDataSequence(this, aRangeRep
));
659 addDataSequenceToMap(aRangeRep
, xSeq
);
666 Reference
< chart2::data::XDataSequence
> InternalDataProvider::createDataSequenceAndAddToMap(
667 const OUString
& rRangeRepresentation
,
668 const OUString
& rRole
)
670 rtl::Reference
< UncachedDataSequence
> xSeq
=
671 new UncachedDataSequence( this, rRangeRepresentation
, rRole
);
672 addDataSequenceToMap( rRangeRepresentation
, xSeq
);
676 // ____ XDataProvider ____
677 sal_Bool SAL_CALL
InternalDataProvider::createDataSourcePossible( const Sequence
< beans::PropertyValue
>& /* aArguments */ )
685 sal_Int32
lcl_getInnerLevelCount( const std::vector
< std::vector
< uno::Any
> >& rLabels
)
687 sal_Int32 nCount
= 1;//minimum is 1!
688 for (auto const& elemLabel
: rLabels
)
690 nCount
= std::max
<sal_Int32
>( elemLabel
.size(), nCount
);
695 }//end anonymous namespace
697 Reference
< chart2::data::XDataSource
> SAL_CALL
InternalDataProvider::createDataSource(
698 const Sequence
< beans::PropertyValue
>& aArguments
)
700 OUString aRangeRepresentation
;
701 bool bUseColumns
= true;
702 bool bFirstCellAsLabel
= true;
703 bool bHasCategories
= true;
704 uno::Sequence
< sal_Int32
> aSequenceMapping
;
705 DataSourceHelper::readArguments( aArguments
, aRangeRepresentation
, aSequenceMapping
, bUseColumns
, bFirstCellAsLabel
, bHasCategories
);
707 if( aRangeRepresentation
== lcl_aCategoriesRangeName
)
709 //return split complex categories if we have any:
710 std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aComplexCategories
;
711 const std::vector
< std::vector
< uno::Any
> > & aCategories( m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels());
712 if( bUseColumns
==m_bDataInColumns
)
714 sal_Int32 nLevelCount
= lcl_getInnerLevelCount( aCategories
);
715 for( sal_Int32 nL
=0; nL
<nLevelCount
; nL
++ )
716 aComplexCategories
.push_back( new LabeledDataSequence(
717 new UncachedDataSequence( this
718 , lcl_aCategoriesLevelRangeNamePrefix
+ OUString::number( nL
)
719 , lcl_aCategoriesRoleName
) ) );
723 sal_Int32 nPointCount
= m_bDataInColumns
? m_aInternalData
.getRowCount() : m_aInternalData
.getColumnCount();
724 for( sal_Int32 nP
=0; nP
<nPointCount
; nP
++ )
725 aComplexCategories
.push_back( new LabeledDataSequence(
726 new UncachedDataSequence( this
727 , lcl_aCategoriesPointRangeNamePrefix
+ OUString::number( nP
)
728 , lcl_aCategoriesRoleName
) ) );
730 //don't add the created sequences to the map as they are used temporarily only ...
731 return new DataSource( comphelper::containerToSequence(aComplexCategories
) );
734 OSL_ASSERT( aRangeRepresentation
== lcl_aCompleteRange
);
736 std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aResultLSeqVec
;
740 aResultLSeqVec
.push_back(
741 new LabeledDataSequence( createDataSequenceAndAddToMap( lcl_aCategoriesRangeName
, lcl_aCategoriesRoleName
) ) );
744 std::vector
< Reference
< chart2::data::XLabeledDataSequence
> > aDataVec
;
745 const sal_Int32 nCount
= (bUseColumns
? m_aInternalData
.getColumnCount() : m_aInternalData
.getRowCount());
746 aDataVec
.reserve(nCount
);
747 for (sal_Int32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
750 new LabeledDataSequence(
751 createDataSequenceAndAddToMap( OUString::number( nIdx
)),
752 createDataSequenceAndAddToMap( lcl_aLabelRangePrefix
+ OUString::number( nIdx
))));
755 // attention: this data provider has the limitation that it stores
756 // internally if data comes from columns or rows. It is intended for
757 // creating only one used data source.
758 // @todo: add this information in the range representation strings
759 m_bDataInColumns
= bUseColumns
;
761 //reorder labeled sequences according to aSequenceMapping; ignore categories
762 for( sal_Int32 nNewIndex
= 0; nNewIndex
< aSequenceMapping
.getLength(); nNewIndex
++ )
764 std::vector
< LabeledDataSequence
* >::size_type nOldIndex
= aSequenceMapping
[nNewIndex
];
765 if( nOldIndex
< aDataVec
.size() )
767 if( aDataVec
[nOldIndex
].is() )
769 aResultLSeqVec
.push_back( aDataVec
[nOldIndex
] );
770 aDataVec
[nOldIndex
] = nullptr;
775 //add left over data sequences to result
776 for (auto const& elem
: aDataVec
)
779 aResultLSeqVec
.push_back(elem
);
782 return new DataSource( comphelper::containerToSequence(aResultLSeqVec
) );
785 Sequence
< beans::PropertyValue
> SAL_CALL
InternalDataProvider::detectArguments(
786 const Reference
< chart2::data::XDataSource
>& /* xDataSource */ )
788 Sequence
< beans::PropertyValue
> aArguments
{
789 beans::PropertyValue(
790 "CellRangeRepresentation", -1, uno::Any( lcl_aCompleteRange
),
791 beans::PropertyState_DIRECT_VALUE
),
792 beans::PropertyValue(
793 "DataRowSource", -1, uno::Any(
795 ? css::chart::ChartDataRowSource_COLUMNS
796 : css::chart::ChartDataRowSource_ROWS
),
797 beans::PropertyState_DIRECT_VALUE
),
798 // internal data always contains labels and categories
799 beans::PropertyValue(
800 "FirstCellAsLabel", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE
),
801 beans::PropertyValue(
802 "HasCategories", -1, uno::Any( true ), beans::PropertyState_DIRECT_VALUE
)
804 // #i85913# Sequence Mapping is not needed for internal data, as it is
805 // applied to the data when the data source is created.
810 sal_Bool SAL_CALL
InternalDataProvider::createDataSequenceByRangeRepresentationPossible( const OUString
& /* aRangeRepresentation */ )
815 Reference
< chart2::data::XDataSequence
> SAL_CALL
InternalDataProvider::createDataSequenceByRangeRepresentation(
816 const OUString
& aRangeRepresentation
)
818 if( aRangeRepresentation
.match( lcl_aCategoriesRangeName
))
820 OSL_ASSERT( aRangeRepresentation
== lcl_aCategoriesRangeName
);//it is not expected nor implemented that only parts of the categories are really requested
823 return createDataSequenceAndAddToMap( lcl_aCategoriesRangeName
, lcl_aCategoriesRoleName
);
825 else if( aRangeRepresentation
.match( lcl_aLabelRangePrefix
))
828 sal_Int32 nIndex
= o3tl::toInt32(aRangeRepresentation
.subView( strlen(lcl_aLabelRangePrefix
)));
829 return createDataSequenceAndAddToMap( lcl_aLabelRangePrefix
+ OUString::number( nIndex
));
831 else if ( aRangeRepresentation
== "last" )
833 sal_Int32 nIndex
= (m_bDataInColumns
834 ? m_aInternalData
.getColumnCount()
835 : m_aInternalData
.getRowCount()) - 1;
836 return createDataSequenceAndAddToMap( OUString::number( nIndex
));
838 else if( !aRangeRepresentation
.isEmpty())
841 return createDataSequenceAndAddToMap( aRangeRepresentation
);
844 return Reference
< chart2::data::XDataSequence
>();
847 Reference
<chart2::data::XDataSequence
> SAL_CALL
848 InternalDataProvider::createDataSequenceByValueArray(
849 const OUString
& aRole
, const OUString
& aRangeRepresentation
, const OUString
& aRoleQualifier
)
851 return createDataSequenceFromArray(aRangeRepresentation
, aRole
, aRoleQualifier
);
854 Reference
< sheet::XRangeSelection
> SAL_CALL
InternalDataProvider::getRangeSelection()
856 // there is no range selection component
857 return Reference
< sheet::XRangeSelection
>();
860 // ____ XInternalDataProvider ____
861 sal_Bool SAL_CALL
InternalDataProvider::hasDataByRangeRepresentation( const OUString
& aRange
)
863 bool bResult
= false;
865 if( aRange
.match( lcl_aCategoriesRangeName
))
867 OSL_ASSERT( aRange
== lcl_aCategoriesRangeName
);//it is not expected nor implemented that only parts of the categories are really requested
870 else if( aRange
.match( lcl_aLabelRangePrefix
))
872 sal_Int32 nIndex
= o3tl::toInt32(aRange
.subView( strlen(lcl_aLabelRangePrefix
)));
873 bResult
= (nIndex
< (m_bDataInColumns
? m_aInternalData
.getColumnCount(): m_aInternalData
.getRowCount()));
877 sal_Int32 nIndex
= aRange
.toInt32();
878 bResult
= (nIndex
< (m_bDataInColumns
? m_aInternalData
.getColumnCount(): m_aInternalData
.getRowCount()));
884 Sequence
< uno::Any
> SAL_CALL
InternalDataProvider::getDataByRangeRepresentation( const OUString
& aRange
)
886 Sequence
< uno::Any
> aResult
;
888 if( aRange
.match( lcl_aLabelRangePrefix
) )
890 auto nIndex
= o3tl::toUInt32(aRange
.subView( strlen(lcl_aLabelRangePrefix
)));
891 std::vector
< uno::Any
> aComplexLabel
= m_bDataInColumns
892 ? m_aInternalData
.getComplexColumnLabel( nIndex
)
893 : m_aInternalData
.getComplexRowLabel( nIndex
);
894 if( !aComplexLabel
.empty() )
895 aResult
= comphelper::containerToSequence(aComplexLabel
);
897 else if( aRange
.match( lcl_aCategoriesPointRangeNamePrefix
) )
899 auto nPointIndex
= o3tl::toUInt32(aRange
.subView( strlen(lcl_aCategoriesPointRangeNamePrefix
) ));
900 std::vector
< uno::Any
> aComplexCategory
= m_bDataInColumns
901 ? m_aInternalData
.getComplexRowLabel( nPointIndex
)
902 : m_aInternalData
.getComplexColumnLabel( nPointIndex
);
903 if( !aComplexCategory
.empty() )
904 aResult
= comphelper::containerToSequence(aComplexCategory
);
906 else if( aRange
.match( lcl_aCategoriesLevelRangeNamePrefix
) )
908 sal_Int32 nLevel
= o3tl::toInt32(aRange
.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix
) ));
909 const std::vector
< std::vector
< uno::Any
> > & aCategories( m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels());
910 if( nLevel
< lcl_getInnerLevelCount( aCategories
) )
912 aResult
.realloc( aCategories
.size() );
913 transform( aCategories
.begin(), aCategories
.end(),
914 aResult
.getArray(), lcl_copyFromLevel(nLevel
) );
917 else if( aRange
== lcl_aCategoriesRangeName
)
919 const std::vector
< std::vector
< uno::Any
> > & aCategories( m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels());
920 sal_Int32 nLevelCount
= lcl_getInnerLevelCount( aCategories
);
921 if( nLevelCount
== 1 )
923 aResult
= getDataByRangeRepresentation( lcl_aCategoriesLevelRangeNamePrefix
+ OUString::number( 0 ) );
927 // Maybe this 'else' part and the functions is not necessary anymore.
928 const Sequence
< OUString
> aLabels
= m_bDataInColumns
? getRowDescriptions() : getColumnDescriptions();
929 aResult
.realloc( aLabels
.getLength() );
930 std::transform( aLabels
.begin(), aLabels
.end(),
931 aResult
.getArray(), CommonFunctors::makeAny
< OUString
>() );
936 sal_Int32 nIndex
= aRange
.toInt32();
939 const Sequence
< double > aData
= m_bDataInColumns
940 ? m_aInternalData
.getColumnValues(nIndex
)
941 : m_aInternalData
.getRowValues(nIndex
);
942 if( aData
.hasElements() )
944 aResult
.realloc( aData
.getLength());
945 std::transform( aData
.begin(), aData
.end(),
946 aResult
.getArray(), CommonFunctors::makeAny
< double >());
954 void SAL_CALL
InternalDataProvider::setDataByRangeRepresentation(
955 const OUString
& aRange
, const Sequence
< uno::Any
>& aNewData
)
957 auto aNewVector( comphelper::sequenceToContainer
<std::vector
< uno::Any
>>(aNewData
) );
958 if( aRange
.match( lcl_aLabelRangePrefix
) )
960 sal_uInt32 nIndex
= o3tl::toInt32(aRange
.subView( strlen(lcl_aLabelRangePrefix
)));
961 if( m_bDataInColumns
)
962 m_aInternalData
.setComplexColumnLabel( nIndex
, std::move(aNewVector
) );
964 m_aInternalData
.setComplexRowLabel( nIndex
, std::move(aNewVector
) );
966 else if( aRange
.match( lcl_aCategoriesPointRangeNamePrefix
) )
968 sal_Int32 nPointIndex
= o3tl::toInt32(aRange
.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix
)));
969 if( m_bDataInColumns
)
970 m_aInternalData
.setComplexRowLabel( nPointIndex
, std::move(aNewVector
) );
972 m_aInternalData
.setComplexColumnLabel( nPointIndex
, std::move(aNewVector
) );
974 else if( aRange
.match( lcl_aCategoriesLevelRangeNamePrefix
) )
976 sal_Int32 nLevel
= o3tl::toInt32(aRange
.subView( strlen(lcl_aCategoriesLevelRangeNamePrefix
)));
977 std::vector
< std::vector
< uno::Any
> > aComplexCategories
= m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels();
979 //ensure equal length
980 if( aNewVector
.size() > aComplexCategories
.size() )
981 aComplexCategories
.resize( aNewVector
.size() );
982 else if( aNewVector
.size() < aComplexCategories
.size() )
983 aNewVector
.resize( aComplexCategories
.size() );
985 transform( aComplexCategories
.begin(), aComplexCategories
.end(), aNewVector
.begin(),
986 aComplexCategories
.begin(), lcl_setAnyAtLevel(nLevel
) );
988 if( m_bDataInColumns
)
989 m_aInternalData
.setComplexRowLabels( std::move(aComplexCategories
) );
991 m_aInternalData
.setComplexColumnLabels( std::move(aComplexCategories
) );
993 else if( aRange
== lcl_aCategoriesRangeName
)
995 std::vector
< std::vector
< uno::Any
> > aComplexCategories
;
996 aComplexCategories
.resize( aNewVector
.size() );
997 transform( aComplexCategories
.begin(), aComplexCategories
.end(), aNewVector
.begin(),
998 aComplexCategories
.begin(), lcl_setAnyAtLevel(0) );
999 if( m_bDataInColumns
)
1000 m_aInternalData
.setComplexRowLabels( std::move(aComplexCategories
) );
1002 m_aInternalData
.setComplexColumnLabels( std::move(aComplexCategories
) );
1006 sal_Int32 nIndex
= aRange
.toInt32();
1009 std::vector
< double > aNewDataVec
;
1010 transform( aNewData
.begin(), aNewData
.end(),
1011 back_inserter( aNewDataVec
), CommonFunctors::AnyToDouble());
1012 if( m_bDataInColumns
)
1013 m_aInternalData
.setColumnValues( nIndex
, aNewDataVec
);
1015 m_aInternalData
.setRowValues( nIndex
, aNewDataVec
);
1020 void SAL_CALL
InternalDataProvider::insertSequence( ::sal_Int32 nAfterIndex
)
1022 if( m_bDataInColumns
)
1024 increaseMapReferences( nAfterIndex
+ 1, m_aInternalData
.getColumnCount());
1025 m_aInternalData
.insertColumn( nAfterIndex
);
1029 increaseMapReferences( nAfterIndex
+ 1, m_aInternalData
.getRowCount());
1030 m_aInternalData
.insertRow( nAfterIndex
);
1034 void SAL_CALL
InternalDataProvider::deleteSequence( ::sal_Int32 nAtIndex
)
1036 deleteMapReferences( OUString::number( nAtIndex
));
1037 deleteMapReferences( lcl_aLabelRangePrefix
+ OUString::number( nAtIndex
));
1038 if( m_bDataInColumns
)
1040 decreaseMapReferences( nAtIndex
+ 1, m_aInternalData
.getColumnCount());
1041 m_aInternalData
.deleteColumn( nAtIndex
);
1045 decreaseMapReferences( nAtIndex
+ 1, m_aInternalData
.getRowCount());
1046 m_aInternalData
.deleteRow( nAtIndex
);
1050 void SAL_CALL
InternalDataProvider::appendSequence()
1052 if( m_bDataInColumns
)
1053 m_aInternalData
.appendColumn();
1055 m_aInternalData
.appendRow();
1058 void SAL_CALL
InternalDataProvider::insertComplexCategoryLevel( sal_Int32 nLevel
)
1060 OSL_ENSURE( nLevel
> 0, "you can only insert category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1063 std::vector
< std::vector
< uno::Any
> > aComplexCategories
= m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels();
1064 std::for_each( aComplexCategories
.begin(), aComplexCategories
.end(), lcl_insertAnyAtLevel(nLevel
) );
1065 if( m_bDataInColumns
)
1066 m_aInternalData
.setComplexRowLabels( std::move(aComplexCategories
) );
1068 m_aInternalData
.setComplexColumnLabels( std::move(aComplexCategories
) );
1070 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1071 std::for_each( aRange
.first
, aRange
.second
, lcl_setModified());
1074 void SAL_CALL
InternalDataProvider::deleteComplexCategoryLevel( sal_Int32 nLevel
)
1076 OSL_ENSURE( nLevel
>0, "you can only delete category levels > 0" );//the first categories level cannot be deleted, check the calling code for error
1079 std::vector
< std::vector
< uno::Any
> > aComplexCategories
= m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels();
1080 std::for_each( aComplexCategories
.begin(), aComplexCategories
.end(), lcl_removeAnyAtLevel(nLevel
) );
1081 if( m_bDataInColumns
)
1082 m_aInternalData
.setComplexRowLabels( std::move(aComplexCategories
) );
1084 m_aInternalData
.setComplexColumnLabels( std::move(aComplexCategories
) );
1086 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1087 std::for_each( aRange
.first
, aRange
.second
, lcl_setModified());
1091 void SAL_CALL
InternalDataProvider::insertDataPointForAllSequences( ::sal_Int32 nAfterIndex
)
1093 sal_Int32 nMaxRep
= 0;
1094 if( m_bDataInColumns
)
1096 m_aInternalData
.insertRow( nAfterIndex
);
1097 nMaxRep
= m_aInternalData
.getColumnCount();
1101 m_aInternalData
.insertColumn( nAfterIndex
);
1102 nMaxRep
= m_aInternalData
.getRowCount();
1105 // notify change to all affected ranges
1106 tSequenceMap::const_iterator
aBegin( m_aSequenceMap
.lower_bound( "0"));
1107 tSequenceMap::const_iterator
aEnd( m_aSequenceMap
.upper_bound( OUString::number( nMaxRep
)));
1108 std::for_each( aBegin
, aEnd
, lcl_setModified());
1110 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1111 std::for_each( aRange
.first
, aRange
.second
, lcl_setModified());
1114 void SAL_CALL
InternalDataProvider::deleteDataPointForAllSequences( ::sal_Int32 nAtIndex
)
1116 sal_Int32 nMaxRep
= 0;
1117 if( m_bDataInColumns
)
1119 m_aInternalData
.deleteRow( nAtIndex
);
1120 nMaxRep
= m_aInternalData
.getColumnCount();
1124 m_aInternalData
.deleteColumn( nAtIndex
);
1125 nMaxRep
= m_aInternalData
.getRowCount();
1128 // notify change to all affected ranges
1129 tSequenceMap::const_iterator
aBegin( m_aSequenceMap
.lower_bound( "0"));
1130 tSequenceMap::const_iterator
aEnd( m_aSequenceMap
.upper_bound( OUString::number( nMaxRep
)));
1131 std::for_each( aBegin
, aEnd
, lcl_setModified());
1133 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1134 std::for_each( aRange
.first
, aRange
.second
, lcl_setModified());
1137 void SAL_CALL
InternalDataProvider::swapDataPointWithNextOneForAllSequences( ::sal_Int32 nAtIndex
)
1139 if( m_bDataInColumns
)
1140 m_aInternalData
.swapRowWithNext( nAtIndex
);
1142 m_aInternalData
.swapColumnWithNext( nAtIndex
);
1143 sal_Int32 nMaxRep
= (m_bDataInColumns
1144 ? m_aInternalData
.getColumnCount()
1145 : m_aInternalData
.getRowCount());
1147 // notify change to all affected ranges
1148 tSequenceMap::const_iterator
aBegin( m_aSequenceMap
.lower_bound( "0"));
1149 tSequenceMap::const_iterator
aEnd( m_aSequenceMap
.upper_bound( OUString::number( nMaxRep
)));
1150 std::for_each( aBegin
, aEnd
, lcl_setModified());
1152 tSequenceMapRange
aRange( m_aSequenceMap
.equal_range( lcl_aCategoriesRangeName
));
1153 std::for_each( aRange
.first
, aRange
.second
, lcl_setModified());
1156 void SAL_CALL
InternalDataProvider::registerDataSequenceForChanges( const Reference
< chart2::data::XDataSequence
>& xSeq
)
1159 addDataSequenceToMap( xSeq
->getSourceRangeRepresentation(), xSeq
);
1162 // ____ XRangeXMLConversion ____
1163 OUString SAL_CALL
InternalDataProvider::convertRangeToXML( const OUString
& aRangeRepresentation
)
1165 XMLRangeHelper::CellRange aRange
;
1166 aRange
.aTableName
= "local-table";
1168 // attention: this data provider has the limitation that it stores
1169 // internally if data comes from columns or rows. It is intended for
1170 // creating only one used data source.
1171 // @todo: add this information in the range representation strings
1172 if( aRangeRepresentation
.match( lcl_aCategoriesRangeName
))
1174 OSL_ASSERT( aRangeRepresentation
== lcl_aCategoriesRangeName
);//it is not expected nor implemented that only parts of the categories are really requested
1175 aRange
.aUpperLeft
.bIsEmpty
= false;
1176 if( m_bDataInColumns
)
1178 aRange
.aUpperLeft
.nColumn
= 0;
1179 aRange
.aUpperLeft
.nRow
= 1;
1180 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1181 aRange
.aLowerRight
.nRow
= m_aInternalData
.getRowCount();
1185 aRange
.aUpperLeft
.nColumn
= 1;
1186 aRange
.aUpperLeft
.nRow
= 0;
1187 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1188 aRange
.aLowerRight
.nColumn
= m_aInternalData
.getColumnCount();
1191 else if( aRangeRepresentation
.match( lcl_aLabelRangePrefix
))
1193 sal_Int32 nIndex
= o3tl::toInt32(aRangeRepresentation
.subView( strlen(lcl_aLabelRangePrefix
)));
1194 aRange
.aUpperLeft
.bIsEmpty
= false;
1195 aRange
.aLowerRight
.bIsEmpty
= true;
1196 if( m_bDataInColumns
)
1198 aRange
.aUpperLeft
.nColumn
= nIndex
+ 1;
1199 aRange
.aUpperLeft
.nRow
= 0;
1203 aRange
.aUpperLeft
.nColumn
= 0;
1204 aRange
.aUpperLeft
.nRow
= nIndex
+ 1;
1207 else if( aRangeRepresentation
== lcl_aCompleteRange
)
1209 aRange
.aUpperLeft
.bIsEmpty
= false;
1210 aRange
.aLowerRight
.bIsEmpty
= false;
1211 aRange
.aUpperLeft
.nColumn
= 0;
1212 aRange
.aUpperLeft
.nRow
= 0;
1213 aRange
.aLowerRight
.nColumn
= m_aInternalData
.getColumnCount();
1214 aRange
.aLowerRight
.nRow
= m_aInternalData
.getRowCount();
1218 sal_Int32 nIndex
= aRangeRepresentation
.toInt32();
1219 aRange
.aUpperLeft
.bIsEmpty
= false;
1220 if( m_bDataInColumns
)
1222 aRange
.aUpperLeft
.nColumn
= nIndex
+ 1;
1223 aRange
.aUpperLeft
.nRow
= 1;
1224 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1225 aRange
.aLowerRight
.nRow
= m_aInternalData
.getRowCount();
1229 aRange
.aUpperLeft
.nColumn
= 1;
1230 aRange
.aUpperLeft
.nRow
= nIndex
+ 1;
1231 aRange
.aLowerRight
= aRange
.aUpperLeft
;
1232 aRange
.aLowerRight
.nColumn
= m_aInternalData
.getColumnCount();
1236 return XMLRangeHelper::getXMLStringFromCellRange( aRange
);
1239 OUString SAL_CALL
InternalDataProvider::convertRangeFromXML( const OUString
& aXMLRange
)
1241 // Handle non-standards-conforming table:cell-range-address="PivotChart", see
1242 // <https://bugs.documentfoundation.org/show_bug.cgi?id=112783> "PIVOT CHARTS: Save produces
1243 // invalid file because of invalid cell address":
1244 if (aXMLRange
== "PivotChart") {
1248 static constexpr OUString
aPivotTableID(u
"PT@"_ustr
);
1249 if (aXMLRange
.startsWith(aPivotTableID
))
1250 return aXMLRange
.copy(aPivotTableID
.getLength());
1252 XMLRangeHelper::CellRange
aRange( XMLRangeHelper::getCellRangeFromXMLString( aXMLRange
));
1253 if( aRange
.aUpperLeft
.bIsEmpty
)
1255 OSL_ENSURE( aRange
.aLowerRight
.bIsEmpty
, "Weird Range" );
1260 if( !aRange
.aLowerRight
.bIsEmpty
&&
1261 ( aRange
.aUpperLeft
.nColumn
!= aRange
.aLowerRight
.nColumn
) &&
1262 ( aRange
.aUpperLeft
.nRow
!= aRange
.aLowerRight
.nRow
) )
1263 return lcl_aCompleteRange
;
1265 // attention: this data provider has the limitation that it stores
1266 // internally if data comes from columns or rows. It is intended for
1267 // creating only one used data source.
1268 // @todo: add this information in the range representation strings
1271 if( m_bDataInColumns
)
1273 if( aRange
.aUpperLeft
.nColumn
== 0 )
1274 return lcl_aCategoriesRangeName
;
1275 if( aRange
.aUpperLeft
.nRow
== 0 )
1276 return lcl_aLabelRangePrefix
+ OUString::number( aRange
.aUpperLeft
.nColumn
- 1 );
1278 return OUString::number( aRange
.aUpperLeft
.nColumn
- 1 );
1282 if( aRange
.aUpperLeft
.nRow
== 0 )
1283 return lcl_aCategoriesRangeName
;
1284 if( aRange
.aUpperLeft
.nColumn
== 0 )
1285 return lcl_aLabelRangePrefix
+ OUString::number( aRange
.aUpperLeft
.nRow
- 1 );
1287 return OUString::number( aRange
.aUpperLeft
.nRow
- 1 );
1293 template< class Type
>
1294 Sequence
< Sequence
< Type
> > lcl_convertVectorVectorToSequenceSequence( const std::vector
< std::vector
< Type
> >& rIn
)
1296 Sequence
< Sequence
< Type
> > aRet
;
1297 sal_Int32 nOuterCount
= rIn
.size();
1300 aRet
.realloc(nOuterCount
);
1301 auto pRet
= aRet
.getArray();
1302 for( sal_Int32 nN
=0; nN
<nOuterCount
; nN
++)
1303 pRet
[nN
]= comphelper::containerToSequence( rIn
[nN
] );
1308 template< class Type
>
1309 std::vector
< std::vector
< Type
> > lcl_convertSequenceSequenceToVectorVector( const Sequence
< Sequence
< Type
> >& rIn
)
1311 std::vector
< std::vector
< Type
> > aRet
;
1312 sal_Int32 nOuterCount
= rIn
.getLength();
1315 aRet
.resize(nOuterCount
);
1316 for( sal_Int32 nN
=0; nN
<nOuterCount
; nN
++)
1317 aRet
[nN
]= comphelper::sequenceToContainer
<std::vector
< Type
>>( rIn
[nN
] );
1322 std::vector
< Sequence
< OUString
> > lcl_convertComplexAnyVectorToStringSequence( const std::vector
< std::vector
< uno::Any
> >& rIn
)
1324 std::vector
< Sequence
< OUString
> > aRet
;
1325 sal_Int32 nOuterCount
= rIn
.size();
1328 aRet
.resize(nOuterCount
);
1329 for( sal_Int32 nN
=0; nN
<nOuterCount
; nN
++)
1330 aRet
[nN
] = comphelper::containerToSequence(lcl_AnyToStringSequence( rIn
[nN
] ));
1335 std::vector
< std::vector
< uno::Any
> > lcl_convertComplexStringSequenceToAnyVector( const Sequence
< Sequence
< OUString
> >& rIn
)
1337 std::vector
< std::vector
< uno::Any
> > aRet
;
1338 sal_Int32 nOuterCount
= rIn
.getLength();
1339 aRet
.reserve(nOuterCount
);
1340 for (sal_Int32 nN
= 0; nN
< nOuterCount
; nN
++)
1341 aRet
.push_back( lcl_StringToAnyVector( rIn
[nN
] ) );
1345 class SplitCategoriesProvider_ForComplexDescriptions
: public SplitCategoriesProvider
1349 explicit SplitCategoriesProvider_ForComplexDescriptions( const std::vector
< std::vector
< uno::Any
> >& rComplexDescriptions
)
1350 : m_rComplexDescriptions( rComplexDescriptions
)
1353 virtual sal_Int32
getLevelCount() const override
;
1354 virtual uno::Sequence
< OUString
> getStringsForLevel( sal_Int32 nIndex
) const override
;
1357 const std::vector
< std::vector
< uno::Any
> >& m_rComplexDescriptions
;
1360 sal_Int32
SplitCategoriesProvider_ForComplexDescriptions::getLevelCount() const
1362 return lcl_getInnerLevelCount( m_rComplexDescriptions
);
1364 uno::Sequence
< OUString
> SplitCategoriesProvider_ForComplexDescriptions::getStringsForLevel( sal_Int32 nLevel
) const
1366 uno::Sequence
< OUString
> aResult
;
1367 if( nLevel
< lcl_getInnerLevelCount( m_rComplexDescriptions
) )
1369 aResult
.realloc( m_rComplexDescriptions
.size() );
1370 transform( m_rComplexDescriptions
.begin(), m_rComplexDescriptions
.end(),
1371 aResult
.getArray(), lcl_getStringFromLevelVector(nLevel
) );
1376 }//anonymous namespace
1378 // ____ XDateCategories ____
1379 Sequence
< double > SAL_CALL
InternalDataProvider::getDateCategories()
1381 const std::vector
< std::vector
< uno::Any
> > & aCategories( m_bDataInColumns
? m_aInternalData
.getComplexRowLabels() : m_aInternalData
.getComplexColumnLabels());
1382 sal_Int32 nCount
= aCategories
.size();
1383 Sequence
< double > aDoubles( nCount
);
1384 auto aDoublesRange
= asNonConstRange(aDoubles
);
1386 for (auto const& category
: aCategories
)
1389 if( category
.empty() || !(category
[0]>>=fValue
) )
1390 fValue
= std::numeric_limits
<double>::quiet_NaN();
1391 aDoublesRange
[nN
++]=fValue
;
1396 void SAL_CALL
InternalDataProvider::setDateCategories( const Sequence
< double >& rDates
)
1398 sal_Int32 nCount
= rDates
.getLength();
1399 std::vector
< std::vector
< uno::Any
> > aNewCategories
;
1400 aNewCategories
.reserve(nCount
);
1401 std::vector
< uno::Any
> aSingleLabel(1);
1403 for(sal_Int32 nN
=0; nN
<nCount
; ++nN
)
1405 aSingleLabel
[0] <<= rDates
[nN
];
1406 aNewCategories
.push_back(aSingleLabel
);
1409 if( m_bDataInColumns
)
1410 m_aInternalData
.setComplexRowLabels( std::move(aNewCategories
) );
1412 m_aInternalData
.setComplexColumnLabels( std::move(aNewCategories
) );
1415 // ____ XAnyDescriptionAccess ____
1416 Sequence
< Sequence
< uno::Any
> > SAL_CALL
InternalDataProvider::getAnyRowDescriptions()
1418 return lcl_convertVectorVectorToSequenceSequence( m_aInternalData
.getComplexRowLabels() );
1420 void SAL_CALL
InternalDataProvider::setAnyRowDescriptions( const Sequence
< Sequence
< uno::Any
> >& aRowDescriptions
)
1422 m_aInternalData
.setComplexRowLabels( lcl_convertSequenceSequenceToVectorVector( aRowDescriptions
) );
1424 Sequence
< Sequence
< uno::Any
> > SAL_CALL
InternalDataProvider::getAnyColumnDescriptions()
1426 return lcl_convertVectorVectorToSequenceSequence( m_aInternalData
.getComplexColumnLabels() );
1428 void SAL_CALL
InternalDataProvider::setAnyColumnDescriptions( const Sequence
< Sequence
< uno::Any
> >& aColumnDescriptions
)
1430 m_aInternalData
.setComplexColumnLabels( lcl_convertSequenceSequenceToVectorVector( aColumnDescriptions
) );
1433 // ____ XComplexDescriptionAccess ____
1434 Sequence
< Sequence
< OUString
> > SAL_CALL
InternalDataProvider::getComplexRowDescriptions()
1436 return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData
.getComplexRowLabels() ));
1438 void SAL_CALL
InternalDataProvider::setComplexRowDescriptions( const Sequence
< Sequence
< OUString
> >& aRowDescriptions
)
1440 m_aInternalData
.setComplexRowLabels( lcl_convertComplexStringSequenceToAnyVector(aRowDescriptions
) );
1442 Sequence
< Sequence
< OUString
> > SAL_CALL
InternalDataProvider::getComplexColumnDescriptions()
1444 return comphelper::containerToSequence(lcl_convertComplexAnyVectorToStringSequence( m_aInternalData
.getComplexColumnLabels() ));
1446 void SAL_CALL
InternalDataProvider::setComplexColumnDescriptions( const Sequence
< Sequence
< OUString
> >& aColumnDescriptions
)
1448 m_aInternalData
.setComplexColumnLabels( lcl_convertComplexStringSequenceToAnyVector(aColumnDescriptions
) );
1451 // ____ XChartDataArray ____
1452 Sequence
< Sequence
< double > > SAL_CALL
InternalDataProvider::getData()
1454 return m_aInternalData
.getData();
1457 void SAL_CALL
InternalDataProvider::setData( const Sequence
< Sequence
< double > >& rDataInRows
)
1459 return m_aInternalData
.setData( rDataInRows
);
1462 void SAL_CALL
InternalDataProvider::setRowDescriptions( const Sequence
< OUString
>& aRowDescriptions
)
1464 std::vector
< std::vector
< uno::Any
> > aComplexDescriptions( aRowDescriptions
.getLength() );
1465 transform( aComplexDescriptions
.begin(), aComplexDescriptions
.end(), aRowDescriptions
.getConstArray(),
1466 aComplexDescriptions
.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1467 m_aInternalData
.setComplexRowLabels( std::move(aComplexDescriptions
) );
1470 void SAL_CALL
InternalDataProvider::setColumnDescriptions( const Sequence
< OUString
>& aColumnDescriptions
)
1472 std::vector
< std::vector
< uno::Any
> > aComplexDescriptions( aColumnDescriptions
.getLength() );
1473 transform( aComplexDescriptions
.begin(), aComplexDescriptions
.end(), aColumnDescriptions
.getConstArray(),
1474 aComplexDescriptions
.begin(), lcl_setAnyAtLevelFromStringSequence(0) );
1475 m_aInternalData
.setComplexColumnLabels( std::move(aComplexDescriptions
) );
1478 Sequence
< OUString
> SAL_CALL
InternalDataProvider::getRowDescriptions()
1480 const std::vector
< std::vector
< uno::Any
> > & aComplexLabels( m_aInternalData
.getComplexRowLabels() );
1481 SplitCategoriesProvider_ForComplexDescriptions
aProvider( aComplexLabels
);
1482 return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider
);
1485 Sequence
< OUString
> SAL_CALL
InternalDataProvider::getColumnDescriptions()
1487 const std::vector
< std::vector
< uno::Any
> > & aComplexLabels( m_aInternalData
.getComplexColumnLabels() );
1488 SplitCategoriesProvider_ForComplexDescriptions
aProvider( aComplexLabels
);
1489 return ExplicitCategoriesProvider::getExplicitSimpleCategories( aProvider
);
1492 // ____ XChartData (base of XChartDataArray) ____
1493 void SAL_CALL
InternalDataProvider::addChartDataChangeEventListener(
1494 const Reference
< css::chart::XChartDataChangeEventListener
>& )
1498 void SAL_CALL
InternalDataProvider::removeChartDataChangeEventListener(
1499 const Reference
< css::chart::XChartDataChangeEventListener
>& )
1503 double SAL_CALL
InternalDataProvider::getNotANumber()
1505 return std::numeric_limits
<double>::quiet_NaN();
1508 sal_Bool SAL_CALL
InternalDataProvider::isNotANumber( double nNumber
)
1510 return std::isnan( nNumber
)
1511 || std::isinf( nNumber
);
1513 // lang::XInitialization:
1514 void SAL_CALL
InternalDataProvider::initialize(const uno::Sequence
< uno::Any
> & _aArguments
)
1516 comphelper::SequenceAsHashMap
aArgs(_aArguments
);
1517 if ( aArgs
.getUnpackedValueOrDefault( "CreateDefaultData", false ) )
1518 m_aInternalData
.createDefaultData();
1521 // ____ XCloneable ____
1522 Reference
< util::XCloneable
> SAL_CALL
InternalDataProvider::createClone()
1524 return Reference
< util::XCloneable
>( new InternalDataProvider( *this ));
1527 OUString SAL_CALL
InternalDataProvider::getImplementationName()
1529 // note: in xmloff this name is used to indicate usage of own data
1530 return "com.sun.star.comp.chart.InternalDataProvider";
1533 sal_Bool SAL_CALL
InternalDataProvider::supportsService( const OUString
& rServiceName
)
1535 return cppu::supportsService(this, rServiceName
);
1538 css::uno::Sequence
< OUString
> SAL_CALL
InternalDataProvider::getSupportedServiceNames()
1540 return { "com.sun.star.chart2.data.DataProvider" };
1543 } // namespace chart
1545 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1546 com_sun_star_comp_chart_InternalDataProvider_get_implementation(css::uno::XComponentContext
*,
1547 css::uno::Sequence
<css::uno::Any
> const &)
1549 return cppu::acquire(new ::chart::InternalDataProvider
);
1552 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */