sc/inc/document.hxx | 4 +++ sc/inc/rangenam.hxx | 20 +++++++++++---- sc/source/core/data/document10.cxx | 48 ++++++++++++++++++++++++++++++++++++ sc/source/core/tool/rangenam.cxx | 23 +++++++++++------ sc/source/ui/docshell/docfunc.cxx | 2 - sc/source/ui/namedlg/namedefdlg.cxx | 2 - sc/source/ui/namedlg/namedlg.cxx | 7 ++++- sc/source/ui/undo/undorangename.cxx | 2 - 8 files changed, 91 insertions(+), 17 deletions(-)
New commits: commit 9710fd565f17278dc5e5ee645b3924544a8c4235 Author: Eike Rathke <er...@redhat.com> Date: Tue Jul 26 16:32:15 2016 +0200 Resolves: tdf#87474 handle renaming of named expressions/ranges in formulas Change-Id: If82b62505624c3c259371fa37de1994a94bbceb5 diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 5d03418..eccc49c 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -648,8 +648,12 @@ public: /** * Call this immediately before updating all named ranges. */ + SC_DLLPUBLIC void PreprocessAllRangeNamesUpdate( const std::map<OUString, std::unique_ptr<ScRangeName>>& rRangeMap ); SC_DLLPUBLIC void PreprocessRangeNameUpdate(); SC_DLLPUBLIC void PreprocessDBDataUpdate(); + /** + * Call this immediately after updating named ranges. + */ SC_DLLPUBLIC void CompileHybridFormula(); /** diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index a7a5aa8..e21c5b3 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -60,8 +60,9 @@ public: }; private: - OUString aName; - OUString aUpperName; // #i62977# for faster searching (aName is never modified after ctor) + OUString aName; + OUString aUpperName; // #i62977# for faster searching (aName is never modified after ctor) + OUString maNewName; ///< used for formulas after changing names in the dialog ScTokenArray* pCode; ScAddress aPos; Type eType; @@ -106,13 +107,15 @@ public: bool operator== (const ScRangeData& rData) const; - void GetName( OUString& rName ) const { rName = aName; } - const OUString& GetName() const { return aName; } + void GetName( OUString& rName ) const { rName = maNewName.isEmpty() ? aName : maNewName; } + const OUString& GetName() const { return maNewName.isEmpty() ? aName : maNewName; } const OUString& GetUpperName() const { return aUpperName; } const ScAddress& GetPos() const { return aPos; } // The index has to be unique. If index=0 a new index value is assigned. void SetIndex( sal_uInt16 nInd ) { nIndex = nInd; } sal_uInt16 GetIndex() const { return nIndex; } + /// Does not change the name, but sets maNewName for formula update after dialog. + void SetNewName( const OUString& rNewName ) { maNewName = rNewName; } ScTokenArray* GetCode() { return pCode; } SC_DLLPUBLIC void SetCode( ScTokenArray& ); const ScTokenArray* GetCode() const { return pCode; } @@ -244,8 +247,15 @@ public: @ATTENTION: The underlying ::std::map<std::unique_ptr>::insert(p) takes ownership of p and if it can't insert it deletes the object! So, if this insert here returns false the object where p pointed to is gone! + + @param bReuseFreeIndex + If the ScRangeData p points to has an index value of 0: + If `TRUE` then reuse a free index slot if available. + If `FALSE` then assign a new index slot. The Manage Names + dialog uses this so that deleting and adding ranges in the same + run is guaranteed to not reuse previously assigned indexes. */ - SC_DLLPUBLIC bool insert(ScRangeData* p); + SC_DLLPUBLIC bool insert( ScRangeData* p, bool bReuseFreeIndex = true ); void erase(const ScRangeData& r); void erase(const OUString& rName); diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx index 0530566..be9c855 100644 --- a/sc/source/core/data/document10.cxx +++ b/sc/source/core/data/document10.cxx @@ -227,6 +227,54 @@ void ScDocument::SwapNonEmpty( sc::TableValues& rValues ) aEndCxt.purgeEmptyBroadcasters(); } +void ScDocument::PreprocessAllRangeNamesUpdate( const std::map<OUString, std::unique_ptr<ScRangeName>>& rRangeMap ) +{ + // Update all existing names with new names. + // The prerequisites are that the name dialog preserves ScRangeData index + // for changes and does not reuse free index slots for new names. + // ScDocument::SetAllRangeNames() hereafter then will replace the + // ScRangeName containers of ScRangeData instances with empty + // ScRangeData::maNewName. + std::map<OUString, ScRangeName*> aRangeNameMap; + GetRangeNameMap( aRangeNameMap); + for (const auto& itTab : aRangeNameMap) + { + ScRangeName* pOldRangeNames = itTab.second; + if (!pOldRangeNames) + continue; + + const auto& itNewTab( rRangeMap.find( itTab.first)); + if (itNewTab == rRangeMap.end()) + continue; + + const ScRangeName* pNewRangeNames = itNewTab->second.get(); + if (!pNewRangeNames) + continue; + + for (ScRangeName::iterator it( pOldRangeNames->begin()), itEnd( pOldRangeNames->end()); + it != itEnd; ++it) + { + ScRangeData* pOldData = it->second.get(); + if (!pOldData) + continue; + + const ScRangeData* pNewData = pNewRangeNames->findByIndex( pOldData->GetIndex()); + if (pNewData) + pOldData->SetNewName( pNewData->GetName()); + } + } + + sc::EndListeningContext aEndListenCxt(*this); + sc::CompileFormulaContext aCompileCxt(this); + + TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end(); + for (; it != itEnd; ++it) + { + ScTable* p = *it; + p->PreprocessRangeNameUpdate(aEndListenCxt, aCompileCxt); + } +} + void ScDocument::PreprocessRangeNameUpdate() { sc::EndListeningContext aEndListenCxt(*this); diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 7626e16..19d403d 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -831,7 +831,7 @@ bool ScRangeName::empty() const return m_Data.empty(); } -bool ScRangeName::insert(ScRangeData* p) +bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex ) { if (!p) return false; @@ -839,17 +839,24 @@ bool ScRangeName::insert(ScRangeData* p) if (!p->GetIndex()) { // Assign a new index. An index must be unique and is never 0. - IndexDataType::iterator itr = std::find( - maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(nullptr)); - if (itr != maIndexToData.end()) + if (bReuseFreeIndex) { - // Empty slot exists. Re-use it. - size_t nPos = std::distance(maIndexToData.begin(), itr); - p->SetIndex(nPos + 1); + IndexDataType::iterator itr = std::find( + maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(nullptr)); + if (itr != maIndexToData.end()) + { + // Empty slot exists. Re-use it. + size_t nPos = std::distance(maIndexToData.begin(), itr); + p->SetIndex(nPos + 1); + } + else + // No empty slot. Append it to the end. + p->SetIndex(maIndexToData.size() + 1); } else - // No empty slot. Append it to the end. + { p->SetIndex(maIndexToData.size() + 1); + } } OUString aName(p->GetUpperName()); diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index d2b1cc8..1f4ed8d 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -4908,7 +4908,7 @@ void ScDocFunc::ModifyAllRangeNames(const std::map<OUString, std::unique_ptr<ScR new ScUndoAllRangeNames(&rDocShell, aOldRangeMap, rRangeMap)); } - rDoc.PreprocessRangeNameUpdate(); + rDoc.PreprocessAllRangeNamesUpdate(rRangeMap); rDoc.SetAllRangeNames(rRangeMap); rDoc.CompileHybridFormula(); diff --git a/sc/source/ui/namedlg/namedefdlg.cxx b/sc/source/ui/namedlg/namedefdlg.cxx index bb65077..73a293b 100644 --- a/sc/source/ui/namedlg/namedefdlg.cxx +++ b/sc/source/ui/namedlg/namedefdlg.cxx @@ -235,7 +235,7 @@ void ScNameDefDlg::AddPushed() // aExpression valid? if ( 0 == pNewEntry->GetErrCode() ) { - if ( !pRangeName->insert( pNewEntry ) ) + if ( !pRangeName->insert( pNewEntry, false /*bReuseFreeIndex*/ ) ) pNewEntry = nullptr; if (mbUndo) diff --git a/sc/source/ui/namedlg/namedlg.cxx b/sc/source/ui/namedlg/namedlg.cxx index 4f0164e..ba3d9cd 100644 --- a/sc/source/ui/namedlg/namedlg.cxx +++ b/sc/source/ui/namedlg/namedlg.cxx @@ -405,6 +405,10 @@ void ScNameDlg::NameModified() // be safe and check for range data if (pData) { + // Assign new index (0) only if the scope is changed, else keep the + // existing index. + sal_uInt16 nIndex = (aNewScope != aOldScope ? 0 : pData->GetIndex()); + pOldRangeName->erase(*pData); mbNeedUpdate = false; m_pRangeManagerTable->DeleteSelectedEntries(); @@ -416,7 +420,8 @@ void ScNameDlg::NameModified() ScRangeData* pNewEntry = new ScRangeData( mpDoc, aNewName, aExpr, maCursorPos, nType); - pNewRangeName->insert(pNewEntry); + pNewEntry->SetIndex( nIndex); + pNewRangeName->insert(pNewEntry, false /*bReuseFreeIndex*/); aLine.aName = aNewName; aLine.aExpression = aExpr; aLine.aScope = aNewScope; diff --git a/sc/source/ui/undo/undorangename.cxx b/sc/source/ui/undo/undorangename.cxx index eb42eb4..f775269 100644 --- a/sc/source/ui/undo/undorangename.cxx +++ b/sc/source/ui/undo/undorangename.cxx @@ -70,7 +70,7 @@ void ScUndoAllRangeNames::DoChange(const std::map<OUString, std::unique_ptr<ScRa { ScDocument& rDoc = pDocShell->GetDocument(); - rDoc.PreprocessRangeNameUpdate(); + rDoc.PreprocessAllRangeNamesUpdate(rNames); rDoc.SetAllRangeNames(rNames); rDoc.CompileHybridFormula(); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits