From 2ea5c1b6dd1d8fda41c1c1fdc3cf994c4f9e5895 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Thu, 5 Dec 2013 15:37:10 -0500 Subject: [PATCH 040/109] fdo#69984: Handle duplicate field names correctly. Duplicate field names are represented in two ways: 1) 'Name' vs 'Name*' in the UNO part of the pivot engine, and 2) Name,0 vs Name,1 which are a pair of textural name and a numeric duplicate index in the non-UNO part of the engine. But some parts lost this duplicate index information and/or confused the 2 ways of representation. Hopefully this change will sort things out. (cherry picked from commit 7e491281d2ba71490fa22cce1e43ba91f60395e3) Conflicts: sc/inc/pivot.hxx Change-Id: I03ae7b6c011c31ace454679837542d6d0909ecaa Reviewed-on: https://gerrit.libreoffice.org/6944 Reviewed-by: Eike Rathke Tested-by: Eike Rathke --- sc/inc/dputil.hxx | 8 +++++++- sc/inc/pivot.hxx | 26 ++++++++++++++------------ sc/source/core/data/dpobject.cxx | 6 ++++++ sc/source/core/data/dputil.cxx | 21 +++++++++++++++++++++ sc/source/core/data/pivot2.cxx | 7 ++++--- sc/source/ui/dbgui/pvfundlg.cxx | 34 +++++++++++++++++++++++----------- sc/source/ui/dbgui/pvlaydlg.cxx | 7 +++++-- sc/source/ui/inc/pvfundlg.hxx | 4 ++-- 8 files changed, 82 insertions(+), 31 deletions(-) diff --git a/sc/inc/dputil.hxx b/sc/inc/dputil.hxx index 294ca97..e4ed831 100644 --- a/sc/inc/dputil.hxx +++ b/sc/inc/dputil.hxx @@ -26,7 +26,13 @@ public: SC_DLLPUBLIC static OUString getSourceDimensionName(const OUString& rName); - static OUString createDuplicateDimensionName(const OUString& rOriginal, size_t nDupCount); + /** + * Get a duplicate index in case the dimension is a duplicate. It returns + * 0 in case it's an original dimension. + */ + sal_uInt8 static getDuplicateIndex(const OUString& rName); + + SC_DLLPUBLIC static OUString createDuplicateDimensionName(const OUString& rOriginal, size_t nDupCount); static OUString getDateGroupName( sal_Int32 nDatePart, sal_Int32 nValue, SvNumberFormatter* pFormatter, diff --git a/sc/inc/pivot.hxx b/sc/inc/pivot.hxx index 85e19e0..a1e063f 100644 --- a/sc/inc/pivot.hxx +++ b/sc/inc/pivot.hxx @@ -52,13 +52,14 @@ #include #include - -struct ScDPName +struct SC_DLLPUBLIC ScDPName { - OUString maName; /// Original name of the dimension. - OUString maLayoutName; /// Layout name (display name) + OUString maName; ///< Original name of the dimension. + OUString maLayoutName; ///< Layout name (display name) + sal_uInt8 mnDupCount; - explicit ScDPName(const OUString& rName, const OUString& rLayoutName); + ScDPName(); + explicit ScDPName(const OUString& rName, const OUString& rLayoutName, sal_uInt8 nDupCount); }; // ============================================================================ @@ -68,13 +69,14 @@ struct ScDPLabelData OUString maName; /// Original name of the dimension. OUString maLayoutName; /// Layout name (display name) OUString maSubtotalName; - SCCOL mnCol; /// 0-based field index (not the source column index) - long mnOriginalDim; /// original dimension index (>= 0 for duplicated dimension) - sal_uInt16 mnFuncMask; /// Page/Column/Row subtotal function. - sal_Int32 mnUsedHier; /// Used hierarchy. - sal_Int32 mnFlags; /// Flags from the DataPilotSource dimension - bool mbShowAll:1; /// true = Show all (also empty) results. - bool mbIsValue:1; /// true = Sum or count in data field. + SCCOL mnCol; ///< 0-based field index (not the source column index) + long mnOriginalDim; ///< original dimension index (>= 0 for duplicated dimension) + sal_uInt16 mnFuncMask; ///< Page/Column/Row subtotal function. + sal_Int32 mnUsedHier; ///< Used hierarchy. + sal_Int32 mnFlags; ///< Flags from the DataPilotSource dimension + sal_uInt8 mnDupCount; + bool mbShowAll:1; ///< true = Show all (also empty) results. + bool mbIsValue:1; ///< true = Sum or count in data field. bool mbDataLayout:1; struct Member diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index fba73d6..3a45a34 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -2278,10 +2278,16 @@ bool ScDPObject::FillLabelDataForDimension( xDimProp, OUString(SC_UNO_DP_FIELD_SUBTOTALNAME), OUString()); bool bIsValue = true; //! check + + // Name from the UNO dimension object may have trailing '*'s in which + // case it's a duplicate dimension. Convert that to a duplicate index. + + sal_uInt8 nDupCount = ScDPUtil::getDuplicateIndex(aFieldName); aFieldName = ScDPUtil::getSourceDimensionName(aFieldName); rLabelData.maName = aFieldName; rLabelData.mnCol = static_cast(nDim); + rLabelData.mnDupCount = nDupCount; rLabelData.mbDataLayout = bData; rLabelData.mbIsValue = bIsValue; diff --git a/sc/source/core/data/dputil.cxx b/sc/source/core/data/dputil.cxx index d1fc655..e34bc79 100644 --- a/sc/source/core/data/dputil.cxx +++ b/sc/source/core/data/dputil.cxx @@ -68,6 +68,27 @@ OUString ScDPUtil::getSourceDimensionName(const OUString& rName) return comphelper::string::stripEnd(rName, '*'); } +sal_uInt8 ScDPUtil::getDuplicateIndex(const OUString& rName) +{ + // Count all trailing '*'s. + + sal_Int32 n = rName.getLength(); + if (!n) + return 0; + + sal_uInt8 nDupCount = 0; + const sal_Unicode* p = rName.getStr(); + const sal_Unicode* pStart = p; + p += n-1; // Set it to the last char. + for (; p != pStart; --p, ++nDupCount) + { + if (*p != '*') + break; + } + + return nDupCount; +} + OUString ScDPUtil::createDuplicateDimensionName(const OUString& rOriginal, size_t nDupCount) { if (!nDupCount) diff --git a/sc/source/core/data/pivot2.cxx b/sc/source/core/data/pivot2.cxx index e8aed77..9460632 100644 --- a/sc/source/core/data/pivot2.cxx +++ b/sc/source/core/data/pivot2.cxx @@ -58,10 +58,10 @@ bool equals(const DataPilotFieldReference& left, const DataPilotFieldReference& } -// ============================================================================ +ScDPName::ScDPName() : mnDupCount(0) {} -ScDPName::ScDPName(const OUString& rName, const OUString& rLayoutName) : - maName(rName), maLayoutName(rLayoutName) {} +ScDPName::ScDPName(const OUString& rName, const OUString& rLayoutName, sal_uInt8 nDupCount) : + maName(rName), maLayoutName(rLayoutName), mnDupCount(nDupCount) {} // ============================================================================ @@ -85,6 +85,7 @@ ScDPLabelData::ScDPLabelData() : mnFuncMask(PIVOT_FUNC_NONE), mnUsedHier(0), mnFlags(0), + mnDupCount(0), mbShowAll(false), mbIsValue(false), mbDataLayout(false) diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx index f9e468b..af369f4 100644 --- a/sc/source/ui/dbgui/pvfundlg.cxx +++ b/sc/source/ui/dbgui/pvfundlg.cxx @@ -35,6 +35,7 @@ #include "dpsave.hxx" #include "pvfundlg.hrc" #include "globstr.hrc" +#include "dputil.hxx" #include @@ -574,8 +575,13 @@ void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const else rLabelData.maSortInfo.Mode = DataPilotFieldSortMode::DATA; - rLabelData.maSortInfo.Field = GetFieldName(maLbSortBy.GetSelectEntry()); - rLabelData.maSortInfo.IsAscending = maRbSortAsc.IsChecked(); + ScDPName aFieldName = GetFieldName(maLbSortBy.GetSelectEntry()); + if (!aFieldName.maName.isEmpty()) + { + rLabelData.maSortInfo.Field = + ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount); + rLabelData.maSortInfo.IsAscending = maRbSortAsc.IsChecked(); + } // *** LAYOUT MODE *** @@ -584,10 +590,15 @@ void ScDPSubtotalOptDlg::FillLabelData( ScDPLabelData& rLabelData ) const // *** AUTO SHOW *** - rLabelData.maShowInfo.IsEnabled = maCbShow.IsChecked(); - rLabelData.maShowInfo.ShowItemsMode = maLbShowFromWrp.GetControlValue(); - rLabelData.maShowInfo.ItemCount = sal::static_int_cast( maNfShow.GetValue() ); - rLabelData.maShowInfo.DataField = GetFieldName(maLbShowUsing.GetSelectEntry()); + aFieldName = GetFieldName(maLbShowUsing.GetSelectEntry()); + if (!aFieldName.maName.isEmpty()) + { + rLabelData.maShowInfo.IsEnabled = maCbShow.IsChecked(); + rLabelData.maShowInfo.ShowItemsMode = maLbShowFromWrp.GetControlValue(); + rLabelData.maShowInfo.ItemCount = sal::static_int_cast( maNfShow.GetValue() ); + rLabelData.maShowInfo.DataField = + ScDPUtil::createDuplicateDimensionName(aFieldName.maName, aFieldName.mnDupCount); + } // *** HIDDEN ITEMS *** @@ -613,7 +624,7 @@ void ScDPSubtotalOptDlg::Init( const ScDPNameVec& rDataFields, bool bEnableLayou for( ScDPNameVec::const_iterator aIt = rDataFields.begin(), aEnd = rDataFields.end(); aIt != aEnd; ++aIt ) { // Cache names for later lookup. - maDataFieldNameMap.insert(NameMapType::value_type(aIt->maLayoutName, aIt->maName)); + maDataFieldNameMap.insert(NameMapType::value_type(aIt->maLayoutName, *aIt)); maLbSortBy.InsertEntry( aIt->maLayoutName ); maLbShowUsing.InsertEntry( aIt->maLayoutName ); // for AutoShow @@ -714,10 +725,10 @@ void ScDPSubtotalOptDlg::InitHideListBox() maLbHide.Enable( bEnable ); } -const OUString& ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const +ScDPName ScDPSubtotalOptDlg::GetFieldName(const OUString& rLayoutName) const { NameMapType::const_iterator itr = maDataFieldNameMap.find(rLayoutName); - return itr == maDataFieldNameMap.end() ? rLayoutName : itr->second; + return itr == maDataFieldNameMap.end() ? ScDPName() : itr->second; } sal_uInt16 ScDPSubtotalOptDlg::FindListBoxEntry( @@ -728,8 +739,9 @@ sal_uInt16 ScDPSubtotalOptDlg::FindListBoxEntry( while (nPos < rLBox.GetEntryCount()) { // translate the displayed field name back to its original field name. - const OUString& rName = GetFieldName(rLBox.GetEntry(nPos)); - if (rName.equals(rEntry)) + ScDPName aName = GetFieldName(rLBox.GetEntry(nPos)); + OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aName.maName, aName.mnDupCount); + if (aUnoName.equals(rEntry)) { bFound = true; break; diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx index 79178c9..b682845 100644 --- a/sc/source/ui/dbgui/pvlaydlg.cxx +++ b/sc/source/ui/dbgui/pvlaydlg.cxx @@ -60,6 +60,7 @@ #include "dpsave.hxx" #include "dpshttab.hxx" #include "scmod.hxx" +#include "dputil.hxx" #include "sc.hrc" #include "scabstdlg.hxx" @@ -783,7 +784,7 @@ void ScPivotLayoutDlg::NotifyDoubleClick( ScPivotFieldType eType, size_t nFieldI OUString aFuncStr = GetFuncString(nMask); aLayoutName = aFuncStr + pDFData->maName; } - aDataFieldNames.push_back(ScDPName(pDFData->maName, aLayoutName)); + aDataFieldNames.push_back(ScDPName(pDFData->maName, aLayoutName, pDFData->mnDupCount)); } bool bLayout = (eType == PIVOTFIELDTYPE_ROW) && @@ -1588,7 +1589,9 @@ IMPL_LINK_NOARG(ScPivotLayoutDlg, OkHdl) for( ScDPLabelDataVector::const_iterator aIt = maLabelData.begin(), aEnd = maLabelData.end(); aIt != aEnd; ++aIt ) { - ScDPSaveDimension* pDim = aSaveData.GetExistingDimensionByName(aIt->maName); + // "UNO" name may have trailing '*'s which signifies duplicate index. + OUString aUnoName = ScDPUtil::createDuplicateDimensionName(aIt->maName, aIt->mnDupCount); + ScDPSaveDimension* pDim = aSaveData.GetExistingDimensionByName(aUnoName); if (!pDim) continue; diff --git a/sc/source/ui/inc/pvfundlg.hxx b/sc/source/ui/inc/pvfundlg.hxx index c02cb5c..6ad269d 100644 --- a/sc/source/ui/inc/pvfundlg.hxx +++ b/sc/source/ui/inc/pvfundlg.hxx @@ -162,7 +162,7 @@ private: void Init( const ScDPNameVec& rDataFields, bool bEnableLayout ); void InitHideListBox(); - const OUString& GetFieldName(const OUString& rLayoutName) const; + ScDPName GetFieldName(const OUString& rLayoutName) const; /** Searches for a listbox entry, starts search at specified position. */ sal_uInt16 FindListBoxEntry( const ListBox& rLBox, const String& rEntry, sal_uInt16 nStartPos ) const; @@ -203,7 +203,7 @@ private: ScDPObject& mrDPObj; /// The DataPilot object (for member names). ScDPLabelData maLabelData; /// Cache for members data. - typedef ::boost::unordered_map< OUString, OUString, OUStringHash > NameMapType; + typedef ::boost::unordered_map NameMapType; NameMapType maDataFieldNameMap; /// Cache for displayed name to field name mapping. }; -- 1.8.4.2