[Libreoffice-commits] core.git: 2 commits - include/oox sc/inc sc/Library_scfilt.mk sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Thu Aug 28 18:37:47 PDT 2014


 include/oox/core/relations.hxx        |    3 
 sc/Library_scfilt.mk                  |    1 
 sc/inc/document.hxx                   |    4 
 sc/inc/dpcache.hxx                    |   21 -
 sc/inc/dpobject.hxx                   |   18 
 sc/inc/dpoutput.hxx                   |    3 
 sc/source/core/data/documen3.cxx      |    5 
 sc/source/core/data/dpcache.cxx       |   28 +
 sc/source/core/data/dpobject.cxx      |   69 +++
 sc/source/core/data/dpoutput.cxx      |   21 +
 sc/source/filter/excel/excdoc.cxx     |   20 -
 sc/source/filter/excel/xepivotxml.cxx |  641 ++++++++++++++++++++++++++++++++++
 sc/source/filter/excel/xeroot.cxx     |    9 
 sc/source/filter/inc/xepivotxml.hxx   |   95 +++++
 sc/source/filter/inc/xeroot.hxx       |    5 
 15 files changed, 920 insertions(+), 23 deletions(-)

New commits:
commit f5aeaa3845ae794a6320f082b1354f946d96cec1
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Fri Aug 22 22:57:05 2014 -0400

    bnc#822173: Initial work on exporting pivot cache and pivot table to xlsx.
    
    Still not perfect, but it somewhat does work.
    
    Change-Id: Ic248e20f7ab18a37f56b2034f57551dded956bab

