diff options
author | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2011-12-17 00:37:45 +0100 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2011-12-17 01:10:07 +0100 |
commit | bfbcd95c3f701251270fac06f9ef58f484580407 (patch) | |
tree | b6520286e8b4ee303070908d6bb9474d07299991 /sc/source | |
parent | Fix assertion in PageSelector::CheckConsistency() (diff) | |
download | core-bfbcd95c3f701251270fac06f9ef58f484580407.tar.gz core-bfbcd95c3f701251270fac06f9ef58f484580407.zip |
Copy Absolute Formulas between documents: Part I
Copying absolute sheet references between different documents now transforms absolute sheet
references into external references if the refered range is not copied.
Working:
References to already saved documents work already with:
-only transform reference into an external reference if range is not in
the copied range
-don't transform relative references
Missing:
handling for copying from not yet saved files
idea:
- add handling of external references to open documents that are not yet
saved through the temporary document name
- transform the url to the correct file url as soon as the source document is
saved
- if target document is saved first show warning message to the user and
save with temporary name as file url
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/data/cell.cxx | 5 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 52 | ||||
-rw-r--r-- | sc/source/core/tool/reftokenhelper.cxx | 59 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 89 |
4 files changed, 203 insertions, 2 deletions
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index 6cc8209f909e..f86d8987e3f0 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -881,6 +881,11 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons adjustDBRange(pToken, rDoc, rCell.pDocument); } } + + if (pDocument->GetPool() != rCell.pDocument->GetPool()) + { + pCode->ReadjusteAbsolute3DReferences( rCell.pDocument, &rDoc, rCell.aPos); + } } if( !bCompile ) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index efb003ba8f1b..d12601fe992e 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -42,12 +42,14 @@ #include <svx/svdocapt.hxx> #include <sfx2/app.hxx> #include <sfx2/objsh.hxx> +#include <sfx2/docfile.hxx> #include <svl/poolcach.hxx> #include <unotools/saveopt.hxx> #include <svl/zforlist.hxx> #include <unotools/charclass.hxx> #include <unotools/transliterationwrapper.hxx> #include <tools/tenccvt.hxx> +#include <tools/urlobj.hxx> #include <com/sun/star/text/WritingMode2.hpp> #include <com/sun/star/script/vba/XVBACompatibility.hpp> @@ -97,6 +99,9 @@ #include <map> #include <limits> +#include <rtl/oustringostreaminserter.hxx> +#include <iostream> + using ::editeng::SvxBorderLine; using namespace ::com::sun::star; @@ -180,6 +185,14 @@ bool ScDocument::GetName( SCTAB nTab, rtl::OUString& rName ) const return false; } +rtl::OUString ScDocument::GetCopyTabName( SCTAB nTab ) const +{ + if (nTab < static_cast<SCTAB>(maTabNames.size())) + return maTabNames[nTab]; + else + return rtl::OUString(); +} + bool ScDocument::SetCodeName( SCTAB nTab, const rtl::OUString& rName ) { if (VALIDTAB(nTab) && nTab < static_cast<SCTAB>(maTabs.size())) @@ -1675,6 +1688,7 @@ void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSe xPoolHelper = pSrcDoc->xPoolHelper; + rtl::OUString aString; for (SCTAB nTab = 0; nTab <= rTabSelection.GetLastSelected(); nTab++) if ( rTabSelection.GetTableSelect( nTab ) ) @@ -1694,9 +1708,9 @@ void ScDocument::InitUndoSelected( ScDocument* pSrcDoc, const ScMarkData& rTabSe } } else - { + { OSL_FAIL("InitUndo"); - } + } } @@ -1708,6 +1722,12 @@ void ScDocument::InitUndo( ScDocument* pSrcDoc, SCTAB nTab1, SCTAB nTab2, Clear(); xPoolHelper = pSrcDoc->xPoolHelper; + if (pSrcDoc->pShell->GetMedium()) + { + maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI); + std::cout << "SfxMedium: " << maFileURL << std::endl; + std::cout << "GetName: " << rtl::OUString(pSrcDoc->pShell->GetName()) << std::endl; + } rtl::OUString aString; if ( nTab2 >= static_cast<SCTAB>(maTabs.size())) @@ -1893,6 +1913,34 @@ void ScDocument::CopyToClip(const ScClipParam& rClipParam, pClipDoc = SC_MOD()->GetClipDoc(); } + if (pShell->GetMedium()) + { + pClipDoc->maFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI); + // for unsaved files use the title name and adjust during save of file + if (pClipDoc->maFileURL.isEmpty()) + pClipDoc->maFileURL = pShell->GetName(); + + std::cout << pClipDoc->maFileURL << std::endl; + std::cout << "GetName: " << rtl::OUString(pShell->GetName()) << std::endl; + } + else + { + pClipDoc->maFileURL = pShell->GetName(); + } + + //init maTabNames + for (TableContainer::iterator itr = maTabs.begin(); itr != maTabs.end(); ++itr) + { + if( *itr ) + { + rtl::OUString aTabName; + (*itr)->GetName(aTabName); + pClipDoc->maTabNames.push_back(aTabName); + } + else + pClipDoc->maTabNames.push_back(rtl::OUString()); + } + pClipDoc->aDocName = aDocName; pClipDoc->SetClipParam(rClipParam); ScRange aClipRange = rClipParam.getWholeRange(); diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx index 0a7ed4e64d99..1d966f1dea0d 100644 --- a/sc/source/core/tool/reftokenhelper.cxx +++ b/sc/source/core/tool/reftokenhelper.cxx @@ -136,6 +136,9 @@ void ScRefTokenHelper::compileRangeRepresentation( rRefTokens.clear(); } +namespace { + +//may return a relative address void singleRefToAddr(const ScSingleRefData& rRef, ScAddress& rAddr) { if (rRef.IsColRel()) @@ -154,6 +157,27 @@ void singleRefToAddr(const ScSingleRefData& rRef, ScAddress& rAddr) rAddr.SetTab(rRef.nTab); } +//returns an absolute address in reference to rPos +void singleRefToAbsAddr(const ScSingleRefData& rRef, ScAddress& rAddr, const ScAddress& rPos) +{ + if (rRef.IsColRel()) + rAddr.SetCol(rRef.nRelCol + rPos.Col()); + else + rAddr.SetCol(rRef.nCol); + + if (rRef.IsRowRel()) + rAddr.SetRow(rRef.nRelRow + rPos.Row()); + else + rAddr.SetRow(rRef.nRow); + + if (rRef.IsTabRel()) + rAddr.SetTab(rRef.nRelTab + rPos.Tab()); + else + rAddr.SetTab(rRef.nTab); +} + +} + bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, bool bExternal) { StackVar eType = pToken->GetType(); @@ -189,6 +213,41 @@ bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScTokenRef& pTok return false; } +bool ScRefTokenHelper::getAbsRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, const ScAddress& rPos, bool bExternal) +{ + StackVar eType = pToken->GetType(); + switch (pToken->GetType()) + { + case svSingleRef: + case svExternalSingleRef: + { + if ((eType == svExternalSingleRef && !bExternal) || + (eType == svSingleRef && bExternal)) + return false; + + const ScSingleRefData& rRefData = pToken->GetSingleRef(); + singleRefToAbsAddr(rRefData, rRange.aStart, rPos); + rRange.aEnd = rRange.aStart; + return true; + } + case svDoubleRef: + case svExternalDoubleRef: + { + if ((eType == svExternalDoubleRef && !bExternal) || + (eType == svDoubleRef && bExternal)) + return false; + + const ScComplexRefData& rRefData = pToken->GetDoubleRef(); + singleRefToAbsAddr(rRefData.Ref1, rRange.aStart, rPos); + singleRefToAbsAddr(rRefData.Ref2, rRange.aEnd, rPos); + return true; + } + default: + ; // do nothing + } + return false; +} + void ScRefTokenHelper::getRangeListFromTokens(ScRangeList& rRangeList, const vector<ScTokenRef>& rTokens) { vector<ScTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end(); diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 11780223c9bf..0e5433881458 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -37,9 +37,12 @@ #include <string.h> #include <tools/mempool.hxx> #include <osl/diagnose.h> +#include <sfx2/docfile.hxx> #include "token.hxx" #include "tokenarray.hxx" +#include "reftokenhelper.hxx" +#include "clipparam.hxx" #include "compiler.hxx" #include <formula/compiler.hrc> #include "rechead.hxx" @@ -49,6 +52,9 @@ #include "externalrefmgr.hxx" #include "document.hxx" +#include <iostream> +#include <rtl/oustringostreaminserter.hxx> + using ::std::vector; #include <com/sun/star/sheet/ComplexReference.hpp> @@ -1815,5 +1821,88 @@ void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos, } } +namespace { + +void GetExternalTableData(const ScDocument* pOldDoc, const ScDocument* pNewDoc, const SCTAB nTab, rtl::OUString& rTabName, sal_uInt16& rFileId) +{ + rtl::OUString aFileName = pOldDoc->GetFileURL();; + std::cout << aFileName << std::endl; + rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName); + rTabName = pOldDoc->GetCopyTabName(nTab); + std::cout << "TabName: " << rTabName << std::endl; +} + +bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc ) +{ + ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam(); + std::cout << "Col: " << rRange.aStart.Col() << "Row: " << rRange.aStart.Row() << "Tab: " << rRange.aStart.Tab() << std::endl; + return rClipParam.maRanges.In(rRange); +} + +} + +void ScTokenArray::ReadjusteAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos ) +{ + for ( sal_uInt16 j=0; j<nLen; ++j ) + { + switch ( pCode[j]->GetType() ) + { + case svDoubleRef : + { + ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef(); + ScSingleRefData& rRef2 = rRef.Ref2; + ScSingleRefData& rRef1 = rRef.Ref1; + + ScRange aRange; + if (!ScRefTokenHelper::getAbsRangeFromToken(aRange, static_cast<ScToken*>(pCode[j]), rPos)) + continue; // might be an external ref token + + if (IsInCopyRange(aRange, pOldDoc)) + continue; // don't adjust references to copied values + + if ( (rRef2.IsFlag3D() && !rRef2.IsTabRel()) || (rRef1.IsFlag3D() && !rRef1.IsTabRel()) ) + { + rtl::OUString aTabName; + sal_uInt16 nFileId; + GetExternalTableData(pOldDoc, pNewDoc, rRef1.nTab, aTabName, nFileId); + pCode[j]->DecRef(); + ScExternalDoubleRefToken* pToken = new ScExternalDoubleRefToken(nFileId, aTabName, rRef); + pToken->IncRef(); + pCode[j] = pToken; + } + } + break; + case svSingleRef : + { + ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef(); + + ScRange aRange; + if (!ScRefTokenHelper::getAbsRangeFromToken(aRange, static_cast<ScToken*>(pCode[j]), rPos)) + continue; // might be an external ref token + + if (IsInCopyRange(aRange, pOldDoc)) + continue; // don't adjust references to copied values + + if ( rRef.IsFlag3D() && !rRef.IsTabRel() ) + { + rtl::OUString aTabName; + sal_uInt16 nFileId; + GetExternalTableData(pOldDoc, pNewDoc, rRef.nTab, aTabName, nFileId); + //replace with ScExternalSingleRefToken and adjust references + pCode[j]->DecRef(); + ScExternalSingleRefToken* pToken = new ScExternalSingleRefToken(nFileId, aTabName, rRef); + pToken->IncRef(); + pCode[j] = pToken; + } + } + break; + default: + { + // added to avoid warnings + } + } + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |