/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace css; namespace sc { namespace { constexpr OUStringLiteral constIdCategories(u"categories"); constexpr OUStringLiteral constIdLabel(u"label"); constexpr OUStringLiteral constIdData(u"data"); const SfxItemPropertyMapEntry* lcl_GetDataProviderPropertyMap() { static const SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] = { { SC_UNONAME_INCLUDEHIDDENCELLS, 0, cppu::UnoType::get(), 0, 0 }, { SC_UNONAME_USE_INTERNAL_DATA_PROVIDER, 0, cppu::UnoType::get(), 0, 0 }, { u"", 0, css::uno::Type(), 0, 0 } }; return aDataProviderPropertyMap_Impl; } uno::Reference lcl_GetXModel(const ScDocument * pDoc) { uno::Reference xModel; SfxObjectShell* pObjSh(pDoc ? pDoc->GetDocumentShell() : nullptr); if (pObjSh) xModel.set(pObjSh->GetModel()); return xModel; } OUString lcl_identifierForData(sal_Int32 index) { return "PT@" + constIdData + " " + OUString::number(index); } OUString lcl_identifierForLabel(sal_Int32 index) { return "PT@" + constIdLabel + " " + OUString::number(index); } OUString lcl_identifierForCategories() { return "PT@" + constIdCategories; } std::vector lcl_getVisiblePageMembers(const uno::Reference & xLevel) { std::vector aResult; if (!xLevel.is()) return aResult; uno::Reference xMembersSupplier(xLevel, uno::UNO_QUERY); if (!xMembersSupplier.is()) return aResult; uno::Reference xMembersAccess = xMembersSupplier->getMembers(); if (!xMembersAccess.is()) return aResult; const css::uno::Sequence aMembersNames = xMembersAccess->getElementNames(); for (OUString const & rMemberNames : aMembersNames) { uno::Reference xProperties(xMembersAccess->getByName(rMemberNames), uno::UNO_QUERY); if (!xProperties.is()) continue; OUString aCaption = ScUnoHelpFunctions::GetStringProperty(xProperties, SC_UNO_DP_LAYOUTNAME, OUString()); if (aCaption.isEmpty()) aCaption = rMemberNames; bool bVisible = ScUnoHelpFunctions::GetBoolProperty(xProperties, SC_UNO_DP_ISVISIBLE); if (bVisible) aResult.push_back(aCaption); } return aResult; } } // end anonymous namespace SC_SIMPLE_SERVICE_INFO(PivotTableDataProvider, "PivotTableDataProvider", SC_SERVICENAME_CHART_PIVOTTABLE_DATAPROVIDER) // DataProvider ============================================================== PivotTableDataProvider::PivotTableDataProvider(ScDocument& rDoc) : m_pDocument(&rDoc) , m_aPropSet(lcl_GetDataProviderPropertyMap()) , m_bIncludeHiddenCells(true) , m_bNeedsUpdate(true) , m_xContext(comphelper::getProcessComponentContext()) { rDoc.AddUnoObject(*this); } PivotTableDataProvider::~PivotTableDataProvider() { SolarMutexGuard g; if (m_pDocument) m_pDocument->RemoveUnoObject( *this); } void PivotTableDataProvider::Notify(SfxBroadcaster& /*rBroadcaster*/, const SfxHint& rHint) { if (rHint.GetId() == SfxHintId::Dying) { m_pDocument = nullptr; } else if (m_pDocument) { if (auto pDataPilotHint = dynamic_cast(&rHint)) { if (pDataPilotHint->GetName() == m_sPivotTableName) { m_bNeedsUpdate = true; for (uno::Reference const & xListener : m_aValueListeners) { css::chart::ChartDataChangeEvent aEvent(static_cast(this), css::chart::ChartDataChangeType_ALL, 0, 0, 0, 0); xListener->modified(aEvent); } } } } } sal_Bool SAL_CALL PivotTableDataProvider::createDataSourcePossible(const uno::Sequence& /*aArguments*/) { SolarMutexGuard aGuard; if (!m_pDocument) return false; if (m_sPivotTableName.isEmpty()) return false; ScDPCollection* pDPCollection = m_pDocument->GetDPCollection(); return bool(pDPCollection->GetByName(m_sPivotTableName)); } uno::Reference SAL_CALL PivotTableDataProvider::createDataSource(const uno::Sequence& aArguments) { SolarMutexGuard aGuard; if (!m_pDocument) throw uno::RuntimeException(); bool bOrientCol = true; OUString aRangeRepresentation; for (beans::PropertyValue const & rProperty : aArguments) { if (rProperty.Name == "DataRowSource") { chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS; if (!(rProperty.Value >>= eSource)) { sal_Int32 nSource(0); if (rProperty.Value >>= nSource) eSource = chart::ChartDataRowSource(nSource); } bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS); } else if (rProperty.Name == "CellRangeRepresentation") rProperty.Value >>= aRangeRepresentation; } uno::Reference xResult; if (aRangeRepresentation == lcl_identifierForCategories()) xResult = createCategoriesDataSource(bOrientCol); else xResult = createValuesDataSource(); return xResult; } uno::Reference PivotTableDataProvider::newLabeledDataSequence() { uno::Reference xResult; if (!m_xContext.is()) return xResult; xResult.set(chart2::data::LabeledDataSequence::create(m_xContext), uno::UNO_QUERY_THROW); return xResult; } uno::Reference PivotTableDataProvider::createCategoriesDataSource(bool bOrientationIsColumn) { if (m_bNeedsUpdate) collectPivotTableData(); uno::Reference xDataSource; std::vector> aLabeledSequences; std::vector> const & rCategoriesVector = bOrientationIsColumn ? m_aCategoriesColumnOrientation : m_aCategoriesRowOrientation; for (std::vector const & rCategories : rCategoriesVector) { uno::Reference xResult = newLabeledDataSequence(); rtl::Reference pSequence(new PivotTableDataSequence(m_pDocument, lcl_identifierForCategories(), std::vector(rCategories))); pSequence->setRole("categories"); xResult->setValues(uno::Reference(pSequence)); aLabeledSequences.push_back(xResult); } xDataSource.set(new PivotTableDataSource(std::move(aLabeledSequences))); return xDataSource; } void PivotTableDataProvider::collectPivotTableData() { ScDPCollection* pDPCollection = m_pDocument->GetDPCollection(); ScDPObject* pDPObject = pDPCollection->GetByName(m_sPivotTableName); if (!pDPObject) return; m_aCategoriesColumnOrientation.clear(); m_aCategoriesRowOrientation.clear(); m_aLabels.clear(); m_aDataRowVector.clear(); m_aColumnFields.clear(); m_aRowFields.clear(); m_aPageFields.clear(); m_aDataFields.clear(); m_aFieldOutputDescriptionMap.clear(); uno::Reference xDPResults(pDPObject->GetSource(), uno::UNO_QUERY); if (!xDPResults.is()) return; const uno::Sequence> xDataResultsSequence = xDPResults->getResults(); std::unordered_set aValidRowIndex; size_t nRowIndex = 0; for (uno::Sequence const & xDataResults : xDataResultsSequence) { std::vector aRow; bool bRowEmpty = true; // First pass - collect a row of valid data and track if the row is empty for (sheet::DataResult const & rDataResult : xDataResults) { if (rDataResult.Flags & css::sheet::DataResultFlags::SUBTOTAL) continue; if (rDataResult.Flags == 0 || rDataResult.Flags & css::sheet::DataResultFlags::HASDATA) { aRow.emplace_back(rDataResult.Flags ? rDataResult.Value : std::numeric_limits::quiet_NaN(), 0); if (rDataResult.Flags != 0) // set as valid only if we have data { bRowEmpty = false; // We need to remember all valid (non-empty) row indices aValidRowIndex.insert(nRowIndex); } } } // Second pass: add to collection only non-empty rows if (!bRowEmpty) { size_t nColumnIndex = 0; for (ValueAndFormat const & aValue : aRow) { if (nColumnIndex >= m_aDataRowVector.size()) m_aDataRowVector.resize(nColumnIndex + 1); m_aDataRowVector[nColumnIndex].push_back(aValue); nColumnIndex++; } } nRowIndex++; } uno::Reference xDimensionsSupplier(pDPObject->GetSource()); uno::Reference xDims = new ScNameToIndexAccess(xDimensionsSupplier->getDimensions()); std::unordered_map aDataFieldNumberFormatMap; std::vector aDataFieldNamesVectors; std::unordered_map aDataFieldCaptionNames; sheet::DataPilotFieldOrientation eDataFieldOrientation = sheet::DataPilotFieldOrientation_HIDDEN; for (sal_Int32 nDim = 0; nDim < xDims->getCount(); nDim++) { uno::Reference xDim(xDims->getByIndex(nDim), uno::UNO_QUERY); uno::Reference xDimProp(xDim, uno::UNO_QUERY); uno::Reference xDimSupp(xDim, uno::UNO_QUERY); if (!xDimProp.is() || !xDimSupp.is()) continue; sheet::DataPilotFieldOrientation eDimOrient = ScUnoHelpFunctions::GetEnumProperty(xDimProp, SC_UNO_DP_ORIENTATION, sheet::DataPilotFieldOrientation_HIDDEN); if (eDimOrient == sheet::DataPilotFieldOrientation_HIDDEN) continue; uno::Reference xHierarchies = new ScNameToIndexAccess(xDimSupp->getHierarchies()); sal_Int32 nHierarchy = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_USEDHIERARCHY); if (nHierarchy >= xHierarchies->getCount()) nHierarchy = 0; uno::Reference xLevelsSupplier(xHierarchies->getByIndex(nHierarchy), uno::UNO_QUERY); if (!xLevelsSupplier.is()) continue; uno::Reference xLevels = new ScNameToIndexAccess(xLevelsSupplier->getLevels()); for (tools::Long nLevel = 0; nLevel < xLevels->getCount(); nLevel++) { uno::Reference xLevel(xLevels->getByIndex(nLevel), uno::UNO_QUERY); uno::Reference xLevelName(xLevel, uno::UNO_QUERY); uno::Reference xLevelResult(xLevel, uno::UNO_QUERY ); if (xLevelName.is() && xLevelResult.is()) { bool bIsDataLayout = ScUnoHelpFunctions::GetBoolProperty(xDimProp, SC_UNO_DP_ISDATALAYOUT); sal_Int32 nDimPos = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_POSITION); sal_Int32 nNumberFormat = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_NUMBERFO); bool bHasHiddenMember = ScUnoHelpFunctions::GetBoolProperty(xDimProp, SC_UNO_DP_HAS_HIDDEN_MEMBER); switch (eDimOrient) { case sheet::DataPilotFieldOrientation_COLUMN: { m_aColumnFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember); const uno::Sequence aSequence = xLevelResult->getResults(); size_t i = 0; OUString sCaption; OUString sName; for (sheet::MemberResult const & rMember : aSequence) { // Skip grandtotals and subtotals if (rMember.Flags & sheet::MemberResultFlags::SUBTOTAL || rMember.Flags & sheet::MemberResultFlags::GRANDTOTAL) continue; if (rMember.Flags & sheet::MemberResultFlags::HASMEMBER || rMember.Flags & sheet::MemberResultFlags::CONTINUE) { if (!(rMember.Flags & sheet::MemberResultFlags::CONTINUE)) { sCaption = rMember.Caption; sName = rMember.Name; } if (i >= m_aLabels.size()) m_aLabels.resize(i + 1); if (o3tl::make_unsigned(nDimPos) >= m_aLabels[i].size()) m_aLabels[i].resize(nDimPos + 1); m_aLabels[i][nDimPos] = ValueAndFormat(sCaption); if (bIsDataLayout) { // Remember data fields to determine the number format of data aDataFieldNamesVectors.push_back(sName); eDataFieldOrientation = sheet::DataPilotFieldOrientation_COLUMN; // Remember the caption name aDataFieldCaptionNames[rMember.Name] = rMember.Caption; } i++; } } } break; case sheet::DataPilotFieldOrientation_ROW: { m_aRowFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember); const uno::Sequence aSequence = xLevelResult->getResults(); size_t i = 0; size_t nEachIndex = 0; std::unique_ptr pItem; for (sheet::MemberResult const & rMember : aSequence) { bool bFound = aValidRowIndex.find(nEachIndex) != aValidRowIndex.end(); nEachIndex++; bool bHasContinueFlag = rMember.Flags & sheet::MemberResultFlags::CONTINUE; if (rMember.Flags & sheet::MemberResultFlags::HASMEMBER || bHasContinueFlag) { if (!bHasContinueFlag) { // Chart2 does not use number format for labels, so use the display string. pItem.reset(new ValueAndFormat(rMember.Caption)); } if (bFound) { if (i >= m_aCategoriesRowOrientation.size()) m_aCategoriesRowOrientation.resize(i + 1); if (o3tl::make_unsigned(nDimPos) >= m_aCategoriesColumnOrientation.size()) m_aCategoriesColumnOrientation.resize(nDimPos + 1); m_aCategoriesColumnOrientation[nDimPos].push_back(*pItem); if (o3tl::make_unsigned(nDimPos) >= m_aCategoriesRowOrientation[i].size()) m_aCategoriesRowOrientation[i].resize(nDimPos + 1); m_aCategoriesRowOrientation[i][nDimPos] = *pItem; if (bIsDataLayout) { // Remember data fields to determine the number format of data aDataFieldNamesVectors.push_back(rMember.Name); eDataFieldOrientation = sheet::DataPilotFieldOrientation_ROW; // Remember the caption name aDataFieldCaptionNames[rMember.Name] = rMember.Caption; } // Set to empty so the sub categories are set to empty when they continue pItem.reset(new ValueAndFormat); i++; } } } } break; case sheet::DataPilotFieldOrientation_PAGE: { m_aPageFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember); // Resolve filtering OUString aFieldOutputDescription; if (bHasHiddenMember) { std::vector aMembers = lcl_getVisiblePageMembers(xLevel); if (aMembers.size() == 1) aFieldOutputDescription = aMembers[0]; else aFieldOutputDescription = ScResId(SCSTR_MULTIPLE); } else { aFieldOutputDescription = ScResId(SCSTR_ALL); } m_aFieldOutputDescriptionMap[nDim] = aFieldOutputDescription; } break; case sheet::DataPilotFieldOrientation_DATA: { aDataFieldNumberFormatMap[xLevelName->getName()] = nNumberFormat; m_aDataFields.emplace_back(xLevelName->getName(), nDim, nDimPos, bHasHiddenMember); } break; default: break; } } } } // Transform the name of data fields for (chart2::data::PivotTableFieldEntry& rDataFields : m_aDataFields) { rDataFields.Name = aDataFieldCaptionNames[rDataFields.Name]; } // Apply number format to the data if (eDataFieldOrientation == sheet::DataPilotFieldOrientation_ROW) { for (std::vector & rDataRow : m_aDataRowVector) { size_t i = 0; for (ValueAndFormat & rItem : rDataRow) { OUString sName = aDataFieldNamesVectors[i]; sal_Int32 nNumberFormat = aDataFieldNumberFormatMap[sName]; rItem.m_nNumberFormat = nNumberFormat; i++; } } } else if (eDataFieldOrientation == sheet::DataPilotFieldOrientation_COLUMN) { size_t i = 0; for (std::vector & rDataRow : m_aDataRowVector) { OUString sName = aDataFieldNamesVectors[i]; sal_Int32 nNumberFormat = aDataFieldNumberFormatMap[sName]; for (ValueAndFormat & rItem : rDataRow) { rItem.m_nNumberFormat = nNumberFormat; } i++; } } // Sort fields so it respects the order of how it is represented in the pivot table auto funcDimensionPositionSortCompare = [] (chart2::data::PivotTableFieldEntry const & entry1, chart2::data::PivotTableFieldEntry const & entry2) { return entry1.DimensionPositionIndex < entry2.DimensionPositionIndex; }; std::sort(m_aColumnFields.begin(), m_aColumnFields.end(), funcDimensionPositionSortCompare); std::sort(m_aRowFields.begin(), m_aRowFields.end(), funcDimensionPositionSortCompare); std::sort(m_aPageFields.begin(), m_aPageFields.end(), funcDimensionPositionSortCompare); std::sort(m_aDataFields.begin(), m_aDataFields.end(), funcDimensionPositionSortCompare); // Mark that we updated the data m_bNeedsUpdate = false; } uno::Reference PivotTableDataProvider::assignValuesToDataSequence(size_t nIndex) { uno::Reference xDataSequence; if (nIndex >= m_aDataRowVector.size()) return xDataSequence; OUString sDataID = lcl_identifierForData(nIndex); std::vector const & rRowOfData = m_aDataRowVector[nIndex]; rtl::Reference pSequence(new PivotTableDataSequence(m_pDocument, sDataID, std::vector(rRowOfData))); pSequence->setRole("values-y"); xDataSequence = pSequence; return xDataSequence; } uno::Reference PivotTableDataProvider::assignLabelsToDataSequence(size_t nIndex) { uno::Reference xDataSequence; OUString sLabelID = lcl_identifierForLabel(nIndex); OUStringBuffer aLabel; bool bFirst = true; if (m_aLabels.empty()) { aLabel = ScResId(STR_PIVOT_TOTAL); } else if (nIndex < m_aLabels.size()) { for (ValueAndFormat const & rItem : m_aLabels[nIndex]) { if (bFirst) { aLabel.append(rItem.m_aString); bFirst = false; } else { aLabel.append(" - " + rItem.m_aString); } } } std::vector aLabelVector { ValueAndFormat(aLabel.makeStringAndClear()) }; rtl::Reference pSequence(new PivotTableDataSequence(m_pDocument, sLabelID, std::move(aLabelVector))); pSequence->setRole("values-y"); xDataSequence = pSequence; return xDataSequence; } css::uno::Reference PivotTableDataProvider::assignFirstCategoriesToDataSequence() { uno::Reference xDataSequence; if (m_aCategoriesColumnOrientation.empty()) return xDataSequence; std::vector const & rCategories = m_aCategoriesColumnOrientation.back(); rtl::Reference pSequence(new PivotTableDataSequence(m_pDocument, lcl_identifierForCategories(), std::vector(rCategories))); pSequence->setRole("categories"); xDataSequence = pSequence; return xDataSequence; } uno::Reference PivotTableDataProvider::createValuesDataSource() { if (m_bNeedsUpdate) collectPivotTableData(); uno::Reference xDataSource; std::vector> aLabeledSequences; // Fill first sequence of categories { uno::Reference xResult = newLabeledDataSequence(); xResult->setValues(assignFirstCategoriesToDataSequence()); aLabeledSequences.push_back(xResult); } // Fill values and labels { for (size_t i = 0; i < m_aDataRowVector.size(); ++i) { uno::Reference xResult = newLabeledDataSequence(); xResult->setValues(assignValuesToDataSequence(i)); xResult->setLabel(assignLabelsToDataSequence(i)); aLabeledSequences.push_back(xResult); } } xDataSource.set(new PivotTableDataSource(std::move(aLabeledSequences))); return xDataSource; } uno::Sequence SAL_CALL PivotTableDataProvider::detectArguments( const uno::Reference & xDataSource) { if (!m_pDocument ||!xDataSource.is()) return uno::Sequence(); return comphelper::InitPropertySequence({ { "CellRangeRepresentation", uno::Any(OUString("PivotChart")) }, { "DataRowSource", uno::Any(chart::ChartDataRowSource_COLUMNS) }, { "FirstCellAsLabel", uno::Any(false) }, { "HasCategories", uno::Any(true) } }); } sal_Bool SAL_CALL PivotTableDataProvider::createDataSequenceByRangeRepresentationPossible(const OUString& /*aRangeRepresentation*/) { return false; } uno::Reference SAL_CALL PivotTableDataProvider::createDataSequenceByRangeRepresentation(const OUString& /*rRangeRepresentation*/) { uno::Reference xDataSequence; return xDataSequence; } uno::Reference SAL_CALL PivotTableDataProvider::createDataSequenceByValueArray(const OUString& /*aRole*/, const OUString& /*aRangeRepresentation*/, const OUString& /*aRoleQualifier*/) { return uno::Reference(); } uno::Reference SAL_CALL PivotTableDataProvider::getRangeSelection() { uno::Reference xResult; uno::Reference xModel(lcl_GetXModel(m_pDocument)); if (xModel.is()) xResult.set(xModel->getCurrentController(), uno::UNO_QUERY); return xResult; } // XPivotTableDataProvider ======================================================== uno::Sequence PivotTableDataProvider::getColumnFields() { return comphelper::containerToSequence(m_aColumnFields); } uno::Sequence PivotTableDataProvider::getRowFields() { return comphelper::containerToSequence(m_aRowFields); } uno::Sequence PivotTableDataProvider::getPageFields() { return comphelper::containerToSequence(m_aPageFields); } uno::Sequence PivotTableDataProvider::getDataFields() { return comphelper::containerToSequence(m_aDataFields); } OUString PivotTableDataProvider::getPivotTableName() { return m_sPivotTableName; } void PivotTableDataProvider::setPivotTableName(const OUString& sPivotTableName) { ScDPCollection* pDPCollection = m_pDocument->GetDPCollection(); ScDPObject* pDPObject = pDPCollection->GetByName(sPivotTableName); if (pDPObject) m_sPivotTableName = sPivotTableName; } sal_Bool PivotTableDataProvider::hasPivotTable() { if (m_sPivotTableName.isEmpty()) return false; ScDPCollection* pDPCollection = m_pDocument->GetDPCollection(); ScDPObject* pDPObject = pDPCollection->GetByName(m_sPivotTableName); if (pDPObject) return true; return false; } uno::Reference PivotTableDataProvider::createDataSequenceOfValuesByIndex(sal_Int32 nIndex) { SolarMutexGuard aGuard; if (m_bNeedsUpdate) collectPivotTableData(); return assignValuesToDataSequence(size_t(nIndex)); } uno::Reference PivotTableDataProvider::createDataSequenceOfLabelsByIndex(sal_Int32 nIndex) { SolarMutexGuard aGuard; if (m_bNeedsUpdate) collectPivotTableData(); return assignLabelsToDataSequence(size_t(nIndex)); } uno::Reference PivotTableDataProvider::createDataSequenceOfCategories() { SolarMutexGuard aGuard; if (m_bNeedsUpdate) collectPivotTableData(); return assignFirstCategoriesToDataSequence(); } OUString PivotTableDataProvider::getFieldOutputDescription(sal_Int32 nDimensionIndex) { if (nDimensionIndex < 0) return OUString(); return m_aFieldOutputDescriptionMap[size_t(nDimensionIndex)]; } // XModifyBroadcaster ======================================================== void SAL_CALL PivotTableDataProvider::addModifyListener(const uno::Reference< util::XModifyListener>& aListener) { SolarMutexGuard aGuard; m_aValueListeners.emplace_back(aListener); } void SAL_CALL PivotTableDataProvider::removeModifyListener(const uno::Reference& aListener ) { SolarMutexGuard aGuard; sal_uInt16 nCount = m_aValueListeners.size(); for (sal_uInt16 n = nCount; n--;) { uno::Reference& rObject = m_aValueListeners[n]; if (rObject == aListener) { m_aValueListeners.erase(m_aValueListeners.begin() + n); } } } // DataProvider XPropertySet ======================================================== uno::Reference< beans::XPropertySetInfo> SAL_CALL PivotTableDataProvider::getPropertySetInfo() { SolarMutexGuard aGuard; static uno::Reference aRef = new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); return aRef; } void SAL_CALL PivotTableDataProvider::setPropertyValue(const OUString& rPropertyName, const uno::Any& rValue) { if (rPropertyName != SC_UNONAME_INCLUDEHIDDENCELLS) throw beans::UnknownPropertyException(rPropertyName); if (!(rValue >>= m_bIncludeHiddenCells)) throw lang::IllegalArgumentException(); } uno::Any SAL_CALL PivotTableDataProvider::getPropertyValue(const OUString& rPropertyName) { uno::Any aRet; if (rPropertyName == SC_UNONAME_INCLUDEHIDDENCELLS) aRet <<= m_bIncludeHiddenCells; else if (rPropertyName == SC_UNONAME_USE_INTERNAL_DATA_PROVIDER) { // This is a read-only property. aRet <<= m_pDocument->PastingDrawFromOtherDoc(); } else throw beans::UnknownPropertyException(rPropertyName); return aRet; } void SAL_CALL PivotTableDataProvider::addPropertyChangeListener( const OUString& /*rPropertyName*/, const uno::Reference& /*xListener*/) { OSL_FAIL("Not yet implemented"); } void SAL_CALL PivotTableDataProvider::removePropertyChangeListener( const OUString& /*rPropertyName*/, const uno::Reference& /*rListener*/) { OSL_FAIL("Not yet implemented"); } void SAL_CALL PivotTableDataProvider::addVetoableChangeListener( const OUString& /*rPropertyName*/, const uno::Reference& /*rListener*/) { OSL_FAIL("Not yet implemented"); } void SAL_CALL PivotTableDataProvider::removeVetoableChangeListener( const OUString& /*rPropertyName*/, const uno::Reference& /*rListener*/ ) { OSL_FAIL("Not yet implemented"); } } // end sc namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */