[Libreoffice-commits] core.git: Branch 'libreoffice-5-2' - sc/inc sc/qa sc/source

Tamás Zolnai tamas.zolnai at collabora.com
Sat Oct 22 18:05:07 UTC 2016


 sc/inc/dpobject.hxx                                           |    2 
 sc/inc/dpsave.hxx                                             |    2 
 sc/qa/unit/data/xlsx/pivot-table/shared-dategroup.xlsx        |binary
 sc/qa/unit/data/xlsx/pivot-table/shared-nested-dategroup.xlsx |binary
 sc/qa/unit/data/xlsx/pivot-table/shared-numgroup.xlsx         |binary
 sc/qa/unit/data/xlsx/pivot-table/shared_group.xlsx            |binary
 sc/qa/unit/subsequent_filters-test.cxx                        |  150 ++++++++++
 sc/source/core/data/dpobject.cxx                              |   80 +++++
 sc/source/filter/inc/pivotcachebuffer.hxx                     |    7 
 sc/source/filter/inc/pivottablebuffer.hxx                     |   10 
 sc/source/filter/oox/pivotcachebuffer.cxx                     |    5 
 sc/source/filter/oox/pivottablebuffer.cxx                     |   77 ++++-
 sc/source/ui/docshell/dbdocfun.cxx                            |   54 ++-
 sc/source/ui/unoobj/dapiuno.cxx                               |    2 
 14 files changed, 364 insertions(+), 25 deletions(-)

New commits:
commit 29999ea70626a4b1dd312ad6e07f1131b6449f93
Author: Tamás Zolnai <tamas.zolnai at collabora.com>
Date:   Tue Sep 27 05:08:51 2016 +0200

    tdf#102694, bnc#957991: Improve pivot cache reading performance
    
    This is an aggregated patch, containing all related changes on
    master. Fixes some functional issues also next to the performance
    problem and add all new test cases related this bug fix.
    
    bnc#957991: Improve pivot cache reading performance
    
    Performance problem was caused by grouping. Pivot
    tables with the same source are linked to each other
    by the pivot cache and so all the pivot tables were
    updated when one group was added to one of the tables.
    
    This code change first of all fixes a functional issue:
    group name was wrongly imported and so pivot tables using
    group fields were broken. This caused by calling
    RefreshPivotTableGroups() on a pivot table which is not part
    of the cache yet and so update was not called on this table.
    Calling ReloadGroupTableData() solve this problem.
    
    Second part of the codechange is about the consistency
    of the pivot cache. We have an invariant in this code to
    have the same groups for tabels with the same source.
    To keep this invariant we update every newly inserted
    tables adding the neccessary groups.
    The performance improvement here is that until the table
    is not part of the cache, it does not updates other tables.
    Group syncronization is done when the table is inserted to
    the ScDPCollection.
    
    (cherry picked from commit 3b64a198568d5b2bb14066581aca112cc6182fd7)
    
    This parameter can be const.
    
    (cherry picked from commit b905116dc41a4101e4e44d39d946bbba6a3a334d)
    
    Test the case for pivot tables sharing a group
    
    Fixed with 3b64a198568d5b2bb14066581aca112cc6182fd7
    
    (cherry picked from commit 049d2ffd329f88934a92b72e4ec650ea46bf8c61)
    
    Test XLSX import of date groups
    
    (cherry picked from commit f1a97fab957629d617b0b0ad44de5beb3d343f5c)
    
    Test XLSX import of number groups
    
    (cherry picked from commit 93098854c2d2b814a21161bd88071918cb382e87)
    
    Pivot tables: Fix wrong group field number in cache
    
    getCache should not append new group fields to the cache,
    but use those which are stored in the dimension data.
    
    (cherry picked from commit 7e1fd9aa86ab8d5e86f35df8615f438a3383af98)
    
    Pivot tables: Fix XLSX import of nested date groups
    
    Same fix which was added for other kind of groups:
    f697d7aa5c26f9fcfd717b76a4827a5bcb38325e
    
    (cherry picked from commit 9d19634c8e719a80674ca4b3dfc3c7e49f049e5b)
    
    Pivot table XLSX import: PivotCache is not handled as a const object.
    
    (cherry picked from commit db481dd30521f9ce498873cdc945cf9544bf983c)
    
    tdf#102694, bnc#957991: Improve pivot cache reading performance
    
    When two or more tables have the same source data, then
    the grouping of source fields are shared between these
    tables, so don't need to import these grouping for each
    tables.
    The added code checkes whether we already imported the
    group fields and don't create them again using API
    functions, but apply the exisiting groups of an other table
    sharing the source.
    
    (cherry picked from commit 03a1143cc75161dab56b20f1ab9e723ddd0caa8e)
    
    Add better comment for this function.
    
    (cherry picked from commit 97ebbb892993507fe19ca069534015637fde497b)
    
    Change-Id: I04d81295491c4c0f351200670f9ebdae5644f858
    Reviewed-on: https://gerrit.libreoffice.org/30048
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx
index 5876bd9..ffafd26 100644
--- a/sc/inc/dpobject.hxx
+++ b/sc/inc/dpobject.hxx
@@ -364,6 +364,7 @@ public:
 
     sal_uLong ReloadCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs);
     bool ReloadGroupsInCache(ScDPObject* pDPObj, std::set<ScDPObject*>& rRefs);
