[Libreoffice-commits] core.git: 13 commits - offapi/com sc/inc sc/Library_sc.mk sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Thu Apr 18 21:28:59 PDT 2013


 offapi/com/sun/star/sheet/XDataPilotResults.idl |    3 
 sc/Library_sc.mk                                |    1 
 sc/inc/dpitemdata.hxx                           |    5 
 sc/inc/dpobject.hxx                             |    6 
 sc/inc/dpoutput.hxx                             |    6 
 sc/inc/dpresfilter.hxx                          |  135 +++++++
 sc/inc/dpsave.hxx                               |   14 
 sc/inc/dptabres.hxx                             |   43 +-
 sc/inc/dptabsrc.hxx                             |    7 
 sc/source/core/data/dpitemdata.cxx              |   31 +
 sc/source/core/data/dpobject.cxx                |   86 ++++
 sc/source/core/data/dpoutput.cxx                |  435 ------------------------
 sc/source/core/data/dpresfilter.cxx             |  195 ++++++++++
 sc/source/core/data/dpsave.cxx                  |   46 ++
 sc/source/core/data/dptabres.cxx                |  223 ++++++++----
 sc/source/core/data/dptabsrc.cxx                |   31 +
 sc/source/core/tool/interpr2.cxx                |  144 ++++---
 17 files changed, 795 insertions(+), 616 deletions(-)

New commits:
commit a210575baa5bc72dc0392eeb20b2da58b6cf14ae
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 23:10:49 2013 -0400

    Handle the old syntax for GETPIVOTDATA.
    
    The old syntax is Calc only (not Excel), and is specified in ODF 1.2.
    
    Change-Id: I9551d408ae136d3567375e905b1273103a8f616a

diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 91d791f..7a2df40 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -3097,42 +3097,64 @@ void ScInterpreter::ScGetPivotData()
             bOldSyntax = true;
     }
 
+    std::vector<sheet::DataPilotFieldFilter> aFilters;
+    OUString aDataFieldName;
+    ScRange aBlock;
+
     if (bOldSyntax)
     {
-        // TODO: I'll handle this later.
-        PushError(errNoRef);
-        return;
-    }
+        aDataFieldName = GetString();
 
-    // Standard syntax: separate name/value pairs
+        switch (GetStackType())
+        {
+            case svDoubleRef :
+                PopDoubleRef(aBlock);
+            break;
+            case svSingleRef :
+            {
+                ScAddress aAddr;
+                PopSingleRef(aAddr);
+                aBlock = aAddr;
+            }
+            break;
+            default:
+                PushError(errNoRef);
+                return;
+        }
+    }
+    else
+    {
+        // Standard syntax: separate name/value pairs
 
-    sal_uInt16 nFilterCount = nParamCount / 2 - 1;
-    std::vector<sheet::DataPilotFieldFilter> aFilters(nFilterCount);
+        sal_uInt16 nFilterCount = nParamCount / 2 - 1;
+        aFilters.resize(nFilterCount);
 
-    sal_uInt16 i = nFilterCount;
-    while (i-- > 0)
-    {
-        //! should allow numeric constraint values
-        aFilters[i].MatchValue = GetString();
-        aFilters[i].FieldName = GetString();
-    }
+        sal_uInt16 i = nFilterCount;
+        while (i-- > 0)
+        {
+            //! should allow numeric constraint values
+            aFilters[i].MatchValue = GetString();
+            aFilters[i].FieldName = GetString();
+        }
 
-    ScRange aBlock;
-    switch (GetStackType())
-    {
-        case svDoubleRef :
-            PopDoubleRef(aBlock);
-        break;
-        case svSingleRef :
+        switch (GetStackType())
         {
-            ScAddress aAddr;
-            PopSingleRef(aAddr);
-            aBlock = aAddr;
+            case svDoubleRef :
+                PopDoubleRef(aBlock);
+            break;
+            case svSingleRef :
+            {
+                ScAddress aAddr;
+                PopSingleRef(aAddr);
+                aBlock = aAddr;
+            }
+            break;
+            default:
+                PushError(errNoRef);
+                return;
         }
-        break;
-        default:
-            PushError(errNoRef);
-            return;
+
+        aDataFieldName = GetString(); // First parameter is data field name.
     }
 
     // NOTE : MS Excel docs claim to use the 'most recent' which is not
@@ -3145,8 +3167,6 @@ void ScInterpreter::ScGetPivotData()
         return;
     }
 
-    OUString aDataFieldName = GetString(); // First parameter is data field name.
-
     double fVal = pDPObj->GetPivotData(aDataFieldName, aFilters);
     if (rtl::math::isNan(fVal))
     {
commit 2bc52ff76deccee1cab1808108b5e4b25c1cc644
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 22:56:17 2013 -0400

    Remove debug statements..
    
    Change-Id: I10e0ef90ea7bfd92b46a54dc3d3feff90e50f724

diff --git a/sc/inc/dpmacros.hxx b/sc/inc/dpmacros.hxx
index ce91b06..79aafaf 100644
--- a/sc/inc/dpmacros.hxx
+++ b/sc/inc/dpmacros.hxx
@@ -29,7 +29,7 @@
 #ifndef __SC_DPMACROS_HXX__
 #define __SC_DPMACROS_HXX__
 
-#define DEBUG_PIVOT_TABLE 1
+#define DEBUG_PIVOT_TABLE 0
 
 #if DEBUG_PIVOT_TABLE
 #include <iostream>
diff --git a/sc/inc/dpresfilter.hxx b/sc/inc/dpresfilter.hxx
index 9d4617d..a151bd3 100644
--- a/sc/inc/dpresfilter.hxx
+++ b/sc/inc/dpresfilter.hxx
@@ -12,14 +12,10 @@
 
 #include "dpitemdata.hxx"
 
+#include <map>
 #include <vector>
 #include <boost/noncopyable.hpp>
 
-#if DEBUG_PIVOT_TABLE
-#include <map>
-#endif
-
-#include <boost/unordered_map.hpp>
 
 namespace com { namespace sun { namespace star { namespace sheet {
     struct DataPilotFieldFilter;
@@ -59,14 +55,8 @@ private:
 
     struct MemberNode;
     struct DimensionNode;
-#if DEBUG_PIVOT_TABLE
-    // To keep the entries sorted in the tree dump.
     typedef std::map<ScDPItemData, MemberNode*> MembersType;
     typedef std::map<OUString, DimensionNode*> DimensionsType;
-#else
-    typedef boost::unordered_map<ScDPItemData, MemberNode*, ScDPItemData::Hash> MembersType;
-    typedef boost::unordered_map<OUString, DimensionNode*, OUStringHash> DimensionsType;
-#endif
 
     struct DimensionNode : boost::noncopyable
     {
diff --git a/sc/source/core/data/dpresfilter.cxx b/sc/source/core/data/dpresfilter.cxx
index fbb74c1..9a23233 100644
--- a/sc/source/core/data/dpresfilter.cxx
+++ b/sc/source/core/data/dpresfilter.cxx
@@ -85,13 +85,12 @@ ScDPResultFilterSet::~ScDPResultFilterSet()
 }
 
 void ScDPResultFilterSet::add(
-    const std::vector<ScDPResultFilter>& rFilters, long nCol, long nRow, double fVal)
+    const std::vector<ScDPResultFilter>& rFilters, long /*nCol*/, long /*nRow*/, double fVal)
 {
     // TODO: I'll work on the col / row to value node mapping later.
 
     MemberNode* pMemNode = mpRoot;
 
-    fprintf(stdout, "(row=%ld; col=%ld; value=%g) : ", nRow, nCol, fVal);
     std::vector<ScDPResultFilter>::const_iterator itFilter = rFilters.begin(), itFilterEnd = rFilters.end();
     for (; itFilter != itFilterEnd; ++itFilter)
     {
@@ -102,12 +101,6 @@ void ScDPResultFilterSet::add(
         if (maPrimaryDimName.isEmpty())
             maPrimaryDimName = filter.maDimName;
 
-        printf("%s: ", rtl::OUStringToOString(filter.maDimName, RTL_TEXTENCODING_UTF8).getStr());
-        if (filter.maValue.IsValue())
-            printf("%g ", filter.maValue.GetValue());
-        else
-            printf("'%s' ", rtl::OUStringToOString(filter.maValue.GetString(), RTL_TEXTENCODING_UTF8).getStr());
-
         // See if this dimension exists.
         DimensionsType& rDims = pMemNode->maChildDimensions;
         DimensionsType::iterator itDim = rDims.find(filter.maDimName);
@@ -146,7 +139,6 @@ void ScDPResultFilterSet::add(
     }
 
     pMemNode->maValues.push_back(fVal);
-    printf("\n");
 }
 
 void ScDPResultFilterSet::swap(ScDPResultFilterSet& rOther)
diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx
index 379f5c1..7cc25bc 100644
--- a/sc/source/core/data/dptabres.cxx
+++ b/sc/source/core/data/dptabres.cxx
@@ -55,48 +55,6 @@ using ::std::vector;
 using ::std::pair;
 using ::com::sun::star::uno::Sequence;
 
-#include <stdio.h>
-#include <string>
-#include <sys/time.h>
-
-namespace {
-
-class stack_printer
-{
-public:
-    explicit stack_printer(const char* msg) :
-        msMsg(msg)
-    {
-        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
-        mfStartTime = getTime();
-    }
-
-    ~stack_printer()
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime - mfStartTime));
-    }
-
-    void printTime(int line) const
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime - mfStartTime));
-    }
-
-private:
-    double getTime() const
-    {
-        timeval tv;
-        gettimeofday(&tv, NULL);
-        return tv.tv_sec + tv.tv_usec / 1000000.0;
-    }
-
-    ::std::string msMsg;
-    double mfStartTime;
-};
-
-}
-
 namespace {
 
 sal_uInt16 nFuncStrIds[12] =     // passend zum enum ScSubTotalFunc
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index 5c0d519..8efadd5 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -69,48 +69,6 @@ using ::com::sun::star::uno::Sequence;
 using ::com::sun::star::uno::Any;
 using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
 
-#include <stdio.h>
-#include <string>
-#include <sys/time.h>
-
-namespace {
-
-class stack_printer
-{
-public:
-    explicit stack_printer(const char* msg) :
-        msMsg(msg)
-    {
-        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
-        mfStartTime = getTime();
-    }
-
-    ~stack_printer()
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime - mfStartTime));
-    }
-
-    void printTime(int line) const
-    {
-        double fEndTime = getTime();
-        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime - mfStartTime));
-    }
-
-private:
-    double getTime() const
-    {
-        timeval tv;
-        gettimeofday(&tv, NULL);
-        return tv.tv_sec + tv.tv_usec / 1000000.0;
-    }
-
-    ::std::string msMsg;
-    double mfStartTime;
-};
-
-}
-
 // -----------------------------------------------------------------------
 
 #define SC_MINCOUNT_LIMIT   1000000
@@ -424,7 +382,6 @@ long ScDPSource::GetSourceDim(long nDim)
 uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
                                                             throw(uno::RuntimeException)
 {
-    stack_printer __stack_printer__("ScDPSource::getResults");
     CreateRes_Impl();       // create pColResRoot and pRowResRoot
 
     if ( bResultOverflow )      // set in CreateRes_Impl
@@ -453,7 +410,6 @@ uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResult
         pColResRoot, aFilterCxt, aSeq, pResData->GetRowStartMeasure());
 
     maResFilterSet.swap(aFilterCxt.maFilterSet); // Keep this data for GETPIVOTDATA.
-    maResFilterSet.dump();
 
     return aSeq;
 }
commit a012bc60f2b3933d9148c2dd595df691a7834ad4
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 22:23:54 2013 -0400

    We can remove all this code now.
    
    This code is the old GETPIVOTDATA implementation, which actually parses
    the pivot table output on the sheet (ugh!) to get the right value.  It
    was susceptible to the table output being configurable.
    
    Change-Id: Iefbefa06b91fc6cfa7a21f9a8031bf6841c1d936

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index c217f1e..735b033 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -183,8 +183,6 @@ public:
         const OUString& rDataFieldName,
         std::vector<com::sun::star::sheet::DataPilotFieldFilter>& rFilters);
 
-    bool                GetPivotData( ScDPGetPivotDataField& rTarget, /* returns result */
-                                      const std::vector< ScDPGetPivotDataField >& rFilters );
     bool                ParseFilters( ScDPGetPivotDataField& rTarget,
                                       std::vector< ScDPGetPivotDataField >& rFilters,
                                       const OUString& rFilterList );
diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 49b9643..293d937 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -143,12 +143,6 @@ public:
         field region. */
     bool            GetDataResultPositionData(::std::vector< ::com::sun::star::sheet::DataPilotFieldFilter >& rFilters, const ScAddress& rPos);
 
-    /**
-     * @return true on success and stores the result in rTarget, or false if
-     *         rFilters or rTarget describe something that is not visible.
-     */
-    bool GetPivotData( ScDPGetPivotDataField& rTarget,
-                       const std::vector< ScDPGetPivotDataField >& rFilters );
     long            GetHeaderDim( const ScAddress& rPos, sal_uInt16& rOrient );
     bool GetHeaderDrag(
         const ScAddress& rPos, bool bMouseLeft, bool bMouseTop, long nDragDim,
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 04273c8..dff56a5 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1363,17 +1363,6 @@ double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<shee
     return aRes[nDataIndex];
 }
 
-// Returns sal_True on success and stores the result in rTarget
-bool ScDPObject::GetPivotData( ScDPGetPivotDataField& rTarget,
-                               const std::vector< ScDPGetPivotDataField >& rFilters )
-{
-    if (!mbEnableGetPivotData)
-        return false;
-
-    CreateOutput();             // create xSource and pOutput if not already done
-    return pOutput->GetPivotData( rTarget, rFilters );
-}
-
 bool ScDPObject::IsFilterButton( const ScAddress& rPos )
 {
     CreateOutput();             // create xSource and pOutput if not already done
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index b12edc5..e774f8e 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -1516,340 +1516,6 @@ bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>&
 
 namespace {
 
-//
-//  helper functions for ScDPOutput::GetPivotData
-//
-
-bool lcl_IsNamedDataField( const ScDPGetPivotDataField& rTarget, const OUString& rSourceName, const OUString& rGivenName )
-{
-    // match one of the names, ignoring case
-    return ScGlobal::GetpTransliteration()->isEqual( rTarget.maFieldName, rSourceName ) ||
-           ScGlobal::GetpTransliteration()->isEqual( rTarget.maFieldName, rGivenName );
-}
-
-bool lcl_IsNamedCategoryField( const ScDPGetPivotDataField& rFilter, const ScDPOutLevelData& rField )
-{
-    return ScGlobal::GetpTransliteration()->isEqual( rFilter.maFieldName, rField.maName );
-}
-
-bool lcl_IsCondition( const sheet::MemberResult& rResultEntry, const ScDPGetPivotDataField& rFilter )
-{
-    //! handle numeric conditions?
-    return ScGlobal::GetpTransliteration()->isEqual( rResultEntry.Name, rFilter.maValStr );
-}
-
-bool lcl_CheckPageField( const ScDPOutLevelData& rField,
-                         const std::vector< ScDPGetPivotDataField >& rFilters,
-                         std::vector<bool>& rFilterUsed )
-{
-    for (SCSIZE nFilterPos = 0; nFilterPos < rFilters.size(); ++nFilterPos)
-    {
-        if ( lcl_IsNamedCategoryField( rFilters[nFilterPos], rField ) )
-        {
-            rFilterUsed[nFilterPos] = true;
-
-            // page field result is empty or the selection as single entry (see lcl_GetSelectedPageAsResult)
-            if ( rField.aResult.getLength() == 1 &&
-                 lcl_IsCondition( rField.aResult[0], rFilters[nFilterPos] ) )
-            {
-                return true;        // condition matches page selection
-            }
-            else
-            {
-                return false;       // no page selection or different entry
-            }
-        }
-    }
-
-    return true;    // valid if the page field doesn't have a filter
-}
-
-uno::Sequence<sheet::GeneralFunction> lcl_GetSubTotals(
-        const uno::Reference<sheet::XDimensionsSupplier>& xSource, const ScDPOutLevelData& rField )
-{
-    uno::Sequence<sheet::GeneralFunction> aSubTotals;
-
-    uno::Reference<sheet::XHierarchiesSupplier> xHierSupp;
-    uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
-    uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName );
-    sal_Int32 nIntCount = xIntDims->getCount();
-    if ( rField.nDim < nIntCount )
-    {
-        uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface(
-                                    xIntDims->getByIndex( rField.nDim ) );
-        xHierSupp = uno::Reference<sheet::XHierarchiesSupplier>( xIntDim, uno::UNO_QUERY );
-    }
-    OSL_ENSURE( xHierSupp.is(), "dimension not found" );
-
-    sal_Int32 nHierCount = 0;
-    uno::Reference<container::XIndexAccess> xHiers;
-    if ( xHierSupp.is() )
-    {
-        uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies();
-        xHiers = new ScNameToIndexAccess( xHiersName );
-        nHierCount = xHiers->getCount();
-    }
-    uno::Reference<uno::XInterface> xHier;
-    if ( rField.nHier < nHierCount )
-        xHier = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex( rField.nHier ) );
-    OSL_ENSURE( xHier.is(), "hierarchy not found" );
-
-    sal_Int32 nLevCount = 0;
-    uno::Reference<container::XIndexAccess> xLevels;
-    uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHier, uno::UNO_QUERY );
-    if ( xLevSupp.is() )
-    {
-        uno::Reference<container::XNameAccess> xLevsName = xLevSupp->getLevels();
-        xLevels = new ScNameToIndexAccess( xLevsName );
-        nLevCount = xLevels->getCount();
-    }
-    uno::Reference<uno::XInterface> xLevel;
-    if ( rField.nLevel < nLevCount )
-        xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex( rField.nLevel ) );
-    OSL_ENSURE( xLevel.is(), "level not found" );
-
-    uno::Reference<beans::XPropertySet> xLevelProp( xLevel, uno::UNO_QUERY );
-    if ( xLevelProp.is() )
-    {
-        try
-        {
-            uno::Any aValue = xLevelProp->getPropertyValue( OUString(SC_UNO_DP_SUBTOTAL) );
-            aValue >>= aSubTotals;
-        }
-        catch(const uno::Exception&)
-        {
-        }
-    }
-
-    return aSubTotals;
-}
-
-void lcl_FilterInclude( std::vector<bool>& rResult, std::vector< sal_Int32 >& rSubtotal,
-                        const ScDPOutLevelData& rField,
-                        const std::vector< ScDPGetPivotDataField >& rFilters,
-                        std::vector<bool>& rFilterUsed,
-                        bool& rBeforeDataLayout,
-                        sal_Int32 nGrandTotals, sal_Int32 nDataLayoutIndex,
-                        const std::vector<OUString>& rDataNames, const std::vector<OUString>& rGivenNames,
-                        const ScDPGetPivotDataField& rTarget, const uno::Reference<sheet::XDimensionsSupplier>& xSource )
-{
-    // returns true if a filter was given for the field
-
-    OSL_ENSURE( rFilters.size() == rFilterUsed.size(), "wrong size" );
-
-    const bool bIsDataLayout = ( rField.nDim == nDataLayoutIndex );
-    if (bIsDataLayout)
-        rBeforeDataLayout = false;
-
-    bool bHasFilter = false;
-    ScDPGetPivotDataField aFilter;
-    if ( !bIsDataLayout )          // selection of data field is handled separately
-    {
-        for (SCSIZE nFilterPos = 0; nFilterPos < rFilters.size() && !bHasFilter; ++nFilterPos)
-        {
-            if ( lcl_IsNamedCategoryField( rFilters[nFilterPos], rField ) )
-            {
-                aFilter = rFilters[nFilterPos];
-                rFilterUsed[nFilterPos] = true;
-                bHasFilter = true;
-            }
-        }
-    }
-
-    bool bHasFunc = bHasFilter && aFilter.meFunction != sheet::GeneralFunction_NONE;
-
-    uno::Sequence<sheet::GeneralFunction> aSubTotals;
-    if ( !bIsDataLayout )
-        aSubTotals = lcl_GetSubTotals( xSource, rField );
-    bool bManualSub = ( aSubTotals.getLength() > 0 && aSubTotals[0] != sheet::GeneralFunction_AUTO );
-
-    const uno::Sequence<sheet::MemberResult>& rSequence = rField.aResult;
-    const sheet::MemberResult* pArray = rSequence.getConstArray();
-    sal_Int32 nSize = rSequence.getLength();
-
-    OSL_ENSURE( (sal_Int32)rResult.size() == nSize, "Number of fields do not match result count" );
-
-    sal_Int32 nContCount = 0;
-    sal_Int32 nSubTotalCount = 0;
-    sheet::MemberResult aPrevious;
-    for( sal_Int32 j=0; j < nSize; j++ )
-    {
-        sheet::MemberResult aResultEntry = pArray[j];
-        if ( aResultEntry.Flags & sheet::MemberResultFlags::CONTINUE )
-        {
-            aResultEntry = aPrevious;
-            ++nContCount;
-        }
-        else if ( ( aResultEntry.Flags & sheet::MemberResultFlags::SUBTOTAL ) == 0 )
-        {
-            // count the CONTINUE entries before a SUBTOTAL
-            nContCount = 0;
-        }
-
-        if ( j >= nSize - nGrandTotals )
-        {
-            // mark as subtotal for the preceding data
-            if ( ( aResultEntry.Flags & sheet::MemberResultFlags::SUBTOTAL ) != 0 )
-            {
-                rSubtotal[j] = nSize - nGrandTotals;
-
-                if ( rResult[j] && nGrandTotals > 1 )
-                {
-                    // grand total is always automatic
-                    sal_Int32 nDataPos = j - ( nSize - nGrandTotals );
-                    if (nDataPos >= 0 && nDataPos < (sal_Int32)rDataNames.size() &&
-                            nDataPos < (sal_Int32)rGivenNames.size())
-                    {
-                        OUString aSourceName( rDataNames[nDataPos] );     // vector contains source names
-                        OUString aGivenName( rGivenNames[nDataPos] );
-
-                        rResult[j] = lcl_IsNamedDataField( rTarget, aSourceName, aGivenName );
-                    }
-                    else
-                    {
-                        OSL_FAIL( "wrong data count for grand total" );
-                        rResult[j] = false;
-                    }
-                }
-            }
-
-            // treat "grand total" columns/rows as empty description, as if they were marked
-            // in a previous field
-
-            OSL_ENSURE( ( aResultEntry.Flags &
-                            ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL ) ) == 0 ||
-                        ( aResultEntry.Flags &
-                            ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL ) ) ==
-                                ( sheet::MemberResultFlags::HASMEMBER | sheet::MemberResultFlags::SUBTOTAL ),
-                        "non-subtotal member found in grand total result" );
-            aResultEntry.Flags = 0;
-        }
-
-        // mark subtotals (not grand total) for preceding data (assume CONTINUE is set)
-        if ( ( aResultEntry.Flags & sheet::MemberResultFlags::SUBTOTAL ) != 0 )
-        {
-            rSubtotal[j] = nContCount + 1 + nSubTotalCount;
-
-            if ( rResult[j] )
-            {
-                if ( bManualSub )
-                {
-                    if ( rBeforeDataLayout )
-                    {
-                        // manual subtotals and several data fields
-
-                        sal_Int32 nDataCount = rDataNames.size();
-                        sal_Int32 nFuncPos = nSubTotalCount / nDataCount;       // outer order: subtotal functions
-                        sal_Int32 nDataPos = nSubTotalCount % nDataCount;       // inner order: data fields
-
-                        OUString aSourceName( rDataNames[nDataPos] );             // vector contains source names
-                        OUString aGivenName( rGivenNames[nDataPos] );
-
-                        if (nFuncPos < aSubTotals.getLength())
-                        {
-                            rResult[j] = lcl_IsNamedDataField( rTarget, aSourceName, aGivenName ) &&
-                                     aSubTotals[nFuncPos] == aFilter.meFunction;
-                        }
-                        else
-                        {
-                            OSL_FAIL( "wrong subtotal count for manual subtotals and several data fields" );
-                            rResult[j] = false;
-                        }
-                    }
-                    else
-                    {
-                        // manual subtotals for a single data field
-
-                        if (nSubTotalCount < aSubTotals.getLength())
-                        {
-                            rResult[j] = ( aSubTotals[nSubTotalCount] == aFilter.meFunction );
-                        }
-                        else
-                        {
-                            OSL_FAIL( "wrong subtotal count for manual subtotals for a single data field" );
-                            rResult[j] = false;
-                        }
-                    }
-                }
-                else    // automatic subtotals
-                {
-                    if ( rBeforeDataLayout )
-                    {
-                        if (nSubTotalCount < (sal_Int32)rDataNames.size() &&
-                                nSubTotalCount < (sal_Int32)rGivenNames.size())
-                        {
-                            OUString aSourceName( rDataNames[nSubTotalCount] );       // vector contains source names
-                            OUString aGivenName( rGivenNames[nSubTotalCount] );
-
-                            rResult[j] = lcl_IsNamedDataField( rTarget, aSourceName, aGivenName );
-                        }
-                        else
-                        {
-                            OSL_FAIL( "wrong data count for automatic subtotals" );
-                            rResult[j] = false;
-                        }
-                    }
-
-                    // if a function was specified, automatic subtotals never match
-                    if ( bHasFunc )
-                        rResult[j] = false;
-                }
-            }
-
-            ++nSubTotalCount;
-        }
-        else
-            nSubTotalCount = 0;
-
-        if( rResult[j] )
-        {
-            if ( bIsDataLayout )
-            {
-                if ( ( aResultEntry.Flags & sheet::MemberResultFlags::HASMEMBER ) != 0 )
-                {
-                    // Asterisks are added in ScDPSaveData::WriteToSource to create unique names.
-                    //! preserve original name there?
-                    OUString aSourceName = ScDPUtil::getSourceDimensionName(aResultEntry.Name);
-
-                    rResult[j] = lcl_IsNamedDataField(
-                        rTarget, aSourceName, aResultEntry.Caption);
-                }
-            }
-            else if ( bHasFilter )
-            {
-                // name must match (simple value or subtotal)
-                rResult[j] = ( ( aResultEntry.Flags & sheet::MemberResultFlags::HASMEMBER ) != 0 ) &&
-                             lcl_IsCondition( aResultEntry, aFilter );
-
-                // if a function was specified, simple (non-subtotal) values never match
-                if ( bHasFunc && nSubTotalCount == 0 )
-                    rResult[j] = false;
-            }
-            // if no condition is given, keep the columns/rows included
-        }
-        aPrevious = aResultEntry;
-    }
-}
-
-void lcl_StripSubTotals( std::vector<bool>& rResult, const std::vector<sal_Int32>& rSubtotal )
-{
-    sal_Int32 nSize = rResult.size();
-    OSL_ENSURE( (sal_Int32)rSubtotal.size() == nSize, "sizes don't match" );
-
-    for (sal_Int32 nPos=0; nPos<nSize; nPos++)
-        if ( rResult[nPos] && rSubtotal[nPos] )
-        {
-            // if a subtotal is included, clear the result flag for the columns/rows that the subtotal includes
-            sal_Int32 nStart = nPos - rSubtotal[nPos];
-            OSL_ENSURE( nStart >= 0, "invalid subtotal count" );
-            if (nStart < 0)
-                nStart = 0;
-
-            for (sal_Int32 nPrev = nStart; nPrev < nPos; nPrev++)
-                rResult[nPrev] = false;
-        }
-}
-
 OUString lcl_GetDataFieldName( const OUString& rSourceName, sheet::GeneralFunction eFunc )
 {
     sal_uInt16 nStrId = 0;
@@ -1905,107 +1571,6 @@ void ScDPOutput::GetDataDimensionNames(
     }
 }
 
-bool ScDPOutput::GetPivotData( ScDPGetPivotDataField& rTarget,
-                               const std::vector< ScDPGetPivotDataField >& rFilters )
-{
-    CalcSizes();
-
-    // need to know about grand total columns/rows:
-    sal_Int32 nGrandTotalCols;
-    sal_Int32 nGrandTotalRows;
-    sal_Int32 nDataLayoutIndex;
-    std::vector<OUString> aDataNames;
-    std::vector<OUString> aGivenNames;
-    sheet::DataPilotFieldOrientation eDataOrient;
-    lcl_GetTableVars( nGrandTotalCols, nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, eDataOrient, xSource );
-
-    if ( aDataNames.empty() )
-        return false;               // incomplete table without data fields -> no result
-
-    if ( eDataOrient == sheet::DataPilotFieldOrientation_HIDDEN )
-    {
-        // no data layout field -> single data field -> must match the selected field in rTarget
-
-        OSL_ENSURE( aDataNames.size() == 1, "several data fields but no data layout field" );
-        if ( !lcl_IsNamedDataField( rTarget, aDataNames[0], aGivenNames[0] ) )
-            return false;
-    }
-
-    std::vector<bool> aIncludeCol(nColCount, true);
-    std::vector< sal_Int32 > aSubtotalCol( nColCount, 0 );
-    std::vector<bool> aIncludeRow(nRowCount, true);
-    std::vector< sal_Int32 > aSubtotalRow( nRowCount, 0 );
-
-    std::vector<bool> aFilterUsed(rFilters.size(), false);
-
-    long nField;
-    long nCol;
-    long nRow;
-    bool bBeforeDataLayout;
-
-    // look in column fields
-
-    bBeforeDataLayout = ( eDataOrient == sheet::DataPilotFieldOrientation_COLUMN );
-    for (nField=0; nField<nColFieldCount; nField++)
-        lcl_FilterInclude( aIncludeCol, aSubtotalCol, pColFields[nField], rFilters, aFilterUsed, bBeforeDataLayout,
-                           nGrandTotalCols, nDataLayoutIndex, aDataNames, aGivenNames, rTarget, xSource );
-
-    // look in row fields
-
-    bBeforeDataLayout = ( eDataOrient == sheet::DataPilotFieldOrientation_ROW );
-    for (nField=0; nField<nRowFieldCount; nField++)
-        lcl_FilterInclude( aIncludeRow, aSubtotalRow, pRowFields[nField], rFilters, aFilterUsed, bBeforeDataLayout,
-                           nGrandTotalRows, nDataLayoutIndex, aDataNames, aGivenNames, rTarget, xSource );
-
-    // page fields
-
-    for (nField=0; nField<nPageFieldCount; nField++)
-        if ( !lcl_CheckPageField( pPageFields[nField], rFilters, aFilterUsed ) )
-            return false;
-
-    // all filter fields must be used
-    for (SCSIZE nFilter=0; nFilter<aFilterUsed.size(); nFilter++)
-        if (!aFilterUsed[nFilter])
-            return false;
-
-    lcl_StripSubTotals( aIncludeCol, aSubtotalCol );
-    lcl_StripSubTotals( aIncludeRow, aSubtotalRow );
-
-    long nColPos = 0;
-    long nColIncluded = 0;
-    for (nCol=0; nCol<nColCount; nCol++)
-        if (aIncludeCol[nCol])
-        {
-            nColPos = nCol;
-            ++nColIncluded;
-        }
-
-    long nRowPos = 0;
-    long nRowIncluded = 0;
-    for (nRow=0; nRow<nRowCount; nRow++)
-        if (aIncludeRow[nRow])
-        {
-            nRowPos = nRow;
-            ++nRowIncluded;
-        }
-
-    if ( nColIncluded != 1 || nRowIncluded != 1 )
-        return false;
-
-    const uno::Sequence<sheet::DataResult>& rDataRow = aData[nRowPos];
-    if ( nColPos >= rDataRow.getLength() )
-        return false;
-
-    const sheet::DataResult& rResult = rDataRow[nColPos];
-    if ( rResult.Flags & sheet::DataResultFlags::ERROR )
-        return false;                                       //! different error?
-
-    rTarget.mbValIsStr = false;
-    rTarget.mnValNum = rResult.Value;
-
-    return true;
-}
-
 bool ScDPOutput::IsFilterButton( const ScAddress& rPos )
 {
     SCCOL nCol = rPos.Col();
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 6732804..91d791f 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -3082,7 +3082,6 @@ void ScInterpreter::ScGetPivotData()
     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGetPivotData" );
     sal_uInt8 nParamCount = GetByte();
 
-#if 1
     if (!MustHaveParamCount(nParamCount, 2, 30) || (nParamCount % 2) == 1)
     {
         PushError(errNoRef);
@@ -3155,95 +3154,6 @@ void ScInterpreter::ScGetPivotData()
         return;
     }
     PushDouble(fVal);
-
-#else
-    if ( MustHaveParamCount( nParamCount, 2, 30 ) )
-    {
-        // there must be an even number of args
-        //      target, ref, then field/item pairs
-        if( (nParamCount % 2) == 1)
-            goto failed;
-
-        bool bOldSyntax = false;
-        if ( nParamCount == 2 )
-        {
-            // if the first parameter is a ref, assume old syntax
-            StackVar eFirstType = GetStackType( 2 );
-            if ( eFirstType == svSingleRef || eFirstType == svDoubleRef )
-                bOldSyntax = true;
-        }
-
-        ScDPGetPivotDataField aTarget;                  // target field, and returns result
-        std::vector< ScDPGetPivotDataField > aFilters;
-        String aFilterList;
-        if ( bOldSyntax )
-            aFilterList = GetString();      // old syntax: second parameter is list of constraints
-        else
-        {
-            // new syntax: separate name/value pairs
-
-            sal_uInt16 nFilterCount = nParamCount / 2 - 1;
-            aFilters.resize( nFilterCount );
-
-            sal_uInt16 i = nFilterCount;
-            while( i-- > 0 )
-            {
-                //! should allow numeric constraint values
-                aFilters[i].mbValIsStr = true;
-                aFilters[i].maValStr = GetString();
-
-                aFilters[i].maFieldName = GetString();
-            }
-        }
-
-        // common to both syntaxes: a reference to the data pilot table
-
-        ScRange aBlock;
-        switch ( GetStackType() )
-        {
-            case svDoubleRef :
-                PopDoubleRef( aBlock );
-                break;
-
-            case svSingleRef :
-                {
-                    ScAddress aAddr;
-                    PopSingleRef( aAddr );
-                    aBlock = aAddr;
-                    break;
-                }
-            default:
-                goto failed;
-        }
-        // NOTE : MS Excel docs claim to use the 'most recent' which is not
-        // exactly the same as what we do in ScDocument::GetDPAtBlock
-        // However we do need to use GetDPABlock
-        ScDPObject* pDPObj = pDok->GetDPAtBlock ( aBlock );
-        if( NULL == pDPObj)
-            goto failed;
-
-        if ( bOldSyntax )
-        {
-            // fill aFilters / aTarget from aFilterList string
-            if ( !pDPObj->ParseFilters( aTarget, aFilters, aFilterList ) )
-                goto failed;
-        }
-        else
-            aTarget.maFieldName = GetString();      // new syntax: first parameter is data field name
-
-        if( pDPObj->GetPivotData( aTarget, aFilters ) )
-        {
-            if( aTarget.mbValIsStr )
-                PushString( aTarget.maValStr );
-            else
-                PushDouble( aTarget.mnValNum );
-            return;
-        }
-    }
-
-failed :
-    PushError( errNoRef );
-#endif
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit f6412b5bd5c8b6421d8bb3939c142cb4a9f68068
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 22:12:55 2013 -0400

    Let's explain what this method returns.
    
    Change-Id: I2b081fe32d8851403867b9ad94de40bbe4b68838

diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index ab0e86e..905bfc8 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -264,6 +264,12 @@ public:
 
     SC_DLLPUBLIC const DimsType& GetDimensions() const;
 
+    /**
+     * Get sort order map to sort row and column dimensions in order of
+     * appearance. Row dimensions get sorted before column dimensions.  This
+     * is used to traverse result tree, which is structured following this
+     * order.
+     */
     const DimOrderType& GetDimensionSortOrder() const;
 
     /**
commit f08b96bfa38e4e0e171d7aca0202d0039f7caad3
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 22:06:00 2013 -0400

    Typo.
    
    Change-Id: I67c6c2fad73d81b7ac9a9d50280f323a1fe88aad

diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index 9cd0022..ab0e86e 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -282,7 +282,7 @@ public:
 
     /**
      * Get a dimension object by its name.  <i>If one doesn't exist for the
-     * given name, it creats a new one.</i>
+     * given name, it creates a new one.</i>
      *
      * @param rName dimension name
      *
commit c5be9ffb731952ecbc037ef036e1fcdb385d9572
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 22:03:30 2013 -0400

    This should be plural, since there are multiple dimensions.
    
    Change-Id: If0994c81867606e0e6c097aeda0f0bd889e01553

diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index 770349f..9cd0022 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -368,7 +368,7 @@ private:
      */
     ScDPSaveDimension* AppendNewDimension(const OUString& rName, bool bDataLayout);
 
-    void DimensionChanged();
+    void DimensionsChanged();
 };
 
 #endif
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
index c6e369a..4572622 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -859,7 +859,7 @@ void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
     CheckDuplicateName(*pDim);
     aDimList.push_back(pDim);
 
-    DimensionChanged();
+    DimensionsChanged();
 }
 
 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const OUString& rName)
@@ -940,7 +940,7 @@ void ScDPSaveData::RemoveDimensionByName(const OUString& rName)
 
         aDimList.erase(iter);
         RemoveDuplicateNameCount(rName);
-        DimensionChanged();
+        DimensionsChanged();
         return;
     }
 }
@@ -1021,7 +1021,7 @@ void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
     }
 
     aDimList.insert(iterInsert,pDim);
-    DimensionChanged();
+    DimensionsChanged();
 }
 
 void ScDPSaveData::SetColumnGrand(bool bSet)
@@ -1399,11 +1399,11 @@ ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const OUString& rName, bool
     if (!maDupNameCounts.count(rName))
         maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
 
-    DimensionChanged();
+    DimensionsChanged();
     return pNew;
 }
 
-void ScDPSaveData::DimensionChanged()
+void ScDPSaveData::DimensionsChanged()
 {
     mpDimOrder.reset();
 }
commit 77c84dd59f438c10d559393e9cc7b63551529203
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 22:00:19 2013 -0400

    Move the dimension order calculation into ScDPSaveData.
    
    To build the dim order map only once.
    
    Change-Id: Ibea5cbfc4f5d335ac7fc5893cda255b06336d8c2

diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index 099f4cb..770349f 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -229,6 +229,7 @@ class ScDPSaveData
 {
     typedef boost::unordered_map<OUString, size_t, OUStringHash> DupNameCountType;
 public:
+    typedef boost::unordered_map<OUString, size_t, OUStringHash> DimOrderType;
     typedef boost::ptr_vector<ScDPSaveDimension> DimsType;
 
 private:
@@ -247,6 +248,7 @@ private:
     bool mbDimensionMembersBuilt;
 
     boost::scoped_ptr<OUString> mpGrandTotalName;
+    mutable boost::scoped_ptr<DimOrderType> mpDimOrder; // dimension order for row and column dimensions, to traverse result tree.
 
 public:
     SC_DLLPUBLIC ScDPSaveData();
@@ -262,6 +264,8 @@ public:
 
     SC_DLLPUBLIC const DimsType& GetDimensions() const;
 
+    const DimOrderType& GetDimensionSortOrder() const;
+
     /**
      * Get all dimensions in a given orientation.  The order represents the
      * actual order of occurrence.  The returned list also includes data
@@ -363,6 +367,8 @@ private:
      * @return pointer to the new dimension just inserted.
      */
     ScDPSaveDimension* AppendNewDimension(const OUString& rName, bool bDataLayout);
+
+    void DimensionChanged();
 };
 
 #endif
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 8ac05ab..04273c8 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1297,38 +1297,22 @@ public:
     }
 };
 
-typedef boost::unordered_map<OUString, size_t, OUStringHash> DimOrderType;
-
-class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
-{
-    DimOrderType& mrNames;
-public:
-    DimOrderInserter(DimOrderType& rNames) : mrNames(rNames) {}
-
-    void operator() (const ScDPSaveDimension* pDim)
-    {
-        size_t nRank = mrNames.size();
-        mrNames.insert(
-            DimOrderType::value_type(pDim->GetName(), nRank));
-    }
-};
-
 class LessByDimOrder : std::binary_function<sheet::DataPilotFieldFilter, sheet::DataPilotFieldFilter, bool>
 {
-    const DimOrderType& mrDimOrder;
+    const ScDPSaveData::DimOrderType& mrDimOrder;
 
 public:
-    LessByDimOrder(const DimOrderType& rDimOrder) : mrDimOrder(rDimOrder) {}
+    LessByDimOrder(const ScDPSaveData::DimOrderType& rDimOrder) : mrDimOrder(rDimOrder) {}
 
     bool operator() (const sheet::DataPilotFieldFilter& r1, const sheet::DataPilotFieldFilter& r2) const
     {
         size_t nRank1 = mrDimOrder.size();
         size_t nRank2 = mrDimOrder.size();
-        DimOrderType::const_iterator it1 = mrDimOrder.find(r1.FieldName);
+        ScDPSaveData::DimOrderType::const_iterator it1 = mrDimOrder.find(r1.FieldName);
         if (it1 != mrDimOrder.end())
             nRank1 = it1->second;
 
-        DimOrderType::const_iterator it2 = mrDimOrder.find(r2.FieldName);
+        ScDPSaveData::DimOrderType::const_iterator it2 = mrDimOrder.find(r2.FieldName);
         if (it2 != mrDimOrder.end())
             nRank2 = it2->second;
 
@@ -1363,19 +1347,9 @@ double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<shee
     if (!xDPResults.is())
         return fRet;
 
-    std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
-    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
-    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
-
     // Dimensions must be sorted in order of appearance, and row dimensions
     // must come before column dimensions.
-    // TODO: dimension order should be generated only once in ScDPSaveData.
-    DimOrderType aDimOrder;
-    std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(aDimOrder));
-    std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(aDimOrder));
-
-    // Sort filters by this dimension order...
-    std::sort(rFilters.begin(), rFilters.end(), LessByDimOrder(aDimOrder));
+    std::sort(rFilters.begin(), rFilters.end(), LessByDimOrder(pSaveData->GetDimensionSortOrder()));
 
     size_t n = rFilters.size();
     uno::Sequence<sheet::DataPilotFieldFilter> aFilters(n);
diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx
index 28d609b..c6e369a 100644
--- a/sc/source/core/data/dpsave.cxx
+++ b/sc/source/core/data/dpsave.cxx
@@ -723,7 +723,8 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
     bFilterButton( r.bFilterButton ),
     bDrillDown( r.bDrillDown ),
     mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
-    mpGrandTotalName(NULL)
+    mpGrandTotalName(NULL),
+    mpDimOrder(NULL)
 {
     if ( r.pDimensionData )
         pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
@@ -800,6 +801,39 @@ const ScDPSaveData::DimsType& ScDPSaveData::GetDimensions() const
     return aDimList;
 }
 
+namespace {
+
+class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
+{
+    ScDPSaveData::DimOrderType& mrNames;
+public:
+    DimOrderInserter(ScDPSaveData::DimOrderType& rNames) : mrNames(rNames) {}
+
+    void operator() (const ScDPSaveDimension* pDim)
+    {
+        size_t nRank = mrNames.size();
+        mrNames.insert(
+            ScDPSaveData::DimOrderType::value_type(pDim->GetName(), nRank));
+    }
+};
+
+}
+
+const ScDPSaveData::DimOrderType& ScDPSaveData::GetDimensionSortOrder() const
+{
+    if (!mpDimOrder)
+    {
+        mpDimOrder.reset(new DimOrderType);
+        std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
+        GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
+        GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
+
+        std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(*mpDimOrder));
+        std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(*mpDimOrder));
+    }
+    return *mpDimOrder;
+}
+
 void ScDPSaveData::GetAllDimensionsByOrientation(
     sheet::DataPilotFieldOrientation eOrientation, std::vector<const ScDPSaveDimension*>& rDims) const
 {
@@ -824,6 +858,8 @@ void ScDPSaveData::AddDimension(ScDPSaveDimension* pDim)
 
     CheckDuplicateName(*pDim);
     aDimList.push_back(pDim);
+
+    DimensionChanged();
 }
 
 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const OUString& rName)
@@ -904,6 +940,7 @@ void ScDPSaveData::RemoveDimensionByName(const OUString& rName)
 
         aDimList.erase(iter);
         RemoveDuplicateNameCount(rName);
+        DimensionChanged();
         return;
     }
 }
@@ -984,6 +1021,7 @@ void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
     }
 
     aDimList.insert(iterInsert,pDim);
+    DimensionChanged();
 }
 
 void ScDPSaveData::SetColumnGrand(bool bSet)
@@ -1361,9 +1399,15 @@ ScDPSaveDimension* ScDPSaveData::AppendNewDimension(const OUString& rName, bool
     if (!maDupNameCounts.count(rName))
         maDupNameCounts.insert(DupNameCountType::value_type(rName, 0));
 
+    DimensionChanged();
     return pNew;
 }
 
+void ScDPSaveData::DimensionChanged()
+{
+    mpDimOrder.reset();
+}
+
 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r )
 {
     return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode;
commit d6cfe8de74969928af13a04ebc5ae9dbc9274196
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 21:52:33 2013 -0400

    UNO API signature has changed.
    
    Change-Id: Id473207b0c9720b8d40f4dbdec184f0c36344da6

diff --git a/offapi/com/sun/star/sheet/XDataPilotResults.idl b/offapi/com/sun/star/sheet/XDataPilotResults.idl
index 0e4486b..6590352 100644
--- a/offapi/com/sun/star/sheet/XDataPilotResults.idl
+++ b/offapi/com/sun/star/sheet/XDataPilotResults.idl
@@ -45,7 +45,7 @@ interface XDataPilotResults: com::sun::star::uno::XInterface
      */
     sequence< sequence< DataResult > > getResults();
 
-    sequence<any> getFilteredResults(
+    sequence<double> getFilteredResults(
         [in] sequence<com::sun::star::sheet::DataPilotFieldFilter> aFilters );
 };
 
commit 378d38f4cab3fc39e735d39e6ecaeae1df408f34
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 21:06:53 2013 -0400

    Retrieve the result value for GETPIVOTDATA for real (finally!)
    
    Change-Id: I68f4fdab667d86e79225a77964ed90373b391d08

diff --git a/sc/inc/dpresfilter.hxx b/sc/inc/dpresfilter.hxx
index 5e6f3e7..9d4617d 100644
--- a/sc/inc/dpresfilter.hxx
+++ b/sc/inc/dpresfilter.hxx
@@ -21,6 +21,10 @@
 
 #include <boost/unordered_map.hpp>
 
+namespace com { namespace sun { namespace star { namespace sheet {
+    struct DataPilotFieldFilter;
+}}}}
+
 struct ScDPResultFilter
 {
     OUString maDimName;
@@ -50,7 +54,6 @@ class ScDPResultFilterSet : boost::noncopyable
 {
 public:
     typedef std::vector<double> ValuesType;
-    typedef boost::unordered_map<OUString, OUString, OUStringHash> FilterSetType;
 
 private:
 
@@ -81,7 +84,6 @@ private:
     struct MemberNode : boost::noncopyable
     {
         const DimensionNode* mpParent;
-        double mfValue;
         ValuesType maValues;
         DimensionsType maChildDimensions;
 
@@ -117,8 +119,11 @@ public:
     void swap(ScDPResultFilterSet& rOther);
 
     bool empty() const;
+    void clear();
 
-    bool getValues(FilterSetType& rFilters, ValuesType& rValues) const;
+    const ValuesType* getResults(
+        const com::sun::star::uno::Sequence<
+            com::sun::star::sheet::DataPilotFieldFilter>& rFilters) const;
 
 #if DEBUG_PIVOT_TABLE
     void dump() const;
diff --git a/sc/inc/dptabsrc.hxx b/sc/inc/dptabsrc.hxx
index a51dd47..51b6759 100644
--- a/sc/inc/dptabsrc.hxx
+++ b/sc/inc/dptabsrc.hxx
@@ -201,7 +201,7 @@ public:
                             ::com::sun::star::sheet::DataResult > > SAL_CALL getResults(  )
                                 throw(::com::sun::star::uno::RuntimeException);
 
-    virtual com::sun::star::uno::Sequence<com::sun::star::uno::Any> SAL_CALL
+    virtual com::sun::star::uno::Sequence<double> SAL_CALL
         getFilteredResults(
             const com::sun::star::uno::Sequence<com::sun::star::sheet::DataPilotFieldFilter>& aFilters )
                 throw (com::sun::star::uno::RuntimeException);
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 7bc111f..8ac05ab 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1357,7 +1357,7 @@ double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<shee
     if (it == aDataDims.end())
         return fRet;
 
-    sal_Int32 nDataIndex = std::distance(aDataDims.begin(), it);
+    size_t nDataIndex = std::distance(aDataDims.begin(), it);
 
     uno::Reference<sheet::XDataPilotResults> xDPResults(xSource, uno::UNO_QUERY);
     if (!xDPResults.is())
@@ -1382,11 +1382,11 @@ double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<shee
     for (size_t i = 0; i < n; ++i)
         aFilters[i] = rFilters[i];
 
-    uno::Sequence<uno::Any> aRes = xDPResults->getFilteredResults(aFilters);
-
-    fRet = 54.0;
+    uno::Sequence<double> aRes = xDPResults->getFilteredResults(aFilters);
+    if (static_cast<sal_Int32>(nDataIndex) >= aRes.getLength())
+        return fRet;
 
-    return fRet;
+    return aRes[nDataIndex];
 }
 
 // Returns sal_True on success and stores the result in rTarget
diff --git a/sc/source/core/data/dpresfilter.cxx b/sc/source/core/data/dpresfilter.cxx
index 5cda36b..fbb74c1 100644
--- a/sc/source/core/data/dpresfilter.cxx
+++ b/sc/source/core/data/dpresfilter.cxx
@@ -8,7 +8,11 @@
  */
 
 #include "dpresfilter.hxx"
+#include "global.hxx"
 
+#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
+
+using namespace com::sun::star;
 using namespace std;
 
 ScDPResultFilter::ScDPResultFilter(const OUString& rDimName, bool bDataLayout) :
@@ -156,9 +160,36 @@ bool ScDPResultFilterSet::empty() const
     return mpRoot->maChildDimensions.empty();
 }
 
-bool ScDPResultFilterSet::getValues(FilterSetType& rFilters, ValuesType& rValues) const
+void ScDPResultFilterSet::clear()
+{
+    maPrimaryDimName = EMPTY_OUSTRING;
+    delete mpRoot;
+    mpRoot = new MemberNode(NULL);
+}
+
+const ScDPResultFilterSet::ValuesType* ScDPResultFilterSet::getResults(
+    const uno::Sequence<sheet::DataPilotFieldFilter>& rFilters) const
 {
-    return false;
+    const sheet::DataPilotFieldFilter* p = rFilters.getConstArray();
+    const sheet::DataPilotFieldFilter* pEnd = p + static_cast<size_t>(rFilters.getLength());
+    const MemberNode* pMember = mpRoot;
+    for (; p != pEnd; ++p)
+    {
+        DimensionsType::const_iterator itDim = pMember->maChildDimensions.find(p->FieldName);
+        if (itDim == pMember->maChildDimensions.end())
+            // Specified dimension not found.
+            return NULL;
+
+        const DimensionNode* pDim = itDim->second;
+        MembersType::const_iterator itMem = pDim->maChildMembers.find(p->MatchValue);
+        if (itMem == pDim->maChildMembers.end())
+            // Specified member not found.
+            return NULL;
+
+        pMember = itMem->second;
+    }
+
+    return &pMember->maValues;
 }
 
 #if DEBUG_PIVOT_TABLE
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index 8d641b1..5c0d519 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -458,28 +458,24 @@ uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResult
     return aSeq;
 }
 
-namespace {
-
-struct OUStringPrinter
-{
-    void operator() (const OUString& r) const
-    {
-        std::cout << r << " ";
-    }
-};
-
-}
-
-uno::Sequence<uno::Any> ScDPSource::getFilteredResults(
+uno::Sequence<double> ScDPSource::getFilteredResults(
             const uno::Sequence<sheet::DataPilotFieldFilter>& aFilters )
                 throw (uno::RuntimeException)
 {
     if (maResFilterSet.empty())
         getResults(); // Build result tree first.
 
-    // TODO: Traverse the tree.
+    // Get result values from the tree.
+    const ScDPResultFilterSet::ValuesType* pVals = maResFilterSet.getResults(aFilters);
+    if (!pVals)
+        return uno::Sequence<double>();
 
-    return uno::Sequence<uno::Any>();
+    size_t n = pVals->size();
+    uno::Sequence<double> aRet(n);
+    for (size_t i = 0; i < n; ++i)
+        aRet[i] = (*pVals)[i];
+
+    return aRet;
 }
 
 void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException)
@@ -574,6 +570,8 @@ void ScDPSource::setRepeatIfEmpty(bool bSet)
 
 void ScDPSource::disposeData()
 {
+    maResFilterSet.clear();
+
     if ( pResData )
     {
         //  reset all data...
commit c128a7712095831dfb378bb2218fc90a9b18c6d2
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 18:04:52 2013 -0400

    More progress. Getting closer...
    
    Change-Id: Ic086804d4ef72f2ee53236436244f0f77447a6d0

diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index d30d1d1..7bc111f 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -77,6 +77,8 @@
 #include <vector>
 #include <memory>
 
+#include <boost/unordered_map.hpp>
+
 using namespace com::sun::star;
 using ::std::vector;
 using ::std::unary_function;
@@ -1295,15 +1297,42 @@ public:
     }
 };
 
-class NameInserter : std::unary_function<const ScDPSaveDimension*, void>
+typedef boost::unordered_map<OUString, size_t, OUStringHash> DimOrderType;
+
+class DimOrderInserter : std::unary_function<const ScDPSaveDimension*, void>
 {
-    std::vector<OUString>& mrNames;
+    DimOrderType& mrNames;
 public:
-    NameInserter(std::vector<OUString>& rNames) : mrNames(rNames) {}
+    DimOrderInserter(DimOrderType& rNames) : mrNames(rNames) {}
 
     void operator() (const ScDPSaveDimension* pDim)
     {
-        mrNames.push_back(pDim->GetName());
+        size_t nRank = mrNames.size();
+        mrNames.insert(
+            DimOrderType::value_type(pDim->GetName(), nRank));
+    }
+};
+
+class LessByDimOrder : std::binary_function<sheet::DataPilotFieldFilter, sheet::DataPilotFieldFilter, bool>
+{
+    const DimOrderType& mrDimOrder;
+
+public:
+    LessByDimOrder(const DimOrderType& rDimOrder) : mrDimOrder(rDimOrder) {}
+
+    bool operator() (const sheet::DataPilotFieldFilter& r1, const sheet::DataPilotFieldFilter& r2) const
+    {
+        size_t nRank1 = mrDimOrder.size();
+        size_t nRank2 = mrDimOrder.size();
+        DimOrderType::const_iterator it1 = mrDimOrder.find(r1.FieldName);
+        if (it1 != mrDimOrder.end())
+            nRank1 = it1->second;
+
+        DimOrderType::const_iterator it2 = mrDimOrder.find(r2.FieldName);
+        if (it2 != mrDimOrder.end())
+            nRank2 = it2->second;
+
+        return nRank1 < nRank2;
     }
 };
 
@@ -1340,11 +1369,13 @@ double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<shee
 
     // Dimensions must be sorted in order of appearance, and row dimensions
     // must come before column dimensions.
-    std::vector<OUString> aDimOrder;
-    std::for_each(aRowDims.begin(), aRowDims.end(), NameInserter(aDimOrder));
-    std::for_each(aColDims.begin(), aColDims.end(), NameInserter(aDimOrder));
+    // TODO: dimension order should be generated only once in ScDPSaveData.
+    DimOrderType aDimOrder;
+    std::for_each(aRowDims.begin(), aRowDims.end(), DimOrderInserter(aDimOrder));
+    std::for_each(aColDims.begin(), aColDims.end(), DimOrderInserter(aDimOrder));
 
-    // TODO: Sort filters by this dimension order...
+    // Sort filters by this dimension order...
+    std::sort(rFilters.begin(), rFilters.end(), LessByDimOrder(aDimOrder));
 
     size_t n = rFilters.size();
     uno::Sequence<sheet::DataPilotFieldFilter> aFilters(n);
commit 1939399c0a1558e7b8b5f05a5eace5d84f896939
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 16:35:23 2013 -0400

    More progress. Getting more clue, but still not out of the dark yet.
    
    Change-Id: I0467cd95e2c6f2f353333b24e1aba737d99e5c20

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index fd7c598..c217f1e 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -181,8 +181,7 @@ public:
 
     double GetPivotData(
         const OUString& rDataFieldName,
-        const com::sun::star::uno::Sequence<
-            com::sun::star::sheet::DataPilotFieldFilter>& rFilters);
+        std::vector<com::sun::star::sheet::DataPilotFieldFilter>& rFilters);
 
     bool                GetPivotData( ScDPGetPivotDataField& rTarget, /* returns result */
                                       const std::vector< ScDPGetPivotDataField >& rFilters );
