tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / unoobj / PivotTableDataProvider.cxx
blobcbd7ebbecda597bb05864e2c3f3ccffa4f3592ed
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <limits>
11 #include <memory>
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>
20 #include <docsh.hxx>
21 #include <unonames.hxx>
22 #include <scresid.hxx>
23 #include <globstr.hrc>
24 #include <strings.hrc>
25 #include <dpobject.hxx>
26 #include <hints.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>
53 using namespace css;
55 namespace sc
57 namespace
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);
77 if (pObjSh)
78 xModel.set(pObjSh->GetModel());
79 return xModel;
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;
100 if (!xLevel.is())
101 return aResult;
103 uno::Reference<sheet::XMembersSupplier> xMembersSupplier(xLevel, uno::UNO_QUERY);
104 if (!xMembersSupplier.is())
105 return aResult;
107 uno::Reference<sheet::XMembersAccess> xMembersAccess = xMembersSupplier->getMembers();
108 if (!xMembersAccess.is())
109 return aResult;
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())
116 continue;
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);
124 if (bVisible)
125 aResult.push_back(aCaption);
128 return aResult;
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)
138 : m_pDocument(&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()
149 SolarMutexGuard g;
151 if (m_pDocument)
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,
173 0, 0, 0, 0);
174 xListener->modified(aEvent);
181 sal_Bool SAL_CALL PivotTableDataProvider::createDataSourcePossible(const uno::Sequence<beans::PropertyValue>& /*aArguments*/)
183 SolarMutexGuard aGuard;
184 if (!m_pDocument)
185 return false;
187 if (m_sPivotTableName.isEmpty())
188 return false;
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;
199 if (!m_pDocument)
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);
226 else
227 xResult = createValuesDataSource();
229 return xResult;
232 uno::Reference<chart2::data::XLabeledDataSequence>
233 PivotTableDataProvider::newLabeledDataSequence()
235 uno::Reference<chart2::data::XLabeledDataSequence> xResult;
236 if (!m_xContext.is())
237 return xResult;
238 xResult.set(chart2::data::LabeledDataSequence::create(m_xContext), uno::UNO_QUERY_THROW);
239 return xResult;
242 uno::Reference<chart2::data::XDataSource>
243 PivotTableDataProvider::createCategoriesDataSource(bool bOrientationIsColumn)
245 if (m_bNeedsUpdate)
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)));
266 return xDataSource;
269 void PivotTableDataProvider::collectPivotTableData()
271 ScDPCollection* pDPCollection = m_pDocument->GetDPCollection();
272 ScDPObject* pDPObject = pDPCollection->GetByName(m_sPivotTableName);
273 if (!pDPObject)
274 return;
276 m_aCategoriesColumnOrientation.clear();
277 m_aCategoriesRowOrientation.clear();
278 m_aLabels.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())
288 return;
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)
302 continue;
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
309 bRowEmpty = false;
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
316 if (!bRowEmpty)
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);
324 nColumnIndex++;
327 nRowIndex++;
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())
347 continue;
349 sheet::DataPilotFieldOrientation eDimOrient =
350 ScUnoHelpFunctions::GetEnumProperty(xDimProp, SC_UNO_DP_ORIENTATION,
351 sheet::DataPilotFieldOrientation_HIDDEN);
353 if (eDimOrient == sheet::DataPilotFieldOrientation_HIDDEN)
354 continue;
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())
359 nHierarchy = 0;
361 uno::Reference<sheet::XLevelsSupplier> xLevelsSupplier(xHierarchies->getByIndex(nHierarchy),
362 uno::UNO_QUERY);
364 if (!xLevelsSupplier.is())
365 continue;
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);
382 switch (eDimOrient)
384 case sheet::DataPilotFieldOrientation_COLUMN:
386 m_aColumnFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember);
388 const uno::Sequence<sheet::MemberResult> aSequence = xLevelResult->getResults();
389 size_t i = 0;
390 OUString sCaption;
391 OUString sName;
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)
397 continue;
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);
414 if (bIsDataLayout)
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;
422 i++;
426 break;
428 case sheet::DataPilotFieldOrientation_ROW:
430 m_aRowFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember);
432 const uno::Sequence<sheet::MemberResult> aSequence = xLevelResult->getResults();
434 size_t i = 0;
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();
442 nEachIndex++;
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));
454 if (bFound)
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;
469 if (bIsDataLayout)
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);
481 i++;
486 break;
488 case sheet::DataPilotFieldOrientation_PAGE:
490 m_aPageFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember);
492 // Resolve filtering
493 OUString aFieldOutputDescription;
494 if (bHasHiddenMember)
496 std::vector<OUString> aMembers = lcl_getVisiblePageMembers(xLevel);
498 if (aMembers.size() == 1)
499 aFieldOutputDescription = aMembers[0];
500 else
501 aFieldOutputDescription = ScResId(SCSTR_MULTIPLE);
503 else
505 aFieldOutputDescription = ScResId(SCSTR_ALL);
507 m_aFieldOutputDescriptionMap[nDim] = aFieldOutputDescription;
509 break;
511 case sheet::DataPilotFieldOrientation_DATA:
513 aDataFieldNumberFormatMap[xLevelName->getName()] = nNumberFormat;
514 m_aDataFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember);
516 break;
518 default:
519 break;
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)
536 size_t i = 0;
537 for (ValueAndFormat & rItem : rDataRow)
539 const OUString& sName = aDataFieldNamesVectors[i];
540 sal_Int32 nNumberFormat = aDataFieldNumberFormatMap[sName];
541 rItem.m_nNumberFormat = nNumberFormat;
542 i++;
546 else if (eDataFieldOrientation == sheet::DataPilotFieldOrientation_COLUMN)
548 size_t i = 0;
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;
557 i++;
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;
602 bool bFirst = true;
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])
612 if (bFirst)
614 aLabel.append(rItem.m_aString);
615 bFirst = false;
617 else
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()
654 if (m_bNeedsUpdate)
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)));
679 return xDataSource;
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*/)
699 return false;
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));
722 if (xModel.is())
723 xResult.set(xModel->getCurrentController(), uno::UNO_QUERY);
725 return xResult;
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);
759 if (pDPObject)
760 m_sPivotTableName = sPivotTableName;
763 sal_Bool PivotTableDataProvider::hasPivotTable()
765 if (m_sPivotTableName.isEmpty())
766 return false;
768 ScDPCollection* pDPCollection = m_pDocument->GetDPCollection();
769 ScDPObject* pDPObject = pDPCollection->GetByName(m_sPivotTableName);
771 if (pDPObject)
772 return true;
774 return false;
777 uno::Reference<chart2::data::XDataSequence>
778 PivotTableDataProvider::createDataSequenceOfValuesByIndex(sal_Int32 nIndex)
780 SolarMutexGuard aGuard;
782 if (m_bNeedsUpdate)
783 collectPivotTableData();
785 return assignValuesToDataSequence(size_t(nIndex));
788 uno::Reference<css::chart2::data::XDataSequence>
789 PivotTableDataProvider::createDataSequenceOfLabelsByIndex(sal_Int32 nIndex)
791 SolarMutexGuard aGuard;
793 if (m_bNeedsUpdate)
794 collectPivotTableData();
796 return assignLabelsToDataSequence(size_t(nIndex));
799 uno::Reference<css::chart2::data::XDataSequence>
800 PivotTableDataProvider::createDataSequenceOfCategories()
802 SolarMutexGuard aGuard;
804 if (m_bNeedsUpdate)
805 collectPivotTableData();
807 return assignFirstCategoriesToDataSequence();
810 OUString PivotTableDataProvider::getFieldOutputDescription(sal_Int32 nDimensionIndex)
812 if (nDimensionIndex < 0)
813 return OUString();
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() );
849 return aRef;
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)
863 uno::Any aRet;
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();
871 else
872 throw beans::UnknownPropertyException(rPropertyName);
873 return aRet;
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: */