+    SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject& rDPObj, const ScDPDimensionSaveData** pGroups) const;
 
     SC_DLLPUBLIC size_t GetCount() const;
     SC_DLLPUBLIC ScDPObject& operator[](size_t nIndex);
@@ -388,6 +389,7 @@ public:
 
     void FreeTable(ScDPObject* pDPObj);
     SC_DLLPUBLIC bool InsertNewTable(ScDPObject* pDPObj);
+    SC_DLLPUBLIC bool HasTable(const ScDPObject* pDPObj) const;
 
     SC_DLLPUBLIC SheetCaches& GetSheetCaches();
     SC_DLLPUBLIC const SheetCaches& GetSheetCaches() const;
diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx
index 2deb35e..bb1e8ac 100644
--- a/sc/inc/dpsave.hxx
+++ b/sc/inc/dpsave.hxx
@@ -352,7 +352,7 @@ public:
     void RemoveAllGroupDimensions( const OUString& rSrcDimName, std::vector<OUString>* pDeletedNames = nullptr );
 
     SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there
-    void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied
+    SC_DLLPUBLIC void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied
     void BuildAllDimensionMembers(ScDPTableData* pData);
     void SyncAllDimensionMembers(ScDPTableData* pData);
 
diff --git a/sc/qa/unit/data/xlsx/pivot-table/shared-dategroup.xlsx b/sc/qa/unit/data/xlsx/pivot-table/shared-dategroup.xlsx
new file mode 100644
index 0000000..60cbd66
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/shared-dategroup.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot-table/shared-nested-dategroup.xlsx b/sc/qa/unit/data/xlsx/pivot-table/shared-nested-dategroup.xlsx
new file mode 100644
index 0000000..4dfb55d
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/shared-nested-dategroup.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot-table/shared-numgroup.xlsx b/sc/qa/unit/data/xlsx/pivot-table/shared-numgroup.xlsx
new file mode 100644
index 0000000..36f36ef
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/shared-numgroup.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/pivot-table/shared_group.xlsx b/sc/qa/unit/data/xlsx/pivot-table/shared_group.xlsx
new file mode 100644
index 0000000..2bc5cdd
Binary files /dev/null and b/sc/qa/unit/data/xlsx/pivot-table/shared_group.xlsx differ
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 0c1428e..16545b9 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -183,6 +183,10 @@ public:
     void testPivotTableNamedRangeSourceODS();
     void testPivotTableSharedCacheGroupODS();
     void testGetPivotDataXLS();
+    void testPivotTableSharedGroupXLSX();
+    void testPivotTableSharedDateGroupXLSX();
+    void testPivotTableSharedNestedDateGroupXLSX();
+    void testPivotTableSharedNumGroupXLSX();
 
     void testFormulaDependency();
 
@@ -280,6 +284,10 @@ public:
     CPPUNIT_TEST(testPivotTableNamedRangeSourceODS);
     CPPUNIT_TEST(testPivotTableSharedCacheGroupODS);
     CPPUNIT_TEST(testGetPivotDataXLS);
+    CPPUNIT_TEST(testPivotTableSharedGroupXLSX);
+    CPPUNIT_TEST(testPivotTableSharedDateGroupXLSX);
+    CPPUNIT_TEST(testPivotTableSharedNestedDateGroupXLSX);
+    CPPUNIT_TEST(testPivotTableSharedNumGroupXLSX);
     CPPUNIT_TEST(testRowHeightODS);
     CPPUNIT_TEST(testFormulaDependency);
     CPPUNIT_TEST(testRichTextContentODS);
