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/.
12 #include <sal/config.h>
14 #include <PivotTableDataProvider.hxx>
15 #include <PivotTableDataSource.hxx>
16 #include <PivotTableDataSequence.hxx>
18 #include <miscuno.hxx>
19 #include <document.hxx>
21 #include <unonames.hxx>
22 #include <scresid.hxx>
23 #include <globstr.hrc>
24 #include <strings.hrc>
25 #include <dpobject.hxx>
28 #include <o3tl/safeint.hxx>
29 #include <vcl/svapp.hxx>
30 #include <comphelper/propertysequence.hxx>
31 #include <comphelper/sequence.hxx>
32 #include <comphelper/processfactory.hxx>
34 #include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
35 #include <com/sun/star/chart/ChartDataRowSource.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/sheet/XDataPilotResults.hpp>
39 #include <com/sun/star/sheet/DataResultFlags.hpp>
41 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
42 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
43 #include <com/sun/star/sheet/XLevelsSupplier.hpp>
44 #include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
45 #include <com/sun/star/sheet/MemberResultFlags.hpp>
46 #include <com/sun/star/sheet/XMembersSupplier.hpp>
48 #include <com/sun/star/chart/ChartDataChangeEvent.hpp>
49 #include <com/sun/star/container/XNamed.hpp>
51 #include <unordered_map>
59 constexpr OUStringLiteral
constIdCategories(u
"categories");
60 constexpr OUStringLiteral
constIdLabel(u
"label");
61 constexpr OUStringLiteral
constIdData(u
"data");
63 std::span
<const SfxItemPropertyMapEntry
> lcl_GetDataProviderPropertyMap()
65 static const SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl
[] =
67 { SC_UNONAME_INCLUDEHIDDENCELLS
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
68 { SC_UNONAME_USE_INTERNAL_DATA_PROVIDER
, 0, cppu::UnoType
<bool>::get(), 0, 0 },
70 return aDataProviderPropertyMap_Impl
;
73 uno::Reference
<frame::XModel
> lcl_GetXModel(const ScDocument
* pDoc
)
75 uno::Reference
<frame::XModel
> xModel
;
76 ScDocShell
* pObjSh(pDoc
? pDoc
->GetDocumentShell() : nullptr);
78 xModel
.set(pObjSh
->GetModel());
82 OUString
lcl_identifierForData(sal_Int32 index
)
84 return "PT@" + constIdData
+ " " + OUString::number(index
);
87 OUString
lcl_identifierForLabel(sal_Int32 index
)
89 return "PT@" + constIdLabel
+ " " + OUString::number(index
);
92 OUString
lcl_identifierForCategories()
94 return "PT@" + constIdCategories
;
97 std::vector
<OUString
> lcl_getVisiblePageMembers(const uno::Reference
<uno::XInterface
> & xLevel
)
99 std::vector
<OUString
> aResult
;
103 uno::Reference
<sheet::XMembersSupplier
> xMembersSupplier(xLevel
, uno::UNO_QUERY
);
104 if (!xMembersSupplier
.is())
107 uno::Reference
<sheet::XMembersAccess
> xMembersAccess
= xMembersSupplier
->getMembers();
108 if (!xMembersAccess
.is())
111 const css::uno::Sequence
<OUString
> aMembersNames
= xMembersAccess
->getElementNames();
112 for (OUString
const & rMemberNames
: aMembersNames
)
114 uno::Reference
<beans::XPropertySet
> xProperties(xMembersAccess
->getByName(rMemberNames
), uno::UNO_QUERY
);
115 if (!xProperties
.is())
118 OUString aCaption
= ScUnoHelpFunctions::GetStringProperty(xProperties
, SC_UNO_DP_LAYOUTNAME
, OUString());
119 if (aCaption
.isEmpty())
120 aCaption
= rMemberNames
;
122 bool bVisible
= ScUnoHelpFunctions::GetBoolProperty(xProperties
, SC_UNO_DP_ISVISIBLE
);
125 aResult
.push_back(aCaption
);
131 } // end anonymous namespace
133 SC_SIMPLE_SERVICE_INFO(PivotTableDataProvider
, u
"PivotTableDataProvider"_ustr
, SC_SERVICENAME_CHART_PIVOTTABLE_DATAPROVIDER
)
135 // DataProvider ==============================================================
137 PivotTableDataProvider::PivotTableDataProvider(ScDocument
& rDoc
)
139 , m_aPropSet(lcl_GetDataProviderPropertyMap())
140 , m_bIncludeHiddenCells(true)
141 , m_bNeedsUpdate(true)
142 , m_xContext(comphelper::getProcessComponentContext())
144 rDoc
.AddUnoObject(*this);
147 PivotTableDataProvider::~PivotTableDataProvider()
152 m_pDocument
->RemoveUnoObject( *this);
155 void PivotTableDataProvider::Notify(SfxBroadcaster
& /*rBroadcaster*/, const SfxHint
& rHint
)
157 if (rHint
.GetId() == SfxHintId::Dying
)
159 m_pDocument
= nullptr;
161 else if (m_pDocument
)
163 if (rHint
.GetId() == SfxHintId::ScDataPilotModified
)
165 auto pDataPilotHint
= static_cast<const ScDataPilotModifiedHint
*>(&rHint
);
166 if (pDataPilotHint
->GetName() == m_sPivotTableName
)
168 m_bNeedsUpdate
= true;
169 for (uno::Reference
<util::XModifyListener
> const & xListener
: m_aValueListeners
)
171 css::chart::ChartDataChangeEvent
aEvent(getXWeak(),
172 css::chart::ChartDataChangeType_ALL
,
174 xListener
->modified(aEvent
);
181 sal_Bool SAL_CALL
PivotTableDataProvider::createDataSourcePossible(const uno::Sequence
<beans::PropertyValue
>& /*aArguments*/)
183 SolarMutexGuard aGuard
;
187 if (m_sPivotTableName
.isEmpty())
190 ScDPCollection
* pDPCollection
= m_pDocument
->GetDPCollection();
191 return bool(pDPCollection
->GetByName(m_sPivotTableName
));
194 uno::Reference
<chart2::data::XDataSource
> SAL_CALL
195 PivotTableDataProvider::createDataSource(const uno::Sequence
<beans::PropertyValue
>& aArguments
)
197 SolarMutexGuard aGuard
;
200 throw uno::RuntimeException();
202 bool bOrientCol
= true;
203 OUString aRangeRepresentation
;
205 for (beans::PropertyValue
const & rProperty
: aArguments
)
207 if (rProperty
.Name
== "DataRowSource")
209 chart::ChartDataRowSource eSource
= chart::ChartDataRowSource_COLUMNS
;
210 if (!(rProperty
.Value
>>= eSource
))
212 sal_Int32
nSource(0);
213 if (rProperty
.Value
>>= nSource
)
214 eSource
= chart::ChartDataRowSource(nSource
);
216 bOrientCol
= (eSource
== chart::ChartDataRowSource_COLUMNS
);
218 else if (rProperty
.Name
== "CellRangeRepresentation")
219 rProperty
.Value
>>= aRangeRepresentation
;
222 uno::Reference
<chart2::data::XDataSource
> xResult
;
224 if (aRangeRepresentation
== lcl_identifierForCategories())
225 xResult
= createCategoriesDataSource(bOrientCol
);
227 xResult
= createValuesDataSource();
232 uno::Reference
<chart2::data::XLabeledDataSequence
>
233 PivotTableDataProvider::newLabeledDataSequence()
235 uno::Reference
<chart2::data::XLabeledDataSequence
> xResult
;
236 if (!m_xContext
.is())
238 xResult
.set(chart2::data::LabeledDataSequence::create(m_xContext
), uno::UNO_QUERY_THROW
);
242 uno::Reference
<chart2::data::XDataSource
>
243 PivotTableDataProvider::createCategoriesDataSource(bool bOrientationIsColumn
)
246 collectPivotTableData();
248 uno::Reference
<chart2::data::XDataSource
> xDataSource
;
249 std::vector
<uno::Reference
<chart2::data::XLabeledDataSequence
>> aLabeledSequences
;
251 std::vector
<std::vector
<ValueAndFormat
>> const & rCategoriesVector
= bOrientationIsColumn
? m_aCategoriesColumnOrientation
252 : m_aCategoriesRowOrientation
;
254 for (std::vector
<ValueAndFormat
> const & rCategories
: rCategoriesVector
)
256 uno::Reference
<chart2::data::XLabeledDataSequence
> xResult
= newLabeledDataSequence();
257 rtl::Reference
<PivotTableDataSequence
> pSequence(new PivotTableDataSequence(m_pDocument
,
258 lcl_identifierForCategories(), std::vector(rCategories
)));
259 pSequence
->setRole(u
"categories"_ustr
);
260 xResult
->setValues(uno::Reference
<chart2::data::XDataSequence
>(pSequence
));
262 aLabeledSequences
.push_back(xResult
);
265 xDataSource
.set(new PivotTableDataSource(std::move(aLabeledSequences
)));
269 void PivotTableDataProvider::collectPivotTableData()
271 ScDPCollection
* pDPCollection
= m_pDocument
->GetDPCollection();
272 ScDPObject
* pDPObject
= pDPCollection
->GetByName(m_sPivotTableName
);
276 m_aCategoriesColumnOrientation
.clear();
277 m_aCategoriesRowOrientation
.clear();
279 m_aDataRowVector
.clear();
280 m_aColumnFields
.clear();
281 m_aRowFields
.clear();
282 m_aPageFields
.clear();
283 m_aDataFields
.clear();
284 m_aFieldOutputDescriptionMap
.clear();
286 uno::Reference
<sheet::XDataPilotResults
> xDPResults(pDPObject
->GetSource(), uno::UNO_QUERY
);
287 if (!xDPResults
.is())
289 const uno::Sequence
<uno::Sequence
<sheet::DataResult
>> xDataResultsSequence
= xDPResults
->getResults();
291 std::unordered_set
<size_t> aValidRowIndex
;
293 size_t nRowIndex
= 0;
294 for (uno::Sequence
<sheet::DataResult
> const & xDataResults
: xDataResultsSequence
)
296 std::vector
<ValueAndFormat
> aRow
;
297 bool bRowEmpty
= true;
298 // First pass - collect a row of valid data and track if the row is empty
299 for (sheet::DataResult
const & rDataResult
: xDataResults
)
301 if (rDataResult
.Flags
& css::sheet::DataResultFlags::SUBTOTAL
)
303 if (rDataResult
.Flags
== 0 || rDataResult
.Flags
& css::sheet::DataResultFlags::HASDATA
)
305 aRow
.emplace_back(rDataResult
.Flags
? rDataResult
.Value
306 : std::numeric_limits
<double>::quiet_NaN(), 0);
307 if (rDataResult
.Flags
!= 0) // set as valid only if we have data
310 // We need to remember all valid (non-empty) row indices
311 aValidRowIndex
.insert(nRowIndex
);
315 // Second pass: add to collection only non-empty rows
318 size_t nColumnIndex
= 0;
319 for (ValueAndFormat
const & aValue
: aRow
)
321 if (nColumnIndex
>= m_aDataRowVector
.size())
322 m_aDataRowVector
.resize(nColumnIndex
+ 1);
323 m_aDataRowVector
[nColumnIndex
].push_back(aValue
);
330 uno::Reference
<sheet::XDimensionsSupplier
> xDimensionsSupplier(pDPObject
->GetSource());
331 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess(xDimensionsSupplier
->getDimensions());
333 std::unordered_map
<OUString
, sal_Int32
> aDataFieldNumberFormatMap
;
334 std::vector
<OUString
> aDataFieldNamesVectors
;
336 std::unordered_map
<OUString
, OUString
> aDataFieldCaptionNames
;
338 sheet::DataPilotFieldOrientation eDataFieldOrientation
= sheet::DataPilotFieldOrientation_HIDDEN
;
340 for (sal_Int32 nDim
= 0; nDim
< xDims
->getCount(); nDim
++)
342 uno::Reference
<uno::XInterface
> xDim(xDims
->getByIndex(nDim
), uno::UNO_QUERY
);
343 uno::Reference
<beans::XPropertySet
> xDimProp(xDim
, uno::UNO_QUERY
);
344 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp(xDim
, uno::UNO_QUERY
);
346 if (!xDimProp
.is() || !xDimSupp
.is())
349 sheet::DataPilotFieldOrientation eDimOrient
=
350 ScUnoHelpFunctions::GetEnumProperty(xDimProp
, SC_UNO_DP_ORIENTATION
,
351 sheet::DataPilotFieldOrientation_HIDDEN
);
353 if (eDimOrient
== sheet::DataPilotFieldOrientation_HIDDEN
)
356 uno::Reference
<container::XIndexAccess
> xHierarchies
= new ScNameToIndexAccess(xDimSupp
->getHierarchies());
357 sal_Int32 nHierarchy
= ScUnoHelpFunctions::GetLongProperty(xDimProp
, SC_UNO_DP_USEDHIERARCHY
);
358 if (nHierarchy
>= xHierarchies
->getCount())
361 uno::Reference
<sheet::XLevelsSupplier
> xLevelsSupplier(xHierarchies
->getByIndex(nHierarchy
),
364 if (!xLevelsSupplier
.is())
367 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess(xLevelsSupplier
->getLevels());
369 for (tools::Long nLevel
= 0; nLevel
< xLevels
->getCount(); nLevel
++)
371 uno::Reference
<uno::XInterface
> xLevel(xLevels
->getByIndex(nLevel
), uno::UNO_QUERY
);
372 uno::Reference
<container::XNamed
> xLevelName(xLevel
, uno::UNO_QUERY
);
373 uno::Reference
<sheet::XDataPilotMemberResults
> xLevelResult(xLevel
, uno::UNO_QUERY
);
375 if (xLevelName
.is() && xLevelResult
.is())
377 bool bIsDataLayout
= ScUnoHelpFunctions::GetBoolProperty(xDimProp
, SC_UNO_DP_ISDATALAYOUT
);
378 sal_Int32 nDimPos
= ScUnoHelpFunctions::GetLongProperty(xDimProp
, SC_UNO_DP_POSITION
);
379 sal_Int32 nNumberFormat
= ScUnoHelpFunctions::GetLongProperty(xDimProp
, SC_UNO_DP_NUMBERFO
);
380 bool bHasHiddenMember
= ScUnoHelpFunctions::GetBoolProperty(xDimProp
, SC_UNO_DP_HAS_HIDDEN_MEMBER
);
384 case sheet::DataPilotFieldOrientation_COLUMN
:
386 m_aColumnFields
.emplace_back(xLevelName
->getName(), nDim
, nDimPos
, bHasHiddenMember
);
388 const uno::Sequence
<sheet::MemberResult
> aSequence
= xLevelResult
->getResults();
392 for (sheet::MemberResult
const & rMember
: aSequence
)
394 // Skip grandtotals and subtotals
395 if (rMember
.Flags
& sheet::MemberResultFlags::SUBTOTAL
||
396 rMember
.Flags
& sheet::MemberResultFlags::GRANDTOTAL
)
398 if (rMember
.Flags
& sheet::MemberResultFlags::HASMEMBER
||
399 rMember
.Flags
& sheet::MemberResultFlags::CONTINUE
)
401 if (!(rMember
.Flags
& sheet::MemberResultFlags::CONTINUE
))
403 sCaption
= rMember
.Caption
;
404 sName
= rMember
.Name
;
407 if (i
>= m_aLabels
.size())
408 m_aLabels
.resize(i
+ 1);
410 if (o3tl::make_unsigned(nDimPos
) >= m_aLabels
[i
].size())
411 m_aLabels
[i
].resize(nDimPos
+ 1);
412 m_aLabels
[i
][nDimPos
] = ValueAndFormat(sCaption
);
416 // Remember data fields to determine the number format of data
417 aDataFieldNamesVectors
.push_back(sName
);
418 eDataFieldOrientation
= sheet::DataPilotFieldOrientation_COLUMN
;
419 // Remember the caption name
420 aDataFieldCaptionNames
[rMember
.Name
] = rMember
.Caption
;
428 case sheet::DataPilotFieldOrientation_ROW
:
430 m_aRowFields
.emplace_back(xLevelName
->getName(), nDim
, nDimPos
, bHasHiddenMember
);
432 const uno::Sequence
<sheet::MemberResult
> aSequence
= xLevelResult
->getResults();
435 size_t nEachIndex
= 0;
436 std::unique_ptr
<ValueAndFormat
> pItem
;
438 for (sheet::MemberResult
const & rMember
: aSequence
)
440 bool bFound
= aValidRowIndex
.find(nEachIndex
) != aValidRowIndex
.end();
444 bool bHasContinueFlag
= rMember
.Flags
& sheet::MemberResultFlags::CONTINUE
;
446 if (rMember
.Flags
& sheet::MemberResultFlags::HASMEMBER
|| bHasContinueFlag
)
448 if (!bHasContinueFlag
)
450 // Chart2 does not use number format for labels, so use the display string.
451 pItem
.reset(new ValueAndFormat(rMember
.Caption
));
456 assert(pItem
&& "bHasContinueFlag must be false on this or some preceding element");
458 if (i
>= m_aCategoriesRowOrientation
.size())
459 m_aCategoriesRowOrientation
.resize(i
+ 1);
461 if (o3tl::make_unsigned(nDimPos
) >= m_aCategoriesColumnOrientation
.size())
462 m_aCategoriesColumnOrientation
.resize(nDimPos
+ 1);
463 m_aCategoriesColumnOrientation
[nDimPos
].push_back(*pItem
);
465 if (o3tl::make_unsigned(nDimPos
) >= m_aCategoriesRowOrientation
[i
].size())
466 m_aCategoriesRowOrientation
[i
].resize(nDimPos
+ 1);
467 m_aCategoriesRowOrientation
[i
][nDimPos
] = *pItem
;
471 // Remember data fields to determine the number format of data
472 aDataFieldNamesVectors
.push_back(rMember
.Name
);
473 eDataFieldOrientation
= sheet::DataPilotFieldOrientation_ROW
;
475 // Remember the caption name
476 aDataFieldCaptionNames
[rMember
.Name
] = rMember
.Caption
;
479 // Set to empty so the sub categories are set to empty when they continue
480 pItem
.reset(new ValueAndFormat
);
488 case sheet::DataPilotFieldOrientation_PAGE
:
490 m_aPageFields
.emplace_back(xLevelName
->getName(), nDim
, nDimPos
, bHasHiddenMember
);
493 OUString aFieldOutputDescription
;
494 if (bHasHiddenMember
)
496 std::vector
<OUString
> aMembers
= lcl_getVisiblePageMembers(xLevel
);
498 if (aMembers
.size() == 1)
499 aFieldOutputDescription
= aMembers
[0];
501 aFieldOutputDescription
= ScResId(SCSTR_MULTIPLE
);
505 aFieldOutputDescription
= ScResId(SCSTR_ALL
);
507 m_aFieldOutputDescriptionMap
[nDim
] = aFieldOutputDescription
;
511 case sheet::DataPilotFieldOrientation_DATA
:
513 aDataFieldNumberFormatMap
[xLevelName
->getName()] = nNumberFormat
;
514 m_aDataFields
.emplace_back(xLevelName
->getName(), nDim
, nDimPos
, bHasHiddenMember
);
525 // Transform the name of data fields
526 for (chart2::data::PivotTableFieldEntry
& rDataFields
: m_aDataFields
)
528 rDataFields
.Name
= aDataFieldCaptionNames
[rDataFields
.Name
];
531 // Apply number format to the data
532 if (eDataFieldOrientation
== sheet::DataPilotFieldOrientation_ROW
)
534 for (std::vector
<ValueAndFormat
> & rDataRow
: m_aDataRowVector
)
537 for (ValueAndFormat
& rItem
: rDataRow
)
539 const OUString
& sName
= aDataFieldNamesVectors
[i
];
540 sal_Int32 nNumberFormat
= aDataFieldNumberFormatMap
[sName
];
541 rItem
.m_nNumberFormat
= nNumberFormat
;
546 else if (eDataFieldOrientation
== sheet::DataPilotFieldOrientation_COLUMN
)
549 for (std::vector
<ValueAndFormat
> & rDataRow
: m_aDataRowVector
)
551 const OUString
& sName
= aDataFieldNamesVectors
[i
];
552 sal_Int32 nNumberFormat
= aDataFieldNumberFormatMap
[sName
];
553 for (ValueAndFormat
& rItem
: rDataRow
)
555 rItem
.m_nNumberFormat
= nNumberFormat
;
561 // Sort fields so it respects the order of how it is represented in the pivot table
563 auto funcDimensionPositionSortCompare
= [] (chart2::data::PivotTableFieldEntry
const & entry1
,
564 chart2::data::PivotTableFieldEntry
const & entry2
)
566 return entry1
.DimensionPositionIndex
< entry2
.DimensionPositionIndex
;
569 std::sort(m_aColumnFields
.begin(), m_aColumnFields
.end(), funcDimensionPositionSortCompare
);
570 std::sort(m_aRowFields
.begin(), m_aRowFields
.end(), funcDimensionPositionSortCompare
);
571 std::sort(m_aPageFields
.begin(), m_aPageFields
.end(), funcDimensionPositionSortCompare
);
572 std::sort(m_aDataFields
.begin(), m_aDataFields
.end(), funcDimensionPositionSortCompare
);
574 // Mark that we updated the data
575 m_bNeedsUpdate
= false;
578 uno::Reference
<chart2::data::XDataSequence
>
579 PivotTableDataProvider::assignValuesToDataSequence(size_t nIndex
)
581 uno::Reference
<chart2::data::XDataSequence
> xDataSequence
;
582 if (nIndex
>= m_aDataRowVector
.size())
583 return xDataSequence
;
585 OUString sDataID
= lcl_identifierForData(nIndex
);
587 std::vector
<ValueAndFormat
> const & rRowOfData
= m_aDataRowVector
[nIndex
];
588 rtl::Reference
<PivotTableDataSequence
> pSequence(new PivotTableDataSequence(m_pDocument
, sDataID
, std::vector(rRowOfData
)));
589 pSequence
->setRole(u
"values-y"_ustr
);
590 xDataSequence
= pSequence
;
591 return xDataSequence
;
594 uno::Reference
<chart2::data::XDataSequence
>
595 PivotTableDataProvider::assignLabelsToDataSequence(size_t nIndex
)
597 uno::Reference
<chart2::data::XDataSequence
> xDataSequence
;
599 OUString sLabelID
= lcl_identifierForLabel(nIndex
);
601 OUStringBuffer aLabel
;
604 if (m_aLabels
.empty())
606 aLabel
= ScResId(STR_PIVOT_TOTAL
);
608 else if (nIndex
< m_aLabels
.size())
610 for (ValueAndFormat
const & rItem
: m_aLabels
[nIndex
])
614 aLabel
.append(rItem
.m_aString
);
619 aLabel
.append(" - " + rItem
.m_aString
);
624 std::vector
<ValueAndFormat
> aLabelVector
{ ValueAndFormat(aLabel
.makeStringAndClear()) };
626 rtl::Reference
<PivotTableDataSequence
> pSequence(new PivotTableDataSequence(m_pDocument
,
627 std::move(sLabelID
), std::move(aLabelVector
)));
628 pSequence
->setRole(u
"values-y"_ustr
);
629 xDataSequence
= pSequence
;
630 return xDataSequence
;
633 css::uno::Reference
<css::chart2::data::XDataSequence
>
634 PivotTableDataProvider::assignFirstCategoriesToDataSequence()
636 uno::Reference
<chart2::data::XDataSequence
> xDataSequence
;
638 if (m_aCategoriesColumnOrientation
.empty())
639 return xDataSequence
;
641 std::vector
<ValueAndFormat
> const & rCategories
= m_aCategoriesColumnOrientation
.back();
643 rtl::Reference
<PivotTableDataSequence
> pSequence(new PivotTableDataSequence(m_pDocument
,
644 lcl_identifierForCategories(), std::vector(rCategories
)));
645 pSequence
->setRole(u
"categories"_ustr
);
646 xDataSequence
= pSequence
;
648 return xDataSequence
;
651 uno::Reference
<chart2::data::XDataSource
>
652 PivotTableDataProvider::createValuesDataSource()
655 collectPivotTableData();
657 uno::Reference
<chart2::data::XDataSource
> xDataSource
;
658 std::vector
<uno::Reference
<chart2::data::XLabeledDataSequence
>> aLabeledSequences
;
660 // Fill first sequence of categories
662 uno::Reference
<chart2::data::XLabeledDataSequence
> xResult
= newLabeledDataSequence();
663 xResult
->setValues(assignFirstCategoriesToDataSequence());
664 aLabeledSequences
.push_back(xResult
);
667 // Fill values and labels
669 for (size_t i
= 0; i
< m_aDataRowVector
.size(); ++i
)
671 uno::Reference
<chart2::data::XLabeledDataSequence
> xResult
= newLabeledDataSequence();
672 xResult
->setValues(assignValuesToDataSequence(i
));
673 xResult
->setLabel(assignLabelsToDataSequence(i
));
674 aLabeledSequences
.push_back(xResult
);
678 xDataSource
.set(new PivotTableDataSource(std::move(aLabeledSequences
)));
683 uno::Sequence
<beans::PropertyValue
> SAL_CALL
PivotTableDataProvider::detectArguments(
684 const uno::Reference
<chart2::data::XDataSource
> & xDataSource
)
686 if (!m_pDocument
||!xDataSource
.is())
687 return uno::Sequence
<beans::PropertyValue
>();
689 return comphelper::InitPropertySequence({
690 { "CellRangeRepresentation", uno::Any(u
"PivotChart"_ustr
) },
691 { "DataRowSource", uno::Any(chart::ChartDataRowSource_COLUMNS
) },
692 { "FirstCellAsLabel", uno::Any(false) },
693 { "HasCategories", uno::Any(true) }
697 sal_Bool SAL_CALL
PivotTableDataProvider::createDataSequenceByRangeRepresentationPossible(const OUString
& /*aRangeRepresentation*/)
702 uno::Reference
<chart2::data::XDataSequence
> SAL_CALL
703 PivotTableDataProvider::createDataSequenceByRangeRepresentation(const OUString
& /*rRangeRepresentation*/)
705 uno::Reference
<chart2::data::XDataSequence
> xDataSequence
;
706 return xDataSequence
;
709 uno::Reference
<chart2::data::XDataSequence
> SAL_CALL
710 PivotTableDataProvider::createDataSequenceByValueArray(const OUString
& /*aRole*/,
711 const OUString
& /*aRangeRepresentation*/,
712 const OUString
& /*aRoleQualifier*/)
714 return uno::Reference
<chart2::data::XDataSequence
>();
717 uno::Reference
<sheet::XRangeSelection
> SAL_CALL
PivotTableDataProvider::getRangeSelection()
719 uno::Reference
<sheet::XRangeSelection
> xResult
;
721 uno::Reference
<frame::XModel
> xModel(lcl_GetXModel(m_pDocument
));
723 xResult
.set(xModel
->getCurrentController(), uno::UNO_QUERY
);
728 // XPivotTableDataProvider ========================================================
730 uno::Sequence
<chart2::data::PivotTableFieldEntry
> PivotTableDataProvider::getColumnFields()
732 return comphelper::containerToSequence(m_aColumnFields
);
735 uno::Sequence
<chart2::data::PivotTableFieldEntry
> PivotTableDataProvider::getRowFields()
737 return comphelper::containerToSequence(m_aRowFields
);
740 uno::Sequence
<chart2::data::PivotTableFieldEntry
> PivotTableDataProvider::getPageFields()
742 return comphelper::containerToSequence(m_aPageFields
);
745 uno::Sequence
<chart2::data::PivotTableFieldEntry
> PivotTableDataProvider::getDataFields()
747 return comphelper::containerToSequence(m_aDataFields
);
750 OUString
PivotTableDataProvider::getPivotTableName()
752 return m_sPivotTableName
;
755 void PivotTableDataProvider::setPivotTableName(const OUString
& sPivotTableName
)
757 ScDPCollection
* pDPCollection
= m_pDocument
->GetDPCollection();
758 ScDPObject
* pDPObject
= pDPCollection
->GetByName(sPivotTableName
);
760 m_sPivotTableName
= sPivotTableName
;
763 sal_Bool
PivotTableDataProvider::hasPivotTable()
765 if (m_sPivotTableName
.isEmpty())
768 ScDPCollection
* pDPCollection
= m_pDocument
->GetDPCollection();
769 ScDPObject
* pDPObject
= pDPCollection
->GetByName(m_sPivotTableName
);
777 uno::Reference
<chart2::data::XDataSequence
>
778 PivotTableDataProvider::createDataSequenceOfValuesByIndex(sal_Int32 nIndex
)
780 SolarMutexGuard aGuard
;
783 collectPivotTableData();
785 return assignValuesToDataSequence(size_t(nIndex
));
788 uno::Reference
<css::chart2::data::XDataSequence
>
789 PivotTableDataProvider::createDataSequenceOfLabelsByIndex(sal_Int32 nIndex
)
791 SolarMutexGuard aGuard
;
794 collectPivotTableData();
796 return assignLabelsToDataSequence(size_t(nIndex
));
799 uno::Reference
<css::chart2::data::XDataSequence
>
800 PivotTableDataProvider::createDataSequenceOfCategories()
802 SolarMutexGuard aGuard
;
805 collectPivotTableData();
807 return assignFirstCategoriesToDataSequence();
810 OUString
PivotTableDataProvider::getFieldOutputDescription(sal_Int32 nDimensionIndex
)
812 if (nDimensionIndex
< 0)
814 return m_aFieldOutputDescriptionMap
[size_t(nDimensionIndex
)];
817 // XModifyBroadcaster ========================================================
819 void SAL_CALL
PivotTableDataProvider::addModifyListener(const uno::Reference
< util::XModifyListener
>& aListener
)
821 SolarMutexGuard aGuard
;
823 m_aValueListeners
.emplace_back(aListener
);
826 void SAL_CALL
PivotTableDataProvider::removeModifyListener(const uno::Reference
<util::XModifyListener
>& aListener
)
828 SolarMutexGuard aGuard
;
830 sal_uInt16 nCount
= m_aValueListeners
.size();
831 for (sal_uInt16 n
= nCount
; n
--;)
833 uno::Reference
<util::XModifyListener
>& rObject
= m_aValueListeners
[n
];
834 if (rObject
== aListener
)
836 m_aValueListeners
.erase(m_aValueListeners
.begin() + n
);
841 // DataProvider XPropertySet ========================================================
843 uno::Reference
< beans::XPropertySetInfo
> SAL_CALL
844 PivotTableDataProvider::getPropertySetInfo()
846 SolarMutexGuard aGuard
;
847 static uno::Reference
<beans::XPropertySetInfo
> aRef
=
848 new SfxItemPropertySetInfo( m_aPropSet
.getPropertyMap() );
852 void SAL_CALL
PivotTableDataProvider::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& rValue
)
854 if (rPropertyName
!= SC_UNONAME_INCLUDEHIDDENCELLS
)
855 throw beans::UnknownPropertyException(rPropertyName
);
857 if (!(rValue
>>= m_bIncludeHiddenCells
))
858 throw lang::IllegalArgumentException();
861 uno::Any SAL_CALL
PivotTableDataProvider::getPropertyValue(const OUString
& rPropertyName
)
864 if (rPropertyName
== SC_UNONAME_INCLUDEHIDDENCELLS
)
865 aRet
<<= m_bIncludeHiddenCells
;
866 else if (rPropertyName
== SC_UNONAME_USE_INTERNAL_DATA_PROVIDER
)
868 // This is a read-only property.
869 aRet
<<= m_pDocument
->PastingDrawFromOtherDoc();
872 throw beans::UnknownPropertyException(rPropertyName
);
876 void SAL_CALL
PivotTableDataProvider::addPropertyChangeListener(
877 const OUString
& /*rPropertyName*/,
878 const uno::Reference
<beans::XPropertyChangeListener
>& /*xListener*/)
880 OSL_FAIL("Not yet implemented");
883 void SAL_CALL
PivotTableDataProvider::removePropertyChangeListener(
884 const OUString
& /*rPropertyName*/,
885 const uno::Reference
<beans::XPropertyChangeListener
>& /*rListener*/)
887 OSL_FAIL("Not yet implemented");
890 void SAL_CALL
PivotTableDataProvider::addVetoableChangeListener(
891 const OUString
& /*rPropertyName*/,
892 const uno::Reference
<beans::XVetoableChangeListener
>& /*rListener*/)
894 OSL_FAIL("Not yet implemented");
897 void SAL_CALL
PivotTableDataProvider::removeVetoableChangeListener(
898 const OUString
& /*rPropertyName*/,
899 const uno::Reference
<beans::XVetoableChangeListener
>& /*rListener*/ )
901 OSL_FAIL("Not yet implemented");
904 } // end sc namespace
906 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */