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 | |
parent | 45a570f55b66c992d7dd1fccfae4424a40d624d5 (diff) |
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
-rw-r--r-- | sc/inc/document.hxx | 8 | ||||
-rw-r--r-- | sc/inc/reftokenhelper.hxx | 1 | ||||
-rw-r--r-- | sc/inc/tokenarray.hxx | 3 | ||||
-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 |
7 files changed, 213 insertions, 4 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index d39940f8685f..526ad41f740f 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -242,6 +242,7 @@ private: ScValidationDataList* pValidationList; // validity SvNumberFormatterIndexTable* pFormatExchangeList; // for application of number formats TableContainer maTabs; + std::vector<rtl::OUString> maTabNames; // for undo document, we need the information tab name <-> index mutable ScRangeName* pRangeName; ScDBCollection* pDBCollection; ScDPCollection* pDPCollection; @@ -280,8 +281,9 @@ private: mutable ::std::auto_ptr< ScFormulaParserPool > mxFormulaParserPool; /// Pool for all external formula parsers used by this document. - rtl::OUString aDocName; // optional: name of document - rtl::OUString aDocCodeName; // optional: name of document (twice?) + rtl::OUString aDocName; // optional: name of document + rtl::OUString aDocCodeName; // optional: name of document (twice?) + rtl::OUString maFileURL; // file URL for copy & paste ScRangePairListRef xColNameRanges; ScRangePairListRef xRowNameRanges; @@ -432,6 +434,7 @@ public: void SetName( const rtl::OUString& r ) { aDocName = r; } const rtl::OUString& GetCodeName() const { return aDocCodeName; } void SetCodeName( const rtl::OUString& r ) { aDocCodeName = r; } + const rtl::OUString& GetFileURL() const { return maFileURL; } void GetDocStat( ScDocStat& rDocStat ); @@ -533,6 +536,7 @@ public: SC_DLLPUBLIC bool GetCodeName( SCTAB nTab, rtl::OUString& rName ) const; SC_DLLPUBLIC bool SetCodeName( SCTAB nTab, const rtl::OUString& rName ); SC_DLLPUBLIC bool GetTable( const rtl::OUString& rName, SCTAB& rTab ) const; + rtl::OUString GetCopyTabName(SCTAB nTab) const; SC_DLLPUBLIC void SetAnonymousDBData(SCTAB nTab, ScDBData* pDBData); SC_DLLPUBLIC ScDBData* GetAnonymousDBData(SCTAB nTab); diff --git a/sc/inc/reftokenhelper.hxx b/sc/inc/reftokenhelper.hxx index 9119e3eb9b82..c076f343937a 100644 --- a/sc/inc/reftokenhelper.hxx +++ b/sc/inc/reftokenhelper.hxx @@ -58,6 +58,7 @@ public: const sal_Unicode cSep, ::formula::FormulaGrammar::Grammar eGrammar); static bool getRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, bool bExternal = false); + static bool getAbsRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, const ScAddress& rPos, bool bExternal = false); static void getRangeListFromTokens(ScRangeList& rRangeList, const ::std::vector<ScTokenRef>& pTokens); diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index b2f4565d5a45..f766a46a66d0 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -95,6 +95,9 @@ public: void ReadjustRelative3DReferences( const ScAddress& rOldPos, const ScAddress& rNewPos ); + + // Make all absolute references external references pointing to the old document + void ReadjusteAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos ); }; #endif // SC_TOKENARRAY_HXX 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: */ |