@@ -2035,6 +2043,148 @@ void ScFiltersTest::testGetPivotDataXLS()
     xDocSh->DoClose();
 }
 
+void ScFiltersTest::testPivotTableSharedGroupXLSX()
+{
+    ScDocShellRef xDocSh = loadDoc("pivot-table/shared_group.", FORMAT_XLSX);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
+    ScDocument& rDoc = xDocSh->GetDocument();
+    rDoc.CalcAll();
+
+    // Check whether right group names are imported for both tables
+    // First table
+    CPPUNIT_ASSERT_EQUAL(OUString("Csoport1"), rDoc.GetString(ScAddress(0,2,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("Csoport2"), rDoc.GetString(ScAddress(0,3,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("Csoport3"), rDoc.GetString(ScAddress(0,4,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("16"), rDoc.GetString(ScAddress(0,5,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("17"), rDoc.GetString(ScAddress(0,6,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("18"), rDoc.GetString(ScAddress(0,7,0)));
+
+    // Second table
+    CPPUNIT_ASSERT_EQUAL(OUString("Csoport1"), rDoc.GetString(ScAddress(0,12,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("Csoport2"), rDoc.GetString(ScAddress(0,13,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("Csoport3"), rDoc.GetString(ScAddress(0,14,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("16"), rDoc.GetString(ScAddress(0,15,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("17"), rDoc.GetString(ScAddress(0,16,0)));
+    CPPUNIT_ASSERT_EQUAL(OUString("18"), rDoc.GetString(ScAddress(0,17,0)));
+
+    xDocSh->DoClose();
+}
+
+void ScFiltersTest::testPivotTableSharedDateGroupXLSX()
+{
+    ScDocShellRef xDocSh = loadDoc("pivot-table/shared-dategroup.", FORMAT_XLSX);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
+    ScDocument& rDoc = xDocSh->GetDocument();
+
+    // Check whether right date labels are imported for both tables
+    // First table
+    CPPUNIT_ASSERT_EQUAL(OUString("1965"), rDoc.GetString(ScAddress(0,4,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("1989"), rDoc.GetString(ScAddress(0,5,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2000"), rDoc.GetString(ScAddress(0,6,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2004"), rDoc.GetString(ScAddress(0,7,1)));
+    // TODO: check why this fails with 2005
+    // CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(0,8,1)));
+
+    // Second table
+    CPPUNIT_ASSERT_EQUAL(OUString("1965"), rDoc.GetString(ScAddress(5,4,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("1989"), rDoc.GetString(ScAddress(5,5,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2000"), rDoc.GetString(ScAddress(5,6,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2004"), rDoc.GetString(ScAddress(5,7,1)));
+    // TODO: check why this fails with 2005
+    // CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(5,8,1)));
+
+    // There should be exactly 2 pivot tables and 1 cache.
+    ScDPCollection* pDPs = rDoc.GetDPCollection();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pDPs->GetCount());
+
+    ScDPCollection::SheetCaches& rSheetCaches = pDPs->GetSheetCaches();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rSheetCaches.size());
+
+    const ScDPCache* pCache = rSheetCaches.getExistingCache(ScRange(0,0,0,9,24,0));
+    CPPUNIT_ASSERT_MESSAGE("Pivot cache is expected for A1:J25 on the first sheet.", pCache);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(10), pCache->GetFieldCount());
+
+    xDocSh->DoClose();
+}
+
+void ScFiltersTest::testPivotTableSharedNestedDateGroupXLSX()
+{
+    ScDocShellRef xDocSh = loadDoc("pivot-table/shared-nested-dategroup.", FORMAT_XLSX);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
+    ScDocument& rDoc = xDocSh->GetDocument();
+
+    // Check whether right date groups are imported for both tables
+    // First table
+    CPPUNIT_ASSERT_EQUAL(OUString("Years"), rDoc.GetString(ScAddress(0,3,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("1965"), rDoc.GetString(ScAddress(0,4,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("1989"), rDoc.GetString(ScAddress(0,11,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2000"), rDoc.GetString(ScAddress(0,18,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2004"), rDoc.GetString(ScAddress(0,21,1)));
+    // TODO: check why this fails with the empty string
+    //CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(0,32,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("Quarters"), rDoc.GetString(ScAddress(1,3,1)));
+
+    // Second table
+    CPPUNIT_ASSERT_EQUAL(OUString("Years"), rDoc.GetString(ScAddress(6,3,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("1965"), rDoc.GetString(ScAddress(6,4,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("1989"), rDoc.GetString(ScAddress(6,11,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2000"), rDoc.GetString(ScAddress(6,18,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("2004"), rDoc.GetString(ScAddress(6,21,1)));
+    // TODO: check why this fails with the empty string
+    //CPPUNIT_ASSERT_EQUAL(OUString("2007"), rDoc.GetString(ScAddress(6,31,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("Quarters"), rDoc.GetString(ScAddress(7,3,1)));
+
+    // There should be exactly 2 pivot tables and 1 cache.
+    ScDPCollection* pDPs = rDoc.GetDPCollection();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pDPs->GetCount());
+
+    ScDPCollection::SheetCaches& rSheetCaches = pDPs->GetSheetCaches();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rSheetCaches.size());
+
+    const ScDPCache* pCache = rSheetCaches.getExistingCache(ScRange(0,0,0,9,24,0));
+    CPPUNIT_ASSERT_MESSAGE("Pivot cache is expected for A1:J25 on the first sheet.", pCache);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(10), pCache->GetFieldCount());
+    // Two new group field is created
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pCache->GetGroupFieldCount());
+
+    xDocSh->DoClose();
+}
+
+void ScFiltersTest::testPivotTableSharedNumGroupXLSX()
+{
+    ScDocShellRef xDocSh = loadDoc("pivot-table/shared-numgroup.", FORMAT_XLSX);
+    CPPUNIT_ASSERT_MESSAGE("Failed to load file", xDocSh.Is());
+    ScDocument& rDoc = xDocSh->GetDocument();
+
+    // Check whether right number groups are imported for both tables
+    // First table
+    CPPUNIT_ASSERT_EQUAL(OUString("32674-47673"), rDoc.GetString(ScAddress(0,4,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("47674-62673"), rDoc.GetString(ScAddress(0,5,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("62674-77673"), rDoc.GetString(ScAddress(0,6,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("77674-92673"), rDoc.GetString(ScAddress(0,7,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("92674-107673"), rDoc.GetString(ScAddress(0,8,1)));
+
+    // Second table
+    CPPUNIT_ASSERT_EQUAL(OUString("32674-47673"), rDoc.GetString(ScAddress(5,4,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("47674-62673"), rDoc.GetString(ScAddress(5,5,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("62674-77673"), rDoc.GetString(ScAddress(5,6,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("77674-92673"), rDoc.GetString(ScAddress(5,7,1)));
+    CPPUNIT_ASSERT_EQUAL(OUString("92674-107673"), rDoc.GetString(ScAddress(5,8,1)));
+
+    // There should be exactly 2 pivot tables and 1 cache.
+    ScDPCollection* pDPs = rDoc.GetDPCollection();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pDPs->GetCount());
+
+    ScDPCollection::SheetCaches& rSheetCaches = pDPs->GetSheetCaches();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rSheetCaches.size());
+
+    const ScDPCache* pCache = rSheetCaches.getExistingCache(ScRange(0,0,0,9,24,0));
+    CPPUNIT_ASSERT_MESSAGE("Pivot cache is expected for A1:J25 on the first sheet.", pCache);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(10), pCache->GetFieldCount());
+
+    xDocSh->DoClose();
+}
+
 void ScFiltersTest::testRowHeightODS()
 {
     ScDocShellRef xDocSh = loadDoc("row-height-import.", FORMAT_ODS);
diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx
index 531ab81..db529fb 100644
--- a/sc/source/core/data/dpobject.cxx
+++ b/sc/source/core/data/dpobject.cxx
@@ -2847,7 +2847,10 @@ const ScDPCache* ScDPCollection::SheetCaches::getCache(const ScRange& rRange, co
         }
 
         if (pDimData)
+        {
+            (itCache->second)->ClearGroupFields();
             pDimData->WriteToCache(*itCache->second);
+        }
 
         return itCache->second.get();
     }
@@ -3440,6 +3443,71 @@ bool ScDPCollection::ReloadGroupsInCache(ScDPObject* pDPObj, std::set<ScDPObject
     return true;
 }
 
+bool ScDPCollection::GetReferenceGroups(const ScDPObject& rDPObj, const ScDPDimensionSaveData** pGroups) const
+{
+    for (const std::unique_ptr<ScDPObject>& aTable : maTables)
+    {
+        const ScDPObject& rRefObj = *aTable.get();
+
+        if (&rRefObj == &rDPObj)
+            continue;
+
+        if (rDPObj.IsSheetData()){
+            if(!rRefObj.IsSheetData())
+                continue;
+
+            const ScSheetSourceDesc* pDesc = rDPObj.GetSheetDesc();
+            const ScSheetSourceDesc* pRefDesc = rRefObj.GetSheetDesc();
+            if (pDesc == nullptr || pRefDesc == nullptr)
+                continue;
+
+            if (pDesc->HasRangeName())
+            {
+                if (!pRefDesc->HasRangeName())
+                    continue;
+
+               if (pDesc->GetRangeName() == pRefDesc->GetRangeName())
+               {
+                    *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
+                    return true;
+               }
+            }
+            else
+            {
+                if (pRefDesc->HasRangeName())
+                    continue;
+
+                if (pDesc->GetSourceRange() == pRefDesc->GetSourceRange())
+                {
+                    *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
+                    return true;
+                }
+            }
+        }
+        else if (rDPObj.IsImportData())
+        {
+            if (!rRefObj.IsImportData ())
+                continue;
+
+            const ScImportSourceDesc* pDesc = rDPObj.GetImportSourceDesc();
+            const ScImportSourceDesc* pRefDesc = rRefObj.GetImportSourceDesc();
+            if (pDesc == nullptr || pRefDesc == nullptr)
+                continue;
+
+            if (pDesc->aDBName.equals(pRefDesc->aDBName) &&
+                pDesc->aObject.equals(pRefDesc->aObject) &&
+                pDesc->GetCommandType() == pRefDesc->GetCommandType())
+            {
+                *pGroups = rRefObj.GetSaveData()->GetExistingDimensionData();
+                return true;
+            }
+
+        }
+    }
+    return false;
+}
+
+
 void ScDPCollection::DeleteOnTab( SCTAB nTab )
 {
     maTables.erase( std::remove_if(maTables.begin(), maTables.end(), MatchByTable(nTab)), maTables.end());
@@ -3619,6 +3687,18 @@ bool ScDPCollection::InsertNewTable(ScDPObject* pDPObj)
     return true;
 }
 
+bool ScDPCollection::HasTable(const ScDPObject* pDPObj) const
+{
+    for (const std::unique_ptr<ScDPObject>& aTable : maTables)
+    {
+        if (aTable.get() == pDPObj)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
 ScDPCollection::SheetCaches& ScDPCollection::GetSheetCaches()
 {
     return maSheetCaches;
diff --git a/sc/source/filter/inc/pivotcachebuffer.hxx b/sc/source/filter/inc/pivotcachebuffer.hxx
index 3bf5406..80e2f45 100644
--- a/sc/source/filter/inc/pivotcachebuffer.hxx
+++ b/sc/source/filter/inc/pivotcachebuffer.hxx
@@ -186,6 +186,8 @@ struct PCFieldGroupModel
     bool                mbDateGroup;        /// True = items are grouped by date ranges or by item names.
     bool                mbAutoStart;        /// True = start value for range groups is calculated from source data.
     bool                mbAutoEnd;          /// True = end value for range groups is calculated from source data.
+    OUString            msFinalGroupName ;  /// Finalized group name of this field used in internal pivot table collaction.
+
 
     explicit            PCFieldGroupModel();
 
@@ -269,6 +271,10 @@ public:
     inline sal_Int32    getParentGroupField() const { return maFieldGroupModel.mnParentField; }
     /** Returns the index of the base field grouping is based on. */
     inline sal_Int32    getGroupBaseField() const { return maFieldGroupModel.mnBaseField; }
+    /** Returns the finalized group name of this field.  */
+    inline const OUString& getFinalGroupName() const { return maFieldGroupModel.msFinalGroupName; }
+    /** Set the finalized group name of this field.  */
+    inline void            setFinalGroupName(const OUString& rFinalGroupName) { maFieldGroupModel.msFinalGroupName = rFinalGroupName; }
 
     /** Returns the shared or group item with the specified index. */
     const PivotCacheItem* getCacheItem( sal_Int32 nItemIdx ) const;
@@ -405,6 +411,7 @@ public:
     /** Returns the number of pivot cache fields. */
     sal_Int32           getCacheFieldCount() const;
     /** Returns the cache field with the specified index. */
+    PivotCacheField* getCacheField( sal_Int32 nFieldIdx );
     const PivotCacheField* getCacheField( sal_Int32 nFieldIdx ) const;
     /** Returns the source column index of the field with the passed index. */
     sal_Int32           getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const;
diff --git a/sc/source/filter/inc/pivottablebuffer.hxx b/sc/source/filter/inc/pivottablebuffer.hxx
index 37ee04e..1838c53 100644
--- a/sc/source/filter/inc/pivottablebuffer.hxx
+++ b/sc/source/filter/inc/pivottablebuffer.hxx
@@ -149,6 +149,8 @@ public:
                             const css::uno::Reference< css::sheet::XDataPilotField >& rxBaseDPField,
                             const PivotCacheField& rBaseCacheField,
                             PivotCacheGroupItemVector& orItemNames );
+    void                finalizeImportBasedOnCache(
+                            const css::uno::Reference< css::sheet::XDataPilotDescriptor >& rxDPDesc);
 
     /** Returns the name of the DataPilot field in the fields collection. */
     inline const OUString& getDPFieldName() const { return maDPFieldName; }
@@ -175,7 +177,7 @@ private:
     PivotTable&         mrPivotTable;       /// The parent pivot table object.
     ItemModelVector     maItems;            /// All items of this field.
     PTFieldModel        maModel;            /// Pivot field settings.
-    OUString     maDPFieldName;      /// Name of the field in DataPilot field collection.
+    OUString            maDPFieldName;      /// Name of the field in DataPilot field collection.
     sal_Int32           mnFieldIndex;       /// Zero-based index of this field.
 };
 
@@ -317,6 +319,8 @@ public:
     PivotTableFilter&   createTableFilter();
     /** Inserts the pivot table into the sheet. */
     void                finalizeImport();
+    /** Finalizes all fields, finds field names and creates grouping fields. */
+    void                finalizeFieldsImport();
     /** Creates all date group fields for the specified cache field after import. */
     void                finalizeDateGroupingImport(
                             const css::uno::Reference< css::sheet::XDataPilotField >& rxBaseDPField,
@@ -338,6 +342,7 @@ public:
                         getDataLayoutField() const;
 
     /** Returns the cache field with the specified index. */
+    PivotCacheField* getCacheField( sal_Int32 nFieldIdx );
     const PivotCacheField* getCacheField( sal_Int32 nFieldIdx ) const;
     /** Returns the base cache field of the data field item with the specified index. */
     const PivotCacheField* getCacheFieldOfDataField( sal_Int32 nDataItemIdx ) const;
@@ -373,9 +378,10 @@ private:
     PivotTableFilterVector maFilters;       /// All field filters.
     PTDefinitionModel     maDefModel;         /// Global pivot table settings.
     PTLocationModel       maLocationModel;    /// Location settings of the pivot table.
-    const PivotCache*     mpPivotCache;       /// The pivot cache this table is based on.
+    PivotCache*           mpPivotCache;       /// The pivot cache this table is based on.
     css::uno::Reference< css::sheet::XDataPilotDescriptor >
                           mxDPDescriptor;     /// Descriptor of the DataPilot object.
+
 };
 
 class PivotTableBuffer : public WorkbookHelper
diff --git a/sc/source/filter/oox/pivotcachebuffer.cxx b/sc/source/filter/oox/pivotcachebuffer.cxx
index c7b75e3..687a47d 100644
--- a/sc/source/filter/oox/pivotcachebuffer.cxx
+++ b/sc/source/filter/oox/pivotcachebuffer.cxx
@@ -1250,6 +1250,11 @@ sal_Int32 PivotCache::getCacheFieldCount() const
     return static_cast< sal_Int32 >( maFields.size() );
 }
 
+PivotCacheField* PivotCache::getCacheField( sal_Int32 nFieldIdx )
+{
+    return maFields.get( nFieldIdx ).get();
+}
+
 const PivotCacheField* PivotCache::getCacheField( sal_Int32 nFieldIdx ) const
 {
     return maFields.get( nFieldIdx ).get();
diff --git a/sc/source/filter/oox/pivottablebuffer.cxx b/sc/source/filter/oox/pivottablebuffer.cxx
index bc3c05c..04a432a 100644
--- a/sc/source/filter/oox/pivottablebuffer.cxx
+++ b/sc/source/filter/oox/pivottablebuffer.cxx
@@ -49,6 +49,9 @@
 #include "dapiuno.hxx"
 #include "dpobject.hxx"
 #include "dpsave.hxx"
+#include "dpdimsave.hxx"
+#include "document.hxx"
+#include "documentimport.hxx"
 
 namespace oox {
 namespace xls {
@@ -424,11 +427,12 @@ void PivotTableField::finalizeDateGroupingImport( const Reference< XDataPilotFie
 {
     if( maDPFieldName.isEmpty() )    // prevent endless loops if file format is broken
     {
-        if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
+        if( PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
         {
             if( !pCacheField->isDatabaseField() && pCacheField->hasDateGrouping() && (pCacheField->getGroupBaseField() == nBaseFieldIdx) )
             {
                 maDPFieldName = pCacheField->createDateGroupField( rxBaseDPField );
+                pCacheField->setFinalGroupName(maDPFieldName);
                 OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
             }
         }
@@ -439,7 +443,7 @@ void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotF
 {
     if( maDPFieldName.isEmpty() )    // prevent endless loops if file format is broken
     {
-        if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
+        if( PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
         {
             // data field can have user defined groupname captions, apply them
             // if they do
@@ -449,10 +453,11 @@ void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotF
                 if ( aIt->mnType == XML_data  && aIt->msCaption.getLength() )
                     captionList.push_back( IdCaptionPair( aIt->mnCacheItem, aIt->msCaption ) );
             }
-            // #FIXME find another way out of this const nightmare prison
             if ( !captionList.empty() )
-                const_cast<PivotCacheField*>( pCacheField )->applyItemCaptions( captionList );
+                pCacheField->applyItemCaptions( captionList );
+
             maDPFieldName = pCacheField->createParentGroupField( rxBaseDPField, rBaseCacheField, orItemNames );
+            pCacheField->setFinalGroupName(maDPFieldName);
             // on success, try to create nested group fields
             Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
             if( xDPField.is() )
@@ -461,6 +466,33 @@ void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotF
     }
 }
 
+void PivotTableField::finalizeImportBasedOnCache( const Reference< XDataPilotDescriptor >& rxDPDesc)
+{
+    /*  Process all fields based on source data, other fields (e.g. group
+        fields) are processed based on cache fields.*/
+    Reference< XDataPilotField > xDPField;
+    sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
+    if( (nDatabaseIdx >= 0) && rxDPDesc.is() ) try
+    {
+        // Try to get the source field and its name from passed DataPilot descriptor
+        Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
+        xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
+        Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
+        maDPFieldName = xDPFieldName->getName();
+        SAL_WARN_IF( maDPFieldName.isEmpty(), "sc.filter", "PivotTableField::finalizeImportBasedOnCache - no field name in source data found" );
+    }
+    catch( Exception& )
+    {
+    }
+
+    // Use group names already generated for another table using the same group field.
+    if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
+    {
+        if(!pCacheField->getFinalGroupName().isEmpty())
+            maDPFieldName = pCacheField->getFinalGroupName();
+    }
+}
+
 void PivotTableField::convertRowField()
 {
     convertRowColPageField( XML_axisRow );
@@ -1190,7 +1222,7 @@ void PivotTable::finalizeImport()
                 aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill );
 
                 // finalize all fields, this finds field names and creates grouping fields
-                maFields.forEachMem(&PivotTableField::finalizeImport, ::std::cref(mxDPDescriptor));
+                finalizeFieldsImport();
 
                 // all row fields
                 for( IndexVector::iterator aIt = maRowFields.begin(), aEnd = maRowFields.end(); aIt != aEnd; ++aIt )
@@ -1250,6 +1282,36 @@ void PivotTable::finalizeImport()
     }
 }
 
+void PivotTable::finalizeFieldsImport()
+{
+    if (maFields.empty())
+        return;
+
+    /* Check whether group fields are already imported for an other table
+       sharing the same groups. */
+    ScDPObject* pDPObj = getDPObject();
+    const ScDocument& rDoc = getDocImport().getDoc();
+    if (rDoc.HasPivotTable())
+    {
+        const ScDPCollection* pDPCollection = rDoc.GetDPCollection();
+        assert(pDPCollection != nullptr);
+        const ScDPDimensionSaveData* pGroups = nullptr;
+        bool bRefFound = pDPCollection->GetReferenceGroups(*pDPObj, &pGroups);
+        // Apply reference groups on this table.
+        if (bRefFound && pGroups && pGroups->HasGroupDimensions()) {
+            ScDPSaveData* pSaveData = pDPObj->GetSaveData();
+            if (pSaveData) {
+                pSaveData->SetDimensionData(pGroups);
+                pDPObj->ReloadGroupTableData();
+                maFields.forEachMem(&PivotTableField::finalizeImportBasedOnCache, ::std::cref(mxDPDescriptor));
+                return;
+            }
+
+        }
+    }
+    maFields.forEachMem(&PivotTableField::finalizeImport, ::std::cref(mxDPDescriptor));
+}
+
 void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
 {
     // process all fields, there is no chaining information in the cache fields
@@ -1300,6 +1362,11 @@ Reference< XDataPilotField > PivotTable::getDataLayoutField() const
     return xDPField;
 }
 
+PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx )
+{
+    return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
+}
+
 const PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx ) const
 {
     return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx
index 983f29d..acbace6 100644
--- a/sc/source/ui/docshell/dbdocfun.cxx
+++ b/sc/source/ui/docshell/dbdocfun.cxx
@@ -1386,6 +1386,19 @@ bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool
     if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName()))
         rDestObj.SetName(OUString());      // ignore the invalid name, create a new name below
 
+    // Syncronize groups between linked tables
+    {
+        bool bRefFound = false;
+        const ScDPDimensionSaveData* pGroups = nullptr;
+        bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups);
+        if (bRefFound)
+        {
+            ScDPSaveData* pSaveData = rDestObj.GetSaveData();
+            if (pSaveData)
+                pSaveData->SetDimensionData(pGroups);
+        }
+    }
+
     if (!rDoc.GetDPCollection()->InsertNewTable(pDestObj.release()))
         // Insertion into collection failed.
         return false;
@@ -1567,25 +1580,34 @@ void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj)
     if (!pSaveData)
         return;
 
-    std::set<ScDPObject*> aRefs;
-    if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
-        return;
-
-    // We allow pDimData being NULL.
-    const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
-    std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
-    for (; it != itEnd; ++it)
+    // Update all linked tables, if this table is part of the cache (ScDPCollection)
+    if (pDPs->HasTable(pDPObj))
     {
-        ScDPObject* pObj = *it;
-        if (pObj != pDPObj)
+        std::set<ScDPObject*> aRefs;
+        if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
+            return;
+
+        // We allow pDimData being NULL.
+        const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
+        std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
+        for (; it != itEnd; ++it)
         {
-            pSaveData = pObj->GetSaveData();
-            if (pSaveData)
-                pSaveData->SetDimensionData(pDimData);
-        }
+            ScDPObject* pObj = *it;
+            if (pObj != pDPObj)
+            {
+                pSaveData = pObj->GetSaveData();
+                if (pSaveData)
+                    pSaveData->SetDimensionData(pDimData);
+            }
 
-        // This action is intentionally not undoable since it modifies cache.
-        UpdatePivotTable(*pObj, false, false);
+            // This action is intentionally not undoable since it modifies cache.
+            UpdatePivotTable(*pObj, false, false);
+        }
+    }
+    else // Otherwise update only this single table
+    {
+        // This table is under construction so no need for a whole update (UpdatePivotTable()).
+        pDPObj->ReloadGroupTableData();
     }
 }
 
diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx
index 32f43a3..97c35e9 100644
--- a/sc/source/ui/unoobj/dapiuno.cxx
+++ b/sc/source/ui/unoobj/dapiuno.cxx
@@ -2790,7 +2790,7 @@ Reference < XDataPilotField > SAL_CALL ScDataPilotFieldObj::createDateGroup( con
 
         // apply changes
         pDPObj->SetSaveData( aSaveData );
-        SetDPObject( pDPObj );
+        ScDBDocFunc(*GetDocShell()).RefreshPivotTableGroups(pDPObj);
     }
 
     // return the UNO object of the new dimension, after writing back saved data


More information about the Libreoffice-commits mailing list