diff options
author | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2011-08-16 06:50:15 +0200 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2011-08-16 06:58:08 +0200 |
commit | 04d2e6469529b6187900659517d6f6dd5ea2cca5 (patch) | |
tree | 040472b44cfc3782c222d2acc22727132a25a881 /sc | |
parent | ade0d4b40af9d1f3f4f16b3bbb55d21ecb6a68e8 (diff) |
update range names/database ranges in formulas cells
we need to update range names/database ranges when we copy/paste formula
cells otherwise the ScNameToken may point to a different entry
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/rangenam.hxx | 2 | ||||
-rw-r--r-- | sc/inc/token.hxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/cell.cxx | 97 | ||||
-rw-r--r-- | sc/source/core/data/table2.cxx | 6 | ||||
-rw-r--r-- | sc/source/core/tool/rangenam.cxx | 4 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 5 |
6 files changed, 113 insertions, 6 deletions
diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index 4411b4895297..5d65bf5876b7 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -104,7 +104,7 @@ public: const String& rName, const ScAddress& rTarget ); // rTarget is ABSPOS jump label - ScRangeData(const ScRangeData& rScRangeData); + ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument = NULL); SC_DLLPUBLIC ~ScRangeData(); diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx index d7cefab1982a..cec672fddb95 100644 --- a/sc/inc/token.hxx +++ b/sc/inc/token.hxx @@ -247,8 +247,9 @@ public: ScNameToken(sal_uInt16 nIndex, bool bGlobal, OpCode eOpCode = ocName); ScNameToken(const ScNameToken& r); virtual ~ScNameToken(); - virtual sal_uInt8 GetByte() const; - virtual sal_uInt16 GetIndex() const; + virtual sal_uInt8 GetByte() const; + virtual void SetByte(sal_uInt8 aGlobal); + virtual sal_uInt16 GetIndex() const; virtual bool operator==( const formula::FormulaToken& rToken ) const; virtual FormulaToken* Clone() const { return new ScNameToken(*this); } }; diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index 89f4cdbb761e..1eb4433da878 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -131,6 +131,88 @@ ScBaseCell* lclCloneCell( const ScBaseCell& rSrcCell, ScDocument& rDestDoc, cons return 0; } +void adjustRangeName(ScToken* pToken, ScDocument& aNewDoc, ScDocument* pOldDoc, ScAddress aNewPos, ScAddress aOldPos) +{ + bool bOldGlobal = static_cast<bool>(pToken->GetByte()); + SCTAB aOldTab = aOldPos.Tab(); + rtl::OUString aRangeName; + int nOldIndex = pToken->GetIndex(); + ScRangeData* pOldRangeData = NULL; + + //search the name of the RangeName + if (!bOldGlobal) + { + pOldRangeData = pOldDoc->GetRangeName(aOldTab)->findByIndex(nOldIndex); + if (!pOldRangeData) + return; //might be an error in the formula array + aRangeName = pOldRangeData->GetName(); + } + else + { + pOldRangeData = pOldDoc->GetRangeName()->findByIndex(nOldIndex); + if (!pOldRangeData) + return; //might be an error in the formula array + aRangeName = pOldRangeData->GetName(); + } + + //find corresponding range name in new document + //first search for local range name then global range names + SCTAB aNewTab = aNewPos.Tab(); + ScRangeName* pRangeName = aNewDoc.GetRangeName(aNewTab); + ScRangeData* pRangeData = NULL; + bool bNewGlobal = false; + //search local range names + if (pRangeName) + { + pRangeData = pRangeName->findByUpperName(aRangeName.toAsciiUpperCase()); + } + //search global range names + if (!pRangeData) + { + //even if it is not in the global scope we'll have a global range name + bNewGlobal = true; + pRangeName = aNewDoc.GetRangeName(); + if (pRangeName) + pRangeData = pRangeName->findByUpperName(aRangeName.toAsciiUpperCase()); + } + //if no range name was found copy it + if (!pRangeData) + { + pRangeData = new ScRangeData(*pOldRangeData, &aNewDoc); + aNewDoc.GetRangeName()->insert(pRangeData); + } + sal_Int32 nIndex = pRangeData->GetIndex(); + pToken->SetIndex(nIndex); + pToken->SetByte(bNewGlobal); +} + +void adjustDBRange(ScToken* pToken, ScDocument& aNewDoc, ScDocument* pOldDoc) +{ + ScDBCollection* pOldDBCollection = pOldDoc->GetDBCollection(); + if (!pOldDBCollection) + return;//strange error case, don't do anything + ScDBCollection::NamedDBs& aOldNamedDBs = pOldDBCollection->getNamedDBs(); + ScDBData* pDBData = aOldNamedDBs.findByIndex(pToken->GetIndex()); + if (!pDBData) + return; //invalid index + rtl::OUString aDBName = pDBData->GetName(); + + //search in new document + ScDBCollection* pNewDBCollection = aNewDoc.GetDBCollection(); + if (!pNewDBCollection) + { + pNewDBCollection = new ScDBCollection(&aNewDoc); + } + ScDBCollection::NamedDBs& aNewNamedDBs = pNewDBCollection->getNamedDBs(); + ScDBData* pNewDBData = aNewNamedDBs.findByName(aDBName); + if (!pNewDBData) + { + pNewDBData = new ScDBData(*pNewDBData); + aNewNamedDBs.insert(pNewDBData); + } + pToken->SetIndex(pNewDBData->GetIndex()); +} + } // namespace ScBaseCell* ScBaseCell::CloneWithoutNote( ScDocument& rDestDoc, int nCloneFlags ) const @@ -771,6 +853,21 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons //! Compile ColRowNames on URM_MOVE/URM_COPY _after_ UpdateReference sal_Bool bCompileLater = false; sal_Bool bClipMode = rCell.pDocument->IsClipboard(); + + //update ScNameTokens + if (!pDocument->IsClipboard()) + { + ScToken* pToken = NULL; + while((pToken = static_cast<ScToken*>(pCode->GetNextName()))!= NULL) + { + OpCode eOpCode = pToken->GetOpCode(); + if (eOpCode == ocName) + adjustRangeName(pToken, rDoc, rCell.pDocument, aPos, rCell.aPos); + else if (eOpCode == ocDBArea) + adjustDBRange(pToken, rDoc, rCell.pDocument); + } + } + if( !bCompile ) { // Name references with references and ColRowNames pCode->Reset(); diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 1954fc62d47b..a11d0c6e8f92 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -463,7 +463,10 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, { if (ValidColRow(nCol1, nRow1) && ValidColRow(nCol2, nRow2)) { - // Inhalte kopieren + // copy content + //local range names need to be copied first for formula cells + if (!pTable->mpRangeName) + pTable->mpRangeName = new ScRangeName(*mpRangeName); SCCOL i; for ( i = nCol1; i <= nCol2; i++) @@ -481,6 +484,7 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, if (pDBDataNoName) pTable->SetAnonymousDBData(new ScDBData(*pDBDataNoName)); + if (pRowFlags && pTable->pRowFlags && mpRowHeights && pTable->mpRowHeights) { pTable->pRowFlags->CopyFromAnded( *pRowFlags, 0, nRow2, CR_MANUALSIZE); diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 14c183334a59..2437eb4844fd 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -167,13 +167,13 @@ ScRangeData::ScRangeData( ScDocument* pDok, eType |= RT_ABSPOS; } -ScRangeData::ScRangeData(const ScRangeData& rScRangeData) : +ScRangeData::ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument) : aName (rScRangeData.aName), aUpperName (rScRangeData.aUpperName), pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // echte Kopie erzeugen (nicht copy-ctor) aPos (rScRangeData.aPos), eType (rScRangeData.eType), - pDoc (rScRangeData.pDoc), + pDoc (pDocument ? pDocument : rScRangeData.pDoc), nIndex (rScRangeData.nIndex), bModified (rScRangeData.bModified), mnMaxRow (rScRangeData.mnMaxRow), diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index baee145b70d8..e9c4e67b718c 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -972,6 +972,11 @@ sal_uInt8 ScNameToken::GetByte() const return static_cast<sal_uInt8>(mbGlobal); } +void ScNameToken::SetByte(sal_uInt8 aGlobal) +{ + mbGlobal = static_cast<bool>(aGlobal); +} + sal_uInt16 ScNameToken::GetIndex() const { return mnIndex; |