diff --git a/include/oox/core/relations.hxx b/include/oox/core/relations.hxx
index bbe2968..38a99c8 100644
--- a/include/oox/core/relations.hxx
+++ b/include/oox/core/relations.hxx
@@ -50,7 +50,8 @@ namespace core {
 #define CREATE_MSOFFICE_RELATION_TYPE( ascii ) \
     ( "http://schemas.microsoft.com/office/2006/relationships/" ascii )
 
-
+#define CREATE_XL_CONTENT_TYPE( ascii ) \
+    ( "application/vnd.openxmlformats-officedocument.spreadsheetml." ascii "+xml" )
 
 struct Relation
 {
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index f01e317..00d32da 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -96,6 +96,7 @@ $(eval $(call gb_Library_add_exception_objects,scfilt,\
 	sc/source/filter/excel/xename \
 	sc/source/filter/excel/xepage \
 	sc/source/filter/excel/xepivot \
+	sc/source/filter/excel/xepivotxml \
 	sc/source/filter/excel/xerecord \
 	sc/source/filter/excel/xeroot \
 	sc/source/filter/excel/xestream \
diff --git a/sc/inc/dpcache.hxx b/sc/inc/dpcache.hxx
index 6324243..ecb3514 100644
--- a/sc/inc/dpcache.hxx
+++ b/sc/inc/dpcache.hxx
@@ -156,6 +156,7 @@ public:
     long GetDimMemberCount(long nDim) const;
     SCROW GetOrder( long nDim, SCROW nIndex ) const;
 
+    const IndexArrayType* GetFieldIndexArray( size_t nDim ) const;
     const ItemsType& GetDimMemberValues( SCCOL nDim ) const;
     bool InitFromDoc(ScDocument* pDoc, const ScRange& rRange);
     bool InitFromDataBase(DBConnector& rDB);
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 1ff7024..46e2000 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -132,6 +132,7 @@ public:
     ScRange             GetNewOutputRange( bool& rOverflow );
 
     ScRange GetOutputRangeByType( sal_Int32 nType );
+    ScRange GetOutputRangeByType( sal_Int32 nType ) const;
 
     void                SetSaveData(const ScDPSaveData& rData);
     ScDPSaveData*       GetSaveData() const     { return pSaveData; }
@@ -287,9 +288,12 @@ public:
             UpdateRefMode eMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz);
 
         SC_DLLPUBLIC ScDPCache* getExistingCache(const ScRange& rRange);
+        SC_DLLPUBLIC const ScDPCache* getExistingCache(const ScRange& rRange) const;
 
         void updateCache(const ScRange& rRange, std::set<ScDPObject*>& rRefs);
         bool remove(const ScDPCache* p);
+
+        SC_DLLPUBLIC const std::vector<ScRange>& getAllRanges() const;
     };
 
     /**
diff --git a/sc/inc/dpoutput.hxx b/sc/inc/dpoutput.hxx
index 2127d37..440f097 100644
--- a/sc/inc/dpoutput.hxx
+++ b/sc/inc/dpoutput.hxx
@@ -112,7 +112,8 @@ public:
     void            SetPosition( const ScAddress& rPos );
 
     void            Output();           //! Refresh?
-    ScRange         GetOutputRange( sal_Int32 nRegionType = ::com::sun::star::sheet::DataPilotOutputRangeType::WHOLE );
+    ScRange GetOutputRange( sal_Int32 nRegionType = ::com::sun::star::sheet::DataPilotOutputRangeType::WHOLE );
+    ScRange GetOutputRange( sal_Int32 nRegionType = ::com::sun::star::sheet::DataPilotOutputRangeType::WHOLE ) const;
     long            GetHeaderRows();
     bool            HasError();         // range overflow or exception from source
 
diff --git a/sc/source/core/data/dpcache.cxx b/sc/source/core/data/dpcache.cxx
index e9687c5..2dc66d3 100644
--- a/sc/source/core/data/dpcache.cxx
+++ b/sc/source/core/data/dpcache.cxx
@@ -850,6 +850,14 @@ SCROW ScDPCache::GetDataSize() const
     return mnDataSize >= 0 ? mnDataSize : 0;
 }
 
+const ScDPCache::IndexArrayType* ScDPCache::GetFieldIndexArray( size_t nDim ) const
+{
+    if (nDim >= maFields.size())
+        return NULL;
+
+    return &maFields[nDim].maData;
+}
+
 const ScDPCache::ItemsType& ScDPCache::GetDimMemberValues(SCCOL nDim) const
 {
     OSL_ENSURE( nDim>=0 && nDim < mnColumnCount ," nDim < mnColumnCount ");
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 4587209..387747c 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -936,6 +936,14 @@ ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType )
     return pOutput->GetOutputRange(nType);
 }
 
+ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType ) const
+{
+    if (!pOutput || pOutput->HasError())
+        return ScRange(ScAddress::INITIALIZE_INVALID);
+
+    return pOutput->GetOutputRange(nType);
+}
+
 static bool lcl_HasButton( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
 {
     return ((const ScMergeFlagAttr*)pDoc->GetAttr( nCol, nRow, nTab, ATTR_MERGE_FLAG ))->HasPivotButton();
@@ -2905,6 +2913,25 @@ ScDPCache* ScDPCollection::SheetCaches::getExistingCache(const ScRange& rRange)
     return itCache->second;
 }
 
+const ScDPCache* ScDPCollection::SheetCaches::getExistingCache(const ScRange& rRange) const
+{
+    RangeIndexType::const_iterator it = std::find(maRanges.begin(), maRanges.end(), rRange);
+    if (it == maRanges.end())
+        // Not cached.
+        return NULL;
+
+    // Already cached.
+    size_t nIndex = std::distance(maRanges.begin(), it);
+    CachesType::const_iterator itCache = maCaches.find(nIndex);
+    if (itCache == maCaches.end())
+    {
+        OSL_FAIL("Cache pool and index pool out-of-sync !!!");
+        return NULL;
+    }
+
+    return itCache->second;
+}
+
 size_t ScDPCollection::SheetCaches::size() const
 {
     return maCaches.size();
@@ -2990,6 +3017,11 @@ bool ScDPCollection::SheetCaches::remove(const ScDPCache* p)
     return false;
 }
 
+const std::vector<ScRange>& ScDPCollection::SheetCaches::getAllRanges() const
+{
+    return maRanges;
+}
+
 ScDPCollection::NameCaches::NameCaches(ScDocument* pDoc) : mpDoc(pDoc) {}
 
 bool ScDPCollection::NameCaches::hasCache(const OUString& rName) const
diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx
index a23110b..eb51035 100644
--- a/sc/source/core/data/dpoutput.cxx
+++ b/sc/source/core/data/dpoutput.cxx
@@ -1166,6 +1166,27 @@ ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType )
     return ScRange(aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
 }
 
+ScRange ScDPOutput::GetOutputRange( sal_Int32 nRegionType ) const
+{
+    using namespace ::com::sun::star::sheet;
+
+    if (!bSizesValid)
+        return ScRange(ScAddress::INITIALIZE_INVALID);
+
+    SCTAB nTab = aStartPos.Tab();
+    switch (nRegionType)
+    {
+        case DataPilotOutputRangeType::RESULT:
+            return ScRange(nDataStartCol, nDataStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
+        case DataPilotOutputRangeType::TABLE:
+            return ScRange(aStartPos.Col(), nTabStartRow, nTab, nTabEndCol, nTabEndRow, nTab);
+        default:
+            OSL_ENSURE(nRegionType == DataPilotOutputRangeType::WHOLE, "ScDPOutput::GetOutputRange: unknown region type");
+        break;
+    }
+    return ScRange(aStartPos.Col(), aStartPos.Row(), nTab, nTabEndCol, nTabEndRow, nTab);
+}
+
 bool ScDPOutput::HasError()
 {
     CalcSizes();
diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx
index 5cb48d2..488f3cc 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -68,6 +68,7 @@
 #include "xeescher.hxx"
 #include "xepivot.hxx"
 #include "XclExpChangeTrack.hxx"
+#include <xepivotxml.hxx>
 
 #include <math.h>
 
@@ -405,10 +406,6 @@ void ExcTable::FillAsHeaderXml( ExcBoundsheetList& rBoundsheetList )
     // Formatting: FONT, FORMAT, XF, STYLE, PALETTE
     aRecList.AppendNewRecord( new XclExpXmlStyleSheet( *this ) );
 
-    // Pivot Cache
-    GetPivotTableManager().CreatePivotTables();
-    aRecList.AppendRecord( GetPivotTableManager().CreatePivotCachesRecord() );
-
     // Change tracking
     if( rDoc.GetChangeTrack() )
     {
@@ -641,10 +638,6 @@ void ExcTable::FillAsTableXml()
     // cell table: DEFCOLWIDTH, COLINFO, DIMENSIONS, ROW, cell records
     aRecList.AppendRecord( mxCellTable );
 
-    // pivot tables
-    // not in the worksheet file
-    aRecList.AppendRecord( GetPivotTableManager().CreatePivotTablesRecord( mnScTab ) );
-
     // list of NOTE records, generated by the cell table
     // not in the worksheet file
     if( mxNoteList != 0 && !mxNoteList->IsEmpty() )
@@ -742,6 +735,10 @@ void ExcTable::WriteXml( XclExpXmlStream& rStrm )
         mxCellTable->Finalize();
     aRecList.SaveXml( rStrm );
 
+    XclExpXmlPivotTables* pPT = GetXmlPivotTableManager().GetTablesBySheet(mnScTab);
+    if (pPT)
+        pPT->SaveXml(rStrm);
+
     rStrm.GetCurrentStream()->endElement( XML_worksheet );
     rStrm.PopStream();
 }
@@ -766,7 +763,10 @@ void ExcDocument::ReadDoc( void )
     if (GetOutput() == EXC_OUTPUT_BINARY)
         aHeader.FillAsHeaderBinary(maBoundsheetList);
     else
+    {
         aHeader.FillAsHeaderXml(maBoundsheetList);
+        GetXmlPivotTableManager().Initialize();
+    }
 
     SCTAB nScTab = 0, nScTabCount = GetTabInfo().GetScTabCount();
     SCTAB nCodeNameIdx = 0, nCodeNameCount = GetExtDocOptions().GetCodeNameCount();
@@ -873,6 +873,10 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm )
     if( pExpChangeTrack )
         pExpChangeTrack->WriteXml( rStrm );
 
+    XclExpXmlPivotCaches& rCaches = GetXmlPivotTableManager().GetCaches();
+    if (rCaches.HasCaches())
+        rCaches.SaveXml(rStrm);
+
     rWorkbook->endElement( XML_workbook );
     rWorkbook.reset();
 
diff --git a/sc/source/filter/excel/xepivotxml.cxx b/sc/source/filter/excel/xepivotxml.cxx
new file mode 100644
index 0000000..cef5a85
--- /dev/null
+++ b/sc/source/filter/excel/xepivotxml.cxx
@@ -0,0 +1,641 @@
+/* -*- 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 <xepivotxml.hxx>
+#include <dpcache.hxx>
+#include <dpobject.hxx>
+#include <dpsave.hxx>
+#include <dputil.hxx>
+#include <document.hxx>
+
+#include <oox/export/utils.hxx>
+
+#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
+#include <com/sun/star/sheet/DataPilotOutputRangeType.hpp>
+
+#include <vector>
+
+using namespace oox;
+using namespace com::sun::star;
+
+namespace {
+
+void savePivotCacheRecordsXml( XclExpXmlStream& rStrm, const ScDPCache& rCache )
+{
+    SCROW nCount = rCache.GetDataSize();
+    size_t nFieldCount = rCache.GetFieldCount();
+
+    sax_fastparser::FSHelperPtr& pRecStrm = rStrm.GetCurrentStream();
+    pRecStrm->startElement(XML_pivotCacheRecords,
+        XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+        FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+        XML_count, OString::number(static_cast<long>(nCount)).getStr(),
+        FSEND);
+
+    for (SCROW i = 0; i < nCount; ++i)
+    {
+        pRecStrm->startElement(XML_r, FSEND);
+        for (size_t nField = 0; nField < nFieldCount; ++nField)
+        {
+            const ScDPCache::IndexArrayType* pArray = rCache.GetFieldIndexArray(nField);
+            assert(pArray);
+            assert(static_cast<size_t>(i) < pArray->size());
+            pRecStrm->singleElement(XML_x, XML_v, OString::number((*pArray)[i]), FSEND);
+        }
+        pRecStrm->endElement(XML_r);
+    }
+
+    pRecStrm->endElement(XML_pivotCacheRecords);
+}
+
+const char* toOOXMLAxisType( sheet::DataPilotFieldOrientation eOrient )
+{
+    switch (eOrient)
+    {
+        case sheet::DataPilotFieldOrientation_COLUMN:
+            return "axisCol";
+        case sheet::DataPilotFieldOrientation_ROW:
+            return "axisRow";
+        case sheet::DataPilotFieldOrientation_PAGE:
+            return "axisPage";
+        case sheet::DataPilotFieldOrientation_DATA:
+            return "axisValues";
+        case sheet::DataPilotFieldOrientation_HIDDEN:
+        default:
+            ;
+    }
+
+    return "";
+}
+
+}
+
+XclExpXmlPivotCaches::XclExpXmlPivotCaches( const XclExpRoot& rRoot ) :
+    XclExpRoot(rRoot) {}
+
+void XclExpXmlPivotCaches::SaveXml( XclExpXmlStream& rStrm )
+{
+    sax_fastparser::FSHelperPtr& pWorkbookStrm = rStrm.GetCurrentStream();
+    pWorkbookStrm->startElement(XML_pivotCaches, FSEND);
+
+    for (size_t i = 0, n = maCaches.size(); i < n; ++i)
+    {
+        const Entry& rEntry = maCaches[i];
+
+        sal_Int32 nCacheId = i + 1;
+        OUString aRelId;
+        sax_fastparser::FSHelperPtr pPCStrm = rStrm.CreateOutputStream(
+            XclXmlUtils::GetStreamName("xl/pivotCache/", "pivotCacheDefinition", nCacheId),
+            XclXmlUtils::GetStreamName(NULL, "pivotCache/pivotCacheDefinition", nCacheId),
+            rStrm.GetCurrentStream()->getOutputStream(),
+            CREATE_XL_CONTENT_TYPE("pivotCacheDefinition"),
+            CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheDefinition"),
+            &aRelId);
+
+        pWorkbookStrm->singleElement(XML_pivotCache,
+            XML_cacheId, OString::number(nCacheId).getStr(),
+            FSNS(XML_r, XML_id), XclXmlUtils::ToOString(aRelId).getStr(),
+            FSEND);
+
+        rStrm.PushStream(pPCStrm);
+        SavePivotCacheXml(rStrm, rEntry, nCacheId);
+        rStrm.PopStream();
+    }
+
+    pWorkbookStrm->endElement(XML_pivotCaches);
+}
+
+void XclExpXmlPivotCaches::SetCaches( const std::vector<Entry>& rCaches )
+{
+    maCaches = rCaches;
+}
+
+bool XclExpXmlPivotCaches::HasCaches() const
+{
+    return !maCaches.empty();
+}
+
+const XclExpXmlPivotCaches::Entry* XclExpXmlPivotCaches::GetCache( sal_Int32 nCacheId ) const
+{
+    if (nCacheId <= 0)
+        // cache ID is 1-based.
+        return NULL;
+
+    size_t nPos = nCacheId - 1;
+    if (nPos >= maCaches.size())
+        return NULL;
+
+    return &maCaches[nPos];
+}
+
+void XclExpXmlPivotCaches::SavePivotCacheXml( XclExpXmlStream& rStrm, const Entry& rEntry, sal_Int32 nCounter )
+{
+    assert(rEntry.mpCache);
+    const ScDPCache& rCache = *rEntry.mpCache;
+
+    sax_fastparser::FSHelperPtr& pDefStrm = rStrm.GetCurrentStream();
+
+    OUString aRelId;
+    sax_fastparser::FSHelperPtr pRecStrm = rStrm.CreateOutputStream(
+        XclXmlUtils::GetStreamName("xl/pivotCache/", "pivotCacheRecords", nCounter),
+        XclXmlUtils::GetStreamName(NULL, "pivotCacheRecords", nCounter),
+        pDefStrm->getOutputStream(),
+        CREATE_XL_CONTENT_TYPE("pivotCacheRecords"),
+        CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheRecords"),
+        &aRelId);
+
+    rStrm.PushStream(pRecStrm);
+    savePivotCacheRecordsXml(rStrm, rCache);
+    rStrm.PopStream();
+
+    pDefStrm->startElement(XML_pivotCacheDefinition,
+        XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+        FSNS(XML_xmlns, XML_r), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+        FSNS(XML_r, XML_id), XclXmlUtils::ToOString(aRelId).getStr(),
+        XML_recordCount, OString::number(rEntry.mpCache->GetDataSize()).getStr(),
+        FSEND);
+
+    if (rEntry.meType == Worksheet)
+    {
+        pDefStrm->startElement(XML_cacheSource,
+            XML_type, "worksheet",
+            FSEND);
+
+        OUString aSheetName;
+        GetDoc().GetName(rEntry.maSrcRange.aStart.Tab(), aSheetName);
+        pDefStrm->singleElement(XML_worksheetSource,
+            XML_ref, XclXmlUtils::ToOString(rEntry.maSrcRange).getStr(),
+            XML_sheet, XclXmlUtils::ToOString(aSheetName).getStr(),
+            FSEND);
+
+        pDefStrm->endElement(XML_cacheSource);
+    }
+
+    size_t nCount = rCache.GetFieldCount();
+    pDefStrm->startElement(XML_cacheFields,
+        XML_count, OString::number(static_cast<long>(nCount)).getStr(),
+        FSEND);
+
+    for (size_t i = 0; i < nCount; ++i)
+    {
+        OUString aName = rCache.GetDimensionName(i);
+
+        pDefStrm->startElement(XML_cacheField,
+            XML_name, XclXmlUtils::ToOString(aName).getStr(),
+            XML_numFmtId, OString::number(0).getStr(),
+            FSEND);
+
+        const ScDPCache::ItemsType& rFieldItems = rCache.GetDimMemberValues(i);
+
+        pDefStrm->startElement(XML_sharedItems,
+            XML_count, OString::number(static_cast<long>(rFieldItems.size())).getStr(),
+            FSEND);
+
+        ScDPCache::ItemsType::const_iterator it = rFieldItems.begin(), itEnd = rFieldItems.end();
+        for (; it != itEnd; ++it)
+        {
+            const ScDPItemData& rItem = *it;
+            switch (rItem.GetType())
+            {
+                case ScDPItemData::String:
+                    pDefStrm->singleElement(XML_s,
+                        XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(),
+                        FSEND);
+                break;
+                case ScDPItemData::Value:
+                    pDefStrm->singleElement(XML_n,
+                        XML_v, OString::number(rItem.GetValue()).getStr(),
+                        FSEND);
+                break;
+                case ScDPItemData::Empty:
+                    pDefStrm->singleElement(XML_m, FSEND);
+                break;
+                case ScDPItemData::Error:
+                    pDefStrm->singleElement(XML_e,
+                        XML_v, XclXmlUtils::ToOString(rItem.GetString()).getStr(),
+                        FSEND);
+                break;
+                case ScDPItemData::GroupValue:
+                case ScDPItemData::RangeStart:
+                    // TODO : What do we do with these types?
+                    pDefStrm->singleElement(XML_m, FSEND);
+                break;
+                default:
+                    ;
+            }
+        }
+
+        pDefStrm->endElement(XML_sharedItems);
+        pDefStrm->endElement(XML_cacheField);
+    }
+
+    pDefStrm->endElement(XML_cacheFields);
+
+    pDefStrm->endElement(XML_pivotCacheDefinition);
+}
+
+XclExpXmlPivotTableManager::XclExpXmlPivotTableManager( const XclExpRoot& rRoot ) :
+    XclExpRoot(rRoot), maCaches(rRoot) {}
+
+void XclExpXmlPivotTableManager::Initialize()
+{
+    const ScDocument& rDoc = GetDoc();
+    if (!rDoc.HasPivotTable())
+        // No pivot table to export.
+        return;
+
+    const ScDPCollection* pDPColl = rDoc.GetDPCollection();
+    if (!pDPColl)
+        return;
+
+    // Go through the caches first.
+
+    std::vector<XclExpXmlPivotCaches::Entry> aCaches;
+    const ScDPCollection::SheetCaches& rSheetCaches = pDPColl->GetSheetCaches();
+    const std::vector<ScRange>& rRanges = rSheetCaches.getAllRanges();
+    for (size_t i = 0, n = rRanges.size(); i < n; ++i)
+    {
+        const ScDPCache* pCache = rSheetCaches.getExistingCache(rRanges[i]);
+        if (!pCache)
+            continue;
+
+        // Get all pivot objects that reference this cache, and set up an
+        // object to cache ID mapping.
+        const ScDPCache::ObjectSetType& rRefs = pCache->GetAllReferences();
+        ScDPCache::ObjectSetType::const_iterator it = rRefs.begin(), itEnd = rRefs.end();
+        for (; it != itEnd; ++it)
+            maCacheIdMap.insert(CacheIdMapType::value_type(*it, aCaches.size()+1));
+
+        XclExpXmlPivotCaches::Entry aEntry;
+        aEntry.meType = XclExpXmlPivotCaches::Worksheet;
+        aEntry.mpCache = pCache;
+        aEntry.maSrcRange = rRanges[i];
+        aCaches.push_back(aEntry); // Cache ID equals position + 1.
+    }
+
+    // TODO : Handle name and database caches as well.
+
+    for (size_t i = 0, n = pDPColl->GetCount(); i < n; ++i)
+    {
+        const ScDPObject* pDPObj = (*pDPColl)[i];
+        assert(pDPObj); // We don't store NULL here.
+
+        // Get the cache ID for this pivot table.
+        CacheIdMapType::iterator itCache = maCacheIdMap.find(pDPObj);
+        if (itCache == maCacheIdMap.end())
+            // No cache ID found.  Something is wrong here....
+            continue;
+
+        sal_Int32 nCacheId = itCache->second;
+        SCTAB nTab = pDPObj->GetOutRange().aStart.Tab();
+
+        TablesType::iterator it = maTables.find(nTab);
+        if (it == maTables.end())
+        {
+            // Insert a new instance for this sheet index.
+            std::pair<TablesType::iterator, bool> r =
+                maTables.insert(nTab, new XclExpXmlPivotTables(GetRoot(), maCaches));
+            it = r.first;
+        }
+
+        XclExpXmlPivotTables* p = it->second;
+        p->AppendTable(pDPObj, nCacheId, i+1);
+    }
+
+    maCaches.SetCaches(aCaches);
+}
+
+XclExpXmlPivotCaches& XclExpXmlPivotTableManager::GetCaches()
+{
+    return maCaches;
+}
+
+XclExpXmlPivotTables* XclExpXmlPivotTableManager::GetTablesBySheet( SCTAB nTab )
+{
+    TablesType::iterator it = maTables.find(nTab);
+    return it == maTables.end() ? NULL : it->second;
+}
+
+XclExpXmlPivotTables::Entry::Entry( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId ) :
+    mpTable(pTable), mnCacheId(nCacheId), mnPivotId(nPivotId) {}
+
+XclExpXmlPivotTables::XclExpXmlPivotTables( const XclExpRoot& rRoot, const XclExpXmlPivotCaches& rCaches ) :
+    XclExpRoot(rRoot), mrCaches(rCaches) {}
+
+void XclExpXmlPivotTables::SaveXml( XclExpXmlStream& rStrm )
+{
+    sax_fastparser::FSHelperPtr& pWSStrm = rStrm.GetCurrentStream(); // worksheet stream
+
+    sal_Int32 nCounter = 1; // 1-based
+    TablesType::iterator it = maTables.begin(), itEnd = maTables.end();
+    for (; it != itEnd; ++it, ++nCounter)
+    {
+        const ScDPObject& rObj = *it->mpTable;
+        sal_Int32 nCacheId = it->mnCacheId;
+        sal_Int32 nPivotId = it->mnPivotId;
+
+        sax_fastparser::FSHelperPtr pPivotStrm = rStrm.CreateOutputStream(
+            XclXmlUtils::GetStreamName("xl/pivotTables/", "pivotTable", nPivotId),
+            XclXmlUtils::GetStreamName(NULL, "../pivotTables/pivotTable", nPivotId),
+            pWSStrm->getOutputStream(),
+            CREATE_XL_CONTENT_TYPE("pivotTable"),
+            CREATE_OFFICEDOC_RELATION_TYPE("pivotTable"),
+            NULL);
+
+        rStrm.PushStream(pPivotStrm);
+        SavePivotTableXml(rStrm, rObj, nCacheId);
+        rStrm.PopStream();
+    }
+}
+
+void XclExpXmlPivotTables::SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rDPObj, sal_Int32 nCacheId )
+{
+    typedef boost::unordered_map<OUString, long, OUStringHash> NameToIdMapType;
+
+    const XclExpXmlPivotCaches::Entry* pCacheEntry = mrCaches.GetCache(nCacheId);
+    if (!pCacheEntry)
+        // Something is horribly wrong.  Check your logic.
+        return;
+
+    const ScDPCache& rCache = *pCacheEntry->mpCache;
+
+    const ScDPSaveData& rSaveData = *rDPObj.GetSaveData();
+
+    size_t nFieldCount = rCache.GetFieldCount();
+    std::vector<const ScDPSaveDimension*> aCachedDims;
+    NameToIdMapType aNameToIdMap;
+
+    aCachedDims.reserve(nFieldCount);
+    for (size_t i = 0; i < nFieldCount; ++i)
+    {
+        OUString aName = rCache.GetDimensionName(i);
+        aNameToIdMap.insert(NameToIdMapType::value_type(aName, aCachedDims.size()));
+        const ScDPSaveDimension* pDim = rSaveData.GetExistingDimensionByName(aName);
+        aCachedDims.push_back(pDim);
+    }
+
+    std::vector<long> aRowFields;
+    std::vector<long> aColFields;
+    std::vector<long> aPageFields;
+    std::vector<long> aDataFields;
+
+    // Use dimensions in the save data to get their correct ordering.
+    // Dimension order here is significant as they specify the order of
+    // appearance in each axis.
+    const ScDPSaveData::DimsType& rDims = rSaveData.GetDimensions();
+
+    for (size_t i = 0, n = rDims.size(); i < n; ++i)
+    {
+        const ScDPSaveDimension& rDim = rDims[i];
+
+        long nPos = -1; // position in cache
+        OUString aSrcName = ScDPUtil::getSourceDimensionName(rDim.GetName());
+        NameToIdMapType::iterator it = aNameToIdMap.find(aSrcName);
+        if (it != aNameToIdMap.end())
+            nPos = it->second;
+
+        if (nPos == -1)
+            continue;
+
+        if (!aCachedDims[nPos])
+            continue;
+
+        sheet::DataPilotFieldOrientation eOrient =
+            static_cast<sheet::DataPilotFieldOrientation>(rDim.GetOrientation());
+
+        switch (eOrient)
+        {
+            case sheet::DataPilotFieldOrientation_COLUMN:
+                aColFields.push_back(nPos);
+            break;
+            case sheet::DataPilotFieldOrientation_ROW:
+                aRowFields.push_back(nPos);
+            break;
+            case sheet::DataPilotFieldOrientation_PAGE:
+                aPageFields.push_back(nPos);
+            break;
+            case sheet::DataPilotFieldOrientation_DATA:
+                aDataFields.push_back(nPos);
+            break;
+            case sheet::DataPilotFieldOrientation_HIDDEN:
+            default:
+                ;
+        }
+    }
+
+    sax_fastparser::FSHelperPtr& pPivotStrm = rStrm.GetCurrentStream();
+    pPivotStrm->startElement(XML_pivotTableDefinition,
+        XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
+        XML_name, XclXmlUtils::ToOString(rDPObj.GetName()).getStr(),
+        XML_cacheId, OString::number(nCacheId).getStr(),
+        XML_applyNumberFormats, BS(false),
+        XML_applyBorderFormats, BS(false),
+        XML_applyFontFormats, BS(false),
+        XML_applyPatternFormats, BS(false),
+        XML_applyAlignmentFormats, BS(false),
+        XML_applyWidthHeightFormats, BS(false),
+        XML_dataCaption, "Values",
+        XML_useAutoFormatting, BS(false),
+        XML_itemPrintTitles, BS(true),
+        XML_indent, BS(false),
+        XML_outline, BS(true),
+        XML_outlineData, BS(true),
+        FSEND);
+
+    // NB: Excel's range does not include page field area (if any).
+    ScRange aOutRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::TABLE);
+
+    sal_Int32 nFirstHeaderRow = aColFields.size();
+    sal_Int32 nFirstDataRow = 2;
+    sal_Int32 nFirstDataCol = 1;
+    ScRange aResRange = rDPObj.GetOutputRangeByType(sheet::DataPilotOutputRangeType::RESULT);
+    if (aOutRange.IsValid() && aResRange.IsValid())
+    {
+        nFirstDataRow = aResRange.aStart.Row() - aOutRange.aStart.Row();
+        nFirstDataCol = aResRange.aStart.Col() - aOutRange.aStart.Col();
+    }
+
+    if (!aOutRange.IsValid())
+        aOutRange = rDPObj.GetOutRange();
+
+    pPivotStrm->write("<")->writeId(XML_location);
+    rStrm.WriteAttributes(XML_ref,
+        XclXmlUtils::ToOString(aOutRange),
+        XML_firstHeaderRow, OString::number(nFirstHeaderRow).getStr(),
+        XML_firstDataRow, OString::number(nFirstDataRow).getStr(),
+        XML_firstDataCol, OString::number(nFirstDataCol).getStr(),
+        FSEND);
+
+    if (!aPageFields.empty())
+    {
+        rStrm.WriteAttributes(XML_rowPageCount, OString::number(static_cast<long>(aPageFields.size())).getStr(), FSEND);
+        rStrm.WriteAttributes(XML_colPageCount, OString::number(1).getStr(), FSEND);
+    }
+
+    pPivotStrm->write("/>");
+
+    // <pivotFields> - It must contain all fields in the pivot cache even if
+    // only some of them are used in the pivot table.  The order must be as
+    // they appear in the cache.
+
+    pPivotStrm->startElement(XML_pivotFields,
+        XML_count, OString::number(static_cast<long>(aCachedDims.size())).getStr(),
+        FSEND);
+
+    for (size_t i = 0, n = aCachedDims.size(); i < n; ++i)
+    {
+        const ScDPSaveDimension* pDim = aCachedDims[i];
+        if (!pDim)
+        {
+            pPivotStrm->singleElement(XML_pivotField,
+                XML_showAll, BS(false),
+                FSEND);
+            continue;
+        }
+
+        sheet::DataPilotFieldOrientation eOrient =
+            static_cast<sheet::DataPilotFieldOrientation>(pDim->GetOrientation());
+
+        if (eOrient == sheet::DataPilotFieldOrientation_HIDDEN)
+        {
+            pPivotStrm->singleElement(XML_pivotField,
+                XML_showAll, BS(false),
+                FSEND);
+            continue;
+        }
+
+        if (eOrient == sheet::DataPilotFieldOrientation_DATA)
+        {
+            pPivotStrm->singleElement(XML_pivotField,
+                XML_dataField, BS(true),
+                XML_showAll, BS(false),
+                FSEND);
+
+            continue;
+        }
+
+        pPivotStrm->startElement(XML_pivotField,
+            XML_axis, toOOXMLAxisType(eOrient),
+            XML_showAll, BS(false),
+            FSEND);
+
+        // TODO : Dump field items.
+
+        pPivotStrm->endElement(XML_pivotField);
+    }
+
+    pPivotStrm->endElement(XML_pivotFields);
+
+    // <rowFields>
+
+    if (!aRowFields.empty())
+    {
+        pPivotStrm->startElement(XML_rowFields,
+            XML_count, OString::number(static_cast<long>(aRowFields.size())),
+            FSEND);
+
+        std::vector<long>::iterator it = aRowFields.begin(), itEnd = aRowFields.end();
+        for (; it != itEnd; ++it)
+        {
+            pPivotStrm->singleElement(XML_field,
+                XML_x, OString::number(*it),
+                FSEND);
+        }
+
+        pPivotStrm->endElement(XML_rowFields);
+    }
+
+    // <rowItems>
+
+    // <colFields>
+
+    if (!aColFields.empty())
+    {
+        pPivotStrm->startElement(XML_colFields,
+            XML_count, OString::number(static_cast<long>(aColFields.size())),
+            FSEND);
+
+        std::vector<long>::iterator it = aColFields.begin(), itEnd = aColFields.end();
+        for (; it != itEnd; ++it)
+        {
+            pPivotStrm->singleElement(XML_field,
+                XML_x, OString::number(*it),
+                FSEND);
+        }
+
+        pPivotStrm->endElement(XML_colFields);
+    }
+
+    // <colItems>
+
+    // <pageFields>
+
+    if (!aPageFields.empty())
+    {
+        pPivotStrm->startElement(XML_pageFields,
+            XML_count, OString::number(static_cast<long>(aPageFields.size())),
+            FSEND);
+
+        std::vector<long>::iterator it = aPageFields.begin(), itEnd = aPageFields.end();
+        for (; it != itEnd; ++it)
+        {
+            pPivotStrm->singleElement(XML_pageField,
+                XML_fld, OString::number(*it),
+                XML_hier, OString::number(-1), // TODO : handle this correctly.
+                FSEND);
+        }
+
+        pPivotStrm->endElement(XML_pageFields);
+    }
+
+    // <dataFields>
+
+    if (!aDataFields.empty())
+    {
+        pPivotStrm->startElement(XML_dataFields,
+            XML_count, OString::number(static_cast<long>(aDataFields.size())),
+            FSEND);
+
+        std::vector<long>::iterator it = aDataFields.begin(), itEnd = aDataFields.end();
+        for (; it != itEnd; ++it)
+        {
+            long nDimIdx = *it;
+            assert(aCachedDims[nDimIdx]); // the loop above should have screened for NULL's.
+            const ScDPSaveDimension& rDim = *aCachedDims[nDimIdx];
+            const OUString* pName = rDim.GetLayoutName();
+            pPivotStrm->write("<")->writeId(XML_dataField);
+            if (pName)
+                rStrm.WriteAttributes(XML_name, XclXmlUtils::ToOString(*pName), FSEND);
+
+            rStrm.WriteAttributes(XML_fld, OString::number(nDimIdx).getStr(), FSEND);
+
+            pPivotStrm->write("/>");
+        }
+
+        pPivotStrm->endElement(XML_dataFields);
+    }
+
+    OUStringBuffer aBuf("../pivotCache/pivotCacheDefinition");
+    aBuf.append(nCacheId);
+    aBuf.append(".xml");
+
+    rStrm.addRelation(
+        pPivotStrm->getOutputStream(),
+        CREATE_OFFICEDOC_RELATION_TYPE("pivotCacheDefinition"),
+        aBuf.makeStringAndClear());
+
+    pPivotStrm->endElement(XML_pivotTableDefinition);
+}
+
+void XclExpXmlPivotTables::AppendTable( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId )
+{
+    maTables.push_back(Entry(pTable, nCacheId, nPivotId));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/excel/xeroot.cxx b/sc/source/filter/excel/xeroot.cxx
index 1cab39a..42f03d4 100644
--- a/sc/source/filter/excel/xeroot.cxx
+++ b/sc/source/filter/excel/xeroot.cxx
@@ -37,6 +37,7 @@
 #include "xepivot.hxx"
 #include "xestyle.hxx"
 #include "xeroot.hxx"
+#include <xepivotxml.hxx>
 
 #include "excrecds.hxx"
 #include "tabprotection.hxx"
@@ -164,6 +165,12 @@ XclExpPivotTableManager& XclExpRoot::GetPivotTableManager() const
     return *mrExpData.mxPTableMgr;
 }
 
+XclExpXmlPivotTableManager& XclExpRoot::GetXmlPivotTableManager()
+{
+    assert(mrExpData.mxXmlPTableMgr);
+    return *mrExpData.mxXmlPTableMgr;
+}
+
 void XclExpRoot::InitializeConvert()
 {
     mrExpData.mxTabInfo.reset( new XclExpTabInfo( GetRoot() ) );
@@ -201,6 +208,8 @@ void XclExpRoot::InitializeGlobals()
 
     if( GetOutput() == EXC_OUTPUT_XML_2007 )
     {
+        mrExpData.mxXmlPTableMgr.reset(new XclExpXmlPivotTableManager(GetRoot()));
+
         do
         {
             ScDocument& rDoc = GetDoc();
diff --git a/sc/source/filter/inc/xepivotxml.hxx b/sc/source/filter/inc/xepivotxml.hxx
new file mode 100644
index 0000000..b671060
--- /dev/null
+++ b/sc/source/filter/inc/xepivotxml.hxx
@@ -0,0 +1,95 @@
+/* -*- 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 INCLUDED_SC_FILTER_XEPIVOTXML_HXX
+#define INCLUDED_SC_FILTER_XEPIVOTXML_HXX
+
+#include <xerecord.hxx>
+#include <xeroot.hxx>
+
+#include <boost/ptr_container/ptr_map.hpp>
+#include <boost/unordered_map.hpp>
+
+class ScDPCache;
+class ScDPCollection;
+class ScDPObject;
+
+class XclExpXmlPivotCaches : public XclExpRecordBase, protected XclExpRoot
+{
+public:
+    enum EntryType { Worksheet, Name, Database };
+
+    struct Entry
+    {
+        const ScDPCache* mpCache;
+        EntryType meType;
+        ScRange maSrcRange;
+    };
+
+    XclExpXmlPivotCaches( const XclExpRoot& rRoot );
+    virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
+    void SetCaches( const std::vector<Entry>& rCaches );
+    bool HasCaches() const;
+    const Entry* GetCache( sal_Int32 nCacheId ) const;
+
+private:
+    void SavePivotCacheXml( XclExpXmlStream& rStrm, const Entry& rEntry, sal_Int32 nCacheId );
+
+private:
+    std::vector<Entry> maCaches;
+};
+
+class XclExpXmlPivotTables : public XclExpRecordBase, protected XclExpRoot
+{
+    struct Entry
+    {
+        const ScDPObject* mpTable;
+        sal_Int32 mnCacheId;
+        sal_Int32 mnPivotId; /// used as [n] in pivotTable[n].xml part name.
+
+        Entry( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId );
+    };
+
+    const XclExpXmlPivotCaches& mrCaches;
+    typedef std::vector<Entry> TablesType;
+    TablesType maTables;
+
+public:
+    XclExpXmlPivotTables( const XclExpRoot& rRoot, const XclExpXmlPivotCaches& rCaches );
+
+    virtual void SaveXml( XclExpXmlStream& rStrm ) SAL_OVERRIDE;
+
+    void AppendTable( const ScDPObject* pTable, sal_Int32 nCacheId, sal_Int32 nPivotId );
+
+private:
+    void SavePivotTableXml( XclExpXmlStream& rStrm, const ScDPObject& rObj, sal_Int32 nCacheId );
+};
+
+class XclExpXmlPivotTableManager : protected XclExpRoot
+{
+    typedef boost::ptr_map<SCTAB, XclExpXmlPivotTables> TablesType;
+    typedef boost::unordered_map<const ScDPObject*, sal_Int32> CacheIdMapType;
+public:
+    XclExpXmlPivotTableManager( const XclExpRoot& rRoot );
+
+    void Initialize();
+
+    XclExpXmlPivotCaches& GetCaches();
+    XclExpXmlPivotTables* GetTablesBySheet( SCTAB nTab );
+
+private:
+    XclExpXmlPivotCaches maCaches;
+    TablesType maTables;
+    CacheIdMapType maCacheIdMap;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/xeroot.hxx b/sc/source/filter/inc/xeroot.hxx
index 4906a18..35de5c6 100644
--- a/sc/source/filter/inc/xeroot.hxx
+++ b/sc/source/filter/inc/xeroot.hxx
@@ -51,6 +51,7 @@ class XclExpObjectManager;
 class XclExpFilterManager;
 class XclExpPivotTableManager;
 class XclExpDxfs;
+class XclExpXmlPivotTableManager;
 
 /** Stores global buffers and data needed for Excel export filter. */
 struct XclExpRootData : public XclRootData
@@ -90,6 +91,8 @@ struct XclExpRootData : public XclRootData
     XclExpPTableMgrRef  mxPTableMgr;        /// All pivot tables and pivot caches.
     XclExpDxfsRef       mxDxfs;             /// All delta formatting entries
 
+    boost::shared_ptr<XclExpXmlPivotTableManager> mxXmlPTableMgr;
+
     ScCompiler::OpCodeMapPtr  mxOpCodeMap;  /// mapping between op-codes and names
 
     bool                mbRelUrl;           /// true = Store URLs relative.
@@ -144,6 +147,8 @@ public:
     /** Returns the differential formatting list */
     XclExpDxfs&          GetDxfs() const;
 
+    XclExpXmlPivotTableManager& GetXmlPivotTableManager();
+
     /** Is called when export filter starts to create the Excel document (all BIFF versions). */
     void                InitializeConvert();
     /** Is called when export filter starts to create the workbook global data (>=BIFF5). */
commit 902e3898d385875029fda3b42c1854b159a18483
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Thu Aug 28 20:42:20 2014 -0400

    Make some methods non-inline, and add method descriptions.
    
    Change-Id: Ib8d5fa666827a7f97035ad37d05e305bb920c300

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6bfb138..fb03521 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -551,9 +551,9 @@ public:
 
     SC_DLLPUBLIC const ScRangeData* GetRangeAtBlock( const ScRange& rBlock, OUString* pName=NULL ) const;
 
-    bool HasPivotTable() const;
+    SC_DLLPUBLIC bool HasPivotTable() const;
     SC_DLLPUBLIC ScDPCollection*       GetDPCollection();
-    const ScDPCollection* GetDPCollection() const { return pDPCollection; }
+    SC_DLLPUBLIC const ScDPCollection* GetDPCollection() const;
     SC_DLLPUBLIC ScDPObject* GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const;
     ScDPObject*         GetDPAtBlock( const ScRange& rBlock ) const;
 
diff --git a/sc/inc/dpcache.hxx b/sc/inc/dpcache.hxx
index 06f66c0..6324243 100644
--- a/sc/inc/dpcache.hxx
+++ b/sc/inc/dpcache.hxx
@@ -118,7 +118,7 @@ private:
     GroupFieldsType maGroupFields;
     mutable StringSetType maStringPool;
 
-    LabelsType maLabelNames;    // Stores dimension names.
+    LabelsType maLabelNames; // Stores dimension names and the data layout dimension name at position 0.
     mdds::flat_segment_tree<SCROW, bool> maEmptyRows;
     SCROW mnDataSize;
     SCROW mnRowCount;
@@ -129,7 +129,7 @@ public:
     const OUString* InternString(const OUString& rStr) const;
     void AddReference(ScDPObject* pObj) const;
     void RemoveReference(ScDPObject* pObj) const;
-    const ObjectSetType& GetAllReferences() const { return maRefObjects;}
+    const ObjectSetType& GetAllReferences() const;
 
     SCROW GetIdByItemData(long nDim, const ScDPItemData& rItem) const;
     OUString GetFormattedString(long nDim, const ScDPItemData& rItem) const;
@@ -160,15 +160,25 @@ public:
     bool InitFromDoc(ScDocument* pDoc, const ScRange& rRange);
     bool InitFromDataBase(DBConnector& rDB);
 
-    SCROW GetRowCount() const { return mnRowCount;}
+    /**
+     * Row count is the number of records plus any trailing empty rows in case
+     * the source data is sheet and contains trailing empty rows.
+     */
+    SCROW GetRowCount() const;
+
+    /**
+     * Data size is the number of records without any trailing empty rows for
+     * sheet source data.  For any other source type, this should equal the
+     * row count.
+     */
     SCROW GetDataSize() const;
     SCROW GetItemDataId( sal_uInt16 nDim, SCROW nRow, bool bRepeatIfEmpty ) const;
     OUString GetDimensionName(LabelsType::size_type nDim) const;
     bool IsRowEmpty(SCROW nRow) const;
     bool ValidQuery(SCROW nRow, const ScQueryParam& rQueryParam) const;
 
-    ScDocument* GetDoc() const { return mpDoc;}
-    long GetColumnCount() const { return mnColumnCount;}
+    ScDocument* GetDoc() const;
+    long GetColumnCount() const;
 
     const ScDPItemData* GetItemDataById( long nDim, SCROW nId ) const;
 
diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 12b83ed..1ff7024 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -130,13 +130,14 @@ public:
 
     void                Output( const ScAddress& rPos );
     ScRange             GetNewOutputRange( bool& rOverflow );
-    const ScRange       GetOutputRangeByType( sal_Int32 nType );
+
+    ScRange GetOutputRangeByType( sal_Int32 nType );
 
     void                SetSaveData(const ScDPSaveData& rData);
     ScDPSaveData*       GetSaveData() const     { return pSaveData; }
 
     void                SetOutRange(const ScRange& rRange);
-    const ScRange&      GetOutRange() const     { return aOutRange; }
+    const ScRange&      GetOutRange() const;
 
     void                SetHeaderLayout(bool bUseGrid);
     bool                GetHeaderLayout() const { return mbHeaderLayout;}
@@ -394,9 +395,12 @@ public:
     void FreeTable(ScDPObject* pDPObj);
     SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj);
 
-    SheetCaches& GetSheetCaches() { return maSheetCaches;}
-    NameCaches& GetNameCaches() { return maNameCaches;}
-    DBCaches& GetDBCaches() { return maDBCaches;}
+    SC_DLLPUBLIC SheetCaches& GetSheetCaches();
+    SC_DLLPUBLIC const SheetCaches& GetSheetCaches() const;
+    NameCaches& GetNameCaches();
+    SC_DLLPUBLIC const NameCaches& GetNameCaches() const;
+    DBCaches& GetDBCaches();
+    SC_DLLPUBLIC const DBCaches& GetDBCaches() const;
 
     ScRangeList GetAllTableRanges( SCTAB nTab ) const;
     bool IntersectsTableByColumns( SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCTAB nTab ) const;
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 7a2bc04..61ac5f8 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -323,6 +323,11 @@ ScDPCollection* ScDocument::GetDPCollection()
     return pDPCollection;
 }
 
+const ScDPCollection* ScDocument::GetDPCollection() const
+{
+    return pDPCollection;
+}
+
 ScDPObject* ScDocument::GetDPAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab) const
 {
     if (!pDPCollection)
diff --git a/sc/source/core/data/dpcache.cxx b/sc/source/core/data/dpcache.cxx
index 9643557..e9687c5 100644
--- a/sc/source/core/data/dpcache.cxx
+++ b/sc/source/core/data/dpcache.cxx
@@ -646,6 +646,16 @@ bool ScDPCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam) const
     return bRet;
 }
 
+ScDocument* ScDPCache::GetDoc() const
+{
+    return mpDoc;
+}
+
+long ScDPCache::GetColumnCount() const
+{
+    return mnColumnCount;
+}
+
 bool ScDPCache::IsRowEmpty(SCROW nRow) const
 {
     bool bEmpty = true;
@@ -829,6 +839,11 @@ size_t ScDPCache::GetGroupFieldCount() const
     return maGroupFields.size();
 }
 
+SCROW ScDPCache::GetRowCount() const
+{
+    return mnRowCount;
+}
+
 SCROW ScDPCache::GetDataSize() const
 {
     OSL_ENSURE(mnDataSize <= GetRowCount(), "Data size should never be larger than the row count.");
@@ -907,6 +922,11 @@ void ScDPCache::RemoveReference(ScDPObject* pObj) const
         mpDoc->GetDPCollection()->RemoveCache(this);
 }
 
