Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/sc/source/ui/unoobj/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 32 kB image not shown  

Quelle  PivotTableDataProvider.cxx   Sprache: C

 
/* -*- 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 <limits>
#include <memory>
#include <sal/config.h>

#include <PivotTableDataProvider.hxx>
#include <PivotTableDataSource.hxx>
#include <PivotTableDataSequence.hxx>

#include <miscuno.hxx>
#include <document.hxx>
#include <docsh.hxx>
#include <unonames.hxx>
#include <scresid.hxx>
#include <globstr.hrc>
#include <strings.hrc>
#include <dpobject.hxx>
#include <hints.hxx>

#include <o3tl/safeint.hxx>
#include <vcl/svapp.hxx>
#include <comphelper/propertysequence.hxx>
#include <comphelper/sequence.hxx>
#include <comphelper/processfactory.hxx>

#include <com/sun/star/chart2/data/LabeledDataSequence.hpp>
#include <com/sun/star/chart/ChartDataRowSource.hpp>
#include <com/sun/star/frame/XModel.hpp>

#include <com/sun/star/sheet/XDataPilotResults.hpp>
#include <com/sun/star/sheet/DataResultFlags.hpp>

#include <com/sun/star/sheet/XDimensionsSupplier.hpp>
#include <com/sun/star/sheet/XHierarchiesSupplier.hpp>
#include <com/sun/star/sheet/XLevelsSupplier.hpp>
#include <com/sun/star/sheet/XDataPilotMemberResults.hpp>
#include <com/sun/star/sheet/MemberResultFlags.hpp>
#include <com/sun/star/sheet/XMembersSupplier.hpp>

#include <com/sun/star/chart/ChartDataChangeEvent.hpp>
#include <com/sun/star/container/XNamed.hpp>

#include <unordered_map>

using namespace css;

namespace sc
{
namespace
{
constexpr OUStringLiteral constIdCategories(u"categories");
constexpr OUStringLiteral constIdLabel(u"label");
constexpr OUStringLiteral constIdData(u"data");

std::span<const SfxItemPropertyMapEntry> lcl_GetDataProviderPropertyMap()
{
    static const SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] =
    {
        { SC_UNONAME_INCLUDEHIDDENCELLS, 0, cppu::UnoType<bool>::get(), 0, 0 },
        { SC_UNONAME_USE_INTERNAL_DATA_PROVIDER, 0, cppu::UnoType<bool>::get(), 0, 0 },
    };
    return aDataProviderPropertyMap_Impl;
}

uno::Reference<frame::XModel> lcl_GetXModel(const ScDocument * pDoc)
{
    uno::Reference<frame::XModel> xModel;
    ScDocShell* 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<OUString> lcl_getVisiblePageMembers(const uno::Reference<uno::XInterface> &&nbsp;xLevel)
{
    std::vector<OUString> aResult;
    if (!xLevel.is())
        return aResult;

    uno::Reference<sheet::XMembersSupplier> xMembersSupplier(xLevel, uno::UNO_QUERY);
    if (!xMembersSupplier.is())
        return aResult;

    uno::Reference<sheet::XMembersAccess> xMembersAccess = xMembersSupplier->getMembers();
    if (!xMembersAccess.is())
        return aResult;

    const css::uno::Sequence<OUString> aMembersNames = xMembersAccess->getElementNames();
    for (OUString const & rMemberNames : aMembersNames)
    {
        uno::Reference<beans::XPropertySet> 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, u"PivotTableDataProvider"_ustr, 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 (rHint.GetId() == SfxHintId::ScDataPilotModified)
        {
            auto pDataPilotHint = static_cast<const ScDataPilotModifiedHint*>(&rHint);
            if (pDataPilotHint->GetName() == m_sPivotTableName)
            {
                m_bNeedsUpdate = true;
                for (uno::Reference<util::XModifyListener> const & xListener : m_aValueListeners)
                {
                    css::chart::ChartDataChangeEvent aEvent(getXWeak(),
                                                            css::chart::ChartDataChangeType_ALL,
                                                            0, 0, 0, 0);
                    xListener->modified(aEvent);
                }
            }
        }
    }
}

sal_Bool SAL_CALL PivotTableDataProvider::createDataSourcePossible(const uno::Sequence<beans::PropertyValue>& /*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<chart2::data::XDataSource> SAL_CALL
    PivotTableDataProvider::createDataSource(const uno::Sequence<beans::PropertyValue>&&nbsp;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<chart2::data::XDataSource> xResult;

    if (aRangeRepresentation == lcl_identifierForCategories())
        xResult = createCategoriesDataSource(bOrientCol);
    else
        xResult = createValuesDataSource();

    return xResult;
}

uno::Reference<chart2::data::XLabeledDataSequence>
    PivotTableDataProvider::newLabeledDataSequence()
{
    uno::Reference<chart2::data::XLabeledDataSequence> xResult;
    if (!m_xContext.is())
        return xResult;
    xResult.set(chart2::data::LabeledDataSequence::create(m_xContext), uno::UNO_QUERY_THROW);
    return xResult;
}

uno::Reference<chart2::data::XDataSource>
PivotTableDataProvider::createCategoriesDataSource(bool bOrientationIsColumn)
{
    if (m_bNeedsUpdate)
        collectPivotTableData();

    uno::Reference<chart2::data::XDataSource> xDataSource;
    std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aLabeledSequences;

    std::vector<std::vector<ValueAndFormat>> const & rCategoriesVector = bOrientationIsColumn ? m_aCategoriesColumnOrientation
                                                                                              : m_aCategoriesRowOrientation;

    for (std::vector<ValueAndFormat> const & rCategories : rCategoriesVector)
    {
        uno::Reference<chart2::data::XLabeledDataSequence> xResult = newLabeledDataSequence();
        rtl::Reference<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument,
                                                   lcl_identifierForCategories(), std::vector(rCategories)));
        pSequence->setRole(u"categories"_ustr);
        xResult->setValues(uno::Reference<chart2::data::XDataSequence>(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<sheet::XDataPilotResults> xDPResults(pDPObject->GetSource(), uno::UNO_QUERY);
    if (!xDPResults.is())
        return;
    const uno::Sequence<uno::Sequence<sheet::DataResult>> xDataResultsSequence = xDPResults->getResults();

    std::unordered_set<size_t> aValidRowIndex;

    size_t nRowIndex = 0;
    for (uno::Sequence<sheet::DataResult> const & xDataResults : xDataResultsSequence)
    {
        std::vector<ValueAndFormat> 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<double>::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<sheet::XDimensionsSupplier> xDimensionsSupplier(pDPObject->GetSource());
    uno::Reference<container::XIndexAccess> xDims = new ScNameToIndexAccess(xDimensionsSupplier->getDimensions());

    std::unordered_map<OUString, sal_Int32> aDataFieldNumberFormatMap;
    std::vector<OUString> aDataFieldNamesVectors;

    std::unordered_map<OUString, OUString> aDataFieldCaptionNames;

    sheet::DataPilotFieldOrientation eDataFieldOrientation = sheet::DataPilotFieldOrientation_HIDDEN;

    for (sal_Int32 nDim = 0; nDim < xDims->getCount(); nDim++)
    {
        uno::Reference<uno::XInterface> xDim(xDims->getByIndex(nDim), uno::UNO_QUERY);
        uno::Reference<beans::XPropertySet> xDimProp(xDim, uno::UNO_QUERY);
        uno::Reference<sheet::XHierarchiesSupplier> 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<container::XIndexAccess> xHierarchies = new ScNameToIndexAccess(xDimSupp->getHierarchies());
        sal_Int32 nHierarchy = ScUnoHelpFunctions::GetLongProperty(xDimProp, SC_UNO_DP_USEDHIERARCHY);
        if (nHierarchy >= xHierarchies->getCount())
            nHierarchy = 0;

        uno::Reference<sheet::XLevelsSupplier> xLevelsSupplier(xHierarchies->getByIndex(nHierarchy),
                                                               uno::UNO_QUERY);

        if (!xLevelsSupplier.is())
            continue;

        uno::Reference<container::XIndexAccess> xLevels = new ScNameToIndexAccess(xLevelsSupplier->getLevels());

        for (tools::Long nLevel = 0; nLevel < xLevels->getCount(); nLevel++)
        {
            uno::Reference<uno::XInterface> xLevel(xLevels->getByIndex(nLevel), uno::UNO_QUERY);
            uno::Reference<container::XNamed> xLevelName(xLevel, uno::UNO_QUERY);
            uno::Reference<sheet::XDataPilotMemberResults> 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<sheet::MemberResult> 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<sheet::MemberResult> aSequence = xLevelResult->getResults();

                        size_t i = 0;
                        size_t nEachIndex = 0;
                        std::unique_ptr<ValueAndFormat> 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)
                                {
                                    assert(pItem && "bHasContinueFlag must be false on this or some preceding element");

                                    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<OUString> 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<ValueAndFormat> & rDataRow : m_aDataRowVector)
        {
            size_t i = 0;
            for (ValueAndFormat & rItem : rDataRow)
            {
                const 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<ValueAndFormat> & rDataRow : m_aDataRowVector)
        {
            const 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 &&nbsp;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;
}

rtl::Reference<PivotTableDataSequence>
PivotTableDataProvider::assignValuesToDataSequence(size_t nIndex)
{
    if (nIndex >= m_aDataRowVector.size())
        return nullptr;

    OUString sDataID = lcl_identifierForData(nIndex);

    std::vector<ValueAndFormat> const & rRowOfData = m_aDataRowVector[nIndex];
    rtl::Reference<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument, sDataID, std::vector(rRowOfData)));
    pSequence->setRole(u"values-y"_ustr);
    return pSequence;
}

rtl::Reference<PivotTableDataSequence>
PivotTableDataProvider::assignLabelsToDataSequence(size_t nIndex)
{
    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<ValueAndFormat> aLabelVector { ValueAndFormat(aLabel.makeStringAndClear()) };

    rtl::Reference<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument,
                                               std::move(sLabelID), std::move(aLabelVector)));
    pSequence->setRole(u"values-y"_ustr);
    return pSequence;
}

rtl::Reference<PivotTableDataSequence>
    PivotTableDataProvider::assignFirstCategoriesToDataSequence()
{
    if (m_aCategoriesColumnOrientation.empty())
        return nullptr;

    std::vector<ValueAndFormat> const & rCategories = m_aCategoriesColumnOrientation.back();

    rtl::Reference<PivotTableDataSequence> pSequence(new PivotTableDataSequence(m_pDocument,
                                               lcl_identifierForCategories(), std::vector(rCategories)));
    pSequence->setRole(u"categories"_ustr);
    return pSequence;
}

uno::Reference<chart2::data::XDataSource>
    PivotTableDataProvider::createValuesDataSource()
{
    if (m_bNeedsUpdate)
        collectPivotTableData();

    uno::Reference<chart2::data::XDataSource> xDataSource;
    std::vector<uno::Reference<chart2::data::XLabeledDataSequence>> aLabeledSequences;

    // Fill first sequence of categories
    {
        uno::Reference<chart2::data::XLabeledDataSequence> 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<chart2::data::XLabeledDataSequence> 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<beans::PropertyValue> SAL_CALL PivotTableDataProvider::detectArguments(
            const uno::Reference<chart2::data::XDataSource> & xDataSource)
{
    if (!m_pDocument ||!xDataSource.is())
        return uno::Sequence<beans::PropertyValue>();

    return comphelper::InitPropertySequence({
        { "CellRangeRepresentation", uno::Any(u"PivotChart"_ustr) },
        { "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<chart2::data::XDataSequence> SAL_CALL
    PivotTableDataProvider::createDataSequenceByRangeRepresentation(const OUString&&nbsp;/*rRangeRepresentation*/)
{
    uno::Reference<chart2::data::XDataSequence> xDataSequence;
    return xDataSequence;
}

uno::Reference<chart2::data::XDataSequence> SAL_CALL
    PivotTableDataProvider::createDataSequenceByValueArray(const OUString& /*aRole*/,
                                                           const OUString& /*aRangeRepresentation*/,
                                                           const OUString& /*aRoleQualifier*/)
{
    return uno::Reference<chart2::data::XDataSequence>();
}

uno::Reference<sheet::XRangeSelection> SAL_CALL PivotTableDataProvider::getRangeSelection()
{
    uno::Reference<sheet::XRangeSelection> xResult;

    uno::Reference<frame::XModel> xModel(lcl_GetXModel(m_pDocument));
    if (xModel.is())
        xResult.set(xModel->getCurrentController(), uno::UNO_QUERY);

    return xResult;
}

// XPivotTableDataProvider ========================================================

uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getColumnFields()
{
    return comphelper::containerToSequence(m_aColumnFields);
}

uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getRowFields()
{
    return comphelper::containerToSequence(m_aRowFields);
}

uno::Sequence<chart2::data::PivotTableFieldEntry> PivotTableDataProvider::getPageFields()
{
    return comphelper::containerToSequence(m_aPageFields);
}

uno::Sequence<chart2::data::PivotTableFieldEntry> 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<chart2::data::XDataSequence>
    PivotTableDataProvider::createDataSequenceOfValuesByIndex(sal_Int32 nIndex)
{
    SolarMutexGuard aGuard;

    if (m_bNeedsUpdate)
        collectPivotTableData();

    return assignValuesToDataSequence(size_t(nIndex));
}

uno::Reference<css::chart2::data::XDataSequence>
    PivotTableDataProvider::createDataSequenceOfLabelsByIndex(sal_Int32 nIndex)
{
    SolarMutexGuard aGuard;

    if (m_bNeedsUpdate)
        collectPivotTableData();

    return assignLabelsToDataSequence(size_t(nIndex));
}

uno::Reference<css::chart2::data::XDataSequence>
    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<util::XModifyListener>& aListener )
{
    SolarMutexGuard aGuard;

    sal_uInt16 nCount = m_aValueListeners.size();
    for (sal_uInt16 n = nCount; n--;)
    {
        uno::Reference<util::XModifyListener>& 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<beans::XPropertySetInfo> 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<beans::XPropertyChangeListener>& /*xListener*/)
{
    OSL_FAIL("Not yet implemented");
}

void SAL_CALL PivotTableDataProvider::removePropertyChangeListener(
        const OUString& /*rPropertyName*/,
        const uno::Reference<beans::XPropertyChangeListener>& /*rListener*/)
{
    OSL_FAIL("Not yet implemented");
}

void SAL_CALL PivotTableDataProvider::addVetoableChangeListener(
        const OUString& /*rPropertyName*/,
        const uno::Reference<beans::XVetoableChangeListener>& /*rListener*/)
{
    OSL_FAIL("Not yet implemented");
}

void SAL_CALL PivotTableDataProvider::removeVetoableChangeListener(
        const OUString& /*rPropertyName*/,
        const uno::Reference<beans::XVetoableChangeListener>& /*rListener*/ )
{
    OSL_FAIL("Not yet implemented");
}

// end sc namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=87 G=91

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.