summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sc/inc/document.hxx12
-rw-r--r--sc/inc/externalrefmgr.hxx30
-rw-r--r--sc/inc/globstr.hrc4
-rw-r--r--sc/inc/tokenarray.hxx15
-rw-r--r--sc/qa/unit/ucalc.cxx2
-rw-r--r--sc/source/core/data/cell.cxx14
-rw-r--r--sc/source/core/data/documen2.cxx24
-rw-r--r--sc/source/core/data/document.cxx195
-rw-r--r--sc/source/core/tool/reftokenhelper.cxx5
-rw-r--r--sc/source/core/tool/token.cxx174
-rw-r--r--sc/source/ui/docshell/docsh.cxx31
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx86
-rw-r--r--sc/source/ui/src/globstr.src8
-rw-r--r--sc/source/ui/view/viewfun2.cxx5
14 files changed, 451 insertions, 154 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index d39940f8685f..83ad4a1a6cae 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);
@@ -1860,10 +1864,6 @@ private: // CLOOK-Impl-methods
void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, const ScMarkData* pMarks, bool bAllTabs);
void CopyRangeNamesToClip(ScDocument* pClipDoc, const ScRange& rClipRange, SCTAB nTab);
- void CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames);
- void UpdateRangeNamesInFormulas(
- ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
- SCCOL nXw, SCROW nYw);
bool HasPartOfMerged( const ScRange& rRange );
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index e39ac2ed6077..c44c8f1dc623 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -33,9 +33,11 @@
#include "address.hxx"
#include "sfx2/objsh.hxx"
#include "sfx2/lnkbase.hxx"
+#include "sfx2/event.hxx"
#include "tools/time.hxx"
#include "vcl/timer.hxx"
#include "svl/zforlist.hxx"
+#include "svl/lstner.hxx"
#include "scmatrix.hxx"
#include "rangelst.hxx"
#include "formula/token.hxx"
@@ -46,6 +48,7 @@
#include <vector>
#include <list>
#include <set>
+#include <iostream>
#include <formula/ExternalReferenceHelper.hxx>
class ScDocument;
@@ -353,7 +356,7 @@ private:
mutable DocDataType maDocs;
};
-class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelper
+class SC_DLLPUBLIC ScExternalRefManager : public formula::ExternalReferenceHelper, SfxListener
{
public:
@@ -426,6 +429,7 @@ public:
::rtl::OUString maRelativeName;
::rtl::OUString maFilterName;
::rtl::OUString maFilterOptions;
+ bool bUnsaved;
void maybeCreateRealFileName(const String& rOwnDocName);
};
@@ -673,6 +677,23 @@ public:
*/
bool isFileLoadable(const ::rtl::OUString& rFile) const;
+ /**
+ * If in maUnsavedDocShells move it to maDocShells and create a correct
+ * external reference entry
+ *
+ * @param Pointer to the newly saved DocumentShell
+ */
+ void transformUnsavedRefToSavedRef( SfxObjectShell* pShell );
+
+ virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
+
+ /**
+ * If we still contain unsaved files we should warn the user before saving
+ *
+ * @return true if the document still contains references to an unsaved file
+ */
+ bool containsUnsavedReferences() { return !maUnsavedDocShells.empty(); }
+
private:
ScExternalRefManager();
ScExternalRefManager(const ScExternalRefManager&);
@@ -749,6 +770,7 @@ private:
sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, const ScDocument* pSrcDoc);
+
private:
/** cache of referenced ranges and names from source documents. */
ScExternalRefCache maRefCache;
@@ -761,6 +783,12 @@ private:
*/
DocShellMap maDocShells;
+ /**
+ * DocShells to unsaved but referenced documents. If not empty ask before saving!
+ * Move to maDocShells if document referenced here is saved
+ */
+ DocShellMap maUnsavedDocShells;
+
/** list of source documents that are managed by the link manager. */
LinkedDocMap maLinkedDocs;
diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc
index 2363aaf326fa..48f4015cdc97 100644
--- a/sc/inc/globstr.hrc
+++ b/sc/inc/globstr.hrc
@@ -599,8 +599,10 @@
#define STR_ERR_NAME_EXISTS 463
#define STR_ERR_NAME_INVALID 464
+#define STR_UNSAVED_EXT_REF 465
+#define STR_CLOSE_WITH_UNSAVED_REFS 466
-#define STR_COUNT 465
+#define STR_COUNT 467
#endif
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index b2f4565d5a45..48bf4c504287 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -95,6 +95,21 @@ public:
void ReadjustRelative3DReferences(
const ScAddress& rOldPos,
const ScAddress& rNewPos );
+
+ /**
+ * Make all absolute references external references pointing to the old document
+ *
+ * @param pOldDoc old document
+ * @param pNewDoc new document
+ * @param rPos position of the cell to determine if the reference is in the copied area
+ * @param bRangeName set for range names, range names have special handling for absolute sheet ref + relative col/row ref
+ */
+ void ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName = false );
+
+ /**
+ * Make all absolute references pointing to the copied range if the range is copied too
+ */
+ void AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName = false );
};
#endif // SC_TOKENARRAY_HXX
diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx
index 724dcedabdfb..5471c47bfb16 100644
--- a/sc/qa/unit/ucalc.cxx
+++ b/sc/qa/unit/ucalc.cxx
@@ -2746,8 +2746,8 @@ void Test::testCopyPaste()
//check values after copying
rtl::OUString aString;
m_pDoc->GetValue(1,1,1, aValue);
- CPPUNIT_ASSERT_MESSAGE("copied formula should return 2", aValue == 2);
m_pDoc->GetFormula(1,1,1, aString);
+ CPPUNIT_ASSERT_MESSAGE("copied formula should return 2", aValue == 2);
CPPUNIT_ASSERT_MESSAGE("formula string was not copied correctly", aString == aFormulaString);
m_pDoc->GetValue(0,1,1, aValue);
CPPUNIT_ASSERT_MESSAGE("copied value should be 1", aValue == 1);
diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx
index 6cc8209f909e..155f4bdb8df2 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -179,6 +179,13 @@ void adjustRangeName(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOl
{
bNewGlobal = bOldGlobal;
pRangeData = new ScRangeData(*pOldRangeData, &rNewDoc);
+ ScTokenArray* pRangeNameToken = pRangeData->GetCode();
+ if (rNewDoc.GetPool() != const_cast<ScDocument*>(pOldDoc)->GetPool())
+ {
+ pRangeNameToken->ReadjustAbsolute3DReferences(pOldDoc, &rNewDoc, pRangeData->GetPos(), true);
+ pRangeNameToken->AdjustAbsoluteRefs(pOldDoc, aOldPos, aNewPos, true);
+ }
+
bool bInserted;
if (bNewGlobal)
bInserted = rNewDoc.GetRangeName()->insert(pRangeData);
@@ -881,6 +888,13 @@ ScFormulaCell::ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, cons
adjustDBRange(pToken, rDoc, rCell.pDocument);
}
}
+
+ if (pDocument->GetPool() != rCell.pDocument->GetPool())
+ {
+ pCode->ReadjustAbsolute3DReferences( rCell.pDocument, &rDoc, rCell.aPos);
+ }
+
+ pCode->AdjustAbsoluteRefs( rCell.pDocument, rCell.aPos, aPos );
}
if( !bCompile )
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 37005ee37298..aa99070d9b77 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -41,6 +41,7 @@
#include <svx/svdobj.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/objsh.hxx>
+#include <sfx2/docfile.hxx>
#include <sfx2/printer.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
@@ -48,6 +49,7 @@
#include <comphelper/processfactory.hxx>
#include <svl/PasswordHelper.hxx>
#include <tools/tenccvt.hxx>
+#include <tools/urlobj.hxx>
#include <rtl/crc.h>
#include <basic/basmgr.hxx>
@@ -920,8 +922,21 @@ sal_uLong ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
bool bResultsOnly )
{
sal_uLong nRetVal = 1; // 0 => Fehler 1 = ok
- // 2 => RefBox, 3 => NameBox
+ // 3 => NameBox
// 4 => beides
+
+ if (pSrcDoc->pShell->GetMedium())
+ {
+ pSrcDoc->maFileURL = pSrcDoc->pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+ // for unsaved files use the title name and adjust during save of file
+ if (pSrcDoc->maFileURL.isEmpty())
+ pSrcDoc->maFileURL = pSrcDoc->pShell->GetName();
+ }
+ else
+ {
+ pSrcDoc->maFileURL = pSrcDoc->pShell->GetName();
+ }
+
bool bValid = true;
if (bInsertNew) // neu einfuegen
{
@@ -1046,15 +1061,8 @@ sal_uLong ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos,
maTabs[nDestPos]->UpdateReference(URM_COPY, 0, 0, nDestPos,
MAXCOL, MAXROW, nDestPos,
0, 0, nDz, NULL);
- // Test for outside absolute references for info box
- bool bIsAbsRef = pSrcDoc->maTabs[nSrcPos]->TestTabRefAbs(nSrcPos);
// Readjust self-contained absolute references to this sheet
maTabs[nDestPos]->TestTabRefAbs(nSrcPos);
- if (bIsAbsRef)
- {
- nRetVal += 1;
- // InfoBox AbsoluteRefs sind moeglicherweise nicht mehr korrekt!!
- }
if (bNamesLost)
{
nRetVal += 2;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index efb003ba8f1b..eb03a7420b99 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,31 @@ 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();
+ }
+ 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();
@@ -1943,6 +1988,31 @@ void ScDocument::CopyTabToClip(SCCOL nCol1, SCROW nRow1,
{
if (!bIsClip)
{
+ 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();
+ }
+ 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());
+ }
+
PutInOrder( nCol1, nCol2 );
PutInOrder( nRow1, nRow2 );
if (!pClipDoc)
@@ -2114,116 +2184,6 @@ void ScDocument::MergeNumberFormatter(ScDocument* pSrcDoc)
}
}
-void ScDocument::CopyRangeNamesFromClip(ScDocument* pClipDoc, ScClipRangeNameData& rRangeNames)
-{
- if (!pClipDoc->pRangeName)
- return;
-
- ScClipRangeNameData aClipRangeNames;
-
- ScRangeName::const_iterator itr = pClipDoc->pRangeName->begin();
- ScRangeName::const_iterator itrEnd = pClipDoc->pRangeName->end();
- for (; itr != itrEnd; ++itr) //! DB-Bereiche Pivot-Bereiche auch
- {
- /* Copy only if the name doesn't exist in this document.
- If it exists we use the already existing name instead,
- another possibility could be to create new names if
- documents differ.
- A proper solution would ask the user how to proceed.
- The adjustment of the indices in the formulas is done later.
- */
- const ScRangeData* pExistingData = GetRangeName()->findByUpperName(itr->first);
- if (pExistingData)
- {
- sal_uInt16 nOldIndex = itr->second->GetIndex();
- sal_uInt16 nNewIndex = pExistingData->GetIndex();
- aClipRangeNames.insert(nOldIndex, nNewIndex);
- if ( !aClipRangeNames.mbReplace )
- aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
- }
- else
- {
- ScRangeData* pData = new ScRangeData( *itr->second );
- pData->SetDocument(this);
- if ( pRangeName->findByIndex( pData->GetIndex() ) )
- pData->SetIndex(0); // need new index, done in Insert
- if ( pRangeName->insert(pData) )
- {
- aClipRangeNames.mpRangeNames.push_back(pData);
- sal_uInt16 nOldIndex = itr->second->GetIndex();
- sal_uInt16 nNewIndex = pData->GetIndex();
- aClipRangeNames.insert(nOldIndex, nNewIndex);
- if ( !aClipRangeNames.mbReplace )
- aClipRangeNames.mbReplace = ( nOldIndex != nNewIndex );
- }
- else
- { // must be an overflow
- pData = NULL;
- aClipRangeNames.insert(itr->second->GetIndex(), 0);
- aClipRangeNames.mbReplace = true;
- }
- }
- }
- rRangeNames = aClipRangeNames;
-}
-
-void ScDocument::UpdateRangeNamesInFormulas(
- ScClipRangeNameData& rRangeNames, const ScRangeList& rDestRanges, const ScMarkData& rMark,
- SCCOL nXw, SCROW nYw)
-{
- // nXw and nYw are the extra width and height of the destination range
- // extended due to presence of merged cell(s).
-
- if (!rRangeNames.mbReplace)
- return;
-
- // first update all inserted named formulas if they contain other
- // range names and used indices changed
- for (size_t i = 0, n = rRangeNames.mpRangeNames.size(); i < n; ++i) //! DB-Bereiche Pivot-Bereiche auch
- {
- rRangeNames.mpRangeNames[i]->ReplaceRangeNamesInUse(rRangeNames.maRangeMap);
- }
- // then update the formulas, they might need just the updated range names
- for ( size_t nRange = 0, n = rDestRanges.size(); nRange < n; ++nRange )
- {
- const ScRange* pRange = rDestRanges[nRange];
- SCCOL nCol1 = pRange->aStart.Col();
- SCROW nRow1 = pRange->aStart.Row();
- SCCOL nCol2 = pRange->aEnd.Col();
- SCROW nRow2 = pRange->aEnd.Row();
-
- SCCOL nC1 = nCol1;
- SCROW nR1 = nRow1;
- SCCOL nC2 = nC1 + nXw;
- if (nC2 > nCol2)
- nC2 = nCol2;
- SCROW nR2 = nR1 + nYw;
- if (nR2 > nRow2)
- nR2 = nRow2;
- do
- {
- do
- {
- ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
- for (; itr != itrEnd; ++itr)
- {
- if ( maTabs[*itr] )
- maTabs[*itr]->ReplaceRangeNamesInUse(nC1, nR1,
- nC2, nR2, rRangeNames.maRangeMap);
- }
- nC1 = nC2 + 1;
- nC2 = Min((SCCOL)(nC1 + nXw), nCol2);
- } while (nC1 <= nCol2);
- nC1 = nCol1;
- nC2 = nC1 + nXw;
- if (nC2 > nCol2)
- nC2 = nCol2;
- nR1 = nR2 + 1;
- nR2 = Min((SCROW)(nR1 + nYw), nRow2);
- } while (nR1 <= nRow2);
- }
-}
-
ScClipParam& ScDocument::GetClipParam()
{
if (!mpClipParam.get())
@@ -2428,9 +2388,6 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
- ScClipRangeNameData aClipRangeNames;
- CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
-
SCCOL nAllCol1 = rDestRange.aStart.Col();
SCROW nAllRow1 = rDestRange.aStart.Row();
SCCOL nAllCol2 = rDestRange.aEnd.Col();
@@ -2587,8 +2544,6 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar
bInsertingFromOtherDoc = false;
- UpdateRangeNamesInFormulas(aClipRangeNames, *pDestRanges, rMark, nXw, nYw);
-
// Listener aufbauen nachdem alles inserted wurde
StartListeningFromClip( nAllCol1, nAllRow1, nAllCol2, nAllRow2, rMark, nInsFlag );
// nachdem alle Listener aufgebaut wurden, kann gebroadcastet werden
@@ -2631,9 +2586,6 @@ void ScDocument::CopyMultiRangeFromClip(
NumFmtMergeHandler aNumFmtMergeHdl(this, pClipDoc);
- ScClipRangeNameData aClipRangeNames;
- CopyRangeNamesFromClip(pClipDoc, aClipRangeNames);
-
SCCOL nCol1 = rDestPos.Col();
SCROW nRow1 = rDestPos.Row();
ScClipParam& rClipParam = pClipDoc->GetClipParam();
@@ -2728,9 +2680,6 @@ void ScDocument::CopyMultiRangeFromClip(
ScRangeList aRanges;
aRanges.Append(aDestRange);
- SCCOL nCols = aDestRange.aEnd.Col() - aDestRange.aStart.Col() + 1;
- SCROW nRows = aDestRange.aEnd.Row() - aDestRange.aStart.Row() + 1;
- UpdateRangeNamesInFormulas(aClipRangeNames, aRanges, rMark, nCols-1, nRows-1);
// Listener aufbauen nachdem alles inserted wurde
StartListeningFromClip(aDestRange.aStart.Col(), aDestRange.aStart.Row(),
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index 75282575214f..2a32e12de85c 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)
{
rAddr.SetCol(rRef.nCol);
@@ -143,6 +146,8 @@ void singleRefToAddr(const ScSingleRefData& rRef, ScAddress& rAddr)
rAddr.SetTab(rRef.nTab);
}
+}
+
bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScTokenRef& pToken, bool bExternal)
{
StackVar eType = pToken->GetType();
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 11780223c9bf..68de15420ead 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"
@@ -1815,5 +1818,176 @@ 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();;
+ rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName);
+ rTabName = pOldDoc->GetCopyTabName(nTab);
+ if (rTabName.isEmpty())
+ pOldDoc->GetName(nTab, rTabName);
+}
+
+bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc )
+{
+ ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam();
+ return rClipParam.maRanges.In(rRange);
+}
+
+bool SkipReference(ScToken* pToken, const ScAddress& rPos, const ScDocument* pOldDoc, bool bRangeName)
+{
+ ScRange aRange;
+
+ pToken->CalcAbsIfRel(rPos);
+ if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken))
+ return true;
+
+ if (bRangeName && aRange.aStart.Tab() == rPos.Tab())
+ {
+ switch (pToken->GetType())
+ {
+ case svDoubleRef:
+ {
+ ScSingleRefData& rRef = pToken->GetSingleRef2();
+ if (rRef.IsColRel() || rRef.IsRowRel())
+ return true;
+ } // fall through
+ case svSingleRef:
+ {
+ ScSingleRefData& rRef = pToken->GetSingleRef();
+ if (rRef.IsColRel() || rRef.IsRowRel())
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (IsInCopyRange(aRange, pOldDoc))
+ return true;
+
+ return false;
+}
+
+void AdjustSingleRefData( ScSingleRefData& rRef, const ScAddress& rOldPos, const ScAddress& rNewPos)
+{
+ SCsCOL nCols = rNewPos.Col() - rOldPos.Col();
+ SCsROW nRows = rNewPos.Row() - rOldPos.Row();
+ SCsTAB nTabs = rNewPos.Tab() - rOldPos.Tab();
+
+ if (!rRef.IsColRel())
+ rRef.nCol += nCols;
+
+ if (!rRef.IsRowRel())
+ rRef.nRow += nRows;
+
+ if (!rRef.IsTabRel())
+ rRef.nTab += nTabs;
+}
+
+}
+
+void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName )
+{
+ for ( sal_uInt16 j=0; j<nLen; ++j )
+ {
+ switch ( pCode[j]->GetType() )
+ {
+ case svDoubleRef :
+ {
+ if (SkipReference(static_cast<ScToken*>(pCode[j]), rPos, pOldDoc, bRangeName))
+ continue;
+
+ ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef();
+ ScSingleRefData& rRef2 = rRef.Ref2;
+ ScSingleRefData& rRef1 = rRef.Ref1;
+
+ 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 :
+ {
+ if (SkipReference(static_cast<ScToken*>(pCode[j]), rPos, pOldDoc, bRangeName))
+ continue;
+
+ ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef();
+
+ 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
+ }
+ }
+ }
+}
+
+void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName)
+{
+ for ( sal_uInt16 j=0; j<nLen; ++j )
+ {
+ switch ( pCode[j]->GetType() )
+ {
+ case svDoubleRef :
+ {
+ if (!SkipReference(static_cast<ScToken*>(pCode[j]), rOldPos, pOldDoc, false))
+ continue;
+
+ ScComplexRefData& rRef = static_cast<ScToken*>(pCode[j])->GetDoubleRef();
+ ScSingleRefData& rRef2 = rRef.Ref2;
+ ScSingleRefData& rRef1 = rRef.Ref1;
+
+ // for range names only adjust if all parts are absolute
+ if (!bRangeName || !(rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel()))
+ AdjustSingleRefData( rRef1, rOldPos, rNewPos );
+ if (!bRangeName || !(rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel()))
+ AdjustSingleRefData( rRef2, rOldPos, rNewPos );
+
+ }
+ break;
+ case svSingleRef :
+ {
+ if (!SkipReference(static_cast<ScToken*>(pCode[j]), rOldPos, pOldDoc, false))
+ continue;
+
+ ScSingleRefData& rRef = static_cast<ScToken*>(pCode[j])->GetSingleRef();
+
+ // for range names only adjust if all parts are absolute
+ if (!bRangeName || !(rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()))
+ AdjustSingleRefData( rRef, rOldPos, rNewPos );
+
+
+ }
+ break;
+ default:
+ {
+ // added to avoid warnings
+ }
+ }
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 9fa5769ee1ff..8f4f3fc68f9f 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -913,11 +913,25 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
if ( !bSuccess )
SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process
}
+
+
if (pSheetSaveData)
pSheetSaveData->SetInSupportedSave(true);
}
break;
case SFX_EVENT_SAVEASDOC:
+ {
+ if ( GetDocument()->GetExternalRefManager()->containsUnsavedReferences() )
+ {
+ WarningBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO ),
+ ScGlobal::GetRscString( STR_UNSAVED_EXT_REF ) );
+
+ if( RET_NO == aBox.Execute())
+ {
+ SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process
+ }
+ }
+ } // fall through
case SFX_EVENT_SAVETODOC:
// #i108978# If no event is sent before saving, there will also be no "...DONE" event,
// and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled
@@ -926,21 +940,11 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
pSheetSaveData->SetInSupportedSave(true);
break;
case SFX_EVENT_SAVEDOCDONE:
+ case SFX_EVENT_SAVEASDOCDONE:
{
- if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
- {
- }
+ // new positions are used after "save" and "save as", but not "save to"
UseSheetSaveEntries(); // use positions from saved file for next saving
- if (pSheetSaveData)
- pSheetSaveData->SetInSupportedSave(false);
- }
- break;
- case SFX_EVENT_SAVEASDOCDONE:
- // new positions are used after "save" and "save as", but not "save to"
- UseSheetSaveEntries(); // use positions from saved file for next saving
- if (pSheetSaveData)
- pSheetSaveData->SetInSupportedSave(false);
- break;
+ } // fall through
case SFX_EVENT_SAVETODOCDONE:
// only reset the flag, don't use the new positions
if (pSheetSaveData)
@@ -1567,6 +1571,7 @@ sal_Bool ScDocShell::SaveAs( SfxMedium& rMedium )
return false;
}
+
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
PrepareSaveGuard aPrepareGuard( *this);
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 6d23ab9fbf2b..83881a5ecd3d 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -44,6 +44,7 @@
#include "viewdata.hxx"
#include "tabvwsh.hxx"
#include "sc.hrc"
+#include "globstr.hrc"
#include "sfx2/app.hxx"
#include "sfx2/docfilt.hxx"
@@ -61,6 +62,7 @@
#include "tools/urlobj.hxx"
#include "unotools/ucbhelper.hxx"
#include "unotools/localfilehelper.hxx"
+#include "vcl/msgbox.hxx"
#include <memory>
#include <algorithm>
@@ -2092,7 +2094,7 @@ const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileI
while (pShell)
{
SfxMedium* pMedium = pShell->GetMedium();
- if (pMedium)
+ if (pMedium && pMedium->GetName().Len())
{
OUString aName = pMedium->GetName();
// TODO: We should make the case sensitivity platform dependent.
@@ -2103,6 +2105,21 @@ const ScDocument* ScExternalRefManager::getInMemorySrcDocument(sal_uInt16 nFileI
break;
}
}
+ else
+ {
+ // handle unsaved documents here
+ OUString aName = pShell->GetName();
+ if (pFileName->equalsIgnoreAsciiCase(aName))
+ {
+ // Found !
+ SrcShell aSrcDoc;
+ aSrcDoc.maShell = pShell;
+ maUnsavedDocShells.insert(DocShellMap::value_type(nFileId, aSrcDoc));
+ StartListening(*pShell);
+ pSrcDoc = pShell->GetDocument();
+ break;
+ }
+ }
pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
}
@@ -2127,6 +2144,17 @@ const ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
return static_cast<ScDocShell*>(p)->GetDocument();
}
+ itrEnd = maUnsavedDocShells.end();
+ itr = maUnsavedDocShells.find(nFileId);
+ if (itr != itrEnd)
+ {
+ //document is unsaved document
+
+ SfxObjectShell* p = itr->second.maShell;
+ itr->second.maLastAccess = Time( Time::SYSTEM );
+ return static_cast<ScDocShell*>(p)->GetDocument();
+ }
+
const OUString* pFile = getExternalFileName(nFileId);
if (!pFile)
// no file name associated with this ID.
@@ -2341,6 +2369,17 @@ bool ScExternalRefManager::isOwnDocument(const OUString& rFile) const
void ScExternalRefManager::convertToAbsName(OUString& rFile) const
{
+ // unsaved documents have no AbsName
+ TypeId aType(TYPE(ScDocShell));
+ ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
+ while (pShell)
+ {
+ if (rFile == rtl::OUString(pShell->GetName()))
+ return;
+
+ pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
+ }
+
SfxObjectShell* pDocShell = mpDoc->GetDocumentShell();
rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
}
@@ -2644,6 +2683,51 @@ sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_u
return nNumFmt;
}
+void ScExternalRefManager::transformUnsavedRefToSavedRef( SfxObjectShell* pShell )
+{
+ DocShellMap::iterator itr = maUnsavedDocShells.begin();
+ while( itr != maUnsavedDocShells.end() )
+ {
+ if (&(itr->second.maShell) == pShell)
+ {
+ // found that the shell is marked as unsaved
+ rtl::OUString aFileURL = pShell->GetMedium()->GetURLObject().GetMainURL(INetURLObject::DECODE_TO_IURI);
+ switchSrcFile(itr->first, aFileURL, rtl::OUString());
+ EndListening(*pShell);
+ maUnsavedDocShells.erase(itr++);
+ }
+ }
+}
+
+void ScExternalRefManager::Notify( SfxBroadcaster&, const SfxHint& rHint )
+{
+ if ( rHint.ISA( SfxEventHint ) )
+ {
+ sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
+ switch ( nEventId )
+ {
+ case SFX_EVENT_PREPARECLOSEDOC:
+ {
+ SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
+ ScDocShell* pDocShell = static_cast< ScDocShell* >( pObjShell );
+ WarningBox aBox( pDocShell->GetActiveDialogParent(), WinBits( WB_OK ),
+ ScGlobal::GetRscString( STR_CLOSE_WITH_UNSAVED_REFS ) );
+ aBox.Execute();
+ }
+ break;
+ case SFX_EVENT_SAVEDOCDONE:
+ case SFX_EVENT_SAVEASDOCDONE:
+ {
+ SfxObjectShell* pObjShell = static_cast<const SfxEventHint&>( rHint ).GetObjShell();
+ transformUnsavedRefToSavedRef(pObjShell);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
{
if (pTimer == &maSrcDocTimer)
diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src
index 464f14119a50..a5a1e6aedac2 100644
--- a/sc/source/ui/src/globstr.src
+++ b/sc/source/ui/src/globstr.src
@@ -1851,5 +1851,13 @@ Resource RID_GLOBSTR
{
Text [ en-US ] = "Invalid name. Only use letters, numbers and underscore.";
};
+ String STR_UNSAVED_EXT_REF
+ {
+ Text [ en-US ] = "This Document contains external references to unsaved documents.\n\nDo you want to continue?";
+ };
+ String STR_CLOSE_WITH_UNSAVED_REFS
+ {
+ Text [ en-US ] = "This Document is referenced by another document and not yet saved. Closing it without saving will result in data loss.";
+ };
};
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx
index cfa027e8d54e..e2c950c4d9b9 100644
--- a/sc/source/ui/view/viewfun2.cxx
+++ b/sc/source/ui/view/viewfun2.cxx
@@ -89,6 +89,7 @@
#include "docuno.hxx"
#include "charthelper.hxx"
#include "tabbgcolor.hxx"
+#include "clipparam.hxx"
#include <basic/sbstar.hxx>
#include <com/sun/star/container/XNameContainer.hpp>
@@ -2562,6 +2563,7 @@ void ScViewFunc::MoveTable(
if(nDestTab==SC_TAB_APPEND)
nDestTab=pDestDoc->GetTableCount();
SCTAB nDestTab1=nDestTab;
+ ScClipParam aParam;
for( sal_uInt16 j=0; j<TheTabs.size(); ++j, ++nDestTab1 )
{ // insert sheets first and update all references
rtl::OUString aName;
@@ -2576,7 +2578,10 @@ void ScViewFunc::MoveTable(
nErrVal = 0; // total error
break; // for
}
+ ScRange aRange( 0, 0, TheTabs[j], MAXCOL, MAXROW, TheTabs[j] );
+ aParam.maRanges.Append(aRange);
}
+ pDoc->SetClipParam(aParam);
if ( nErrVal > 0 )
{
nDestTab1 = nDestTab;