+const ScDPCache::ObjectSetType& ScDPCache::GetAllReferences() const
+{
+    return maRefObjects;
+}
+
 SCROW ScDPCache::GetIdByItemData(long nDim, const ScDPItemData& rItem) const
 {
     if (nDim < 0)
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 481541e..4587209 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -416,6 +416,11 @@ void ScDPObject::SetOutRange(const ScRange& rRange)
         pOutput->SetPosition( rRange.aStart );
 }
 
+const ScRange& ScDPObject::GetOutRange() const
+{
+    return aOutRange;
+}
+
 void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc, bool /*bFromRefUpdate*/)
 {
     if ( pSheetDesc && rDesc == *pSheetDesc )
@@ -921,7 +926,7 @@ void ScDPObject::Output( const ScAddress& rPos )
     pDoc->ApplyFlagsTab(s.Col(), s.Row(), e.Col(), e.Row(), s.Tab(), SC_MF_DP_TABLE);
 }
 
-const ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType )
+ScRange ScDPObject::GetOutputRangeByType( sal_Int32 nType )
 {
     CreateOutput();
 
@@ -3611,6 +3616,36 @@ bool ScDPCollection::InsertNewTable(ScDPObject* pDPObj)
     return true;
 }
 
+ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches()
+{
+    return maSheetCaches;
+}
+
+const ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches() const
+{
+    return maSheetCaches;
+}
+
+ScDPCollection::NameCaches& ScDPCollection::GetNameCaches()
+{
+    return maNameCaches;
+}
+
+const ScDPCollection::NameCaches& ScDPCollection::GetNameCaches() const
+{
+    return maNameCaches;
+}
+
+ScDPCollection::DBCaches& ScDPCollection::GetDBCaches()
+{
+    return maDBCaches;
+}
+
+const ScDPCollection::DBCaches& ScDPCollection::GetDBCaches() const
+{
+    return maDBCaches;
+}
+
 ScRangeList ScDPCollection::GetAllTableRanges( SCTAB nTab ) const
 {
     return std::for_each(maTables.begin(), maTables.end(), AccumulateOutputRanges(nTab)).getRanges();


More information about the Libreoffice-commits mailing list