summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Mohrhard <markus.mohrhard@googlemail.com>2011-08-16 06:50:15 +0200
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2011-08-16 06:58:08 +0200
commit04d2e6469529b6187900659517d6f6dd5ea2cca5 (patch)
tree040472b44cfc3782c222d2acc22727132a25a881
parentade0d4b40af9d1f3f4f16b3bbb55d21ecb6a68e8 (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
-rw-r--r--sc/inc/rangenam.hxx2
-rw-r--r--sc/inc/token.hxx5
-rw-r--r--sc/source/core/data/cell.cxx97
-rw-r--r--sc/source/core/data/table2.cxx6
-rw-r--r--sc/source/core/tool/rangenam.cxx4
-rw-r--r--sc/source/core/tool/token.cxx5
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;