diff --git a/sc/inc/dpresfilter.hxx b/sc/inc/dpresfilter.hxx
index 05bcdcb..5e6f3e7 100644
--- a/sc/inc/dpresfilter.hxx
+++ b/sc/inc/dpresfilter.hxx
@@ -17,10 +17,10 @@
 
 #if DEBUG_PIVOT_TABLE
 #include <map>
-#else
-#include <boost/unordered_map.hpp>
 #endif
 
+#include <boost/unordered_map.hpp>
+
 struct ScDPResultFilter
 {
     OUString maDimName;
@@ -48,6 +48,12 @@ struct ScDPResultFilter
  */
 class ScDPResultFilterSet : boost::noncopyable
 {
+public:
+    typedef std::vector<double> ValuesType;
+    typedef boost::unordered_map<OUString, OUString, OUStringHash> FilterSetType;
+
+private:
+
     struct MemberNode;
     struct DimensionNode;
 #if DEBUG_PIVOT_TABLE
@@ -58,7 +64,6 @@ class ScDPResultFilterSet : boost::noncopyable
     typedef boost::unordered_map<ScDPItemData, MemberNode*, ScDPItemData::Hash> MembersType;
     typedef boost::unordered_map<OUString, DimensionNode*, OUStringHash> DimensionsType;
 #endif
-    typedef std::vector<double> ValuesType;
 
     struct DimensionNode : boost::noncopyable
     {
@@ -92,6 +97,7 @@ class ScDPResultFilterSet : boost::noncopyable
     MemberNode* mpRoot;
 
 public:
+
     ScDPResultFilterSet();
     ~ScDPResultFilterSet();
 
@@ -110,6 +116,10 @@ public:
 
     void swap(ScDPResultFilterSet& rOther);
 
+    bool empty() const;
+
+    bool getValues(FilterSetType& rFilters, ValuesType& rValues) const;
+
 #if DEBUG_PIVOT_TABLE
     void dump() const;
 #endif
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index d04197e..d30d1d1 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1295,9 +1295,21 @@ public:
     }
 };
 
+class NameInserter : std::unary_function<const ScDPSaveDimension*, void>
+{
+    std::vector<OUString>& mrNames;
+public:
+    NameInserter(std::vector<OUString>& rNames) : mrNames(rNames) {}
+
+    void operator() (const ScDPSaveDimension* pDim)
+    {
+        mrNames.push_back(pDim->GetName());
+    }
+};
+
 }
 
-double ScDPObject::GetPivotData(const OUString& rDataFieldName, const uno::Sequence<sheet::DataPilotFieldFilter>& rFilters)
+double ScDPObject::GetPivotData(const OUString& rDataFieldName, std::vector<sheet::DataPilotFieldFilter>& rFilters)
 {
     double fRet;
     rtl::math::setNan(&fRet);
@@ -1306,23 +1318,40 @@ double ScDPObject::GetPivotData(const OUString& rDataFieldName, const uno::Seque
 
     CreateObjects();
 
-    std::vector<const ScDPSaveDimension*> aDims;
-    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
-    if (aDims.empty())
+    std::vector<const ScDPSaveDimension*> aDataDims;
+    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDataDims);
+    if (aDataDims.empty())
         return fRet;
 
     std::vector<const ScDPSaveDimension*>::iterator it = std::find_if(
-        aDims.begin(), aDims.end(), FindByName(rDataFieldName));
-    if (it == aDims.end())
+        aDataDims.begin(), aDataDims.end(), FindByName(rDataFieldName));
+    if (it == aDataDims.end())
         return fRet;
 
-    sal_Int32 nDataIndex = std::distance(aDims.begin(), it);
+    sal_Int32 nDataIndex = std::distance(aDataDims.begin(), it);
 
     uno::Reference<sheet::XDataPilotResults> xDPResults(xSource, uno::UNO_QUERY);
     if (!xDPResults.is())
         return fRet;
 
-    uno::Sequence<uno::Any> aRes = xDPResults->getFilteredResults(rFilters);
+    std::vector<const ScDPSaveDimension*> aRowDims, aColDims;
+    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_ROW, aRowDims);
+    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_COLUMN, aColDims);
+
+    // Dimensions must be sorted in order of appearance, and row dimensions
+    // must come before column dimensions.
+    std::vector<OUString> aDimOrder;
+    std::for_each(aRowDims.begin(), aRowDims.end(), NameInserter(aDimOrder));
+    std::for_each(aColDims.begin(), aColDims.end(), NameInserter(aDimOrder));
+
+    // TODO: Sort filters by this dimension order...
+
+    size_t n = rFilters.size();
+    uno::Sequence<sheet::DataPilotFieldFilter> aFilters(n);
+    for (size_t i = 0; i < n; ++i)
+        aFilters[i] = rFilters[i];
+
+    uno::Sequence<uno::Any> aRes = xDPResults->getFilteredResults(aFilters);
 
     fRet = 54.0;
 
diff --git a/sc/source/core/data/dpresfilter.cxx b/sc/source/core/data/dpresfilter.cxx
index 0ae8c94..5cda36b 100644
--- a/sc/source/core/data/dpresfilter.cxx
+++ b/sc/source/core/data/dpresfilter.cxx
@@ -151,6 +151,16 @@ void ScDPResultFilterSet::swap(ScDPResultFilterSet& rOther)
     std::swap<MemberNode*>(mpRoot, rOther.mpRoot);
 }
 
+bool ScDPResultFilterSet::empty() const
+{
+    return mpRoot->maChildDimensions.empty();
+}
+
+bool ScDPResultFilterSet::getValues(FilterSetType& rFilters, ValuesType& rValues) const
+{
+    return false;
+}
+
 #if DEBUG_PIVOT_TABLE
 void ScDPResultFilterSet::dump() const
 {
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index b7a1c51..8d641b1 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -45,6 +45,7 @@
 #include "dpitemdata.hxx"
 #include "dputil.hxx"
 #include "dpresfilter.hxx"
+#include "dpmacros.hxx"
 
 #include <com/sun/star/beans/PropertyAttribute.hpp>
 #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
@@ -457,20 +458,26 @@ uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResult
     return aSeq;
 }
 
+namespace {
+
+struct OUStringPrinter
+{
+    void operator() (const OUString& r) const
+    {
+        std::cout << r << " ";
+    }
+};
+
+}
+
 uno::Sequence<uno::Any> ScDPSource::getFilteredResults(
             const uno::Sequence<sheet::DataPilotFieldFilter>& aFilters )
                 throw (uno::RuntimeException)
 {
-    sal_Int32 n = aFilters.getLength();
-    std::vector<sheet::DataPilotFieldFilter> aSorted;
-    aSorted.reserve(n);
-    for (sal_Int32 i = 0; i < n; ++i)
-        aSorted.push_back(aFilters[i]);
-
-    // Sort filters by order of appearance. Row fields come before column fields.
+    if (maResFilterSet.empty())
+        getResults(); // Build result tree first.
 
-    // TODO: maResFilterSet maintains the result tree, so we can probably
-    // extract the field sort order from there somehow.
+    // TODO: Traverse the tree.
 
     return uno::Sequence<uno::Any>();
 }
diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index a5a8d83..6732804 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -3108,7 +3108,7 @@ void ScInterpreter::ScGetPivotData()
     // Standard syntax: separate name/value pairs
 
     sal_uInt16 nFilterCount = nParamCount / 2 - 1;
-    uno::Sequence<sheet::DataPilotFieldFilter> aFilters(nFilterCount);
+    std::vector<sheet::DataPilotFieldFilter> aFilters(nFilterCount);
 
     sal_uInt16 i = nFilterCount;
     while (i-- > 0)
commit 09d8d7554d6fa02aefcd84a898b12fa63c344b26
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Thu Apr 18 11:19:01 2013 -0400

    Add some more notes to make it easier to pick up on this for my next visit.
    
    Looks like I have to put this on the shelf once again...
    
    Change-Id: I6288d019170278e484befaac3ee57cea24a69c0e

diff --git a/sc/inc/dpresfilter.hxx b/sc/inc/dpresfilter.hxx
index db32f6e..05bcdcb 100644
--- a/sc/inc/dpresfilter.hxx
+++ b/sc/inc/dpresfilter.hxx
@@ -32,6 +32,20 @@ struct ScDPResultFilter
     ScDPResultFilter(const OUString& rDimName, bool bDataLayout);
 };
 
+/**
+ * This class maintains pivot table calculation result in a tree structure
+ * which represents the logical structure of pivot table result layout as
+ * presented in the sheet.
+ *
+ * <p>The root node has two child nodes if the pivot table consists of both
+ * column and row dimensions. The first child stores the result tree that is
+ * first filtered by row dimensions then by column dimensions. The second
+ * child stores the result tree that is filtered by column dimensions only
+ * (for column grand totals).</p>
+ *
+ * <p>If the pivot table layout only consists of either column or row
+ * dimensions, the root node only has one child node.</p>
+ */
 class ScDPResultFilterSet : boost::noncopyable
 {
     struct MemberNode;
@@ -74,6 +88,7 @@ class ScDPResultFilterSet : boost::noncopyable
 #endif
     };
 
+    OUString maPrimaryDimName;
     MemberNode* mpRoot;
 
 public:
diff --git a/sc/source/core/data/dpresfilter.cxx b/sc/source/core/data/dpresfilter.cxx
index b08cc4a..0ae8c94 100644
--- a/sc/source/core/data/dpresfilter.cxx
+++ b/sc/source/core/data/dpresfilter.cxx
@@ -95,6 +95,9 @@ void ScDPResultFilterSet::add(
         if (filter.mbDataLayout)
             continue;
 
+        if (maPrimaryDimName.isEmpty())
+            maPrimaryDimName = filter.maDimName;
+
         printf("%s: ", rtl::OUStringToOString(filter.maDimName, RTL_TEXTENCODING_UTF8).getStr());
         if (filter.maValue.IsValue())
             printf("%g ", filter.maValue.GetValue());
@@ -144,12 +147,14 @@ void ScDPResultFilterSet::add(
 
 void ScDPResultFilterSet::swap(ScDPResultFilterSet& rOther)
 {
+    std::swap(maPrimaryDimName, rOther.maPrimaryDimName);
     std::swap<MemberNode*>(mpRoot, rOther.mpRoot);
 }
 
 #if DEBUG_PIVOT_TABLE
 void ScDPResultFilterSet::dump() const
 {
+    cout << "primary dimension name: " << maPrimaryDimName << endl;
     mpRoot->dump(0);
 }
 #endif
diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx
index 058a029..b7a1c51 100644
--- a/sc/source/core/data/dptabsrc.cxx
+++ b/sc/source/core/data/dptabsrc.cxx
@@ -469,6 +469,8 @@ uno::Sequence<uno::Any> ScDPSource::getFilteredResults(
 
     // Sort filters by order of appearance. Row fields come before column fields.
 
+    // TODO: maResFilterSet maintains the result tree, so we can probably
+    // extract the field sort order from there somehow.
 
     return uno::Sequence<uno::Any>();
 }
commit ac569ed4cf5064248b9952f182f6572f20dc9bcb
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Mar 11 17:16:54 2013 -0400

    fdo#60300: Work-in-progress change to rework pivot table core.
    
    The idea is to avoid parsing the pivot table sheet output in order
    to calculate GETPIVOTDATA.  The table outout is configurable, and it
    will only be more configurable in the future.  The gist of my rework
    is to calcualte the result of GETPIVOTDATA with the internl result
    tree alone.
    
    Also, the same result tree can be used for drill down too, which also
    currently parses the table output, therefore subject to the same
    limitation & fragility.
    
    Change-Id: Ib0147e2aa2b710dfd627df7f535a685301214a52

diff --git a/offapi/com/sun/star/sheet/XDataPilotResults.idl b/offapi/com/sun/star/sheet/XDataPilotResults.idl
index e5b2c3c..0e4486b 100644
--- a/offapi/com/sun/star/sheet/XDataPilotResults.idl
+++ b/offapi/com/sun/star/sheet/XDataPilotResults.idl
@@ -22,6 +22,7 @@
 
 #include <com/sun/star/uno/XInterface.idl>
 #include <com/sun/star/sheet/DataResult.idl>
+#include <com/sun/star/sheet/DataPilotFieldFilter.idl>
 
 
 module com {  module sun {  module star {  module sheet {
@@ -44,6 +45,8 @@ interface XDataPilotResults: com::sun::star::uno::XInterface
      */
     sequence< sequence< DataResult > > getResults();
 
+    sequence<any> getFilteredResults(
+        [in] sequence<com::sun::star::sheet::DataPilotFieldFilter> aFilters );
 };
 
 
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 5631f55..77e3e35 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -135,6 +135,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
 	sc/source/core/data/dpobject \
 	sc/source/core/data/dpoutput \
 	sc/source/core/data/dpoutputgeometry \
+	sc/source/core/data/dpresfilter \
 	sc/source/core/data/dpsave \
 	sc/source/core/data/dpsdbtab \
 	sc/source/core/data/dpshttab \
diff --git a/sc/inc/dpitemdata.hxx b/sc/inc/dpitemdata.hxx
index eeb79b7..84a5f92 100644
--- a/sc/inc/dpitemdata.hxx
+++ b/sc/inc/dpitemdata.hxx
@@ -62,6 +62,11 @@ public:
         sal_Int32 mnValue;
     };
 
+    struct Hash
+    {
+        size_t operator() (const ScDPItemData& rVal) const;
+    };
+
 private:
 
     union {
diff --git a/sc/inc/dpmacros.hxx b/sc/inc/dpmacros.hxx
index 79aafaf..ce91b06 100644
--- a/sc/inc/dpmacros.hxx
+++ b/sc/inc/dpmacros.hxx
@@ -29,7 +29,7 @@
 #ifndef __SC_DPMACROS_HXX__
 #define __SC_DPMACROS_HXX__
 
-#define DEBUG_PIVOT_TABLE 0
+#define DEBUG_PIVOT_TABLE 1
 
 #if DEBUG_PIVOT_TABLE
 #include <iostream>
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index c2c07f5..fd7c598 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -179,6 +179,11 @@ public:
                                        Rectangle& rPosRect, sal_uInt16& rOrient, long& rDimPos );
     bool                IsFilterButton( const ScAddress& rPos );
 
+    double GetPivotData(
+        const OUString& rDataFieldName,
+        const com::sun::star::uno::Sequence<
+            com::sun::star::sheet::DataPilotFieldFilter>& rFilters);
+
     bool                GetPivotData( ScDPGetPivotDataField& rTarget, /* returns result */
                                       const std::vector< ScDPGetPivotDataField >& rFilters );
     bool                ParseFilters( ScDPGetPivotDataField& rTarget,
diff --git a/sc/inc/dpresfilter.hxx b/sc/inc/dpresfilter.hxx
new file mode 100644
index 0000000..db32f6e
--- /dev/null
+++ b/sc/inc/dpresfilter.hxx
@@ -0,0 +1,115 @@
+/* -*- 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/.
+ */
+
+#ifndef __SC_DPRESFILTER_HXX__
+#define __SC_DPRESFILTER_HXX__
+
+#include "dpitemdata.hxx"
+
+#include <vector>
+#include <boost/noncopyable.hpp>
+
+#if DEBUG_PIVOT_TABLE
+#include <map>
+#else
+#include <boost/unordered_map.hpp>
+#endif
+
+struct ScDPResultFilter
+{
+    OUString maDimName;
+    ScDPItemData maValue;
+
+    bool mbHasValue:1;
+    bool mbDataLayout:1;
+
+    ScDPResultFilter(const OUString& rDimName, bool bDataLayout);
+};
+
+class ScDPResultFilterSet : boost::noncopyable
+{
+    struct MemberNode;
+    struct DimensionNode;
+#if DEBUG_PIVOT_TABLE
+    // To keep the entries sorted in the tree dump.
+    typedef std::map<ScDPItemData, MemberNode*> MembersType;
+    typedef std::map<OUString, DimensionNode*> DimensionsType;
+#else
+    typedef boost::unordered_map<ScDPItemData, MemberNode*, ScDPItemData::Hash> MembersType;
+    typedef boost::unordered_map<OUString, DimensionNode*, OUStringHash> DimensionsType;
+#endif
+    typedef std::vector<double> ValuesType;
+
+    struct DimensionNode : boost::noncopyable
+    {
+        const MemberNode* mpParent;
+        MembersType maChildMembers;
+
+        DimensionNode(const MemberNode* pParent);
+        ~DimensionNode();
+
+#if DEBUG_PIVOT_TABLE
+        void dump(int nLevel) const;
+#endif
+    };
+
+    struct MemberNode : boost::noncopyable
+    {
+        const DimensionNode* mpParent;
+        double mfValue;
+        ValuesType maValues;
+        DimensionsType maChildDimensions;
+
+        MemberNode(const DimensionNode* pParent);
+        ~MemberNode();
+
+#if DEBUG_PIVOT_TABLE
+        void dump(int nLevel) const;
+#endif
+    };
+
+    MemberNode* mpRoot;
+
+public:
+    ScDPResultFilterSet();
+    ~ScDPResultFilterSet();
+
+    /**
+     * Add a single value filter path.  The filters are expected to be sorted
+     * by row dimension order then by column dimension order.
+     *
+     * @param rFilter set of filters.
+     * @param nCol column position relative to the top-left cell within the
+     *             data field range.
+     * @param nRow row position relative to the top-left cell within the data
+     *             field range.
+     * @param fVal result value, as displayed in the table output.
+     */
+    void add(const std::vector<ScDPResultFilter>& rFilter, long nCol, long nRow, double fVal);
+
+    void swap(ScDPResultFilterSet& rOther);
+
+#if DEBUG_PIVOT_TABLE
+    void dump() const;
+#endif
+};
+
+struct ScDPResultFilterContext
+{
+    ScDPResultFilterSet maFilterSet;
+    std::vector<ScDPResultFilter> maFilters;
+    long mnCol;
+    long mnRow;
+
+    ScDPResultFilterContext();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/dptabres.hxx b/sc/inc/dptabres.hxx
index 96ebe53..e6289be 100644
--- a/sc/inc/dptabres.hxx
+++ b/sc/inc/dptabres.hxx
@@ -52,6 +52,7 @@ class ScDPResultVisibilityData;
 
 struct ScDPValue;
 class ScDPItemData;
+struct ScDPResultFilterContext;
 
 /**
  * Member names that are being processed for InitFrom/LateInitFrom (needed
@@ -403,11 +404,12 @@ public:
             com::sun::star::sheet::MemberResult>* pSequences,
         long& rPos, long nMeasure, bool bRoot, const OUString* pMemberName, const OUString* pMemberCaption );
 
-    void                FillDataResults( const ScDPResultMember* pRefMember,
-                                    com::sun::star::uno::Sequence<
-                                        com::sun::star::uno::Sequence<
-                                            com::sun::star::sheet::DataResult> >& rSequence,
-                                    long& rRow, long nMeasure ) const;
+    void FillDataResults(
+        const ScDPResultMember* pRefMember, ScDPResultFilterContext& rFilterCxt,
+        com::sun::star::uno::Sequence<
+            com::sun::star::uno::Sequence<
+                com::sun::star::sheet::DataResult> >& rSequence,
+        long nMeasure) const;
 
     void                UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const;
     void                UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure,
@@ -471,10 +473,12 @@ public:
     const ScDPAggData*  GetConstAggData( long nMeasure, const ScDPSubTotalState& rSubState ) const;
     ScDPAggData*        GetAggData( long nMeasure, const ScDPSubTotalState& rSubState );
 
-    void                FillDataRow( const ScDPResultMember* pRefMember,
-                                    com::sun::star::uno::Sequence<com::sun::star::sheet::DataResult>& rSequence,
-                                    long& rCol, long nMeasure, bool bIsSubTotalRow,
-                                    const ScDPSubTotalState& rSubState ) const;
+    void FillDataRow(
+        const ScDPResultMember* pRefMember,
+        ScDPResultFilterContext& rFilterCxt,
+        com::sun::star::uno::Sequence<com::sun::star::sheet::DataResult>& rSequence,
+        long nMeasure, bool bIsSubTotalRow,
+        const ScDPSubTotalState& rSubState) const;
 
     void UpdateDataRow( const ScDPResultMember* pRefMember, long nMeasure, bool bIsSubTotalRow,
                         const ScDPSubTotalState& rSubState );
@@ -557,11 +561,13 @@ public:
                                                 com::sun::star::sheet::MemberResult>* pSequences,
                                             long nStart, long nMeasure );
 
-    void                FillDataResults( const ScDPResultMember* pRefMember,
-                                    com::sun::star::uno::Sequence<
-                                        com::sun::star::uno::Sequence<
-                                            com::sun::star::sheet::DataResult> >& rSequence,
-                                    long nRow, long nMeasure ) const;
+    void FillDataResults(
+        const ScDPResultMember* pRefMember,
+        ScDPResultFilterContext& rFilterCxt,
+        com::sun::star::uno::Sequence<
+            com::sun::star::uno::Sequence<
+                com::sun::star::sheet::DataResult> >& rSequence,
+        long nMeasure) const;
 
     void                UpdateDataResults( const ScDPResultMember* pRefMember, long nMeasure ) const;
     void                UpdateRunningTotals( const ScDPResultMember* pRefMember, long nMeasure,
@@ -629,10 +635,11 @@ public:
     void                InitFrom( const ScDPResultDimension* pDim );        // recursive
     void                ProcessData( const ::std::vector< SCROW >& aDataMembers, const ::std::vector<ScDPValue>& aValues,
                                        const ScDPSubTotalState& rSubState );
-    void                FillDataRow( const ScDPResultDimension* pRefDim,
-                                    com::sun::star::uno::Sequence<com::sun::star::sheet::DataResult>& rSequence,
-                                    long nCol, long nMeasure, bool bIsSubTotalRow,
-                                    const ScDPSubTotalState& rSubState ) const;
+    void FillDataRow(
+        const ScDPResultDimension* pRefDim,
+        ScDPResultFilterContext& rFilterCxt,
+        com::sun::star::uno::Sequence<com::sun::star::sheet::DataResult>& rSequence,
+        long nMeasure, bool bIsSubTotalRow, const ScDPSubTotalState& rSubState) const;
 
     void                UpdateDataRow( const ScDPResultDimension* pRefDim, long nMeasure, bool bIsSubTotalRow,
                                     const ScDPSubTotalState& rSubState ) const;
diff --git a/sc/inc/dptabsrc.hxx b/sc/inc/dptabsrc.hxx
index e98b651..a51dd47 100644
--- a/sc/inc/dptabsrc.hxx
+++ b/sc/inc/dptabsrc.hxx
@@ -49,6 +49,7 @@
 
 #include "dptabdat.hxx"
 #include "dpglobal.hxx"
+#include "dpresfilter.hxx"
 
 #include <boost/unordered_map.hpp>
 #include <boost/unordered_set.hpp>
@@ -103,6 +104,7 @@ private:
     std::vector<long> maRowDims;
     std::vector<long> maDataDims;
     std::vector<long> maPageDims;
+    ScDPResultFilterSet maResFilterSet;
 
     bool                    bColumnGrand;
     bool                    bRowGrand;
@@ -199,6 +201,11 @@ public:
                             ::com::sun::star::sheet::DataResult > > SAL_CALL getResults(  )
                                 throw(::com::sun::star::uno::RuntimeException);
 
+    virtual com::sun::star::uno::Sequence<com::sun::star::uno::Any> SAL_CALL
+        getFilteredResults(
+            const com::sun::star::uno::Sequence<com::sun::star::sheet::DataPilotFieldFilter>& aFilters )
+                throw (com::sun::star::uno::RuntimeException);
+
                             // XRefreshable
     virtual void SAL_CALL   refresh() throw(::com::sun::star::uno::RuntimeException);
     virtual void SAL_CALL   addRefreshListener( const ::com::sun::star::uno::Reference<
diff --git a/sc/source/core/data/dpitemdata.cxx b/sc/source/core/data/dpitemdata.cxx
index a9147652..c417317f 100644
--- a/sc/source/core/data/dpitemdata.cxx
+++ b/sc/source/core/data/dpitemdata.cxx
@@ -29,6 +29,33 @@
 const sal_Int32 ScDPItemData::DateFirst = -1;
 const sal_Int32 ScDPItemData::DateLast  = 10000;
 
+size_t ScDPItemData::Hash::operator() (const ScDPItemData& rVal) const
+{
+    switch (rVal.GetType())
+    {
+        case GroupValue:
+        case Value:
+        case RangeStart:
+            return (size_t)(rVal.mfValue);
+        case String:
+        case Error:
+        {
+            if (!rVal.mpString)
+                return 0;
+
+            if (rVal.mbStringInterned)
+                return reinterpret_cast<size_t>(rVal.mpString);
+
+            OUStringHash aStrHasher;
+            return aStrHasher(*rVal.mpString);
+        }
+        default:
+            ;
+    }
+
+    return 0;
+}
+
 sal_Int32 ScDPItemData::Compare(const ScDPItemData& rA, const ScDPItemData& rB)
 {
     if (rA.meType != rB.meType)
@@ -337,10 +364,10 @@ OUString ScDPItemData::GetString() const
         case Error:
             return *mpString;
         case Value:
+        case RangeStart:
             return OUString::valueOf(mfValue);
         case GroupValue:
-        case RangeStart:
-            return OUString::createFromAscii("fail");
+            return OUString::valueOf(maGroupValue.mnValue);
         case Empty:
         default:
             ;
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 7033170..d04197e 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -1278,6 +1278,57 @@ void ScDPObject::GetHeaderPositionData(const ScAddress& rPos, DataPilotTableHead
         aPosData.PositionData >>= rData;
 }
 
+namespace {
+
+class FindByName : std::unary_function<const ScDPSaveDimension*, bool>
+{
+    OUString maName;
+public:
+    FindByName(const OUString& rName) : maName(rName) {}
+    bool operator() (const ScDPSaveDimension* pDim) const
+    {
+        const OUString* pLayoutName = pDim->GetLayoutName();
+        if (pLayoutName)
+            return *pLayoutName == maName;
+
+        return maName == pDim->GetName();
+    }
+};
+
+}
+
+double ScDPObject::GetPivotData(const OUString& rDataFieldName, const uno::Sequence<sheet::DataPilotFieldFilter>& rFilters)
+{
+    double fRet;
+    rtl::math::setNan(&fRet);
+    if (!mbEnableGetPivotData)
+        return fRet;
+
+    CreateObjects();
+
+    std::vector<const ScDPSaveDimension*> aDims;
+    pSaveData->GetAllDimensionsByOrientation(sheet::DataPilotFieldOrientation_DATA, aDims);
+    if (aDims.empty())
+        return fRet;
+
+    std::vector<const ScDPSaveDimension*>::iterator it = std::find_if(
+        aDims.begin(), aDims.end(), FindByName(rDataFieldName));
+    if (it == aDims.end())
+        return fRet;
+
+    sal_Int32 nDataIndex = std::distance(aDims.begin(), it);
+
+    uno::Reference<sheet::XDataPilotResults> xDPResults(xSource, uno::UNO_QUERY);
+    if (!xDPResults.is())
+        return fRet;
+
+    uno::Sequence<uno::Any> aRes = xDPResults->getFilteredResults(rFilters);
+
+    fRet = 54.0;
+
+    return fRet;
+}
+
 // Returns sal_True on success and stores the result in rTarget
 bool ScDPObject::GetPivotData( ScDPGetPivotDataField& rTarget,
                                const std::vector< ScDPGetPivotDataField >& rFilters )
diff --git a/sc/source/core/data/dpresfilter.cxx b/sc/source/core/data/dpresfilter.cxx
new file mode 100644
index 0000000..b08cc4a
--- /dev/null
+++ b/sc/source/core/data/dpresfilter.cxx
@@ -0,0 +1,157 @@
+/* -*- 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 "dpresfilter.hxx"
+
+using namespace std;
+
+ScDPResultFilter::ScDPResultFilter(const OUString& rDimName, bool bDataLayout) :
+    maDimName(rDimName), mbHasValue(false), mbDataLayout(bDataLayout) {}
+
+ScDPResultFilterContext::ScDPResultFilterContext() :
+    mnCol(0), mnRow(0) {}
+
+ScDPResultFilterSet::DimensionNode::DimensionNode(const MemberNode* pParent) :
+    mpParent(pParent) {}
+
+ScDPResultFilterSet::DimensionNode::~DimensionNode()
+{
+    MembersType::iterator it = maChildMembers.begin(), itEnd = maChildMembers.end();
+    for (; it != itEnd; ++it)
+        delete it->second;
+}
+
+#if DEBUG_PIVOT_TABLE
+void ScDPResultFilterSet::DimensionNode::dump(int nLevel) const
+{
+    string aIndent(nLevel*2, ' ');
+    MembersType::const_iterator it = maChildMembers.begin(), itEnd = maChildMembers.end();
+    for (; it != itEnd; ++it)
+    {
+        cout << aIndent << "member: ";
+        const ScDPItemData& rVal = it->first;
+        if (rVal.IsValue())
+            cout << rVal.GetValue();
+        else
+            cout << rVal.GetString();
+        cout << endl;
+
+        it->second->dump(nLevel+1);
+    }
+}
+#endif
+
+ScDPResultFilterSet::MemberNode::MemberNode(const DimensionNode* pParent) :
+    mpParent(pParent) {}
+
+ScDPResultFilterSet::MemberNode::~MemberNode()
+{
+    DimensionsType::iterator it = maChildDimensions.begin(), itEnd = maChildDimensions.end();
+    for (; it != itEnd; ++it)
+        delete it->second;
+}
+
+#if DEBUG_PIVOT_TABLE
+void ScDPResultFilterSet::MemberNode::dump(int nLevel) const
+{
+    string aIndent(nLevel*2, ' ');
+    ValuesType::const_iterator itVal = maValues.begin(), itValEnd = maValues.end();
+    for (; itVal != itValEnd; ++itVal)
+        cout << aIndent << "value: " << *itVal << endl;
+
+    DimensionsType::const_iterator it = maChildDimensions.begin(), itEnd = maChildDimensions.end();
+    for (; it != itEnd; ++it)
+    {
+        cout << aIndent << "dimension: " << it->first << endl;
+        it->second->dump(nLevel+1);
+    }
+}
+#endif
+
+ScDPResultFilterSet::ScDPResultFilterSet() : mpRoot(new MemberNode(NULL)) {}
+ScDPResultFilterSet::~ScDPResultFilterSet()
+{
+    delete mpRoot;
+}
+
+void ScDPResultFilterSet::add(
+    const std::vector<ScDPResultFilter>& rFilters, long nCol, long nRow, double fVal)
+{
+    // TODO: I'll work on the col / row to value node mapping later.
+
+    MemberNode* pMemNode = mpRoot;
+
+    fprintf(stdout, "(row=%ld; col=%ld; value=%g) : ", nRow, nCol, fVal);
+    std::vector<ScDPResultFilter>::const_iterator itFilter = rFilters.begin(), itFilterEnd = rFilters.end();
+    for (; itFilter != itFilterEnd; ++itFilter)
+    {
+        const ScDPResultFilter& filter = *itFilter;
+        if (filter.mbDataLayout)
+            continue;
+
+        printf("%s: ", rtl::OUStringToOString(filter.maDimName, RTL_TEXTENCODING_UTF8).getStr());
+        if (filter.maValue.IsValue())
+            printf("%g ", filter.maValue.GetValue());
+        else
+            printf("'%s' ", rtl::OUStringToOString(filter.maValue.GetString(), RTL_TEXTENCODING_UTF8).getStr());
+
+        // See if this dimension exists.
+        DimensionsType& rDims = pMemNode->maChildDimensions;
+        DimensionsType::iterator itDim = rDims.find(filter.maDimName);
+        if (itDim == rDims.end())
+        {
+            // New dimenison.  Insert it.
+            std::pair<DimensionsType::iterator, bool> r =
+                rDims.insert(DimensionsType::value_type(filter.maDimName, new DimensionNode(pMemNode)));
+
+            if (!r.second)
+                // Insertion failed!
+                return;
+
+            itDim = r.first;
+        }
+
+        // Now, see if this dimension member exists.
+        DimensionNode* pDim = itDim->second;
+        MembersType& rMembers = pDim->maChildMembers;
+        MembersType::iterator itMem = rMembers.find(filter.maValue);
+        if (itMem == rMembers.end())
+        {
+            // New member.  Insert it.
+            std::pair<MembersType::iterator, bool> r =
+                rMembers.insert(
+                    MembersType::value_type(filter.maValue, new MemberNode(pDim)));
+
+            if (!r.second)
+                // Insertion failed!
+                return;
+
+            itMem = r.first;
+        }
+
+        pMemNode = itMem->second;
+    }
+
+    pMemNode->maValues.push_back(fVal);
+    printf("\n");
+}
+
+void ScDPResultFilterSet::swap(ScDPResultFilterSet& rOther)
+{
+    std::swap<MemberNode*>(mpRoot, rOther.mpRoot);
+}
+
+#if DEBUG_PIVOT_TABLE
+void ScDPResultFilterSet::dump() const
+{
+    mpRoot->dump(0);
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx
index 322dc5f..379f5c1 100644
--- a/sc/source/core/data/dptabres.cxx
+++ b/sc/source/core/data/dptabres.cxx
@@ -29,6 +29,7 @@
 
 #include "document.hxx"     // for DumpState only!
 #include "stlalgorithm.hxx"
+#include "dpresfilter.hxx"
 
 #include <osl/diagnose.h>
 #include <rtl/math.hxx>
@@ -38,6 +39,7 @@
 #include <float.h>          //! Test !!!
 #include <algorithm>
 #include <boost/unordered_map.hpp>
+#include <boost/scoped_ptr.hpp>
 
 #include <com/sun/star/sheet/DataResultFlags.hpp>
 #include <com/sun/star/sheet/MemberResultFlags.hpp>
@@ -53,9 +55,51 @@ using ::std::vector;
 using ::std::pair;
 using ::com::sun::star::uno::Sequence;
 
-// -----------------------------------------------------------------------
+#include <stdio.h>
+#include <string>
+#include <sys/time.h>
+
+namespace {
 
-static sal_uInt16 nFuncStrIds[12] =     // passend zum enum ScSubTotalFunc
+class stack_printer
+{
+public:
+    explicit stack_printer(const char* msg) :
+        msMsg(msg)
+    {
+        fprintf(stdout, "%s: --begin\n", msMsg.c_str());
+        mfStartTime = getTime();
+    }
+
+    ~stack_printer()
+    {
+        double fEndTime = getTime();
+        fprintf(stdout, "%s: --end (duration: %g sec)\n", msMsg.c_str(), (fEndTime - mfStartTime));
+    }
+
+    void printTime(int line) const
+    {
+        double fEndTime = getTime();
+        fprintf(stdout, "%s: --(%d) (duration: %g sec)\n", msMsg.c_str(), line, (fEndTime - mfStartTime));
+    }
+
+private:
+    double getTime() const
+    {
+        timeval tv;
+        gettimeofday(&tv, NULL);
+        return tv.tv_sec + tv.tv_usec / 1000000.0;
+    }
+
+    ::std::string msMsg;
+    double mfStartTime;
+};
+
+}
+
+namespace {
+
+sal_uInt16 nFuncStrIds[12] =     // passend zum enum ScSubTotalFunc
 {
     0,                              // SUBTOTAL_FUNC_NONE
     STR_FUN_TEXT_AVG,               // SUBTOTAL_FUNC_AVE
@@ -70,35 +114,62 @@ static sal_uInt16 nFuncStrIds[12] =     // passend zum enum ScSubTotalFunc
     STR_FUN_TEXT_VAR,               // SUBTOTAL_FUNC_VAR
     STR_FUN_TEXT_VAR                // SUBTOTAL_FUNC_VARP
 };
-namespace {
 
-    bool lcl_SearchMember( const std::vector <ScDPResultMember *>& list, SCROW nOrder, SCROW& rIndex)
+bool lcl_SearchMember( const std::vector <ScDPResultMember *>& list, SCROW nOrder, SCROW& rIndex)
+{
+    rIndex = list.size();
+    bool bFound = false;
+    SCROW  nLo = 0;
+    SCROW nHi = list.size() - 1;
+    SCROW nIndex;
+    while (nLo <= nHi)
     {
-        rIndex = list.size();
-        bool bFound = false;
-        SCROW  nLo = 0;
-        SCROW nHi = list.size() - 1;
-        SCROW nIndex;
-        while (nLo <= nHi)
+        nIndex = (nLo + nHi) / 2;
+        if ( list[nIndex]->GetOrder() < nOrder )
+            nLo = nIndex + 1;
+        else
         {
-            nIndex = (nLo + nHi) / 2;
-            if ( list[nIndex]->GetOrder() < nOrder )
-                nLo = nIndex + 1;
-            else
+            nHi = nIndex - 1;
+            if ( list[nIndex]->GetOrder() == nOrder )
             {
-                nHi = nIndex - 1;
-                if ( list[nIndex]->GetOrder() == nOrder )
-                {
-                    bFound = true;
-                    nLo = nIndex;
-                }
+                bFound = true;
+                nLo = nIndex;
             }
         }
-        rIndex = nLo;
-        return bFound;
     }
+    rIndex = nLo;
+    return bFound;
+}
+
+class FilterStack
+{
+    std::vector<ScDPResultFilter>& mrFilters;
+public:
+    FilterStack(std::vector<ScDPResultFilter>& rFilters) : mrFilters(rFilters) {}
+
+    void pushDimName(const OUString& rName, bool bDataLayout)
+    {
+        mrFilters.push_back(ScDPResultFilter(rName, bDataLayout));
+    }
+
+    void pushDimValue(const ScDPItemData& rValue)
+    {
+        ScDPResultFilter& rFilter = mrFilters.back();
+        rFilter.maValue = rValue;
+        rFilter.mbHasValue = true;
+    }
+
+    ~FilterStack()
+    {
+        ScDPResultFilter& rFilter = mrFilters.back();
+        if (rFilter.mbHasValue)
+            rFilter.mbHasValue = false;
+        else
+            mrFilters.pop_back();
+    }
+};
+
 }
-// -----------------------------------------------------------------------
 
 //
 // function objects for sorting of the column and row members:
@@ -1497,14 +1568,26 @@ void ScDPResultMember::FillMemberResults(
     }
 }
 
-void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember,
-                            uno::Sequence< uno::Sequence<sheet::DataResult> >& rSequence,
-                            long& rRow, long nMeasure ) const
+void ScDPResultMember::FillDataResults(
+    const ScDPResultMember* pRefMember,
+    ScDPResultFilterContext& rFilterCxt, uno::Sequence<uno::Sequence<sheet::DataResult> >& rSequence,
+    long nMeasure) const
 {
+    boost::scoped_ptr<FilterStack> pFilterStack;
+    const ScDPMember* pDPMember = GetDPMember();
+    if (pDPMember)
+    {
+        // Root result has no corresponding DP member. Only take the non-root results.
+        ScDPItemData aItem;
+        pDPMember->FillItemData(aItem);
+        pFilterStack.reset(new FilterStack(rFilterCxt.maFilters));
+        pFilterStack->pushDimValue(aItem);
+    }
+
     //  IsVisible() test is in ScDPResultDimension::FillDataResults
     //  (not on data layout dimension)
     const ScDPLevel*     pParentLevel = GetParentLevel();
-    long nStartRow = rRow;
+    long nStartRow = rFilterCxt.mnRow;
 
     long nExtraSpace = 0;
     if ( pParentLevel && pParentLevel->IsAddEmpty() )
@@ -1520,13 +1603,16 @@ void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember,
     if (bHasChild)
     {
         if ( bTitleLine )           // in tabular layout the title is on a separate row
-            ++rRow;                 // -> fill child dimension one row below
+            ++rFilterCxt.mnRow;                 // -> fill child dimension one row below
 
-        pChildDimension->FillDataResults( pRefMember, rSequence, rRow, nMeasure );  // doesn't modify rRow
-        rRow += GetSize( nMeasure );
+        long nOldRow = rFilterCxt.mnRow;
+        pChildDimension->FillDataResults(pRefMember, rFilterCxt, rSequence, nMeasure);
+        rFilterCxt.mnRow = nOldRow; // Revert to the original row before the call.
+
+        rFilterCxt.mnRow += GetSize( nMeasure );
 
         if ( bTitleLine )           // title row is included in GetSize, so the following
-            --rRow;                 // positions are calculated with the normal values
+            --rFilterCxt.mnRow;                 // positions are calculated with the normal values
     }
 
     long nUserSubStart;
@@ -1545,15 +1631,15 @@ void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember,
         long nSubSize = pResultData->GetCountForMeasure(nMeasure);
         if (bHasChild)
         {
-            rRow -= nSubSize * ( nUserSubCount - nUserSubStart );   // GetSize includes space for SubTotal
-            rRow -= nExtraSpace;                                    // GetSize includes the empty line
+            rFilterCxt.mnRow -= nSubSize * ( nUserSubCount - nUserSubStart );   // GetSize includes space for SubTotal
+            rFilterCxt.mnRow -= nExtraSpace;                                    // GetSize includes the empty line
         }
 
         long nMoveSubTotal = 0;
         if ( bSubTotalInTitle )
         {
-            nMoveSubTotal = rRow - nStartRow;   // force to first (title) row
-            rRow = nStartRow;
+            nMoveSubTotal = rFilterCxt.mnRow - nStartRow;   // force to first (title) row
+            rFilterCxt.mnRow = nStartRow;
         }
 
         if ( pDataRoot )
@@ -1575,24 +1661,23 @@ void ScDPResultMember::FillDataResults( const ScDPResultMember* pRefMember,
                     else if ( pResultData->GetColStartMeasure() == SC_DPMEASURE_ALL )
                         nMemberMeasure = SC_DPMEASURE_ALL;
 
-                    OSL_ENSURE( rRow < rSequence.getLength(), "bumm" );
-                    uno::Sequence<sheet::DataResult>& rSubSeq = rSequence.getArray()[rRow];
-                    long nSeqCol = 0;
+                    OSL_ENSURE( rFilterCxt.mnRow < rSequence.getLength(), "bumm" );
+                    uno::Sequence<sheet::DataResult>& rSubSeq = rSequence.getArray()[rFilterCxt.mnRow];
+                    rFilterCxt.mnCol = 0;
                     if (pRefMember->IsVisible())
-                        pDataRoot->FillDataRow(pRefMember, rSubSeq, nSeqCol, nMemberMeasure, bHasChild, aSubState);
+                        pDataRoot->FillDataRow(pRefMember, rFilterCxt, rSubSeq, nMemberMeasure, bHasChild, aSubState);
 
-                    rRow += 1;
+                    rFilterCxt.mnRow += 1;
                 }
             }
         }
         else
-            rRow += nSubSize * ( nUserSubCount - nUserSubStart );   // empty rows occur when ShowEmpty is true
+            rFilterCxt.mnRow += nSubSize * ( nUserSubCount - nUserSubStart );   // empty rows occur when ShowEmpty is true
 
         // add extra space again if subtracted from GetSize above,
         // add to own size if no children
-        rRow += nExtraSpace;
-
-        rRow += nMoveSubTotal;
+        rFilterCxt.mnRow += nExtraSpace;
+        rFilterCxt.mnRow += nMoveSubTotal;
     }
 }
 
@@ -1990,14 +2075,28 @@ const ScDPAggData* ScDPDataMember::GetConstAggData( long nMeasure, const ScDPSub
     return pAgg;
 }
 
-void ScDPDataMember::FillDataRow( const ScDPResultMember* pRefMember,
-                                    uno::Sequence<sheet::DataResult>& rSequence,
-                                    long& rCol, long nMeasure, bool bIsSubTotalRow,
-                                    const ScDPSubTotalState& rSubState ) const
+void ScDPDataMember::FillDataRow(
+    const ScDPResultMember* pRefMember, ScDPResultFilterContext& rFilterCxt,
+    uno::Sequence<sheet::DataResult>& rSequence, long nMeasure, bool bIsSubTotalRow,
+    const ScDPSubTotalState& rSubState) const
 {
+    boost::scoped_ptr<FilterStack> pFilterStack;
+    if (pResultMember)
+    {
+        // Topmost data member (pResultMember=NULL) doesn't need to be handled
+        // since its immediate parent result member is linked to the same
+        // dimension member.
+        ScDPItemData aItem;
+        const ScDPMember* pDPMember = pResultMember->GetDPMember();
+        if (pDPMember)
+            pDPMember->FillItemData(aItem);
+        pFilterStack.reset(new FilterStack(rFilterCxt.maFilters));
+        pFilterStack->pushDimValue(aItem);
+    }
+
     OSL_ENSURE( pRefMember == pResultMember || !pResultMember, "bla" );
 
-    long nStartCol = rCol;
+    long nStartCol = rFilterCxt.mnCol;
 
     const ScDPDataDimension* pDataChild = GetChildDimension();
     const ScDPResultDimension* pRefChild = pRefMember->GetChildDimension();
@@ -2021,14 +2120,18 @@ void ScDPDataMember::FillDataRow( const ScDPResultMember* pRefMember,
     if ( bHasChild )
     {
         if ( bTitleLine )           // in tabular layout the title is on a separate column
-            ++rCol;                 // -> fill child dimension one column below
+            ++rFilterCxt.mnCol;                 // -> fill child dimension one column below
 
         if ( pDataChild )
-            pDataChild->FillDataRow( pRefChild, rSequence, rCol, nMeasure, bIsSubTotalRow, rSubState );
-        rCol += (sal_uInt16)pRefMember->GetSize( nMeasure );
+        {
+            long nOldCol = rFilterCxt.mnCol;
+            pDataChild->FillDataRow(pRefChild, rFilterCxt, rSequence, nMeasure, bIsSubTotalRow, rSubState);
+            rFilterCxt.mnCol = nOldCol; // Revert to the old column value before the call.
+        }
+        rFilterCxt.mnCol += (sal_uInt16)pRefMember->GetSize( nMeasure );
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list